abulka / vscode-snippet-creator

An extension to simplify the snippet creation
11 stars 2 forks source link

No snippets created in WSL #4

Open AlanBF1992 opened 3 years ago

AlanBF1992 commented 3 years ago

When using VS Code in WSL it doesn't add the new snippet to the files.

DanNYSPD commented 3 years ago

Can you provide more info?, the exactly input and what kind of language the tarjet is. Please

AlanBF1992 commented 3 years ago

Any language, any input.

Looking in other threads, it looks like 2 options:

  1. It's looking for the file using the Windows location without taking into account that the drive is mounted
  2. It doesn't have permissions to modify the file

In Windows without WSL it works fine

Stabledog commented 2 years ago

It's true: the extension fails to save changes if the VSCode back-end is running in WSL. The workaround is to "Reopen Folder in Windows" -- less than ideal, but it's usable.

It looks like this change from @qyuirla probably fixes the issue, but has never been pushed upstream or published.

abulka commented 2 years ago

Nice find re the code changes required to fix this issue - I will test and hopefully do a new release soon.

abulka commented 2 years ago

I've published wware.snippet-creator v1.1.3 with the code changes referred to above.

Tested on Mac - but not yet tested on other platforms, nor in vscode insiders, nor in WSL - please provide feedback if the issue is fixed for you.

Stabledog commented 2 years ago

Thanks @abulka, I expect to check it with WSL and Docker back ends this week. --- Edit --- My quick test on WSL fails: adding a new snippet does not alter the contents of the VSCode front-end snippets content. I will try to check out the latest and debug it, drawing on my limited extensions-debugging skills :)

My investigation notes linked below, this is a work in progress:

sumsyper commented 1 year ago

I was fixed this issue by reinstalling VSCode. I don't know how It's being fixed by reinstalling. I tried to uninstall the extension on WSL but It broke again. I tried everything to fix it. The extension cannot create snippets while using WSL, also created snippets cannot be used in the VSCode. Is there any solution?

abulka commented 1 year ago

I'm happy to take a PR if anyone can investigate by running the source code of this extension and debugging this - I don't use WSL / Windows so prefer if someone who is more familiar look into this.

sumsyper commented 1 year ago

While using the WSL extension, there is a way to install extensions on WSL category of VSCode. When I install Snippet Creator extension, it automatically being installed on the WSL category of VSCode. I think Snippet Creator has to be just a local extension for windows. Like If I install Vibrancy-Continued extension, it just being installed on locally. If I install Code Runner, its being installed on just WSL category. They both works fine. If I install Snippet Creator, its being installed on both and says "Install this extension to WSL" then its not working anymore. Snippet Creator can be just installed locally, not to WSL.

Solution that I've found by myself is; 1- Uninstalling the WSL extension on VSCode. 2- Finding the WSL folder (Called Linux) on Windows' file manager. 3- Inside of WSL folder, go to home folder, if you want pin here to quick access menu by right clicking or wherever you want inside home folder. Home folder is your first directory when you starting WSL. 4- Installing Snippet Creator extension on VSCode, because of it will be installed locally, it will work fine. 5- Open file explorer and open home directory of your WSL Linux Distribution from quick access (or where you added to quick access) then right right click and open VSCode in here, open terminal inside VSCode and type "wsl" to connect your WSL without installing WSL extension.

When do this, Snippet Creator works fine. But other extensions like Code Runner does not work may be because of nodejs does not installed on the Windows and just insalled on the WSL. May be because of directory issue like "\wsl.localhost\Ubuntu-22.04\home\x\Code".

Can you make Snippet Creator being not installed on the WSL? Also sorry for my bad English.

image Install in WSL button, if you click it, Snippet Creator being broken. If you don't do it, Create Snippet is not working so you cannot create a snippet by extension.

May be Snippet Creator extension does not have a access to the some file inside WSL i don't know.

I will try to debug the extension. May I found why it's broken.

sumsyper commented 1 year ago

