vscode snippets: repeat what's being typed into given location on the snippet body - visual-studio-code

I want to know if I can repeat whats being typed on position $1 into the snippet location shown below:
"BootstrapCol": {
"prefix": "BSCol",
"body": [
"<div class="col-$1">$0</div><!-- ./col-{REPEAT WHAT IS BEING TYPED HERE} -->"
],
"description": "Create a Bootstrap Grid col Markup"
}
If so, how?

"<div class=\"col-${1}\">$0</div><!-- ./col-${1} -->"

Related

how to make a custom comment style in vscode

I got a source code commented like below.
// //------------------------------------------------------------------------------
// //======================= Variable Declaration =================================
Is there any way to make a comment like the above in vs code.
I only got single and multiline comments.
But I want the above custom style.
You can make a snippet to do that. In one of your snippets files:
"Variable Declaration Comment": {
"prefix": "_gc", // whatever trigger you want
"body": [
"$LINE_COMMENT $LINE_COMMENT------------------------------------------------------------------------------",
"$LINE_COMMENT $LINE_COMMENT======================= ${TM_SELECTED_TEXT} =================================$0",
],
"description": "Insert a Variable Declaration comment header"
}
That will use whatever the line comment style is for the type of file you are in: $LINE_COMMENT.
You could set that to a keybinding like this (in your keybindings.json file):
{
"key": "alt+q", // whatever keybinding you want
"command": "editor.action.insertSnippet",
"args": {
"name": "Variable Declaration Comment"
},
"when": "editorTextFocus"
}
If you want to get fancy and see how to build other custom comment blocks, you can do this with an extension I wrote, Find and Transform. Use this keybinding in your keybindings.json:
{
"key": "alt+f", // whatever keybinding you want
"command": "findInCurrentFile",
"args": {
"replace": [
"$${",
"const lineLength = 80;", // how long you want the block
// what is the length of the comment characters in this language
"const commentCharsLength = 2 * (`${LINE_COMMENT}`.length) + 1;", // + 1 for the space between comment markers
// select the text you want to wrap first
"const selectionLength = `${selectedText}`.length;",
"const gapLength = 1;", // the spaces around the text
"let str = `${LINE_COMMENT} ${LINE_COMMENT}` + '-'.padEnd(lineLength - commentCharsLength, '-') + `\n`;",
"const totalSpacers = lineLength - commentCharsLength - selectionLength - (2 * gapLength);",
"const beforeSelectionLength = totalSpacers/2 - commentCharsLength/2;",
"const afterSelectionLength = totalSpacers/2 + commentCharsLength/2;",
// ${LINE_COMMENT} in backticks to treat as a string
"str += `${LINE_COMMENT} ${LINE_COMMENT}` + '='.padEnd(beforeSelectionLength, '=') + ` `;",
"if (selectionLength %2 === 0) str += `${selectedText} ` + '='.padEnd(afterSelectionLength, '=');",
"if (selectionLength %2 === 1) str += `${selectedText} ` + '='.padEnd(afterSelectionLength+1, '=');",
"return str;",
"}$$"
],
"restrictFind": "line",
// "postCommands": "cancelSelection"
},
// "when": "editorLangId == javascript"
}
As you can see, you can write javascript in a keybinding (or setting).
You can use the extension HyperSnips
Define the following snippet in the all.hsnips file
snippet comment "Comment Section"
// //------------------------------------------------------------------------------
// //``s = '='.repeat((78-(t[0].length + 2))/2); rv = s;`` $1 ``rv = '='.repeat(78-(t[0].length + 2 + s.length));``
endsnippet
If you type comment and select the snippet with Tab you can type the text and the === strings adjust to keep the text centered.
You can also cut some text - start the snippet - and paste the text.

VSCode/TextMate syntax highlighting grammar -- matching code until end of line

