Search code examples
jsonvisual-studio-codecode-snippetsvscode-snippets

Can I include conditional logic in VS Code snippets?


I would like to write a snippet in VS Code that writes a "switch" expression (in Javascript), but one where I can define the number of cases.

Currently there is a snippet that produces the outline of a switch expression with 1 case, and allows you to tab into the condition, case name, and the code contained within.

I want to be able to type "switch5" ("5" being any number) and a switch with 5 cases to be created, where I can tab through the relevant code within.

I know the snippets are written in a JSON file, can I include such conditional logic in this, or is it not possible?

Thanks!


Solution

  • The short answer is that you cannot do that kind of thing in a standard vscode snippet because it cannot dynamically evaluate any input outside of its designated variables with some limited workarounds like I'll mention next.

    You might - I and others have written answers on SO about his - type your various case values first and then trigger a snippet tat would transform them into a switch statement. It is sort of doing it backwords but it might be possible.

    There are extensions, however, that do allow you to evaluate javascript right in a snippet or setting and output the result. macro-commander is one such extension. I'll show another simpler extension doing what you want: HyperSnips.

    In your javascript.hsnips:

    snippet `switch(\d)` "add number of cases to a switch statement" A
    ``
    let numCases = Number(m[1])     // 'm' is an array of regex capture groups
    let caseString = ''
    
    if (numCases) {       // if not 'switch0'
        let tabStopNum = 1
        caseString = `switch (\${${tabStopNum++}:key}) {\n`
    
        for (let index = 0; index < m[1]; index++) {
            caseString += `\tcase \${${tabStopNum++}:value}:\n\t\t\$${tabStopNum++}\n`
            caseString += '\t\tbreak;\n\n'
        }
    
        caseString += '\tdefault:\n'
        caseString += '\t\tbreak;\n}\n'
    }
    rv = `${caseString}`       // return value
    ``
    endsnippet
    

    switch HyperSnips demo


    The trickiest part was getting the unknown number of tabstops to work correctly. This is how I did it:

    \${${tabStopNum++}:key}
    

    which will resolve to ${n:defaultValue} where n gets incremented every time a tabstop is inserted. And :defaultValue is an optional default value to that tabstop. If you don't need a defaultValue just use \$${tabStopNum++} there.

    See https://stackoverflow.com/a/62562886/836330 for more info on how to set up HyperSnips.