I want to create VSCode snippet to quickly use React's useState. E.g. for a state open
const [open, setOpen] = useState()
I'm currently using
"const [ ${1}, set$1 ] = useState()"
But this gives me const [open, setopen] = useState(). Note the lack of caps on open.
I want to be able to just enter the state name open, and have the snippet sort out the capitalization for setOpen. I know I could use 2 variables, but I don't want to type it out twice since it'll always follow the pattern [foo, setFoo]
I know I can do transforms like ${1:/upcase}, but this capitalizes the entire variable, not just the first letter.
This should work:
"const [ ${1}, set${1/(.*)/${1:/capitalize}/} ] = useState()"
Related
See the following snippet:
"srcPath":{
"prefix": "getSrcPath",
"body": [
"$TM_FILEPATH",
"${1:${TM_FILEPATH/(.*)src.(.*)/${2}/i}}",
"${TM_FILEPATH/[\\\\]/./g}"
]
},
The output of lines 1-3 is :
D:\root\src\view\test.lua
view\test.lua
D:.root.src.view.test.lua
How can I get output like 'view/test.lua'?
Try this snippet:
"srcPath":{
"prefix": "getSrcPath",
"body": [
"$TM_FILEPATH",
"${TM_FILEPATH/.*src.|(\\\\)/${1:+/}/g}",
"${TM_FILEPATH/[\\\\]/\\//g}"
]
}
.*src.|(\\\\) will match everything up to and including the ...src\ path information. We don't save it in a capture group because we aren't using it in the replacement part of the transform.
The (\\\\) matches any \ in the rest of the path - need the g flag to get them all.
Replace: ${1:+/} which means if there is a capture group 1 in .*src.|(\\\\) then replace it with a /. Note we don't match the rest of the path after src\ only the \'s that might follow it. So, not matching those other path parts just allows them to remain in the result.
You were close on this one:
"${TM_FILEPATH/[\\\\]/\\//g}" just replace any \\\\ with \\/.
With the extension File Templates you can insert a "snippet" that contains a variable and multiple find-replace operations.
With a key binding:
{
"key": "ctrl+alt+f", // or any other combo
"command": "templates.pasteTemplate",
"args": {
"text": [
"${relativeFile#find=.*?src/(.*)#replace=$1#find=[\\\\/]#flags=g#replace=.#}"
]
}
}
At the moment only possible with a key binding or via multi command (or similar). Will add an issue to also make it possible by prefix.
Also some of the standard variables are missing.
I'm in a file called event-list.tsx, and I'm trying to create a snippet that writes the following code:
const EventList: FC = () => {
return <div>
</div>;
};
export default EventList;
Thus far, in typescriptreact.json I've written the following snippet setting, which results in awkward-looking code (it puts out const event-list rather than const EventList
"react arrow func component": {
"prefix": "rafce",
"body": [
"const ${TM_FILENAME_BASE}: FC = () => {",
" return <div>",
" ",
" </div>;",
"};",
"",
"export default ${TM_FILENAME_BASE};",
""
]
},
I know how to remove the hyphen from the snippet:
${TM_FILENAME_BASE/-//}
I also figured out how to capitalize the first character:
${TM_FILENAME_BASE/(^.)/${1:/upcase}/}
But I can't figure out how to apply all three of the changes I want. I know the regular expression needed to capitalize every character that comes after a hyphen (a positive lookbehind), but I don't know how to apply it here. There is nothing in the documentation chapter implying the possibility to chain multiple transforms onto each other.
Try the following global regex
${TM_FILENAME_BASE/(.)([^-]*)-?/${1:/upcase}${2}/g}
Find a part before a - and Upcase the first letter, repeat for the whole string
"${TM_FILENAME_BASE/(\\w+)-?/${1:/capitalize}/g}",
(\\w+)-? : You only need one capture group if you use /capitalize.
The hyphens are removed by virtue of matching them (-?) but not including them in the output.
The g flag is necessary to keep matching every (\\w+)-? instance and perform a transform for each.
And since you are reusing an earlier transform you can simplify the whole thing like this:
"react arrow func component": {
"prefix": "rafce",
"body": [
"const ${1:${TM_FILENAME_BASE/(\\w*)-?/${1:/capitalize}/g}}: FC = () => {",
" return <div>",
" ",
" </div>;",
"};",
"",
"export default $1;",
""
]
},
Note that
${1:${TM_FILENAME_BASE/(\\w*)-?/${1:/capitalize}/g}}
stores the result of that transform in variable $1 - which can simply be used later (or earlier) by itself to output the same result!
I am trying to create a snippet using vs code (javascript.json) to do the following code.
const [click, setClick] = useState(false)
I have created the following snippet which sort of works.
"My Custom useState": {
"prefix": "myus",
"body": [
"const [${1:name}, set${1:name}] = useState(${2|true,false|})"
],
"description": "My Custom useState"
}
But in the example, I want to try and find a way to capitalise the second word. So the above snippet output is
const [click, setclick] = useState(false)
Currently, I go back into the code and change to a capital letter by hand, but it has reduced the amount of code I write.
Try this as the body:
"const [${1:name}, set${1/(.)/${1:/capitalize}/}] = useState(${2|true,false|})"
That will "transform" the first letter (.) of that capture group 1 into a capital letter ${1:/capitalize}.
In your case ${1:/upcase} would do the same thing since the capture group only contains the first letter. Normally, ${1:/upcase} will capitalize the entire capture group, not just the first letter like ${1:/capitalize} does.
What will not work is set${1:name/(.)/${1:/capitalize}/} where the default :name is used. You cannot transform a default. See https://github.com/microsoft/vscode/issues/56703
I'm using vscode to edit latex (with the latex workshop plugin), and
I recently started creating my own snippets and really like the feature. However, I find the syntax a bit heavy for creating "small" snippets that just abbreviate frequent sequences of words. In particular, I find it cumbersome to have to give a 'name' to each snippet.
Is there a mechanism for "slim" snippets/aliases, that would e.g. take as input a file where each snippet is one line -- the first word being the abbreviation and the rest what is abbreviated?
You have a couple of options. One is to write an extension that could do this - I'll show code that works like an extension that'll work - it looks complicated but use is pretty simple.
Second, you can come close using the Hyper Snips extension where your snippet file (say latex.hsnips) could like like this:
snippet dategreeting "Gives you the current date!"
Hello from your hsnip on ``rv = new Date().toDateString()``!
endsnippet
snippet // "Fraction simple" A
\frac{$1}{$2}$0
endsnippet
snippet stte A
some text to expand
endsnippet
The descriptions in "" are not necessary and I eliminated it in the last snippet. The A flag will immediately insert your replacement text, without it you would Tab to insert the replacement text. As the examples here show you can use javascript within a snippet if you want.
The gif doesn't show it well bit here is a demo of auto-expansion with Hyper Snips:
Alternatively, download the extension macro-commander. It allows you to use vscode extension commands in a macro within your settings. This macro would go into your settings.json file:
"macros": {
"slimSnippetsInsertion" : [
{
"javascript": [
"const editor = vscode.window.activeTextEditor;",
"const document = editor.document;",
"const we = new vscode.WorkspaceEdit();",
"const cursorPosition = editor.selection.active;", // use whether an actual selection or not, returns a Position
"let keyWordRange = document.getWordRangeAtPosition(cursorPosition);", // returns a Range of start/end Positions or undefined
"if (keyWordRange === undefined) {",
"await window.showInformationMessage(`cursor must be in or immediately after word to be replaced`);",
"return;",
"}",
"let wordAtCursor = document.getText(keyWordRange);", // this is the key word to find in slimSnippets.txt
"const thisWorkspace = vscode.workspace.workspaceFolders[0].uri.toString();",
// file:///c:/Users/Mark/OneDrive/Test Bed
"const snippetFileContent = await vscode.workspace.fs.readFile(vscode.Uri.parse(`${thisWorkspace}/.vscode/slimSnippets.txt`));",
"const snippets = snippetFileContent.toString();",
// ignore leading spaces/tabs before keys
// using a named capturing group for the replacement text
"const regex = new RegExp(`\\r?(?<=\\n|^)[\\t ]*(?<key>${wordAtCursor})[\\t ]+?(?<replacementText>.*?)(?=\\r?\\n|$)`);",
"let found = snippets.match(regex);", // returns null if no matches
// matched a key but only spaces as replacement text, so do nothing and exit
"if (found && found.groups.replacementText.trimStart().length === 0) {",
"await window.showInformationMessage(`replacement text is only spaces, not replacing`);",
"return;",
"}",
"if (found) {", // found at least a matching key
"if (found.groups.replacementText) {", // found non-space replacement text
// replace `\n` and `\t` with unicode values for newline and tab
"let replace = found.groups.replacementText.replace(/\\\\n/g, '\\u000A').replace(/\\\\t/g, '\\u0009');",
"let snippet = new vscode.SnippetString(replace)",
"if (editor.selections.length === 1) editor.insertSnippet(snippet, keyWordRange);", // if zero or one selection"
// if multiple selections, uses first key and replacement text"
"else editor.insertSnippet(snippet);",
"}",
"else await window.showInformationMessage(`matching key found but with no replacement text in slimSnippets.txt`);",
"}",
"else await window.showInformationMessage(`no matching key found in slimSnippets.txt`);",
]
}
You can see where I made it to read a simpleSnippets.txt file located in the .vscode folder in the workspace - but you can change the location as long as you alter the path info in the command: vscode.workspace.fs.readFile above.
The slimSnippets.txt file is just a simple text file where the first word in each line is the key and the rest of the line is the replacement.
howdy1 $1 first $2 sentence with tabstops
howdy1 this won't be used, duplicate key above
howdy2 second sentence with variable $TM_FILENAME
key3 videos 111111 // one space necessary between key and replacement text
// it will be removed, others retained
key1 222222
stte some text to expand
mt2e more text to expand
[replacement text can have placeholders, tabstops and choices just like regular snippets]
[join multiple-lines snippets into one string with newlines as below]
[some text\nsome more text] [\t can be used for tabs]
key5 line 1\n\tline 2\n\t\tline 3
Keys are single words and if there is no replacement text (or there are only spaces in the file after a key) nothing will happen - the key will not be replaced.
The text actually inserted can be plain text or use vscode's snippet format - see the sample text file above.
The cursor must be immediately after the word or in the word and the word can be selected or not. It must be a word in the regex sense - not continuous text adjoining the word before or after it - just a standalone word, it can be anywhere on the line.
If you have duplicate keys, the first will be used. There can be empty line spaces between key/replacement lines or not.
You will not get intellisense for the keys. I may work on that.
Finally, you will need a keybinding to trigger this macro (in keybindings.json):
{
"key": "ctrl+;", // whatever keybinding you wish
"command": "macros.slimSnippetsInsertion"
},
With dfmt, the source code formatter for D language, the following code:
auto carModels = [
"alpha",
"bravo",
"charlie",
"delta"
];
gets re-formatted into:
auto carModels = ["alpha", "bravo", "charlie", "delta"];
Is there a way to make the formatter keep the elements one per line as specified in the original, without turning off dfmt for that line?
I am using the vs-code D language extension called code-d, it invokes dfmt when formatting files.
This has now been added to dfmt with a new flag called keep_line_breaks
https://github.com/dlang-community/dfmt/pull/471