Search code examples
powershellvisual-studio-codevscode-snippets

Keep $ for Powershell variable in VS code snippet


I’m able to save my code snippets with tabbed spacing in VS code for Powershell, but it keeps ignoring my variables by not displaying the $ for my variables when I call the snippet. It will just paste in the name and omit the $.

How do you get VS code to paste in the $ when you select your code snippet?

Here is the VS Code JSON file I'm using for my "template" snippet

{
    // Place your snippets for powershell here. Each snippet is defined under a snippet name and has a prefix, body and 
    // description. The prefix is what is used to trigger the snippet and the body will be expanded and inserted. Possible variables are:
    // $1, $2 for tab stops, $0 for the final cursor position, and ${1:label}, ${2:another} for placeholders. Placeholders with the 
    // same ids are connected.
    // Example:
    // "Print to console": {
    //  "prefix": "log",
    //  "body": [
    //      "console.log('$1');",
    //      "$2"
    //  ],
    //  "description": "Log output to console"
    // }

"Template": {
    "prefix": "template",
    "body": [
        "<#",
        ".SYNOPSIS",
        "\t<Overview of script>",
        "",
        ".SYNTAX",
        "\t<Cmdlet-Name> -Parameter <value>",
        "",
        ".DESCRIPTION",
        "\t<Brief description of script>",
        "",
        ".PARAMETER <Parameter_Name>",
        "\t<Brief description of parameter input required. Repeat this attribute if required>",
        "",
        ".INPUTS",
        "\t<Inputs if any, otherwise state None>",
        "",
        ".OUTPUTS",
        "\t<Outputs if any, otherwise state None - example: Log file stored in C:\file.log>",
        "", 
        ".EXAMPLE",
        "\t<Example goes here. Repeat this attribute for more than one example>",
        "",
        ".REMARKS",
        "\tVersion:        1.0",
        "#>",
        "",
        "#---------------------------------------------------------[Variables]------------------------------------------------------------",
        "",
        "$var1 = <stuff>",
        "$var2 = <stuff>",
        "",
        "#---------------------------------------------------------[Import Modules]--------------------------------------------------------",
        "",
        "Import-Module <name>",
        "",
        "#-----------------------------------------------------------[Functions]------------------------------------------------------------",
        "",
        "Function <FunctionName> {",
        "\t[CmdletBindinging()]",
        "\tparam(",
        "\t\t[Parameter()]",
        "\t\t[string]$MyOptionalParameter,",
        "",
        "\t\t[Parameter(Mandatory)]",
        "\t\t[int]$MyMandatoryParameter",
        "\t)",
        "",   
        "\tTry{",
        "\t\t<code goes here>",
        "\t}",
        "", 
        "\tCatch {",
        "\t\tWrite-Host $Error.Exception",
        "\t\t$Error.Exception | Out-File Out-File $env:TEMP\file.log",
        "\t\tBreak",
        "\t}",
        "",
        "\tFinally {",
        "\t\t$time = Get-Date",
        "\t\tcompleted at $time | Out-File $env:TEMP\file.log",
        "\t}",
        "}",
        "",
        "#-----------------------------------------------------------[Execution]------------------------------------------------------------",
        "",
        "<FunctionName>",
    ],
    "description": "test"
}

}

When I call this snippet to paste the template into a new .ps1 file, it omits the all the $. How do you get those to stay?


Solution

  • Use \\$ inside a Visual Studio Code snippet body to embed a literal $.

    For instance, to embed PowerShell variable $HOME, use \\$HOME.

    Note: From the snippet parser's perspective, a single \ is required for escaping, but since snippets are defined as JavaScript strings, which themselves use \ as an escape character, \\ is need in order to pass a single \ through to the snippet parser.

    See the docs.


    As an aside:

    Using $$ accidentally, somewhat works, but its purpose is not to escape, and it results in different behavior:

    The location of a $$-prefixed identifier becomes a tab-stop, because Visual Studio Code interprets the sequence as follows:

    The first $ becomes a literal[1], but the second $ and the identifier that follows is interpreted as a Visual Studio Code variable reference; if a built-in variable by that name doesn't exist, it is used as placeholder text.


    [1] Any $ not followed by a valid Visual Studio Code placeholder name or variable reference is treated literally.