VSCode Snippets: Remove Char After Capitalizing? [duplicate] - regex

https://code.visualstudio.com/docs/editor/userdefinedsnippets#_placeholdertransform
My aim is to automatically set the class name within the context of the snippet being inserted. VSCode does not natively support class or method names, but it does support the file name.
My file names closely mimic the class name:
foo-bar.ts for class FooBar.
Here is my current code snippet wherein I can transform "foo-bar" to "Foo-bar" using the native "capitalize" grammar provided by VSCode.
TM_FILENAME_BASE is a native variable which extracts the filename without the extension:
"My Snippet": {
"scope": "typescript",
"prefix": "snippet",
"body": [
"${1}() {",
"\treturn this.get(${TM_FILENAME_BASE/(.*)/${1:/capitalize}/}.FIELD.${3});",
"}",
"",
"$0"
],
"description": "Creates a function wrapper for a model's attribute."
}
I'd like to transform "foo-bar" to "FooBar".

Try this:
"My Snippet": {
"scope": "typescript",
"prefix": "snippet",
"body": [
"${1}() {",
// "\treturn this.get(${TM_FILENAME_BASE/([a-z]*)-*([a-z]*)/${1:/capitalize}${2:/capitalize}/g}.FIELD.${3});",
"\treturn this.get(${TM_FILENAME_BASE/(.*)/${1:/pascalcase}/g}.FIELD.${3});",
"}",
"",
"$0"
],
"description": "Creates a function wrapper for a model's attribute."
}
EDIT : In October, 2018 the \pascalcase transform was added to vscode - see
commit, but not yet added to the documentation (as of the date of this edit). I have added the much simpler transform above which accomplishes the PascalCase transform.
Demo added, uses the clipboard after the first filename case (test-bed-snippets.xxx) just to make the various possibilities easy to demonstrate.
See also snippet transform to CamelCase

Thought it might be useful to supplement Mark's excellent answer with another example.
In my case, I wanted to take a name - as selected text - and convert it to Swift code that would instantiate a new class passing in variables name and email address.
So for example I select John Smith as first name, last name and convert to:
let johnSmith = User(name: "John Smith", email: "john.smith#foorbar.com")
Code snippet for this would be as follows:
"User": {
"prefix": "u",
"body": [
"\tlet ${TM_SELECTED_TEXT/([a-zA-Z]*) *([a-zA-Z]*)/${1:/downcase}$2/} = User(name: \"${TM_SELECTED_TEXT}\", email: \"${TM_SELECTED_TEXT/([a-zA-Z]*) *([a-zA-Z]*)/${1:/downcase}.${2:/downcase}/}#foobar.com\")\n",
],
"description": "Create User with name and email"
}

Related

How to get comments and string in regex?

