Multiple line to single line comment find & replace - visual-studio-code

what's the quickest way for me, in VSCode, to find and replace a comment structured like this:
/**
* Comment here
*/
With:
// Comment here
Bearing in mind here the actual comment itself should persist, so just the comment syntax being changed.
I'm hoping there is an easy find & replace operation I haven't come across before that I can perform in the editor.
Thanks!

Unless there is a vscode command to toggle a doc comment (which would make this much easier) you can do it with an extension that can run multiple finds and replaces and commands.
Using Find and Transform, an extension I wrote, make this keybinding (in your keybindings.json):
{
"key": "alt+s", // whatever keybinding you want
"command": "findInCurrentFile",
"args": {
// 2 finds and 2 replaces
"find": ["(^[ \t]*\\/\\*\\*\n)([\\s\n\\S]*?)(^\\s*\\*\\/\n)", "^([ \t]*) \\*\\s*(.*)"],
"replace": ["$2", "$1$2"],
"isRegex": true,
"cursorMoveSelect": "$1$2", // select the result for the postCommands to act on
"postCommands": ["editor.action.commentLine", "cancelSelection"]
},
}
The first find captures the entire jdoc-style comment and keeps only the interior lines. The second find and replace removes the leading * from those lines.
The result is then selected so that the postCommands can be run adding line comments.
[I didn't spend a lot of time on the regex's so double-check those.]

Related

How to place a cursor after every N characters in VS Code?

