Search code examples
bashshellvisual-studio-codevscode-tasks

VSCode shell task escaping single quotes


VSCode provides shell escaping when defining tasks. I have tried the different mechanisms, and don't have a results that would work universally.

Given a test string:

hello 'world' (what's your name? --)

tasks.json has:

    {
        "label": "test",
        "type": "shell",
        "command": "echo",
        "args":[
            {
                "value": ["${selectedText}"],
                "quoting": "escape"
            }

        ]
    },

With this approach, vscode has parsed the task to:

echo hello\ \'world\'\ (what\'s\ your\ name?\ --)

That's totally wrong. - not escaped, ) not escaped, and no quotes around the parameter.

I tried quoting="strong"

Now the task was parsed to:

 echo 'hello 'world' (what's your name? --)'

That's no good! Now the single quotes in the string are in the way.

I've also tried changing value to ['${selectedText}'] - and in this case, we get

echo ''

It does not appear that we can get proper shell escaping out of the box. I think I need to create a script internal to vscode and avoid the shell altogether. What's the best way to proceed?

I am on Windows 10, WSL, bash, VSCode 1.55.1


Solution

  • I have a solution, and it works. Hopefully, someone else will feel the happiness that it brought me. :-)

        {
            "label": "test",
            "type": "shell",
            "command": "echo \"$(cat << 'HEREDOC' \n${selectedText}\nHEREDOC\n)\" ",
        }
    

    This takes advantage of the HEREDOC mechanism that exists in bash. Credit goes (a bit belatedly) to skztr in this thread - posted in 2010!

    This takes advantage of HEREDOC syntax bash supports:

    << 'TAG' 
    stuff
    TAG
    

    allows stuff to be passed to bash completely unprocessed. It's important to note that the line breaks after << 'TAG' and before the final TAG are required. To make it work in the json files, I placed \n into the string, and that worked well since they will be passed to the shell, which will know what to do with them.

    Finally, the quotation marks around the "command" value are required as well as the quotations around what's passed to echo. The inner set has to be escaped with ". Thus we get

    "command":  "echo \"...\""