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

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:

Related

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.

Hyperlinks for Markdown in VSCode

I want to change hyperlinks to Markdown Hyperlinks all at once.
For example I have (and more of them)
https://stackoverflow.com/questions/ask
https://stackoverflow.com/questions/59030873/keyboard-shortcut-in-vscode-for-markdown-links
https://stackoverflow.com/questions/ask
https://stackoverflow.com/questions/59030873/keyboard-shortcut-in-vscode-for-markdown-links
and want to have:
[ask](https://stackoverflow.com/questions/ask)
[keyboard-shortcut-in-vscode-for-markdown-links](https://stackoverflow.com/questions/59030873/keyboard-shortcut-in-vscode-for-markdown-links)
[ask](https://stackoverflow.com/questions/ask)
[keyboard-shortcut-in-vscode-for-markdown-links](https://stackoverflow.com/questions/59030873/keyboard-shortcut-in-vscode-for-markdown-links)
I already found (for keybindings.json)
{
"key": "ctrl+q b", // Lines 2 Array Only
"command": "editor.action.insertSnippet",
"args": {
"snippet": "${TM_SELECTED_TEXT/(.+)(\\r?(?=\\S))?/[]($1)/g}",
},
"when": "editorTextFocus && editorLangId == 'markdown'"
}
which does a lot, but maybe anybody can add or give me a possibility to find out myself:
The link description from the last part of the link or to go through all link descriptions with tab so you can add the description easily
only change links (if there is any text between the links)
tia
I don't think using a snippet will work (or I can't figure it out) because of your requirement to only change links if there is any text following the link. That makes TM_SELECTED_TEXT not work. But it can be done with a find and replace pretty easily.
I wrote an extension Find and Transform that you can use to save the find/replace for future use. Example keybinding:
{
"key": "alt+q", // whatever keybinding you want
"command": "findInCurrentFile",
"args": {
// "find": "(^https:.+\\/)(.*$)(\r?\n)(?=(?!https:))", // if single line of text between links
"find": "(.+\\/)(.*$)(\r?\n)(?=\\s*(?!https:)[\\s\\S]*^https:)", // if multiple lines of text
"replace": "[$2]($1$2)$3",
"restrictFind": "selections" // if you want to only find within selections
},
"when": "editorTextFocus && editorLangId == 'markdown'"
}
I believe that satisfies your requirement that some text (I made it for any amount of lines of intervening text) be between links. And thus the last link - which may have text after it - but no following link - should not be transformed.
[If there is only ever one line of text between links, the regex could be simplified quite a bit.]

VS Code search and replace and change line order Vuejs

I have this tag occurring in multiple files - same path but with different image files:
<img
id="logo"
style="margin-left:170px;margin-top:8px;width:85px"
class="shrunk"
src="~/static/img/poweredby-grey.png"
alt=" logo"
>
I want to replace the src line everywhere BUT I also need to move the new :src line up in order because the Vue js linter will say the :src needs to be before class and style.
<img
id="logo"
:src="require('~/static/' + imgURL + '/poweredby-grey.png')"
style="margin-left:170px;margin-top:8px;width:85px"
class="shrunk"
alt=" logo"
>
I used regex replace and was able to replace the src line to the correct :src line. Given I have about 100 files to do this how can i do this quickly in VS Code?
My current search and replace regex is:
src="~/static/img/(.+?)"
:src="require('~/static/' + imgURL + '/$1')"
How can I adapt the two regex to search and replace across the whole <img> tag - this way in my replace regex I correct the line order at the same time.
Thanks a lot.
I guess that Multiline search can help you here. You can create group for different properties and then rearrange it. Also Search Editor feature of VS Code in combination with this experimental plugin might help.
However I'd not recommend to use regexp for such transformation, if there is alternative.
The best possible way is to use autofix option of the rule (if it has it). I suspect that it is this rule that gives you an error: attributes-order. In this case you can simply run eslint with --fix flag, and it'll reorder props automatically.
One way to do it that keep your regex's a little simpler is to run two find and replaces in series. Using an extension like Replace Rules you can do this.
In your settings.json:
"replacerules.rules": {
"editImgSrc": {
"find": "src=\"~/static/img/(.*?)\"",
"replace": ":src=\"require('~/static/' + imgURL + '/$1')\""
},
"reorder vueImgSrc": {
// get the src line and the two preceding lines
"find": "((.*\r?\n){2})( *:src=\"require.*\r?\n)",
"replace": "$3$1" // reorder them
},
},
"replacerules.rulesets": { // bundle the 2 find/replaces into one ruleset
"Replace with vueImgSrc and reorder": {
"rules": [
"editImgSrc",
"reorder vueImgSrc"
]
}
},
and then a keybinding to run that (in keybindings.json):
{
"key": "alt+w", // whatever keybinding you want
"command": "replacerules.runRuleset",
"when": "editorTextFocus && !editorReadonly",
"args": {
"rulesetName": "Replace with vueImgSrc and reorder"
}
},

Visual Studio Code: How to automate a simple regex-find and replace?

I try to create a simple regex-find and replace task in Visual Studio Code.
Currently I copy from the AD some Users to a temporary file in Visual Studio code and remove the "CN=" at the beginning of the line and all the aditional informations after the first "," (regex: ,.*$). This works fine with Find&Replace in VSCode but I have manually to type it in every time I want to remove this.
So the question is, is it possible to automate this kind of task? I know there are some external tools (https://code.visualstudio.com/docs/editor/tasks) but I'm struggling to get it working...
Edit: Example requested (my regex is working, that's not the problem:/. I need an example how to automate this task... )
EXAMPLE
CN=Test User,OU=Benutzer,OU=TEST1,OU=Vert,OU=ES1,OU=HEADQUARTERS,DC=esg,DC=corp
Expected Output
Test User
This extension does the job:
https://marketplace.visualstudio.com/items?itemName=joekon.ssmacro#overview
It seems like the regex adheres to:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions
Example
Create a file regex.json:
[{
"command": "ssmacro.replace",
"args": {
"info": "strip out EOL whitespace",
"find": "\\s+$",
"replace": "",
"all": true,
"reg": true,
"flag": "gm"
}
}]
"info" is just a reminder, doesn't do anything.
Set a shortcut in keybindings.json:
"key": "ctrl+9",
"command": "ssmacro.macro", "args": {"path": "C:\\...\\regex.json"}
You can batch multiple commands together [{...},{...}] which is useful for applying a whole set of regex operations in one go.
As of today, it seems it's still not possible without an extension. Here are 2 other extensions than the one proposed in the accepted answer (both are also open-source):
● Batch Replacer (but it doesn't work on the documents open in the editor : "you must have a folder open for editing and all files in it will be updated."*)
● Replace Rules: you simply add some rules in your settings.json (open the palette with F1 or ctrl+shift+p and select Preferences: open settings (JSON)).
"replacerules.rules": {
"Remove trailing and leading whitespace": {
"find": "^\\s*(.*)\\s*$",
"replace": "$1"
},
"Remove blank lines": {
"find": "^\\n",
"replace": "",
"languages": [
"typescript"
]
}
}
Extensions folder is : %USERPROFILE%\.vscode\extensions
And here is an extension I wrote that allows you to save find/replaces in a file or searches across files as a named command and/or as a keybinding: Find and Transform. Using the OP's original question, make this setting (in settings.json):
"findInCurrentFile": { // in settings.json
"reduceUserEntry": {
"title": "Reduce User to ...", // will appear in the Command Palette
"find": "CN=([^,]+).*",
"replace": "$1",
"isRegex": true,
// "restrictFind": "selections", // default is entire document
}
},
You could also make that for searches across files with this setting:
"runInSearchPanel": {
"reduceUserEntry": {
"title": "Reduce User to ...", // will appear in the Command Palette
"find": "CN=([^,]+).*",
"replace": "$1",
"isRegex": true
// "filesToInclude": "${fileDirname}"
// "onlyOpenEditors": true
// and more options
}
}
As a standalone keybinding:
{
"key": "alt+r", // whatever keybinding you want
"command": "findInCurrentFile", // or runInSearchPanel
"args": {
"find": "CN=([^,]+).*",
"replace": "$1",
"isRegex": true
The extension can also run multiple finds/replaces - just put them into an array:
"find": ["<some find term 1>", "<some find term 2>", etc.
and the same with replacements, make an array of them.

How to set SublimeText to auto match brackets but neither quotes or parenthesis?

I find the auto match behavior in sublime text 3 is not quite up to snuff when you're typing code and more importantly when you're going back to edit in real time it can add all kinds of parens or quotes you don't really need.
But it's pretty much always perfect at auto matching squirly brackets {} so that's still a very useful feature especially since I type a lot of them in a local markup language.
I know I can turn auto match off but I don't want to turn off the behavior entirely, just modify it to not auto match "" or ().
Does anyone know the command to put in the user settings for this?
Here's the steps I've done to try to resolve this:
find ~/ -name "Sublime Text"
find ~/ -name "BracketHighlighter"
Both return nothing. So I can't find this 'BracketHighlighter.sublime-settings'
Instead of looking for it on the hard drive, I accessed it via the built in menus in Sublime Text via:
Preferences ->
Package Settings ->
Bracket Highlighter ->
Bracket Settings - User
This last menu option opens a file called "~/.config/sublime-text-3/Packages/User/bh_core.sublime-settings. In there I've pasted the code from AGS' answer and toggled:
"auto_match_enabled" : true,
"auto_match_enabled" : false,
I have tried both auto match settings while the code has been saved to the bh_core.sublime-settings file. Neither option produces the result as expected. With auto match on, braces, brackets, and quotes are matched. With auto match off, nothing is matched. But I have confirmed the module is on and active as brackets are getting highlighted when selected.
I know I can turn auto match off but I don't want to turn off the behavior entirely, just modify it to not auto match "" or ()
You could install and customize the settings of the BracketHighlighter package.
Disable the system auto-matching:
~/Library/Application Support/Sublime Text 2/Packages/User/Preferences.sublime-settings
"auto_match_enabled": true,
Then edit:
OS X file location:
~/Library/Application Support/Sublime Text 2/Packages/User/BracketHighlighter.sublime-settings
{
"name": "round",
"open": "(\\()",
"close": "(\\))",
"style": "round",
"scope_exclude_exceptions": ["string.other.math.block.environment.latex"],
"scope_exclude": ["string", "comment"],
"language_filter": "blacklist",
"language_list": ["Plain text"],
"find_in_sub_search": "true",
"ignore_string_escape": true,
"enabled": true
},
{
"name": "double_quote",
"open": "(\")",
"close": "(\")",
"style": "double_quote",
"scopes": ["string"],
"language_filter": "blacklist",
"language_list": ["Plain text"],
"sub_bracket_search": "true",
"enabled": true
},