Say for example I have a very long line of text in a single line in VS Code (let's pretend that the example given below is very long).
0xffffffffeeeeeeee02020202aaaaaaaa
At first I placed my cursor after the characters 0x.
(the cursor is denoted by the | character in the example below)
0x|ffffffffeeeeeeee02020202aaaaaaaa
Then I want to add more cursors after every N characters from the current cursor. In this case N is equal to 8 and I want to do this twice to add two more cursor like in the example below.
0x|ffffffff|eeeeeeee|02020202aaaaaaaa
So that after I press the following sequence of keys in the keyboard, in this case those sequence of keys are ,(space)0x I should be able to get these final result.
0x, 0x|ffffffff, 0x|eeeeeeee, 0x|02020202aaaaaaaa
After I deselect the cursors I should be getting this
0x, 0xffffffff, 0xeeeeeeee, 0x02020202aaaaaaaa
Is this possible to do in VS code?
There is a straightforward regex that can do what you want:
Find: ^0x|(.{8})(?!$)
But you have to enable the Find in Selection option and trigger the Select All Matches command yourself after entering it.
Or use a macro extension like multi-command and this keybinding to automate it:
{
"key": "alt+p",
"command": "extension.multiCommand.execute",
"args": {
"sequence": [
{
"command": "editor.actions.findWithArgs",
"args": {
"findInSelection": true,
"isRegex": true,
"searchString": "^0x|.{8}",
}
},
"editor.action.selectAllMatches",
"cursorRight"
]
},
}
You must select up to where you want the last cursor and then trigger the macro.
Because of a flaky implementation, you must start with the Find in Selection option disabled in the Find Widget. I haven't found a way around that.
The setting Editor > Find: Seed Search String From Selection must be set to never. Otherwise your selected text will over-ride the searchString from the macro above.
Here is the pure regex method with no extensions:
Enter ^0x|(.{8})(?!$) in your Find Widget with the regex option enabled.
^0x the first part of the string you ultimately want a cursor after.
(.{8})(?!$) select each 8-character block, but not the last - that is why there is a negative lookahead for the end of the line (?!$) - so the last 8 characters are not matched. Don't worry, there will be a cursor in front of those last 8 characters as you want. (.{8}) doesn't actually need to be in a capture group, it is just clearer to see.
Select all the text to match: 0xffffffffeeeeeeee. Stop the selection there - wherever you want the last cursor.
Enable the Find in Selection option in the Find Widget by Alt+L.
Alt+Enter to select all the find matches respecting the Find in Selection option: editor.action.selectHighlights.
Step (4) will select your matches - you should have 4 for the above string. But you don't want the matches selected you just want a cursor at the beginning of each, so do step (5):
Right arrow: this cancels each selection with a cursor at the right end of each.
Type.
You can use the extension Select By
It has a command to add a new cursor by keyboard
{
"key": "ctrl+i ctrl+alt+right", // or any other key combo
"when": "editorTextFocus",
"command": "selectby.addNewSelection",
"args": {"offset": 8}
}
Now the offset is hard coded but I will add an option to ask the user the offset.
The possibility of the context switch is already working. I have to update the README.

Emmet Snippet to Write Many Numbered Variables

I'm writing some JS that requires a bunch of similar variables, numbered. I can do this just fine with multiple cursors etc, but since I'm using Emmet so much I wondered if there was a simple one line way of writing a list like:
let element1, element2, element3 ...
Is there a reason?
If you have to regularly have to apply numbers at the current cursor positions you can use the extension Regex Text Generator with a predefined setting.
"regexTextGen.predefined": {
"sequantial numbers" : {
"originalTextRegex": "(.*)",
"generatorRegex": "{{=i+1}}"
}
}
Place the cursors at the location needed (select all element and RightArrow)
execute command: Generate text based on Regular Expression
choose the sequantial numbers option
Enter and possibly adjust the offset
If you don't define a preset you can type the expressions yourself.
If you don't get an emmet answer, an extension I wrote, Find and Transform, can do this pretty easily:
{ // put this keybinding into your keybindings.json
"command": "findInCurrentFile",
"key": "alt+i",
"args": {
// "find": "element", // not necessary
"replace": "$1${matchNumber}",
"restrictFind": "line",
"isRegex": true
}
}
Just put your cursor on the word that you want matched. And then each match will be replaced by itself plus an incremented counter.
Thanks for these examples, I was using Asuka's extension Insert Numbers and it's quite helpful especially for additional sets of variables.

Is there a keyboard shortcut to select word occurrences in just one line in visual studio code

I know the topic of multi cursors-editing in visual studio code is duplicate but what I want is the way (by keyboard) to select word occurrences in just one line in visual studio code, because the other option: ctrl + F2 it selects all the occurrences in all the file, and not the mouse way by holding alt and click.
let say I have this:
const FETCH_USERS_REQUEST = "FETCH_USERS_REQUEST";
const FETCH_USERS_REQUEST = "FETCH_USERS_REQUEST";
when the cursor is on REQUEST word for the second line I want to do two cursors in the second line after the two occurrences of REQUEST.
You have 2 alternatives:
Enable the Find in Selection option in the Find Widget after entering your find query.
An extension that I wrote does this fairly well, see Find and Transform.
With this simple keybinding:
{
"key": "alt+y", // whatever keybinding you want
"command": "findInCurrentFile",
"args": {
"restrictFind": "line" // find all on current line only
// with multiple cursors you can have as many current lines as you wish
}
}
It does a find in the current file. Since there is no actual find query, like REQUEST, designated in the args. It will find the current word at the cursor on the line. Different languages define what a "word" is differently. For javascript, for example, FETCH_USERS_REQUEST is the current word even if the cursor is on Request only.
You can manage this by actually selecting, double-clicking on Request or Ctrl+D, and then trigger the above keybinding. Then the extesnion will search for whatever is selected, if there is a non-empty selection.
The extension is designed to select those find matches, not put the cursor after them, but you can simply right-arrow to dismiss the selection and the cursor will be where you want.
[I have to update the extension, the current version v0.9.7 in the Marketplace won't do this - but here is a demo of it already working. It should be updated tomorrow at the latest, look for v0.9.8.]

VSCode snippets - how to run a regex transform on the 'choice' result?

In this snippet defined in keybindings.json I'm trying to run a regex transform on the input result from choice dialogue - I need the same value inserted twice, in 1st position I need the part before the first semicolon and in 2nd position I want the full choice value.
I tried examples from the doc but they don't seem to be working with the choice, or am I missing something? How do I achieve this?
{
"key": "cmd+alt+ctrl+t",
"command": "editor.action.insertSnippet",
"when": "editorTextFocus",
"args": {
"snippet": "Before semicolon: ${2/(\\w);{1,}/$1/} & Full value: ${2|1; testValue1, 2; testValue2|}"
}
},
expected output:
BeforeSemicolon: 1 & Full value: 1; testValue1
After some experimentation I have found a partial working.
It is important that the regex matches the full string. So add .* at the end.
(This should be added to the documentation)
{
"key": "cmd+alt+ctrl+t",
"command": "editor.action.insertSnippet",
"when": "editorTextFocus",
"args": {
"snippet": "Before semicolon: ${1/([^;]*).*/$1/} && Full value: ${1|123; testValue1,223; testValue2|}" }
},
And it only works for the first choice, AND you have to move the cursor inside the option text, just 1 Left Arrow is enough, this accepts the choice but keeps the field active. And then TAB. Now the transform is applied.
You have to file a bug for this.
Transform of choice variables is not supported. There is a general discussion mentioning this at https://github.com/Microsoft/vscode/pull/51621.
There are a couple of workarounds because transforms of placeholders do work as long as there is one non-transformed usage of the placeholder somewhere in the snippet. Then a transformed version elsewhere will work. This technique works for placeholder transforms but NOT choice transforms as you are trying to do. Why that difference I don't know??
Simpler workaround 1 using one placeholder:
"snippet": "Before semicolon: ${1/([^;]*).*/$1/} && Full value: ${1:1; testValue1}"
Here you would have to accept the default placeholder value (1; testValue1) or overwrite it with another value. Then on tab the transform will be applied to any other references to that same tabstop.
Complex workaround 2 usings multiple placeholders (in this case for 3 "choices":
"snippet": "Before semicolon: ${1/([^;]*).*/$1/}${2/([^;]*).*/$1/}${3/([^;]*).*/$1/} && Full value: ${1:1; testValue}${2:2; testValue}${3:3; testValue}"
Here you have to list your three (or however many you have) choices as separate placeholder tabstops. Then you will either tab to accept that placeholder you want or deletetab those you don't. It is a little tricky getting the delete/tab sequence down but once you have it, it is repetitve. You see the cursor appears to be at the beginning of the next "choice" but it is really at the end of the previous "choice".
Here is a demo of version 2 where I choose each "choice"/placeholder in turn. [I'm just using the alti keybinding here to simplify.]
Obviously if potentially have a lot of "choices" you'll probably want to use version 1. If you have a small number of "choices" that you want to be presented with and not have to type, version 2 does work pretty well.

How to avoid multi cursor on wrapped lines in VS Code?

I have turned on Word Wrap in VSCode, so that long lines are wrapped at certain window widths.
If I want to comment out some code or text, I usually just move the cursor to the beginning of the first line of the block of code, use ctrl+shift+down to add cursors, and type the // or # etc..
The problem with Word Wrap is that I not only get cursors in the beginning of each actual line, but in the beginning of every line as it is displayed at the moment in the editor.
For example, for the following document:
1 This is the first line.
2 Second line.
It might be wrapped like this:
1 This is the first
line.
2 Second line.
So if I use the method above and add % I would get:
1 %This is the first
%line.
2 %Second line.
But what I want is the following:
1 %This is the first
line.
2 %Second line.
Otherwise, I have a % in the middle of the line, just because I resized the editor window.
At the moment, I actually turn off Word Wrap to achieve this, but I hope there is a better way?
Follow the next steps:
Alt+Shift+i to put a cursor on every selected line
Cmd/Ctrl+← to move all cursors to the beginning of the [wrapped] lines
Cmd/Ctrl+← (again) to move all cursors to the actual beginning of the [wrapped] lines
Enjoy! 🙂
Update v1.62+ (October 2021)
This is now natively available in VSCode thanks to this PR on changing the default behavior of InsertCursorAbove/Below. However, it's not enabled by default.
You'll need to update your keybindings to pass in an args like this:
{
"key": "shift+alt+down",
"command": "editor.action.insertCursorBelow",
"when": "textInputFocus",
"args": { "logicalLine": true },
},
{
"key": "shift+alt+up",
"command": "editor.action.insertCursorAbove",
"when": "textInputFocus",
"args": { "logicalLine": true },
},
This appears to be a known issue. The CursorColumnSelectOnTrueLines extension by Martin Zimmermann provides commands that show the desired behavior, by default mapped to Ctrl+Alt+Shift+Up/Down.