How to get file name when overriding VS Code snippet - visual-studio-code

I'm trying to override the rfce snippet in VS code but I can't seem to be able to get the filename autofilled when there's a named file. Where the file is not saved(unnamed) it should just be NameOfComponent but if the file is saved(has a name), the snippet should name the component the same as the file name but without the extension. Here's what I have so far:
"React Component": {
"prefix": "rfce",
"body": [
"import React, { useState, useEffect } from \"react\";",
"",
"const ${1:NameOfComponent} = () => {",
" return (",
" <>",
" ${2:<div>Hello World</div>}",
" </>",
" );",
"};",
"",
"export default ${1:NameOfComponent};"
],
"description": "React Component"
}

If you want to make your snippet into a template for new files see https://stackoverflow.com/a/73043147/836330. Snippet template functionality is being built in to vscode.
Presumably you have found $TM_FILENAME_BASE from vscode snippet variables documentation as the variable you need to get the file name of the current file without its extension.
Ideally what you would like to do is a choice element (see Choice doc and something like this:
"const ${1|NameOfComponent},$TM_FILENAME_BASE|}...", // does not work
That won't work because according to the snippet grammar choice options can only be text:
choice ::= '${' int '|' text (',' text)* '|}'
So you would have to simulate a choice as close as possible. The following snippet does that in two ways:
"React Component": {
"prefix": "rfce",
"body": [
"import React, { useState, useEffect } from \"react\";",
"",
// "const ${1:NameOfComponent}${2:$TM_FILENAME_BASE} = () => {", // option 1 works
"const ${1:${2:NameOfComponent}${3:$TM_FILENAME_BASE}} = () => {", // option 2 works
" return (",
" <>",
" ${4:<div>Hello World</div>}",
" </>",
" );",
"};",
"",
"export default $1;" // uses option 2
],
"description": "React Component"
}
Option 1 simply lists both ${1:NameOfComponent}${2:$TM_FILENAME_BASE} presents both "options" - each will be selected in turn, just delete the one you don't want when it is selected and tab to go on. This is pretty straightforward but does require you to use the whole construction ${1:NameOfComponent}${2:$TM_FILENAME_BASE} every time you want that value.
Option 2 wraps the whole thing in another tabstop:
${1:${2:NameOfComponent}${3:$TM_FILENAME_BASE}}} which is a little trickier but then the result is put into tabstop $1 and then that is all you need to refer to when you want the result (as in the last line of the snippet).
You just have to practice a little - there is an extra tab at the start to select NameOfComponent. To accept it just tab past it to select the fileName and delete that, or vice versa - delete NameOfComponent when it is selected and tab to select the fileName - if you want it just tab to go on to the next tabstop.
The result of that inital tabstop will be put into $1 which can then be used elsewhere without the need to go through the option selection stuff again.
Here is a demo using option 2:

You can use TM_FILENAME_BASE - The filename of the current document without its extensions
Example for a react functional typed component:
"create react functional component": {
"prefix": "trafce",
"body": [
"import { FC } from \"react\"",
"\n",
"interface Props {\n\n}",
"\n",
"const $TM_FILENAME_BASE:FC<Props> = ({}) => {",
" return (",
" <div> ${1:$TM_FILENAME_BASE} </div>",
" )",
"}",
"\n",
"export default $TM_FILENAME_BASE"
],
"description": "Create a react-typed functional component "
}
See the demo
Demo for the code snippet

Related

How to change TM_FILENAME_BASE when creating snippets in vs code?

