Vim duplicate line multiple times with 2 keypresses - ideavim

I use this key mapping to duplicate a line, and go to the same cursor position on this newly created line:
nnoremap , mqYp`qj
What this does:
Create mark 'q'
Yank line
Paste/put line (below current line, cursor is now at start of new line)
Go back to mark at previous line
Move one line down. (cursor is now on new line at the same place of start of previous line)
This works perfectly fine, however I see a flaw when putting a number in front of the command. Imagine I want to duplicate this line 10 times. It would try to create 10 marks basically. I could do Y10p for this, I do understand that. My problem with that approach is that I'm not on the same cursor position as I was in the first line, the one I'm duplicating.
So I'm looking for a way to do basically 10,, using my previously made mapping, and ending on the last line, at the same cursor position of where I was in the first line. Note that I am using IdeaVIM exclusively to code, which means I can't make any functions for this.
Is it possible to get this 10, working in this situation?
Edit #1:
Example text
# Start
# Initialize new variables
new_invoice_name_one = 'New Name One'
new_invoice_name_two = 'New Name Two'
new_invoice_address_one = 'New Address One'
Command executed: 3, with the cursor being on the first I of line 2
Desired output
# Start
# Initialize new variables
# Initialize new variables
# Initialize new variables
# Initialize new variables
new_invoice_name_one = 'New Name One'
new_invoice_name_two = 'New Name Two'
new_invoice_address_one = 'New Address One'
with the cursor being on the first I of line 5 `
Edit #2:
I see some potential at the LetHandler.java here, however I can not seem to figure out how to use it to match the use case. On the other hand, here it says it is not supported at all.

When I play vimgolf, I use a trick [count]#='... sometimes. It could be used for your requirement.
you can map:
nnoremap , #='mqYp`q'<cr>
Then you can just simple press 200, to achieve what you want.

You can achieve this by pasting to the above of current line. Do this nnoremap , YmqP`q
update
You cannot do that since vim's key mapping is just string concatenation. One way to achieve this is to predefine a macro. Put this in the related rc file,
let #q="mqYP`q"
nnoremap , #q

Related

In VSCode, how can I turn a multi-line comment into a paragraph with no line breaks?