i have create a programming language KAGSA, and i have to create a syntax highlighter i start with VSCode highlighter i write every thing well but i have problem with regex of strings (more than one line) and comments (more than one line) this is the code :
Match is the code:
Comments :
"comments": {
"patterns": [{
"name": "comment.line.shebang.kagsa",
"match": "//..*|/\\*(.*?|\n)*\\*/|//|/\\**\\*"
}]
},
The problem is wit the /*Comment*/ comment.
and string code :
"strings": {
"name": "string.quoted.double.kagsa",
"patterns": [{
"name": "string.quoted.double.kagsa",
"match": "'(.*?)'|\"(.*?)\"|``(.*?|\n)*``"
}]
},
my problem is with ``String``
and the Color i get :
[the output color][https://i.stack.imgur.com/NPbS0.png]
You have this issue because match doesn't work for multiline string literals.
I found a similar problem.
As said by Gama11 in his answer:
Try to use a begin / end pattern instead of a simple match.

I want to apply the regular expression used in gitleaks in secretlint

I am now trying to migrate from gitleaks to a tool called secretlint.
Originally, there was a warning in the generic-api-key rule when executing gitleaks, but after moving to secretlint, the warning no longer occurs.
Specifically, I wrote the regular expression of gitleaks.toml provided by gitleaks in the secretlint configuration file .secretlintrc.json according to the format of #secretlint-rule-pattern provided by secretlint.
[[rules]]
id = "generic-api-key"
description = "Generic API Key"
regex = '''(?i)((key|api[^Version]|token|secret|password|auth)[a-z0-9_ .\-,]{0,25})(=|>|:=|\|\|:|<=|=>|:).{0,5}['\"]([0-9a-zA-Z\-_=]{8,64})['\"]'''
entropy = 3.7
secretGroup = 4
keywords = [
"key",
"api",
"token",
"secret",
"password",
"auth",
]
to
{
"rules": [
{
"id": "#secretlint/secretlint-rule-pattern",
"options": {
"patterns": [
{
"name": "Generic API key",
"pattern": "/(?i)((key|api[^Version]|token|secret|password|auth)[a-z0-9_ .\\-,]{0,25})(=|>|:=|\\|\\|:|<=|=>|:).{0,5}['\"]([0-9a-zA-Z\\-_=]{8,64})['\"]/"
}
]
}
}
]
}
I'm thinking that perhaps I'm not migrating the regex correctly, but if anyone can tell me where I'm going wrong, I'd like to know.
The main issue is the the inline (?i) modifier is not supported by the JavaScript regex engine. You must use the normal i flag after the second regex delimiter (/.../i).
Also, the api[^Version] is a typical user error. If you meant to say api not followed with Version, you need api(?!Version).
So you can use
"pattern": "/((key|api(?!Version)|token|secret|password|auth)[\\w .,-]{0,25})([=>:]|:=|\\|\\|:|<=|=>).{0,5}['\"]([\\w=-]{8,64})['\"]/i"
Note that I "shrunk" [A-Za-z0-9_] into a single \w, they are equivalent here. Note the - char does not need escaping when used at the end (or start) of a character class.

Regex Statement in VSCode snippet for removing file extension

I'd like to create a VS-Code snippet for importing css into a react component. If I'm using the snippet in "MyComponent.tsx", then I'd like the snippet to import the associated css file for the component:
import "./MyComponent.css";
The component and it's css will always be located in the same directory.
I thought that the following snippet would be able to do this:
//typescriptreact.json
"import componet css": {
"prefix": "icss2",
"body": [
"import \"./${1:$TM_FILENAME/^(.+)(\.[^ .]+)?$/}.css\";"
],
"description": ""
},
But this results in:
import "./MyComponent.tsx/^(.+)([^ .]+)?$/.css";
What's the correct way to do this?
You can use
"import componet css": {
"prefix": "icss2",
"body": [
"import \"./${TM_FILENAME_BASE/^(.*)\\..*/$1/}.css\";"
],
"description": ""
}
The ${TM_FILENAME_BASE} variable holds the file name without the path, and the ^(.*)\\..* regex matches and captures all up to the last . while just matching the extension, and only the captured part remains due to the $1 replacement pattern (that refers to Group 1 value).
"import component css": {
"prefix": "icss2",
"body": [
"import \"./${TM_FILENAME_BASE}.css\";"
],
"description": ""
}
TM_FILENAME_BASE The filename of the current document without its
extensions
from snippet variables documentation.
So there is no need to remove the .tsx extension via a transform - it is already done for you.
The more interesting question is what if you have a file like
myComponent.next.tsx // what should the final result be?
${TM_FILENAME_BASE} will only take off the final .tsx resulting in import "./myComponent.next.css";
#Wiktor's results in import "./myComponent.css";
Which is correct in your case? Is something like myComponent.next.tsx a possible case for you? If not just use ${TM_FILENAME_BASE} with no need for a transform.

How to convert snippet placeholder from CamelCase to snake_case

I would like to create a VS Code snippet where I input a part in CamelCase, and the same string is output in snake_case at some other place in the snippet.
Based on this SO post Here's my attempted snippet, but I have a trailing _ that needs to be removed by hand, not ideal:
"test": {
"prefix": "test",
"body": "${1} -> ${1/([A-Z])+([a-z]+)/${1:/downcase}${2}_/g}"
},
"camelToSnakeCase": {
"prefix": "test",
"body": [
"${1} -> ${1/([A-Z][a-z]+$)|([A-Z][a-z]+)/${1:/downcase}${2:/downcase}${2:+_}/g}"
],
"description": "transform from CamelCase to snake_case"
}
In order to differentiate between some last capture group like Abcd and the preceding capture groups, I used an alternation:
([A-Z][a-z]+$)|([A-Z][a-z]+) must be in this order
so group 1 will be at the end of the input because of the $ indicator and group 2 will not be at the end. And group 2s will always have at least one more group after them. Then, using the conditional ${2:+_} only insert an underscore if there is a group 2 - because there must be a following group 1.
This keybinding version also works if you have a different workflow:
{
"key": "alt+3", // whatever keybinding you wish
"command": "extension.multiCommand.execute",
"args": {
"sequence": [
"cursorWordLeftSelect",
"editor.action.transformToSnakecase",
"editor.action.transformToLowercase",
// "cursorLineEnd" // if you want this
]
},
"when": "editorTextFocus && !editorHasSelection"
}
Type your word and trigger the keybinding. Uses the macro extension multi-command.

How do I convert this Sublime snippet into a VS Code snippet?

See below my attempt and result. The Sublime snippet first:
<snippet>
<content>
<![CDATA[<${1:p}>${2:$SELECTION}</${1/([^ ]+).*/$1/}>]]>
</content>
<tabTrigger><</tabTrigger>
<scope>text.xml</scope>
<description>Long Tag</description>
</snippet>
and the keybinding:
{ "keys": ["super+shift+o"], "command": "insert_snippet", "args": { "name": "Packages/XML/long-tag.sublime-snippet" } },
What this does is the following:
Pressing Cmd + Shift + O will create an html tag <p></p> in with the p linked so you can start typing and it updates both sides. Pressing tab will place your cursor in the center of the tags.
Highlighting a section, then pressing cmd + shift + O will surround that section with the tags.
What I've managed to get trying on my own is the following in VS Code:
{
"blank_tag": {
"prefix": "<cmdso>",
"body": [
// "<$1>$2</$1>$3"
"<${1:p}>${2:$SELECTION}</$1/([^ ]+).*}>"
],
"description": "Adds a blank tag to use"
}
}
This almost gets what I want but not quite. I'm not very good with regex but the result of this prints <p></p/([^ ]+).*}> I can remove that last bit of regex and it will get #1 satisfied. The #2 above is extremely helpful and I'd like to figure out what I'm doing wrong. I'm betting that last bit of regex is what allows you to highlight a section and surround it with the tags.
Can you help me fix this to work and satisfy #1 and #2?
Ok these are two different snippets, the first you already did so i'm going to speak about the second:
You want to surround a text in a tag based on a shortcut, you need two thing first to create the snippet, then to add the shortcut
This snippet when inserted will surround your text with a p tag, that changes immediately while you are writing.
"surround_tag": {
"prefix": "<stag>",
"body": [
"<${1:p}>${TM_SELECTED_TEXT}</$1>"
],
"description": "surround text by tag"
}
Notice that we are using a specific variable called TM_SELECTED_TEXT, you can find more about these variables here, https://code.visualstudio.com/docs/editor/userdefinedsnippets
Then add a keyboard shortcut to insert that snippet
{
"key": "cmd+w cmd+t",
"command": "editor.action.insertSnippet",
"when": "editorTextFocus",
"args": {
"name": "surround_tag",
}
}
// in args here you can add a key langId to specify specific languages like
"args": {
"langId": "javascript",
"name": "surround_tag",
}
You can find language identifiers here https://code.visualstudio.com/docs/languages/identifiers
Of course, you can also insert the snippet without the keyboard shortcut by using the insertSnippet command (CMD + Shift + P and then insertSnippet, then pick your one)
You can also use the following site to generate snippets for both vscode and sublime https://snippet-generator.app/
You may fix your code using
"blank_tag": {
"prefix": "<cmdso>",
"body": [
"<${1:p}>${2:$SELECTION}</${1/(\\S+).*/$1/}>"
],
"description": "Adds a blank tag to use"
}
The [^ ] can be written as \\S+ in the code, \S+ matches 1 or more non-whitespace chars. The syntax is ${ID/pattern/replacement/flags}, so you had an incomplete code.
If you're using Sublime Text, you can use the Atomizr package to convert snippets within the editor.
Example:
Install the package using Package Control
Open a Sublime Text snippet
Run the Atomizr: Sublime Text to Visual Studio Code command (or CtrlS, CtrlV on macOS)
To convert many files, it's probably more convenient to install the CLI equivalent (requires NodeJS)
Example:
# Single conversion
atomizr example.sublime-snippet --target vscode
# Batch conversion
atomizr *.sublime-snippet --target vscode
If you want to use the same keybinding for two different actions as it seems you do, then you will have to find a way to differentiate between the then existing conditions so that the appropriate version is triggered properly.
In your case, that involves utilizing that in one situation you will start with selected text. So we can use the when clause editorHasSelection to distinguish between the twp desired actions.
In your keybindings.json:
{
"key": "cmd+shift+O",
"command": "editor.action.insertSnippet",
"args": {
"snippet": "<${1:p}>$0</$1>"
},
"when": "editorTextFocus && !editorHasSelection"
},
{
"key": "cmd+shift+O",
"command": "editor.action.insertSnippet",
"args": {
"snippet": "<${1:p}>${TM_SELECTED_TEXT}</$1>"
},
"when": "editorTextFocus && editorHasSelection"
}
We see that only the second command will be triggered if there is a selection in the editor!!
!editorHasSelection means if there is no selection, trigger this one. Otherwise, we will trigger the other command.
Note that there is already a command also bound to Cmd+Shift+O: workbench.action.gotoSymbol You should disable that command if you want to stick with Cmd+Shift+O as your triggers. This will disable it:
{
"key": "cmd+shift+O",
"command": "-workbench.action.gotoSymbol"
},
Here is a demo of it working: