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.
Related
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.
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.]
What I want to know
How to set a keyboard shortcut to replace "" with ''.
Or is there a default shortcut to replace "" with ''?
Purpose
I use Visual Studio Code on a Mac. I often replace "" with ''.
For example,
const foo = "foo";
const bar = "bar";
⬇️
const foo = 'foo';
const bar = 'bar';
I usually use Visual Studio Code's replace function with a regular expression like this.
I want to register a keyboard shortcut for this operation because I do it frequently.
What I tried / Issue
I opened keybindings.json and tried to set a keyboard shortcut in it. But I have no idea what to write.
[
{
"key": "shift+cmd+'",
"command": "actions.find" // ?????????
}
]
What should I write in there? Or is there a default shortcut to replace "" with ''?
Edit:
According to Jeff Brower's answer (thank you!), "args" can be helpful for my purpose. I'm trying to change his/her code.
I wrote in keybindings.json like this but it doesn't work:
{
"key": "shift+cmd+'",
"command": "editor.action.startFindReplaceAction",
"args": {
"query": "\"(.+)\"",
"replace": "'$1'",
"triggerSearch": true,
"isRegex": true,
"matchWholeWord": true,
"isCaseSensitive": false
}
}
According to the answers of this question, there is no built-in way to do this. However, I did get a similar keybinding to work. This searches all files in the workbench:
{
"key": "ctrl+shift+'",
"command": "workbench.action.findInFiles",
"args": {
"query": "\"((?:\\\\[\"'\\\\bfnrt]|[^\\\\\"'\\n\\r])*)\"",
"replace": "'$1'",
"triggerSearch": true,
"isRegex": true,
"matchWholeWord": true,
"isCaseSensitive": true
}
}
The main caveat is that it doesn't automatically perform the replacement, but it does fill in the fields of the find and replace.
I also improved the regular expression a bit to handle javascript-style escaping, and allow empty strings (unit tests). To use your original regular expression, replace the whole string with:
"\"(.+)\""
It can be done with an extension, I'll show the code for that. An extension allows you to set a keybinding if that is what you want.
But it is easy to accomplish what you want with these steps.
Select any ".
Cmd+Shift+L to select all occurrences of ".
Type '.
The working part of the extension code:
let disposable = vscode.commands.registerCommand('yourExtensionName.someCommandName', async function () {
const fileName = vscode.workspace.asRelativePath(vscode.window.activeTextEditor.document.uri);
vscode.commands.executeCommand('workbench.action.findInFiles',
{
query: "\"(.+)\"",
replace: "'$1'",
triggerSearch: true,
isRegex: true,
filesToInclude: fileName
// preserveCase: true,
// useExcludeSettingsAndIgnoreFiles: true,
// isCaseSensitive: true,
// matchWholeWord: true,
// filesToExclude: "./*.css"
}).then(() => {
setTimeout(() => {
vscode.commands.executeCommand('search.action.replaceAll');
}, 1000);
});
});
context.subscriptions.push(disposable);
Demo:
The extension works with the findInFiles command, since actions.find will not take arguments. But it is restricted to the current file. It finds the current fileName:
const fileName = vscode.workspace.asRelativePath(vscode.window.activeTextEditor.document.uri);
and uses that in the filesToInclude argument.
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:
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
},