What's an easy way to convert a multi-line comment (e.g. JSDoc with each line separated by line breaks) into a paragraph without any line breaks that I can copy into an email or another document?
I know I can use search & replace with regular expressions, but is there a more ergonomic way to do it?
You probably knew that you can use multiple cursors to change multiple lines at once, but did you know you can also use them to remove line breaks? Assume you start with this comment:
/**
* Returns a new `Temporal.LocalDateTime` instance representing the first
* valid time during the current calendar day and time zone of `this`.
*
* The local time of the result is almost always `00:00`, but in rare cases it
* could be a later time e.g. if DST starts at midnight in a time zone. For
* example:
* ```
* const ldt = Temporal.LocalDateTime.from('2015-10-18T12:00-02:00[America/Sao_Paulo]');
* ldt.startOfDay; // => 2015-10-18T01:00-02:00[America/Sao_Paulo]
* ```
*/
First part: use multiple cursors to remove the prefix characters on each line.
Click on the upper-left corner of the comment (the /**).
Now hold down Cmd+Shift (Alt+Shift on PC) and click after the */ on the last line of the comment section.
This will create a columnar, multi-line selection that includes the non-text prefix characters on each line. If the selection doesn't include all the prefix characters, you can hold down the Shift key and use the left or right arrow keys to adjust the width of the selection.
Press the Delete key to remove prefix characters on all lines.
Second part: it's time to delete the line breaks and replace them with spaces. I discovered today that you can use multiple cursors for this part too!
After you've deleted the prefix text above, but before you've pressed any other keys, press the backspace key. It will delete the line breaks but leave each cursor in the same place!
Type the spacebar once to insert one space to replace each line break.
Press ESC to clear multiple selections, and delete the extra space at the start of the line. You may have an extra space(s) at the end of the line too that may need trimming.
Copy the resulting one-line text.
Use Cmd+Z (Ctrl+Z on Windows) to undo the last few changes so your code comment will be back to normal.
Now you can paste the copied text into an email!
The same solution works to replace line breaks with spaces in any multi-line text, not only code comments.
I'm sure that many of you already knew how to do this trick, but I found it so easy and so cool that I thought it was worth sharing as a Q&A here so others can learn about this trick too.
Here's what the steps look like in the VSCode IDE:
Before deleting, you should see something like this:
After deleting prefix characters:
After deleting line breaks (note the multiple cursors are still there):
After inserting spaces in place of the deleted line breaks:
I usually select the first line break, then hit/hold command+D repeatedly to add cursors at all line endings I want to edit. Then, just hit space once.

vscode multicursor reorder lines how to

I am finding a common issue I have with vscode multi-cursor editing mode is how to deal with "fields" of different lengths. To give an example:-
I have an sql file which contains multiple lines of the form
INSERT INTO settings (name,value) VALUES('key_for_value', 'value_to_set'); -- a comment about this setting
Which I want to turn into
UPDATE settings SET name = 'value_to_set' WHERE name = 'key_for_value'; -- a comment about this setting
Obviously each 'key_for_value' and 'value_to_set' are different lengths in each line.
Its fairly easy to grab a bit of the first line of INSERT INTO... and with a control-D get multiple cursors from there, and edit the lines to to get to UPDATE settings SET name = but then I am stuck - I can't find a key binding to (for instance) jump to the next comma - then start a selection and jump the next closing round bracket. I could then do a multiline cut, move the cursor back to start of line, more forward to after the = sign and do a multiline paste.
Is this sort of thing possible?
you can do it with a regex search replace
Search for
INSERT INTO (\w+) \((\w+),(\w+)\) VALUES\('([^']+)', '([^']+)'\);(.*)
replace with
UPDATE $1 SET $2 = '$5' WHERE $2 = '$4';$6

How can I remove duplicate lines in Visual Studio Code?

Say you have the following text:
abc
123
abc
456
789
abc
abc
I want to remove all "abc" lines and just keep one. I don't mind sorting. The result should be like this:
abc
123
456
789
If the order of lines is not important
Sort lines alphabetically, if they aren't already, and perform these steps:
(based on this related question: How do I find and remove duplicate lines from a file using Regular Expressions?)
Control+F
Toggle "Replace mode"
Toggle "Use Regular Expression" (the icon with the .* symbol)
In the search field, type ^(.*)(\n\1)+$
In the "replace with" field, type $1
Click ("Replace All").
If the order of lines is important so you can't sort
In this case, either resort to a solution outside VS Code (see here), or - if your document is not very large and you don't mind spamming the Replace All button - follow the previous steps, but in steps 4 and 5, enter these:
(based on Remove specific duplicate lines without sorting)
Caution: Blocks for files with too many lines (1000+); may cause VS Code to crash; may introduce blank lines in some cases.
search: ((^[^\S$]*?(?=\S)(?:.*)+$)[\S\s]*?)^\2$(?:\n)?
replace with: $1
and then click the "Replace All" button as many times as there are duplicate occurrences.
You'll know it's enough when the line count stops decreasing when you click the button. Navigate to the last line of the document to keep an eye on that.
Coming in vscode v1.62 is a command to eliminate duplicate lines from a selection:
Delete Duplicate Lines in the Command Palette
or
editor.action.removeDuplicateLines as a command in a keybinding
(there is no default keybinding for this command)
Here is a very interesting extension: Transformer
Features:
Unique Lines As New Document
Unique Lines
Align CSV
Align To Cursor
Compact CSV
Copy To New Document
Count Duplicate Lines As New Document
Encode / Decode
Filter Lines As New Document
Filter Lines
Join Lines
JSON String As Text
Lines As JSON String Array
Normalize Diacritical Marks
Randomize Lines
Randomize Selections
Reverse Lines
Reverse Selections
Rotate Backward Selections
Rotate Forward Selections
Select Highlights
Select Lines
Selection As JSON String
Sort Lines By Length
Sort Lines
Sort Selections
Split Lines After
Split Lines Before
Split Lines
Trim Lines
Trim Selections
Unique Lines
Removes duplicate lines from the document Operates on selection or
current block if no selection
Unique Lines As New Document
Unique lines are opened in a new document Operates on selection or
current block if no selection
I haven't played with it much besides the "Unique Lines" command but it seems quite nicely done (including attempting a macro recorder!).
To add to #Marc.2377 's reply.
If the order is important and you don't care that you just keep the last of the duplicate lines, simply search for the following regexp if you want to only remove duplicte non-empty lines
^(.+)\n(?=(?:.*\n)*?\1$)
If you also want to remove duplicate empty lines, use * instead of +
^(.*)\n(?=(?:.*\n)*?\1$)
and replace with nothing.
This will take a line and try to find ahead some more (maybe 0) lines followed by the exact same line taken. It will remove the taken line.
This is just a one-shot regex. No need to spam the replace button.
This now also takes the comment of #awk into account, in where the last line has to have a linefeed in order to be identified as a duplicate. This is no longer the case now by excluding the \n from the line to search and adding a $ to the line found.
I just had the same issue and found the Visual Studio Code package "Sort lines". See the Visual Studio Code market place for details (e.g. Sort lines).
This package has the option "Sorting lines (unique)", which did it for me. Take care of any white spaces at the beginning/end of lines. They influence whether lines are considered unique or not.
Install the DupChecker extension, hit F1, and type "Check Duplicates".
It will check for duplicates and ask if you want to remove them.
Try find and replace with a regular expression.
Find:
^(.+)((?:\r?\n.*)*)(?:\r?\n\1)$
Replace:
$1$2
It is possible to introduce some variance in the first group.
If you don't mind some Vim in your VS Code. You can install Vim emulation plugin.
Then you can use vim commands
:sort u
It will sort lines and it will remove duplicates
Sublime Text 3
It has blisteringly fast native permutation functions.
Edit > Permute Lines > Unique or ⇧⌘U, and
Edit > Permute Selections > Unique
Visual Studio Code is my daily driver. But, I keep Sublime Text on standby for these situations.
Not actually in Visual Studio Code, but if it works, it works.
Open a new Excel spreadsheet
Paste the data into a column
Go to the Data tab
Select the column of data (if you haven't already)
Click Remove Duplicates (somewhat in the middle of the bar)
Click OK to remove duplicates.
It is not the best answer, as you specified Visual Studio Code, but as I said: If it works, it works :)

Does Eclipse have a shortcut to split a line and introduce a variable?

During typing in code, I often have code lines that become long:
String result = new MyObject(foo, bar).getBaz().getFoo(new Config(new File(f))).get(key).get(0);
I frequently break up such a line manually, making two of them:
Foo foo = new MyObject(foo, bar).getBaz().getFoo(new Config(new File(f)));
String result = foo.get(key).get(0);
This means positioning the cursor after new File(f))), pressing Enter, then select the String result = part, cut and paste it from the first to the second line, create a new variable named like the getter, type it in at the beginning of the second line and at the beginning of the first line, the latter as an assignment, with declaration. A lot of manual typework if you do it often enaugh.
I wonder again and again if there is a help, like a keyboard short cut, which does this for me: I position the cursor after new File(f))), press Ctrl+something and the result is the two lines. A second one I wonder if it exists is if I would position the cursor on Config at the first line, Ctrl+something and it would form these lines:
Config config = new Config(new File(f));
String result = new MyObject(foo, bar).getBaz().getFoo(config).get(key).get(0);
I finally found it. Long version:
Position the cursor as described in the question, press Shift+Alt+L. A dialog will appear to configure the variable name, whether all occurrences shall be replaced or the variable should be declared final. Press Enter as you aggree to the settings.
Short version:
Position the cursor as described in the question, press Ctrl+1 and the quick fix menu will appear (even if there is nothing marked red or yellow). Select Extract to local variable (or one of the related options, as you need) and press Enter.
For the second example to work, the cursor must be positioned either after the expression you want to cut out
….getBaz().getFoo(new Config(new File(f))<CURSOR HERE>).get(key).get(0);
or on the new keyword.

Sublime Text Macro Command Move to Specific Column Number

I'm trying to move to a specific column number in a Sublime Text macro command, so that I can delete everything after that point, but I can't get the move command to work.
I've compared the old and new versions of the unofficial documentation, and it looks like the move command used to have an "amount" parameter, but it hasn't been working for me. So the reason I'm writing is because I feel like there's something the docs are leaving out, but I don't know what it is, or how to even debug it in Sublime Text.
Here's an example of what I'm trying to do:
/*//////////////////////////////////////////////////////////
// Comment Block ///////////////////////////////////////////////
//////////////////////////////////////////////////////////*/
When the caret is at the end of the phrase "Comment Block", I need to run a command that advances the caret to a specific column number. After that, I can expand the selection to the end of the line and delete, trimming the line to be equal with its counterparts.