use dollar sign in a vscode snippet regex - visual-studio-code

I am trying to make a vs code php snippet which generate this line from the $code placeholder input:
Utils::getLogger.debug("code", ["code" => $code])
The regex I use for this is /(\$?)(.*)/ (I am interested in the second capture group to get the variable name).
This is my snippet code :
"log debug": {
"prefix": ["log debug", "debug"],
"body": ["Utils::getLogger.debug(\"${1/(^\\$?)(.*)/$2/}\", [\"${1/(^\\$?)(.*)/$2/}\" => ${1:variable}])"],
"description": "Quick variable debug."
},
The problem is that it doesn't replace the dollar sign from my input. If I give $variable as placeholder, it generates Utils::getLogger.debug("$variable", ["$variable" => $variable]).
I got it working for a charater different than the dollar sign, for example a comma or another letter and also I got it working using TM_SELECTED_TEXT variable and selecting my variable before.
I suspect that it is a conflict with vs code php variable name autocompletion in vscode as if I copy my variable then call the snippet and paste the variable inside the placeholder (instead of typing it), it also works.
I was tempted to post this as an issue on vscode github but maybe am doing something wrong here.
ps: I know that is can also type in the variable name without the $ and add it in the replacement regex, but you know how developpers can be...

This works:
"body": ["Utils::getLogger.debug(\"${2:${1/\\$?(.*)/$1/}}\", [\"$2\" => ${1:variable}])"],
Note that since you are reusing the first transform, I set it to a placeholder ${2} by wrapping it like so:
${2:${1/\\$?(.*)/$1/}}
Now you can reuse that $2 placeholder wherever you want the result of the same transform - as in \"$2\" =>.
Thanks to https://stackoverflow.com/a/66449064/836330 for that usage.

After discussions and further testing, I think there is nothing wrong with the snippet code and it is a "conflict" with php variable autocompletion.
There are some optimisations in the answers that are interesting tho.
For information, I finally took the solution to enter the variable name without the $ and add it in the transform.
"log debug quick": {
"prefix": ["log debug quick", "debug quick"],
"body": ["Utils::getLogger.debug(\"${1:variable}\", [\"${1}\" => \\$${1}]);"],
"description": "Quick variable debug."
},
Note that the original method works with the TM_SELECTED_TEXT variable (as the autocompletion does not happen), so the folowing is working :
"log debug selection": {
"prefix": ["log debug selection", "debug selection"],
"body": ["Utils::getLogger.debug(\"${1:${TM_SELECTED_TEXT/^\\$?(.*)/$1/}}\", [\"${1}\" => $TM_SELECTED_TEXT]);"],
"description": "Quick variable debug."
},
Note that I optimized the snippet with both #Mark and #rioV8 suggestions

Related

VS Code Snippet - Change position of linked tabstops

I am currently switching from IntelliJ to VS Code for a project and want to take some of my custom live templates with me.
VS Code supports "User Snippets", but I can't get them to work like they do in IntelliJ.
I want to achieve the following output:
console.log('variableName', variableName);
Now the thing is, I want my cursor to start right after the , so I get IntelliSense for auto completion of a defined variable. Then that variable name should be placed in the string.
I am right at the start and know that tabstops with the same ID get the same value:
"console.log variable": {
"scope": "javascript,typescript",
"prefix": "cl",
"body": [
"console.log('${1}', ${1});",
"$0"
],
"description": "console.log variable with name"
}
The problem with this is though, that the first tabstop is the start of the snippet and since I am inside a string I don't get IntelliSense for the variable name.
Is there a way to reverse the tabstop order of linked tabstops or anything similar that helps with the problem at hand?
"Print to console": {
"prefix": "clog",
"body": [
"console.log('${1:variable}', ${1:variable});$0"
],
"description": "Log output to console"
}
Works but you have to press Ctrl+Space to get completion items.

Snippet with prefix "``" (double backtick) not working for inline Markdown code block

For writing inline Markdown code blocks quickly, I want to use the following snippet:
"prefix": "``",
"body": ["`$1` $2"],
This snippet would enable me to just tab through the code block.
The snippet however does not trigger when using ``.
If I try to escape the backticks with backslashes, the prefix ends up empty and doesn't work either.
"prefix": "\`\`",
"body": ["`$1` $2"],
Is it possible to use `` as a prefix?
I found an explanation for why backticks work as a prefix but the snippet suggestion must be manually triggered with Ctr/+space.
From snippets prefix support utf-8:
The prefix can be anything but "suggestions as you type" are only
triggered when typing a word character. What that is defines the
corresponding language. For non word prefixes suggestion must be
triggered manually, using ctrl+space
Backticks are apparently not word characters in markdown, so you need to manually trigger the suggestions with Ctr/+space.
Otherwise this works:
"backticks": {
"scope": "markdown",
"prefix": "\\`\\`", // note double backslashes
"body": ["`$1` $2"],
}

Is there a way to add a blank option with VS Code snippets placeholder choices?