I wanted to make some test in source codes but I could not able to install dependencies like vscode, it always says vscode module not found and I could not fix it :(

sumsyper commented 1 year ago

I've fixed the issue by adding a control mechanism for WSL, if file system inside of WSL, finds the right snippet folder on /mnt.

Added a new js file to export the control function. Here is modified files;

Project Structure that inside of src folder is

extension.js Snippet.js SnippetManager.js wsl.js

src/SnippetsManager.js =>

const vscode = require('vscode');
const os = require('os');
const fs = require('fs');
const path = require('path');
const jsonc = require('jsonc-parser');
const wsl = require('./wsl');

class SnippetsManager {

    addSnippet(snippet, context) {
        /**
         * The location of user snippets folder is different from
         * the officially documented one when VSCode is in portable mode.
         * It's the safest way to get the unpredictable path of user-data folder.
         */

        var snippetFile;
        if (wsl) {
            snippetFile = path.join(wsl.toString(), snippet.language + '.json');
        }
        else {
            snippetFile = path.join(
                context.globalStorageUri.fsPath, '..', '..', 'snippets', snippet.language + '.json'
            );
        }
        // console.log('Location of snippets file for OS', os.type(), 'snippetFile: ' + snippetFile);

        if (!fs.existsSync(snippetFile)) {
            fs.openSync(snippetFile, "w+");
            fs.writeFileSync(snippetFile, '{}');
        }

        fs.readFile(snippetFile, (err, text) => {
            if (err) {
                return;
            }

            let jsonText = text.toString();

            let parsingErrors = [];
            let snippets = jsonc.parse(jsonText, parsingErrors);

            if (parsingErrors.length > 0) {
                let errors = [];
                parsingErrors.forEach(e => {
                    let errorText = `'${jsonc.printParseErrorCode(e.error)}' error at offset ${e.offset}`;
                    errors.push(errorText);
                });

                vscode.window.showErrorMessage(`Error${parsingErrors.length > 1 ? "s" : ""} on parsing current ${snippet.language} snippet file: ${errors.join(', ')}`);
                return;
            }

            if (snippets[snippet.name] !== undefined) {
                let proposedName = snippet.name
                snippet.name = snippet.name + '_' + this.uuidv4()
                vscode.window.showErrorMessage(`A snippet '${proposedName}' already exists - so adding a unique id: '${snippet.name}'`);
            }

            // if user has not entered anything for 'prefix' or 'description', auto set to some sensible values
            if (snippet.prefix == "")
                snippet.prefix = snippet.name;
            if (snippet.description == "")
                snippet.description = `description for ${snippet.name}`;

            // Edit the snippet json file by inserting the snippet entry
            let path = snippet.name
            let snippetEntry = {
                prefix: snippet.prefix,
                body: snippet.body,  // array of strings
                description: snippet.description
            }
            let options = {
                formattingOptions: {
                    // If indentation is based on spaces (`insertSpaces` = true), then what is the number of spaces that make an indent?
                    tabSize: 2,  // based on default vscode snippet format

                    // Is indentation based on spaces?
                    insertSpaces: false,

                    // The default 'end of line' character
                    eol: ''
                }
            }
            let edit = jsonc.modify(jsonText, [path], snippetEntry, options); // create the 'edit'
            let fileContent = jsonc.applyEdits(jsonText, edit); // apply the 'edit'
            fs.writeFile(snippetFile, fileContent, () => { });
            vscode.window.showInformationMessage(`Snippet '${snippet.prefix}' added to '${snippet.language}.json' snippets. Tip: Edit snippets using the command "Configure User Snippets"`)
        });

    }

    uuidv4() {
        return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
            var r = Math.random() * 16 | 0, v = c == 'x' ? r : (r & 0x3 | 0x8);
            return v.toString(16);
        });
    }

}

module.exports = SnippetsManager;

And added WSL.js to support for WSL systems (src/wsl.js);

const fs = require('fs');
const path = require('path');

function getSnippetFolderLocationOnWSL() {
    const mntFolderPath = '/mnt'; // /mnt folder's path
    const letters = 'abcdefghijklmnopqrstuvwxyz1234567890'; // letter array
    const targetPath = '/AppData/Roaming/Code/User/snippets/'; // search path

    for (const letter of letters) {
        const userFolderPath = path.join(mntFolderPath, letter, 'Users');

        if (fs.existsSync(userFolderPath)) {
            const defaultFolderPath = path.join(userFolderPath, 'Default');

            if (fs.existsSync(defaultFolderPath)) {
                const parentFolderPath = path.dirname(defaultFolderPath);

                // find "Default" folder's path
                const parentSubfolders = fs.readdirSync(parentFolderPath).map(subfolder => path.join(parentFolderPath, subfolder));

                for (const subfolder of parentSubfolders) {
                    const snippetsFolderPath = path.join(subfolder, targetPath);
                    if (fs.existsSync(snippetsFolderPath)) {
                        return snippetsFolderPath;
                    }
                }
            }
        }
    }

    return false;
}

module.exports = getSnippetFolderLocationOnWSL();

Tested on Ubuntu 22.04.3 (Working fine) (Linux) Tested on Windows 11 without WSL (Working fine) (Windows) Tested on WSL 2 on Windows 11 (Working fine) (Windows)

Extension is working fine with WSL now. I'm currently using it.

@abulka