I have a file named "Card.styled.js"
I want to create a snippet to write easier the styled component:
"styled": {
"prefix": "styled",
"body": [
"import styled from \"styled-components\"",
"",
"export const ${1:${TM_FILENAME_BASE}} = styled.$2`",
"",
"${3}",
"`"
]
}
But ${1:${TM_FILENAME_BASE}} is returning me Card.styled.
I want to return only Card in this case.
Card.styled is the correct TM_FILENAME_BASE of Card.styled.js. You will have to modify it further.
You want something like this:
"styled": {
"prefix": "styled",
"body": [
"import styled from \"styled-components\"",
"",
"export const ${1:${TM_FILENAME_BASE/(.*?)\\..*/$1/}} = styled.$2`",
"",
"${3}",
"`"
]
}
(.*?)\\..* get everything before the first . into capture group 1
Match the entire filename_base and replace it with only capture group 1 .

Snippet to split variable TM_FILENAME_BASE in two parts for VScode

I have a file with the name KEY - My text with spaces.md and what to split that filename as a Visual Studio Code (vscode) Snippet. The Goal: Split the file name in KEY and in My text with spaces and drop the splitter -.
I was able to get the last part (value) in the correct way. But I am failing with the first part (key).
Q1: How can I get the key part?
Q2: Is there a better way to get the value part?
markdown.code-snippets file
{
"Add new acronym":{
"prefix": "kw-new-acronym",
"scope": "markdown",
"body": [
"key : \"${TM_FILENAME_BASE/[^0-9^a-z]//gi}\"",
"value: \"${TM_FILENAME_BASE/\\w* - //gi}\""
],
"description": "Add new acronym"
}
}
Some Links:
VScode Snippets
Stackoverflow Search
I found a solution for Q1 and Q2, it is quiet easy :-)
markdown.code-snippets file
{
"Add new acronym":{
"prefix": "kw-new-acronym",
"scope": "markdown",
"body": [
"key : \"${TM_FILENAME_BASE/(.*) - (.*)/$1/}\"",
"value: \"${TM_FILENAME_BASE/(.*) - (.*)/$2/}\""
],
"description": "Add new acronym"
}
}

Can you use a snippet within a snippet?

Like, say I have a snippet:
"Script with vue-property-decorator": {
"prefix": "script",
"body": [
"<script lang='ts'>",
"import {",
" Vue,",
" Component,",
"} from 'vue-property-decorator';",
"",
"#Component",
"export default class $1 extends Vue {",
"",
"}",
"</script>",
],
},
And I want to make a sort of 'meta-snippet' for an entire .vue file -- does VSCode have the capability to call a snippet within another snippet?
I apologize if this has been asked before. A cursory google search turned up nothing.
My initial solution was just to copy-paste the snippet contents into my new snippet and add onto it.

How to change default snippets in VSCode?

VSCode Version:1.20.1
OS Version:windows 10 1709
Steps to Reproduce:
1.When I input fun and press tab,this code will show.
function name(params) {
}
2.I don't like this snippet.I want to change it, but I can not find a file about this snippet.
What should I do?
It is a default snippet but you can overwrite it. So assuming javascript, try this in your javascript.json file:
"Function no name": {
"prefix": "fun",
"body": [
"function () {",
"",
"}"
],
"description": "Function no name or parameters"
},
Gear icon/User Snippets/choose your language.

Control the tab stop order for code snippet of VS Code

For example, with following code, when I type "im" and tab, I will get "import { } from ''", and the initial focus will be at $2 postion, not $1 postion. How can I have the initial focus at $1? Thanks.
{
"import": {
"prefix": "im",
"body": [
"import { $2 } from '$1'"
],
"description": "import element from a module"
}
}
Not sure why it is not following the tab stop order, maybe a bug?
A workaround could be to explicitly set $0 as end of your tab stop
"import": {
"prefix": "im",
"body": [
"import { $0 } from '$1'"
],
"description": "import element from a module"
}
vscode Docs:
The snippet syntax follows the TextMate snippet syntax with the
exception of 'regular expression replacements', 'interpolated shell
code' and 'transformations', which are not supported.
TextMate snippet syntax Manual:
The caret will start at $1, then when pressing tab it will move to $2
and $3 on next tab etc. until there are no more tab stops. If you do
not explicitly set $0, the caret will be at the end of the snippet.