I am writing a TextMate grammar to implement syntax highlighting in VSCode for a custom flavor of Markdown. I would like everything on the same line after ##$ to be highlighted as Javascript.
This is what I came up with:
"majsdown_execute_statement": {
"begin": "(.*?)(##\\$)",
"name": "test",
"end": "(\\r\\n|\\r|\\n)",
"beginCaptures": {
"2": {
"name": "keyword.control.majsdown"
}
},
"patterns": [
{
"include": "source.js"
}
]
},
That almost works:
But I would like the ##$ part to always be highlighted as a keyword. Here's a mockup (edited image) of my desired result:
I've tried a lot of different combinations of "begin" and "end", and I've also tried many nested patterns like the following one:
"patterns": [
{
"begin": "\\s",
"while": "^(\\r\\n|\\r|\\n)",
"patterns": [
{
"include": "source.js"
}
]
}
]
Unfortunately, nothing provides the result I desire. How can I achieve my desired result?
To handle multiline constructs, I think you'll have to provide modified embedded language(JavaScript) definition as well. Easiest way to do it would be to make ##$ a comment in JavaScript, so it'll not mess up existing constructs.
I have no idea about VScode syntax highlighting. I'll try to demonstrate the idea using HighlightJs. It has very similar way of defining a language.
Demo: View in full page mode.
hljs.debugMode();
// default code for the demo
src.innerText = `
My custom markdown highlighted with custom rules.
Here is how javascript code looks:
##$ function test()
##$ {
##$ // TODO: stuff
##$ let rand = Math
##$ .random()
##$ .toFixed(2);
##$ }
##$ var string = "hello";
##$ const string2 = \`some long
##$ string\`;
Leave one empty line to get out of the code block.
Here is some more code:
##$ var rand = Math.random();
##$ console.log(rand);
We are out of the second code block now.
`;
// define our markup language, say 'mdown'
let langDef = {
name: 'Mdown',
aliases: ['mdown'],
case_insensitive: true,
contains: [
{
className: 'mscript',
begin: /##/,
end: /\$/,
keywords: { name: 'mscript' },
contains: [],
starts: {
end: /^\s*$/, // end on empty line
returnEnd: true,
subLanguage: ['js'], //embedded language
},
},
],
};
hljs.registerLanguage('mscript', () => langDef);
// patch javascript multiline structures
let js = hljs.getLanguage('javascript');
for (let c of js.contains) {
if (c.begin === "`") { // handle templet literals
c.contains.unshift({
begin: /^##/,
"relevance": 0,
end: /\$/,
contains: [],
scope: 'mscripttag'
})
}
}
// console.log(js);
// make '##$' a comment :)
// So it'll not mess existing styling
js.contains.push(hljs.COMMENT(/##/, /\$/, { scope: 'mscripttag', relevance: 10 }));
// for demo update highlighted code on user input
let handleChange = (event) => {
let html = hljs.highlight(src.innerText, { language: 'mscript', ignoreIllegals: true }).value;
code.innerHTML = html;
};
// javascript patching done
document.addEventListener('DOMContentLoaded', handleChange);
src.addEventListener('input', handleChange);
body { font-size: .8rem; }
.input {
width: 46%;
background-color: #eee;
display: inline-block;
overflow: auto;
}
.output {
width: 50%;
display: block;
float: right;
background-color: #ccc;
}
/* add extra theme for our tag ##$ */
.hljs { color: #bbb !important; }
.hljs-mscript,
.hljs-mscripttag { color: red; }
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.4.0/styles/base16/snazzy.min.css" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.4.0/highlight.min.js"></script>
<div>Edit below markdown code.</div>
<pre class="input"><div id="src" contenteditable></div></pre>
<pre class="output"><code id="code" class="javascript hljs">abcd</code></pre>
In case the library not available, here is how the output looks like:
In above code I have defined ##$ <jscontent> \n as a tag in our markdown language definition. And the content will be processed according to the embedded language JavaScript. Next I've modified the default JS language definition and added ##$ as a comment so it'll be harmless to exiting syntax. Now we just need to handle template literals which are multiline. In the literal definition I've added ##$ as a part of the literal, but with different scope/name/styleOption msscripttag.
I hope you'll be able to define similar syntax in TextMate for VSCode.
try using match instead...
"patterns": [
{
"name": "keyword.control.factory",
"match": "(\\w|-)[^(]*"
}
]
this code matches everything up to a "(" character
so your code look something like this:
"majsdown_execute_statement": {
"patterns": [
{
"name": "keyword.control.majsdown",
"match": "(?<=##\$)\\w*"
}
]
}
you can also try [^##$]*(\\w)
try it out here

cannot make VSCode Snippet $TM_CURRENT_LINE work

I created this custom snippet to get line number with alert
"alert-line": {
"scope": "javascript,typescript",
"prefix": "al",
"body": [
"alert(`Line $TM_CURRENT_LINE`);",
],
"description": "alert line"
},
as output I get something weird
alert(`Line al`);
You want TM_LINE_NUMBER or TM_LINE_INDEX, see https://code.visualstudio.com/docs/editor/userdefinedsnippets#_variables.
Your output is correct for $TM_CURRENT_LINE which is the text on the current line. And since your prefix was al and you typed that on an line with a few tabs only - that was the current line's text.

Why will my vs-code snippet not work when the format has been met?

i am trying to get the snippet to do this
recipes.addShaped("name", output,
[
[input,input,input],
[input,input,input],
[input,input,input]
]);
the code i am trying to use is this
"Add a shaped": {
"prefix": ["rec", "add"],
"body": ["
recipes.addShaped("${1:name}", ${2:output},
[
[${3:input},${4:input},${5:input}],
[${6:input},${7:input},${8:input}],
[${9:input},${10:input},${11:input}]
]);
"],
"description": "Add a shaped recipe."
}
any help would be appreciated.
dan
Try this:
"Add a shaped": {
"prefix": ["rec", "add"],
"body": [
"recipes.addShaped(\"${1:name}\", ${2:output},",
"[",
"[${3:input},${4:input},${5:input}],",
"[${6:input},${7:input},${8:input}],",
"[${9:input},${10:input},${11:input}]",
"]);"
],
"description": "Add a shaped recipe."
},
All lines of the body have to be separately quoted and the qoutes within a line have to be escaped.
And the result will appear flush left with your current indentation without having to put the body far left like you had it. Just indent the snippet normally to set the left point. Any indentation from there will indent the result.

How to add space in vscode emmet key suggestions?

There is inbuilt emmet suggestion of #media like in the image below and I wanted to add my custom snippets for max-width and min-width. Which I successfully did with below codes.
{
"css": {
"snippets": {
"#mediaMaxWidth": "#media(max-width: ${1:768}px) {\n\t${2}\n}",
"#mediaMinWidth": "#media(min-width: ${1:768}px) {\n\t${2}\n}"
}
}
}
Problem: : Like in inbuilt emmet there is space between #media screen , I want to create same for my custom one to looks like it so it become #media max-width and #media min-width which I can't seems to achieve.
What I tried and what I expected it to work:
{
"css": {
"snippets": {
"#media max-width": "#media(max-width: ${1:768}px) {\n\t${2}\n}",
"#media min-width": "#media(min-width: ${1:768}px) {\n\t${2}\n}"
}
}
}
There’s no way to add space in abbreviation shortcut. What you see in screenshot is a preview of expanded result, not actual snippet
As #Mark had mentioned in the comment, we can put snippets in snippets/css.json (less.json) if you use less. BUT snippet structure looks different.
To add snippets open File > Preferences > User Snippets then choose the language you want to add snippets to, in this case i choose css.
Add codes based on the documentation in the file it self. Based on my requirement codes look like this.
"media min width 768px": {
"prefix": "#media min-width",
"body": [
"#media(min-width: ${1:768}px) {\n\t${2}\n}",
"$3"
],
"description": "Media min width"
},
"media max width 768px": {
"prefix": "#media max-width",
"body": [
"#media(max-width: ${1:768}px) {\n\t${2}\n}",
"$3"
],
"description": "Media max width"
}
Result: