How to create VSCode bindings to input bra and ket efficiently - visual-studio-code

I'm currently using VSCode for Q# programming. This sometimes entails including simple qubit expressions in the comments for clarity. It is of course possible to just settle with using regular angle brackets (such as |00> or <00|), but it looks nicer using the appropriate Unicode characters (such as |00⟩ or ⟨00|). Copying and pasting these characters whenever needed is a bit cumbersome, so it would be nice to have key bindings in VSCode just for this purpose. Actually, I'd like to be able to configure VSCode for quick access to any selection of characters I might be interested at the moment.

VSCode customization supports a type command which does exactly that - types in its argument. In order to create an entry for a keybinding, open the command prompt (Ctrl+Shift+P or ⌘+Shift+P on Mac) and type Preferences: Open Keyboard Shortcuts (JSON) and insert entries of the form:
{
"key": "<key-binding>",
"command": "type",
"args": {
"text": "<character>"
}
}
where <key-binding> is the usual description of the keybinding and <character> is the desired character literal. So, for the bra-ket case above, my customization looks like this:
[
{
"key": "ctrl+shift+.",
"command": "type",
"args": {
"text": "⟩"
}
},
{
"key": "ctrl+shift+,",
"command": "type",
"args": {
"text": "⟨"
}
}
]

Related

Possible to move cursor to next instance of specific word?

I need to run VSCode through some XML that's at least 90% auto-generated. There are a few things the automatic generation can't determine on its own and needs manual intervention on-- hand-editing where a specific piece of text will be generated on each entry.
What I'm trying to do is to find a way (through extension or through built-in commands) to set up a keybinding that will move the cursor down to the next instance of a specific phrase of my choice (that I wouldn't be manually typing; it would be assigned as part of the keybind) in the current file when I press the binding for it.
For instance, press F17 to go to the next instance of "FIXME" in the current document.
I've been through at least a dozen extensions and haven't found anything that matches my need, and the built-in actions.find doesn't support parameters. actions.findWithSelection requires the text to be selected, so that won't work either.
Any ideas? Someone surely has had the same need for this at some point. I can't see this as a rare need at the very least.
I modified the other extension I mentioned, Find and Transform, to make this really easy. With this keybinding
{
"key": "alt+r",
"command": "findInCurrentFile",
"args": {
"find": "FIXME",
// "replace": "DONE",
"restrictFind": "nextMoveCursor"
}
}
or
{
"key": "alt+r",
"command": "findInCurrentFile",
"args": {
// "find": "FIXME", // no find necessary !!
// "replace": "DONE",
"restrictFind": "nextMoveCursor"
}
},
The first example uses a fixed find and will go to the next FIXME from wherever the cursor is - and it will wrap to the beginning of the file if there are no matches in the rest of the file.
The second example will use the word under the cursor, and thus requires that you start at the word FIXME for example.
First demo (with a find value):
Second demo (with no find, note using during words under cursor to search):
The extension can do a lot more. There are many examples at its link above.
{
"key": "alt+r",
"command": "findInCurrentFile",
"args": {
"find": "FIXME",
// "replace": "DONE",
"restrictFind": "nextSelect"
}
}
The nextSelect option will go to and select the matches in turn so you could modify some of the selections and then move to the next.
I think this extension (that I wrote) is what you are looking for: Jump and select.
Example keybinding (without optional selection of the phrase):
{
"key": "alt+r", // whatever keybinding you wish
"command": "jump-and-select.jumpForward",
"args": {
"text": "FIXME",
// "restrictSearch": "document",
}
},
[If you actually wanted to find all matches and optionally replace them with a pre-defined regex find/replace see Find and Transform.]
You are most probably looking for Move Last Selection To Next Find Match (editor.action.moveSelectionToNextFindMatch), by default bound to ctrl+k ctrl+d. Opposite direction (editor.action.moveSelectionToPreviousFindMatch) has no default binding.
Personally I use Ctrl+Shift+vertical arrows for this, and take my word I use them all the time. keybindings.json snippet:
{
"command": "editor.action.moveSelectionToPreviousFindMatch",
"key": "ctrl+shift+up",
"when": "editorFocus"
},
{
"command": "editor.action.moveSelectionToNextFindMatch",
"key": "ctrl+shift+down",
"when": "editorFocus"
},
Indeed, these command names are quite impossible to find in command palette, when you just want to "jump to next occurrence of word or selection under cursor". It is beyond comprehension how they got such convoluted names.
Congratulations for the first question, BTW!

Regex in VSCode: case conversion in replace, modifiers \l, \L, \U, \u not working

I'm trying to replace a structure like this:
testVars.bread.componentFlour
testVars.bread.componentWater
to something like this:
testVars.dough.flour
testVars.dough.water
this happens with multiple variable names; I want to remove the component and have the first letter converted to lowercase to match CamelCase.
What I tried doing was matching testVars.bread.component(.) replacing it with testVars.dough.\l$1.
According to regex documentation, that should convert my match to lowercase. However, VSCode wants to insert \l as text.
How do I get VSCode to convert my match to lowercase?
EDIT: To clarify, this is strictly for VSCode's implementation, not a regex question itself. Matching this group in notepad++ and replacing with testVars.dough.\l\1 does exactly what I want it to do.
NEW ANSWER: !! Those case modifiers like \l and \u are being added to the find/replace functionality in vscode (both in find within one file and search across multiple files [v1.49] - see https://github.com/microsoft/vscode/pull/105101) (see https://github.com/microsoft/vscode-docs/blob/vnext/release-notes/v1_47.md#case-changing-in-regex-replace) - will be in v1.47 (find) and v1.49 (search across files).
So that your original thought to
Find : testVars.bread.component(.)
Replace : testVars.dough.\l$1
is now working.
For more on how the case modifiers work in vscode, see https://stackoverflow.com/a/62270300/836330
OLD ANSWER:
While you cannot replace with a lowercase identifier in vscode, you still have some of options.
Use a regex like (?<=testVars\.).*\.component(.*) so that testVars. is not captured - because you do not want to change its case.
Ctrl+Shift+L to select all your matches (same aseditor.action.selectHighlights).
Ctrl+Shift+P, type lowerand trigger that command (or make a keybinding for this unbound command).
Trigger your replaceAll
To speed that up you have two options. (1) Make a macro that would run steps 2, 3 and 4. Or (2) make a snippet that will transform your selections - effectively running steps 3 and 4 at once.
Snippet in your keybindings.json (not in a snippets file):
{
"key": "alt+m", // choose some keybinding
"command": "editor.action.insertSnippet",
"args": {
"snippet": "${TM_SELECTED_TEXT/.*\\.component(.*)/dough.${1:/downcase}/}"
},
},
and then Ctrl+Shift+L to select all, and alt+m to trigger the above insertSnippet.
Macro approach:
Using some macro extension, here multi-command, put this into your settings.json:
"multiCommand.commands": [
{
"command": "multiCommand.findReplaceLowercase",
"sequence": [
"editor.action.selectHighlights", {
"command": "editor.action.insertSnippet",
"args": {
"name": "replace and lowercase",
}
},
]
}
]
and a snippet, in one of your snippets files:
"replace and lowercase": { // this "label" is used in the macro
"prefix": "for",
"body": [
"${TM_SELECTED_TEXT/.*\\.component(.*)/dough.${1:/downcase}/}"
// "${TM_SELECTED_TEXT/(.*)/${1:/downcase}/}" // to downcase all selected text
],
"description": "replace selected text"
},
and a keybinding to trigger the macro:
{
"key": "alt+m", // choose some keybinding
"command": "extension.multiCommand.execute",
"args": { "command": "multiCommand.findReplaceLowercase" },
}
In the demo I copy the find regex into the find widget (or just write it there, it doesn't matter how it gets there or where focus is) and then hit alt+m (the macro keybinding) and that is it.
Obviously, this looks like a lot of work but you could keep reusing the macro and snippet, transforming to the replace result you would like the next time. And there you can use /downcase, /upcase, /capitalize and /pascalcase all you want which you can't use in the replace field of the find/search widgets.

Perform pre-defined Find-Replace-All in VSCode using a keybinding

I can't seem to find a good list of documented commands that can be run from VSCode keybindings.
On the online VSCode documentation, the Commands Guide lists two ways to discover commands:
Browse the keyboard shortcuts
Look through VS Code's built-in
advanced commands api
The commands found for keyboard shortcuts are usually "simple" commands that do not take arguments. The "advanced commands api" seems to be missing some very basic, fundamental commands.
For example, on the VSCode Keybindings page there is a section called "Command Arguments" that has the following example entry:
{ "key": "enter", "command": "type",
"args": { "text": "Hello World" },
"when": "editorTextFocus" }
But I don't see anywhere that the type command is documented. So I assume there are probably several other basic commands like this that exist but I don't know where to find documentation for them.
Anyway, what I am really looking for at the moment is a command that I can run to do a pre-defined search and replace in the current editor, specifying the find text, replacement text, and options... something like below:
{ "key": "ctrl+shift+8",
"command": "findReplaceAll",
"args": {
"findText": "Company(\\w+)",
"replaceText": "User$1"
"options": { "ignoreCase": false, "wholeWord": true, "regex": true }
},
"when": "editorTextFocus" }
But I haven't been able to find any such findReplaceAll command or anything similar in the documentation, but certainly something like this must exist, right?
Thanks!
As #AurSaraf points out, there is new work coming that will allow creating a command (or use in an extension) of a built-in way to find in the current file with preset find/replace and options.
I have commented on the github issues trying to get the args to be consistent with other similar commands to no avail. Here are the current available args in a keybinding:
{
"key": "alt+p",
"command": "editor.actions.findWithArgs",
"args": {
"searchString": "howd\\d", // double-escaped
"replaceString": "qqqq9",
"isRegex": true,
// "regexOverride": 1,
"findInSelection": false,
"matchWholeWord": false,
// "matchCase": false,
// "matchCaseOverride": 0,
"preserveCase": false,
"isCaseSensitive": false
// "preserveCaseOverride": 0,
// "wholeWordOverride": 0
}
}
The commented-out args are not available although intellisense shows that they are - so the command is still a little "rough" - and currently available only in the Insiders Build. Do not rely on the intellisense for the args keys - many of them are mis-named or non-functional at this point.
Also, note that instead of query and replace as used in the workbench.action.findInFiles and in the search.action.openEditor (open a new search editor) keybindings, this command currently uses searchString and replaceString for some reason.
For a powerful extension to do lots of predefined find/replaces or searches/replaces with all arguments, see Find and Transform (which I wrote). In particular with a lot of options for setting the files to include scope filter - like the current file or the last files found in the previous search results to narrow a search to only those files.
There is also a built-in way to do this for finding across files, I don't know if arguments were added after your question or not. In any case, I agree that it is sometimes difficult to discover which commands can take arguments.
Sometimes, intellisense within the keybindings in your command will surface them but not always.
So examining this:
{
"key": "ctrl+shift+f",
"command": "workbench.action.findInFiles",
"args": {
<cursor here> // cursor there and type Ctrl+space
}
}
will show those the available args as in the below example.
{
"key": "ctrl+shift+f",
"command": "workbench.action.findInFiles",
"args": {
"query": "Company(\\w+)", // needs to be double-escaped
"replace": "User$1",
"triggerSearch": true,
"isRegex": true,
// "filesToExclude": "",
// "filesToInclude": "",
"matchWholeWord": true,
"isCaseSensitive": true
}
},
This will perform the search but not do the actual replacement in your files - you will have to trigger replace [all] yourself.
I was looking for an API to do this as an extension writer and it seems one was added less than a month ago (which you could also presumably use to manually define a keybinding, if I understand correctly):
https://github.com/microsoft/vscode/commit/8e96e0b389aedf46423431487190b878d4243edb
Install the extension Replace Rules.
Construct a search-replace in your settings.json (Workspace or User). Read the page about the possibilities.
"replacerules.rules": {
"Replace User": {
"find": "User(\d+)",
"replace": "Player$1"
}
}
In keybindings.json define the following keybinding:
{
"key": "ctrl+shift+alt+u",
"command": "replacerules.runRule",
"when": "editorTextFocus",
"args": { "ruleName": "Replace User"}
}
If you select some text the search-replace will only be performed within the selection.
If you are willing to use tasks.json; a native VS Code concept -- and you have access to a shell like bash (I use Windows with GitBash), or Powershell (builtin to Windows), you can use the power of that shell without a VS Code extension, or any new deployments -- in my case, I use sed command to make file replacements:
{
"label": "find-replace-task-name",
"type": "shell",
"command": "sed -i -E \"s/Company(\\w+)/User\\1/g; s/user/User/g\" \"${file}\""
},
Advantages of using tasks.json with a shell command:
In my case, I want to other developers on my team to use my solution, so I like using the tasks.json because it's stored in the .vscode folder, which we do include in our version control (keybindings.json is not stored in .vscode folder)
I can use my solution on today's version of VSCode (I don't need Insiders build),
I can use my it without installing any VSCode extension.
Because my task relies on a shell, I get the power of a shell and any of its "builtin" commands
In my case, I could use the bash shell and the sed utility, which are powerful, expressive and easy-to-use for file manipulation (including find-replace).
A shell helps me approach this question from a different angle; i.e. "how to find-replace a file, using (bash|Powershell)..." (So you could adapt this approach to Powershell instead of bash, more on that...)
Notice:
I used sed to perform multiple find-replacements (which I needed, the OP of this question did not need - So I chained a replacement of "user"->"User" in my command)
I used the "${file}" variable replacement to pass the filepath to the currently-open-file
And I can associate with a keybinding so it's easier to run the task. Notice the keybinding only works "when":"editorTextFocus", maybe I should add a condition that there is some file open!
{
"key": "ctrl+shift+alt+s",
"when": "editorTextFocus",
"command": "workbench.action.tasks.runTask",
"args": "find-replace-task-name"
}
There are some disadvantages to my approach:
the sed script I write is very dense, and has multiple levels of "escape characters", so it's hard to read/interpret/troubleshoot (compared to an easy-to-read JSON snippet like {"searchString":..., "replaceString":...})
it operates on the file outside of VS Code, so no "Undo" operation it seems like you can "undo" the changes, specifically you would "undo" VS Code's automatic reloading of the file, (VS Code probably recognizes that sed modified the file; but VS Code still lets you "Ctrl+Z" to go back before the modifications)
can't work unless you have a file open
doesn't use the $1 for RegEx replacement, instead uses the "extended regular expressions" flag -E and the syntax \1, etc
etc...

How to Create Custom Key Binded Snippets in VS Code

I am a huge Sublime Text user, and learned ways to improve my productivity using customizations in Sublime text. But as VScode is becoming popular day by day, wanted to check if there is any way which I can bind the shortcut keys to the custom actions.
For example, I select a word ABC in any file in VSCode and hit CTRL+B, and it places my own defined values around it like it should become
<b>ABC</b>
I had created the following snippet in Sublime Text, which when I wrote in Visual Studio Code - keybindings.json nothing worked.
{
"keys": [
"ctrl+b"
],
"command": "insert_snippet",
"args": {
"contents": "<b>${0:$SELECTION}</b>"
}
}
This will work in your keybindings.json:
{
"key": "ctrl+b",
"command": "editor.action.insertSnippet",
"when": "resourceExtname == .html", // this is optional
"args": {
"snippet": "<b>${TM_SELECTED_TEXT}</b>"
}
},
The optional when clause is if you want to limit the snippet's operation to .html files.
More general though is to use the emmet command which is built-in: Emmet: Wrap with Abbreviation in the command palette. Select your text, open the command palette, find that command and trigger it - type b or whatever your element is and it will wrap the selected text with the opening and closing elements.
[Note that there is a command workbench.action.toggleSidebarVisibility already bound to Ctrl-B, but the snippet above version seems to take precedence - meaning you lose the toggleSidebarVisibility keybinding functionality - that may be acceptable to you?]

Auto-add quotes around new lines in VS Code like Netbeans does

Just about completed my transition from Netbeans to VS Code, and there's one thing missing from VS Code that I miss dearly from Netbeans that essentially handles quotes automatically when you press enter from within a string.
These pictures should show what I mean, with this first picture being a lengthy string inside of Netbeans.
And this one is after I press enter somewhere in the middle of the string without pressing any other keys
You can see that it puts a quote where the cursor was, adds a newline, adds indentation, adds a dot (the PHP concat operator), and then another quote, which is such a fantastic feature.
Two things; what is this called, and how do I get this behavior in VS Code?
Pretty easy to do with a macro. Install the macrosRE extension.
In your settings.json:
"macros": {
"netbeans": [
{
"command": "type",
"args": {
"text": "\"\n\t\t. \""
}
}
]
},
and set up some keybinding for it in keybindings.json:
{
"key": "ctrl+alt+n",
"command": "macros.netbeans"
},
It would really interesting if there was a "when" condition to detect if within a string (and within a php file) ...and then bind to Enter. But I doubt there is such a "when" clause.
[EDIT]:
I should have remembered that in your case the 'macro' is so simple that you don't need to use the macro functionality. Try simply this in your keybindings.json:
{
"key": "ctrl+alt+n",
"command": "editor.action.insertSnippet",
//"when": "editorTextFocus && editorLangId == php",
//"when": "editorTextFocus && resourceLangId == php"
"args": {
"snippet": "\"\n\t\t. \""
}
}
It just inserts a snippet which is right there in the args. You may or may not want the 'php' limitation. You can also use the method below if you want to insert a snippet that actually lives in a snippets file:
{
"key": "cmd+k 1",
"command": "editor.action.insertSnippet",
"when": "editorTextFocus",
"args": {
"langId": "csharp",
"name": "myFavSnippet"
}
}
From vscode doc: assigning a keybinding to a snippet.
But you will eventually want to chain commands together which the macros extension allows you to do.