Is there a way to create custom variables inside a VScode snippet? I have these kind of snippets where I create a singleton, based on the name of a file and a folder.
Here's the snippet:
"Service": {
"prefix": "singletonByPath",
"body": [
"class ${TM_DIRECTORY/.*[^\\w]([a-z])(\\w+)$/${1:/upcase}$2/g}${TM_FILENAME_BASE/([a-z])(\\w+)/${1:/upcase}$2/g} {",
" $0",
"}",
"",
"export const ${TM_DIRECTORY/.*[^\\w]([a-z])(\\w+)$/${1:/downcase}$2/g}${TM_FILENAME_BASE/([a-z])(\\w+)/${1:/upcase}$2/g} = new ${TM_DIRECTORY/.*[^\\w]([a-z])(\\w+)$/${1:/upcase}$2/g}${TM_FILENAME_BASE/([a-z])(\\w+)/${1:/upcase}$2/g}();",
""
],
"description": "Create an exported singleton instance and a class based on the filename and path"
},
So, when the snippet is triggered in a path like: '..../customers/service.ts' You will have this result:
class CustomersService {
}
export const customersService = new CustomersService();
The problem is that I have duplications of long hard to read regexes, and I would like to extract them to variables (or mirrors without tab stops).
I would even prefer having these variables in a "snippet-global location" so that I can use them in multiple snippets.
Is it possible to somehow reduce these duplications?
There are a couple of things you can do to simplify your snippet. There is no built-in way to save "variables" of pre-defined snippet parts.
Here though is a simplification of your code:
"Service": {
"prefix": "singletonByPath",
"body": [
// "class ${TM_DIRECTORY/.*[^\\w]([a-z])(\\w+)$/${1:/upcase}$2/g}${TM_FILENAME_BASE/([a-z])(\\w+)/${1:/upcase}$2/g} {",
"class ${1:${TM_DIRECTORY/.*[^\\w]([a-z])(\\w+)$/${1:/upcase}$2/g}}${2:${TM_FILENAME_BASE/([a-z])(\\w+)/${1:/upcase}$2/g}} {",
-- --
" $0",
"}",
"",
// "export const ${TM_DIRECTORY/.*[^\\w]([a-z])(\\w+)$/${1:/downcase}$2/g}${TM_FILENAME_BASE/([a-z])(\\w+)/${1:/upcase}$2/g} = new ${TM_DIRECTORY/.*[^\\w]([a-z])(\\w+)$/${1:/upcase}$2/g}${TM_FILENAME_BASE/([a-z])(\\w+)/${1:/upcase}$2/g}();",
"export const ${1/(\\w+)/${1:/downcase}/}$2 = new $1$2();",
""
],
"description": "Create an exported singleton instance and a class based on the filename and path"
}
Note the use of $1:${TM_DIRECTORY...}
and likewise ${2:${TM_FILENAME_BASE...}
This effectively sets $1
to the result of the TM_DIRECTORY
transform and $2
to the result of the TM_FILENAME_BASE
transform and those "variables" can be used elsewhere in the snippet by just referring to $1
and $2
.
Those "variables" can even be transformed themselves as in the ${1/(\\w+)/${1:/downcase}/}
transform in the last line.
The last line of your snippet then becomes simply:
"export const ${1/(\\w+)/${1:/downcase}/}$2 = new $1$2();",
You will have to tab a couple of times because those "variables" are now tabstops, and the last transform won't be completed until you do tabstop past it, but that is a small price to pay for such a simplification.
There are other simplifications to your snippet that aren't "variable-related":
"body": [
"class ${1:${TM_DIRECTORY/.*[\\/\\\\](.*)/${1:/capitalize}/}}${2:${TM_FILENAME_BASE/(.*)/${1:/capitalize}/}} {",
" $0",
"}",
"",
"export const ${1/(\\w+)/${1:/downcase}/g}$2 = new $1$2();",
""
],
You can use the capitalize
transform. Also note that this last body
works for Windows and linux path separators.