I am trying to create a snippet that gives me choices for optional attributes. I have used this approach in the past where I just put a blank space as a choice in the placeholder. That works when there is only one option between other parts of the snippet but like in the following example if I wanted to skip both placeholders (optional attributes on the adorn) there would be multiple spaces in the generated code which I would have to delete manually.
"Adorn":
"prefix": ["adorn"],
"body": [
"<%= adorn${1| , color: :blue, color: :white|}${2| , inline: true|} do |a| %>",
"\t$0",
"\t<%= a.adornment %>",
"\t\t",
"\t<% end %>",
"<% end %>"
],
"description": "An adorn"
},
From what I can see in the documentation it doesn't seem possible to do what I want using placeholders and choices. I thought I could use a variable and just have it resolve to empty string but the grammar doesn't seem to allow for that.
Is there any other way to accomplish what I am trying to do?
You can use some unicode characters in snippets, so I tried backspace (did not work) but \u200B which is a "zero-width space" does. So you can do this in your choices:
{1|\u200B, color: :blue, color: :white|}${2|\u200B, inline: true|}
and if you choose the blanks (i.e., the \u200B's) a zero-width space will be inserted. And you get what you want - no spaces to be deleted.
But I leave it to you to see if there are any parsing or other problems with having that character in your code. Maybe it is or isn't a problem in your language. See the open issue (which I found after posting this answer initially) https://github.com/microsoft/vscode/issues/34368 ("Allow "empty" as a choice in snippets
") where the zero-width space option is warned against and may cause problems - so test it. It doesn't look like there is any other option but a regular space which you have tried.
I tried "null" \u0000 and it wasn't recognized by vscode.
if a blank space is all you need, then all is needed is an '$1' that the placeholder.
but first let's see if you have errthing
First
at the root of yow project you need a new dir call .vscode
in side yow dir add a new file NOTE name is very important yow new file's must have this pattern any.code-snippets
in side yow new file add this
{
// Place your global snippets here. Each snippet is defined under a snippet name and has a scope, prefix, body and
// description. Add comma separated ids of the languages where the snippet is applicable in the scope field. If scope
// is left empty or omitted, the snippet gets applied to all languages. 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": {
"scope": "javascript,typescript",
"prefix": "log",
"body": [
"console.log('$1');",
"$2"
],
"description": "Log output to console"
}
}
To finish I recommend you to remove the scope attribute. and do not use the file for more than one language, bcuz if you do so it may not work at all.
The best way to get an empty value for a placeholder with choices is to add a choice of 1 character and remove this with Delete or Backspace (depending where the cursor is, it differs for the 2 placeholders) and then TAB to the next placeholder.
To get the choice list for placeholder 2 press TAB when you are at placeholder 2.
Watch the location of the separating spaces, they are at the end of the choice.
"Adorn": {
"prefix": ["adorn"],
"body": [
"<%= adorn ${1|e,color: :blue ,color: :white |}${2|e,inline: true |}do |a| %>",
"\t$0",
"\t<%= a.adornment %>",
"\t\t",
"\t<% end %>",
"<% end %>"
],
"description": "An adorn"
}

VS Code Snippets too greedy with dot character

I have the following snippet configured.
{
"Pandas Display All Columns": {
"scope": "python",
"prefix": "pd.options.display.max_columns",
"body": [
"pd.options.display.max_columns = None"
],
"description": "Allows all columns of the dataframe to print"
}
The problem is every time I type a period . and hit enter it auto-completes with this snippet. For example if I'm typing a doc string and use a period and hit enter. I know, I know... working as designed.
If I shorten the prefix so it does not contain and dot character . so only pd is used, it is not intuitive when the intellisense pops up. How do you suggest I formulate my snippet so it is intuitive and not showing every time I type . all by itself?

vscode Nest snippet choices and add tab stops to choices

I want to do something like that in my snippets for visual studio code:
"V.G.${1|BLOCK_NR,MASS_MM,MASS_360,I,J,K,R,FEEDRATE,FEEDRATE_SCALE,MERR[${2}]|}"
So after choose the option MERR[] I will see the cursor inside the brackets.
and how i have to manage sub choices like:
"V.G.${1|choice${2|subchoiceA,subchoiceB|},choice, choice......}"
If I choose MERR[] Option I will jump into [Cursor should be here]. How can i handle this?
Here is a workaround to your subchoiceA/B question because you cannot have anything except plain text as choices - no tabstops or subchoices, etc. Your example:
V.G.${1|choice${2|subchoiceA,subchoiceB|},choice, choice......}"
This can be achieved however with 2 snippets:
"choices with subchoices": {
"prefix": "_choices", // whatever prefix you want
"body": [
"V.G.${1|choice1, _subchoices,choice2,choice3|}"
],
"description": "variables in a choice element"
},
"my subchoice list": {
"prefix": "_subchoices", // this prefix must be what you used in the main snippet
// as your subchoice option
"body": [ "${1|subchoiceA,subchoiceB|}" ],
"description": "subChoices"
},
What happens is that when you choose the subchoices option in the main snippet it will see it as the prefix for the second snippet - that is pretty neat. But it will not do so until you trigger that recognition with Ctrl+Space the usual intellisense trigger and then tab to select the second snippet.
It is only one or two extra keystrokes to get subchoices working inside of a parent choice element when otherwise it can't be done at all.
The only issue is that your second prefix - here subchoices cannot be a continuation of another string with no spaces otherwise it won't be recognized as a standalone snippet prefix by vscode. That is why I added the space before subchoices in the main snippet since your example has "V.G.${1....} with no space before the option would be inserted.
Here is a demo: