microsoft / monaco-editor

A browser based code editor
https://microsoft.github.io/monaco-editor/
MIT License
40.43k stars 3.6k forks source link

How do I recreate the vscode's snippet functionality? #1112

Closed jackrobertscott closed 4 years ago

jackrobertscott commented 6 years ago

Hello 👋

I would like to have the exact same functionality as vscode does for snippets when they are inserted into the editor.

To clarify; I would like to insert a piece of snippet text into the editor e.g.

const snippetTextToInsert = [
  "for (const ${2:defaultElement} of ${1:defaultArray}) {",
  "\tconsole.log(${2});",
  "}",
];

Then have that render in the editor as it does in vscode e.g.

for (const defaultElement of defaultArray) {
  console.log(defaultElement);
}

Once the code is inserted in the editor, I would like to be able to press the TAB key and have it focus on the variable elements in the order provided i.e. ${1:defaultArray} then ${2:defaultElement} and so on.

Thank you!

rcjsuen commented 6 years ago

Duplicate of #734.

function createDependencyProposals() {
    return [
        {
            label: 'forloop',
            insertText: {
                value: 'for (const ${2:defaultElement} of ${1:defaultArray}) {\n\tconsole.log(${2});\n}'
            }
        }
    ];
}

monaco.languages.registerCompletionItemProvider('javascript', {
    provideCompletionItems: function(model, position) {
        return createDependencyProposals();
    }
});

monaco.editor.create(document.getElementById("container"), {
    value: "for",
    language: "javascript"
});
jackrobertscott commented 6 years ago

Is there a way I can activate snippet in the editor without having to use the completion provider?

I.e. as soon as editor loads, the value is automatically loaded into the editor and focused on the first variable.

Thanks! @rcjsuen

rcjsuen commented 6 years ago

@jackrobertscott I don't understand fully understand your requirement(s).

Please provide a detailed description of what you imagine the workflow to be and/or describe your use case as it is achieved in VS Code.

jackrobertscott commented 6 years ago

@rcjsuen The code you provided is nearly exactly what I want. However, it still requires the person to begin typing and then select "forloop" from the auto-complete menu. I want to skip this step i.e.

monaco.editor.create(document.getElementById("container"), {
    value: "for (const ${2:defaultElement} of ${1:defaultArray}) {\n\tconsole.log(${2});\n}",
    language: "javascript"
});

As you can see, the editor starts with the snippet code already inserted. It does not require the user to type "forloop" in the editor. Is this possible?

rcjsuen commented 6 years ago

@jackrobertscott There is no good way to do this. See #342.

let editor = monaco.editor.create(document.getElementById("container"), {
    value: "",
    language: "javascript"
});

let contribution = editor.getContribution("snippetController2");
contribution.insert('for (const ${2:defaultElement} of ${1:defaultArray}) {\n\tconsole.log(${2});\n}');
alexdima commented 4 years ago

The TM snippet parser functionality does not ship with the Monaco Editor. But the code is open source. You can extract it from https://github.com/microsoft/vscode/tree/master/src/vs/workbench/contrib/snippets/browser . There you will find a parser which transforms the TM snippet to a snippet the Monaco Editor can understand.