Yank and paste but with small change - vim

I want to put a specified number after each pasted line automatically and this number will increment every past.
Sometimes I want to declare many variables. So I write one declaration and copy(yank) it and past to a second line. Then I can repeat this operation with dot operator ".". But it's very annoying to make these variables vary.
I want to achieve something like this:
variable (yy) variable1 (yy)
variable (p) variable2 (p)
variable (.) => variable3 (.)
variable (.) variable4 (.)
variable (.) variable5 (.)
Is it possible to perform such a operation in just the vim?

I don't know if someone can do it with ultisnips interpolation, I think it is possible but I came up with this solution
yy4p .......... copy 4 times
v} ............ select block
g<Ctrl-a> ..... increase the sequence
Until here you have the main solution that is increasing the numbers fast
fy ............ jump to the first 'y'
<Ctrl-v> ...... start selection block
3jl ........... extend selection
c.<Esc> ....... swich 'yy' with .
fy. ........... finishes
Using macro
qa ............ start recording marcro 'a'
yyp ........... copy line
ci(.<Esc> ..... change first ()
Ctrl-a ........ increase
ci(. .......... change second ()
Esc ........... stop recording macro 'a'
3#a ........... 4x macro 'a'

:%s/variable/\= printf("variable%d",line('.')-6)/
or if you have a vim with perl support (default in many linux distributions)
:perldo s/variable/$& . ++$n/e

My UnconditionalPaste plugin has gpp and gPp mappings for this (and many more paste variations). The first only increments the first decimal number, the second one all numbers.
So, starting with
variable1 = 'foo1'
yygpp will create:
variable1 = 'foo1'
variable2 = 'foo1'
whereas yygPp will do this:
variable1 = 'foo1'
variable2 = 'foo2'
These support a [count] and can be repeated with ., too.

Related

Vim change & jump lists override behaviour

I'm new at vim, started to play with macroses, and founded not obvious override behaviour for jump/change lists.
The main question - are there any stable ways to jump by changes/moves inside same line (except marking each point), cause this lists remember only last change on the same line (if changes are consequtive withing on line).
Example for jumplist. Cursor position at '(', '{' - marked as m.
( smth ) { } %`m%
I jumped firt to ')', next by mark at the same line and next to last bracket
I'm able to do only one ^o - last jump at first line. But expected to jump 2 times more.
Same situation with changes list and g;
't1 t2 t3' -> 't2 t3 t4', I can't move between all 3 t
At least I wanted to jump by same points as stored at undo history. All modern editors like VSCode, Sublime, e.t.c. have this stable option "Alt -" / "Alt +" to jump all prev. cursor positions. What is Vim way?
Founded this when tried to make macro, which swaps any 2 pair of brackets.
{ smth } (
)
Let's mark first pair of brackets with 'mm', to remember whith whom should we swap.
let's mark '{' as main bracket and go to '(', starting macro 'qq'. I'm marking current pair of brackets as 'mc' and swapping later between main and current.
#q=mc%x`m%Plx^O^Op`mx`cPlx`mP
( smth ) {
}
moving cursor to { and running '#q' - we get initial text, double swapping brackets
Problems started, case second pair brackets marked as mm, and cursor located at first pair of brackets. '(' - mm, '{' - start position
{ smth } (
)
only first ^o would work, and then macro will jump outside of this block
There are two rules: "small" moves are never remembered; and, "changes" are remembered upon leaving from insert mode.
So all those macros and stuff they are sort of "batch processing tools", not "usual line editing tools".
Instead, to get t2 t3 t4 from t1 t2 t3 you could do ctrl-a w . w . Or to swap the brackets with d%%p. And so on.
This sort of "small edits" should be done by normals in Vim. So you need to master the normals first. Maybe reading the "Practical Vim" by Drew Neil could help.

Vim Insert Sequence with incremental numbers

On a single line I am looking to turn this:
"".format(...)
into this:
"{0}, {1}, {2}, ..... {n}".format(...)
where n is the number of elements I wish to repeate. Without the need to manually insert each argument.
I don't know if this way is ok for you:
"I(cursor here)
".format(...)
execute command:
:r! seq -s, -f "{\%g}" 0 20
then join (J) the 3 lines. 20 is n in your case.
or "I".format(...)
to insert mode, ctrl-R then type =system("seq -s, -f '{%g}' 0 20")
With the cursor between the empty double quotes, I would do (for n = 5):
i<C-R>=join(map(range(5), 'printf("{%d}", v:val)'), ', ')<CR>
Some vimgolf enthusiasts can probably condense this further. But I would probably either write a mapping for it (if the need occurs so frequently), or do it manually like this:
5i{0}, <Esc>^f0;<C-A>;2<C-A>;3<C-A>;4<C-A>
I would use a macro, like:
0a{0}, <esc>lqqyF{f"PB<C-a>;q
Then just use whatever n-1 is with #q. E.g. 4#qXX would give:
"{0}, {1}, {2}, {3}, {4}, {5}".format(...)
There is no "seq" command in Windows, so I prefer this:
:call append(".", map(range(6), '"{".v:val."},"'))
and then join these lines use '6J'.

Vim Copy and paste text on the same line

I have an input text as follows -
(command (and (A B C) ))
(command (and (D E F) ))
(command (and (G H I) ))
...
...
I would like to copy and paste part of text on the same line as
(command (and (A B C) (A B C)))
(command (and (D E F) (D E F)))
(command (and (G H I) (G H I)))
...
...
Will it be possible to do it using VI Editor automatically?
Update :
I think I missed one important point that the values A,B,C ... I... can have variable length. I just used them as symbols.
Thanks !
If all the lines are the same length and format as in your example:
With cursor anywhere on or inside of parens (A B C):
va(Ctrl+v
Now you have (A B C) selected and are in block select mode. Use any mechanism to block select downward. If it is a few lines, you can just move downward. If it is many you can add a count, or use a search (/) or end of file Shift+g.
Once you have selected all:
y/)Enterp
This will yank (y) the whole block, move to the close paren, and paste the block after it (p).
If the lines vary in length or otherwise cannot be reasonably selected as a block
You can use a pattern replacement. This is specific to your example, where we are looking for the pattern (A B C) where A, B and C are capital letters contained in parentheses and separated by spaces. We take a match of that pattern plus the following space, and replace it with the match of that pattern, a space, and the pattern match again.
:%s/\(([A-Z] [A-Z] [A-Z])\) /\1 \1/
Yes, several ways to do this in vim (as with most things). I would probably opt for a quick macro: go to the first line and hit qa from normal mode to start recording a macro named "a". Now do the edit on that line manually. Of course you'll want the operations to be generic, so don't just type in the values, use yank and put to copy it. Once the edit is done, escape to normal mode and press j to move down to the next line (this will set you up to run the macro on the next line). Hit q again to stop recording, then type #a to execute the macro on the next line, then hit it again to run it on the next line, etc. Or, once you do #a once, you can do ## to run the same macro again. You can also supply a count to ## to do is several times.
Alternatively, you can do a regex with the :s command, but it depends on what your lines actually look like and how good you are with regex.
(these work for me in vim)
using block select:
14l<C-v>jj6ly7lp
using macro (if lengths are varied):
record the macro using:
qqf(;vf)y;pj0q
and then repeat as neccessary:
100#q
works for a file with 100 lines
I combine the techniques given by bmearns and Kev.
So what I did is as follows
start recording the macro by q.
/( to find the opening bracket, so it goes to the second one.
n to goto the third one.
v to mark the visual block
/) to search for the end of the bracket
y to copy the visual block
n to goto next ) bracket
One time arrow key to go next to the closing bracket
p to paste the visual block
Down Arrow key to goto next line.
Home Key to goto first location of the next line.
q to stop recording the macro
#a to do the same operation for all the lines.
And it worked just completely fine !
Thanks a lot guys !

vim repeat find next character 'x'

I often navigate in vim by f x to find next occurrence of character 'x',
but overlook that there is a word (or more words) containing 'x' in between the word I want to edit and the beginning cursor position.
So i have to f x again, which is kind of annoying since there is this nice button ., which does repeat the last command. So is there a way to repeat f x with a single button press.
The command to repeat an f is ; (semicolon); , (comma) reverses the direction of the search.
Time has passed since I asked this question - nowadays I use vim-easymotion, which makes the need for ; almost unnecessary.
This plugin allows to jump to a certain letter directly - triggering the plugin makes all letters grey except for all 'x' on the screen - and those are replaced by red letters which you can press to jump directly to it.
To add to #Jeremiah Willcock answer, We can add count to f command to go to the nth occurrence [count]f{char}. For e.g.
2fx => goes to the second occurrence of x [if available]
similarly we can use the same counter to ; and ,. For e.g.
2; => goes to the second occurrence of last search [if available]
2, => goes to the second occurrence of last search in reverse [if available]
This is very useful when using it with c{motion}(change) or d{motion}(delete). For e.g. If we want to change or delete to 3rd occurrence of a char we can do
c3fx => change to 3rd occurrence of character x (included)
d3fx => delete to 3rd occurrence of character x (included)

How can I quickly add something to a few lines in vim?

I'm trying to get away from my arrow use but there is one thing I've yet to solve without using the arrow keys. Take this example:
var1 = "1"
var2 = "2"
var3 = "3"
var4 = "4"
Now I want this to be:
var_1 = "1"
var_2 = "2"
var_3 = "3"
var_4 = "4"
Using arrows I would just goto the var1, insert and add the underscore and then arrow down and do the same thing. The problem with using hjkl is I can't be in insert mode so I have to esc out, move down, insert...rinse repeat which required more work. Is there another way to accomplish this?
You can also use a visual block insert:
go to the "1" in "var1"
press CTRL+V
go down with j to select all the rows you wish to affect
I (that's capital i)
_
<ESC>
The underscore should now be inserted at the correct place in all the rows selected (for some reason it takes a second for it to happen on my machine)
There are many ways to do this. Using movement commands for example:
1G0 → Go to the start of the first line
f1 → go to the first occurence of "1"
i_<ESC> → insert "_" and go back to normal mode
j. → go down a line and repeat the insert command
j. → go down a line and repeat the insert command
...
Or, better yet, use an "ex" command:
:%s/var/var_/
Or even with the visual block command, as johusman notes.
Assuming you're at line 1, character 1...
Using a macro:
qqfra_<Esc>+q3#q
q Record macro
q Into register q
f find
r 'r'
a append
_ underscore
Esc Normal mode
+ Start of next line
3 Three times
# Play macro
q from register q
Par 11.
Or (better) using substitute:
:%s!r!&_<CR>
Par 9!
[Sorry... too much VimGolf!]
I tend to prefer :substitute over the visual block mode.
%s/var\zs\ze\d/_/
I always have line numbers turned on, so I'd do e.g.
1,4 s/var/var_/
This is similar to the
% s/var/var_/
answer, but it only functions on the named lines. You can use visual mode to mark the lines, if you don't like typing the range (the 1,4 prefix) in your command.

Resources