In Vim, paste over text between two parenthesis? - vim

Something that I find myself doing often is yanking the text between two parenthesis and pasting that over another pair of parenthesis. For example:
foo(int a, int b, int c)
bar(int d, int e)
becomes
foo(int a, int b, int c)
bar(int a, int b, int c)
Is there a quick way in Vim to yank the text from foo and paste it over the text in bar?

Yank the content of the first pair of parentheses:
yib
Visually select the content of the second pair of parentheses and put:
vibp

One way would be yi) inside foo's arguments and "_di)P within bar's arguments.
yi) yanks the text inside the parentheses
"_di)P uses the null register to delete the text inside the parentheses and pastes the text, vi)p also works and avoids the null register
The only thing changing is the function name though, so you could also just yank the line and use cw (change word) to change foo to bar.

Cursor over the first paren of foo, then use y% to yank all the text until the matching paren. (You can also use v%y if you prefer to visually see the text you're yanking.)
Then cursor over the first paren of bar, then use v%p. It selects the text up until the matching paren then pastes over it.

Use this to go to last parenthesis shift + 5.
Press 5 twice for the first parentheses.

I use vim-scripts/ReplaceWithRegister.
Copy as usual with
yi(
Paste with gri(

Related

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 !

column copy and paste in row

I have a file with follow content:
sensor_write_reg(client,0x57,0x00);
sensor_write_reg(client,0x58,0x00);
sensor_write_reg(client,0x59,0x00);
sensor_write_reg(client,0xfe,0x00);
sensor_write_reg(client,0x46,0x00);
I want to column copy the following text to a new file:
struct reg reg_table[] =
{
// paste here
}
int a;
int b;
int c;
// ...
the following content expected:
struct reg reg_table[] =
{
0xfe,0x01
0x54,0x11
0x55,0x03
0x56,0x00
0x57,0x00
0x58,0x00
0x59,0x00
0xfe,0x00
0x46,0x00
}
int a;
int b;
int c;
// ...
In the source file, I type CTRL+v to enter column mode, select and copy.
Type CTRL+W to enter the destination file, and type p to paste.
However, the pasted content overrides the following statements. That's not I want.
0xfe,0x01
0x54,0x11}
0x55,0x03int a;
0x56,0x00int b;
0x57,0x00int c;
0x58,0x00
Is the any way to paste it in row mode, in a number of new lines?
To always paste something linewise you can use the :put command.
:put
If you want to convert to characterwise or blockwise you can use the setreg() function as shown in this vim tip or use this plugin, UnconditionalPaste.
Blockwise selection doesn't work like linewise selection.
You are copying text from 6 lines so you have to free 6 lines for pasting. Try 6O<CR>p
You also could try a macro; after some trying, I found this one:
y:tabe^MP:%s/^.*\(0x\x\+,0x\x\+\).*$/\1/^MVggy:tabclose!^M^Wjp
(the ^M and ^W are carriage return and control-W)
The setup of your vim would be...
one tab with two windows, horz splitted (via C-W S)
the sensor_write_reg-stuff in the upper window,
the paste here-source code in the lower one.
lower window: got to line "paste here"
upper window: visual select (now with capital V) the lines you want
then press #q (if the macro is saved to q; or just type the commands on the fly...) and let the magic happen...
what happens here?
ywe yank the text
:tabe^MPand open a new tab with an empty buffer, paste the text
(caution: if you have an unnamed buffer, this will not work)
:%s/^.(0x\x+,0x\x+).$/\1/here we filter: only two hex-digits, seperated by a comma, will survive.
Vggy:tabclose!^Myank everything, close the buffer (without saving)
(now we are back to the first tab, still in the upper window)
^Wjpmove one window down, and paste.
Finally you could use a kD to delete the "paste here"-line...

How to append to the clipboard

I know how to copy to the clipboard but how can I append to it?
I use this in my code:
let #+ = my_expression
but that overwrites the clipboard.
I know that I can use the registers a-z to append to:
let #B = my_expression
which appends to register b, but what do I when I want to append to the clipboard?
use:
let #+ = #+ . my_expression
or shorter:
let #+ .= my_expression
Reference: :help :let.=
If you're not macro-ing, it's probably worth checking out registers as well. :help registers was mind-blowing.
In an oversimplified nutshell, there are 26 additional "customizable clipboards", called registers, where you can store text, starting with a and going through z.
You add text to a register in command mode by hitting ", naming the register (say f), and then typing the "motion" you want to select text.
NOTE: We're using the named f register here b/c it's probably under your left index finger. That is, f is picked just b/c it's handy. You could replace f with a or u or z or whatever throughout if you wanted.
Copying with a register (cursor at [T]):
Initial File State
This is my first line.
[T]his is my second line.
This is my third line.
Type "fyy in command mode to fill the register with one line (yy).
Type p (* see below) to immediately paste it from the default register.
Type "f to pick the f register and then p to paste from the f register directly. Right now f and default as the same.
So the result of typing "fyyp is exactly the same as having typed yyp with the default clipboard.
Result
This is my first line.
This is my second line.
[T]his is my second line.
This is my third line.
Appending to a register:
Use the capital letter to append to your existing register.
In the above example after pasting, press j to go down a line and then "Fyy. Then type p to paste. You've appended "This is my third line." to f's contents.
Result
This is my first line.
This is my second line.
This is my second line.
This is my third line.
This is my second line.
[T]his is my third line.
(Using a lower case f would have cleared out f's contents and ended up with it only holding "This is my third line.")
Why does p paste what's in register f immediately after you yanked into f? Because your default register holds a pointer to the last selection, and apparently doesn't simply hold what you added to f, but pulls everything that's in f when you append. It might be more expository to say, in the first case, "the result of typing "fyy"fp is exactly the same as having typed yyp with the default clipboard."
But if you were now to yy a new line into the default register, you can hit "f to select the f register and then p to paste that previous value.

How to add a word at the beginning of multiple lines in vim?

In Vim,
How do i add a word at the beginning of all lines?
Also how do i add it at end?
Eg..
If i have
A
B
C
D
I want to make it to
int A =
int B =
etc..
use visual block mode (Ctrl-v) to select the column you want, and then hit I, type the characters you want, and then hit Esc
So in this case, you'd put your cursor on A, hit Ctrl-v, go down to D, hit I and type int (it'll only appear on the first line while you type it), and then hit Esc at which point it'll apply that insert to all visually selected portions.
This works for anywhere in the document, beginning of line or end of line.
:he v_b_I for more info on Visual Block Insert
You can do this:
:%s/^/at the beginning/
:%s/$/at the end/
:%s/.\+/int & =
+ won't match on empty lines
If you need to copy just the first word, then do:
:%s/^\w\+/int & =/g
If you want to preserve indentation, then do:
:%s/^\(\s*\)\(\w\+\)/\1int \2 =/g
A global substitute should do i:
:%s/.\+/int & =/
This is how it works: in the second part of the substitution (ie in the int & =) the ampersand is replaced with what machted in the first part (the .*). Since .* matches the entire line, each line is subsituted as wanted.
If you have empty lines (in which you don't want to have any replacements), you could go with a
:%s/^\S\+$/int & =/

Reordering methods using vim

I have 2 methods in a source file:
def Foo
puts "hello"
puts "bar"
end
def Bar
puts "hello"
puts "bar"
end
I would like to swap the order of the methods, so Bar is first.
Assuming the cursor is on the d in def Foo, the simple way is to:
shift v -> jjjj -> d -> jjj -> p -> O -> esc
But that feels a little long winded and does not account well for arbitrarily long methods:
What is the most efficient way to do this in Vim, keystroke wise?
EDIT
Keep in mind, I would like the solution to account for a situation where the methods are in a context of a big class, so G is probably best avoided
Assuming the cursor is somewhere in the first method, press dap}p and they should be swapped.
What dap does is simply "delete a paragraph". Try :help object-select to learn other way of deleting/selecting text objects in VIM.
EDIT: Replaced G with } in the command.
Similar to Spatz's
d}}p
delete to the next blank line (below Foo), skip to the next blank line (below Bar), paste.
Found another method ( from godlygeek on #vim ):
with:
def function():
first
first
first
def lol():
second
second
second
From line 1, count up until the 'def lol', which is 5. Then:
:1,5m$
A couple of ways off the top of my head. You could say
5dd/end[enter key]pO
Deletes five lines, searches for end, places the lines underneath, adds a space.
If you have VimRuby installed, I believe you can use % to jump between def and end. In that case, you could say
v%x5jpO
Edit: I defer to spatz on this :P
From line 1, 5ddGp , or 5dd:5p is the most concise/shortest I can think of.
personally, I would go '4dd' then down under bar and press 'p', but I'm not a vim guru

Resources