column copy and paste in row - vim

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...

Related

Copy block of code with increasing index

I have the following function declaration:
function f1(s)
real f1,s
f1 = 1/s
end
I would like to copy the same block but with increasing function name, i.e. f1, f2, f3, ... in order to get this:
function f1(s)
real f1,s
f1 = 1/s
end
function f2(s)
real f2,s
f2 = 1/s
end
function f3(s)
real f3,s
f3 = 1/s
end
My present approach is to copy the block in visual mode, paste it several times and then rename the functions manually. I would like to know how to achieve this faster using Vim. Thanks.
You can always use a recording (see :h recording). Assuming you have a blank line before and after your function and no blank lines in between
// empty line here, cursor here
function f1(s)
real f1,s
f1 = 1/s
end
// empty line here
With the cursor on the empty line above, make a recording to any register you like. Here I'm using register c. Press qc then press y}}Pjw*Ne^Ane^Ane^A{ and exit with q.
Explanation
y} - yank next paragraph
} - move down one paragraph
P - put above this line
j - move one line done
w - move to next word
* - search for word under cursor ( this is the function name here)
N - search backwards ( we moved with * to get the pattern into the register )
e - go to end of word
^A - Ctrl a to increase the number
n - go to next match / search forward ( this is the function name )
e - go to end of word
^A - increase the number
n - go to next match / search forward
e - go to end of word
^A - increase the number
{ - move up one paragraph (same relative position as in the beginning, but at the inserted function f2 )
Now you can use #c to copy the function and increase all numbers. Prefix with the count you want, e.g. 5#c will copy the function 5 times and adjust the numbering.
In case you don't want to remember the string y}}Pjw*Ne^Ane^Ane^A{ you can paste it in the vim buffer. You will have to replace the ^A before yanking though. Delete ^A and when in insert mode press Ctrl va. ( If you are inside a screen session you will have to press Ctrl aa, this is CTRL-a and a)
With the cursor on the line in normal mode press "cY to yank it in register c.
Then you can replay it with #c.
This way you can also modify it or yank it to another register.
Use let #c=y}}Pjw*Ne^Ane^Ane^A{ in your .vimrc to have it always load to register c when starting vim.
I figured out the solution. It may seems complex but does not, cause you have just to copy this function to the clipboard and load the function with:
:#+
Below the function with additional features
fun! CopyAndIncrease()
try
let l:old_copy = getreg('0')
normal yip
let #0 = substitute(#0,'\d\+','\=submatch(0) + 1','g')
exec "normal }O\<Esc>p"
finally
call setreg('0', l:old_copy)
endtry
endfun
command! -nargs=0 CopyIncrease silent call CopyAndIncrease() | exec "normal \<Esc>"
let mapleader = ','
nnoremap <Leader>c :CopyIncrease<CR>
Now pressing ,c Now you can use the keybinding and commands defined in the function.
Function's explanation:
let l:old_copy = getreg('0') -> save copy register
normal yip -> copy block
let #0 ... increase numbers on copy register
exec "normal }O\<Esc>p" -> paste increased block

Way to remove two non-consecutive lines in vim

Is there a way to remove two non-consecutive lines with a single vim command (which could be undone in a single step).
I have file like this:
if (enabled) {
const a = 1;
const b = 2;
console.log(a + b);
}
And would like to end up with this:
const a = 1;
const b = 2;
console.log(a + b);
Use visual mode and paste over the whole block.
yiBvaBVp
Vimcasts episode: Pasting from Visual mode
For more help see:
:h iB
:h aB
:h v_p
If you select your example (with v$% for instance), then
:'<,'>g/{\|}/d
will give you what you want (if there are no nested { or }).
Another way would be to record a macro, something like
# qa to start recording, the final q to stop. ^O is <Ctrl-o>
qaf{%dd^Oddq
then use it with #a.
Edit: more general solution (still using visual mode though):
You could add a mapping:
:xnoremap <leader>d <esc>:'<d \| '>d<cr>
to delete the first and last line of the last visual selection.

In Vim, paste over text between two parenthesis?

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(

How cut and paste in the line in Vim editor?

I'm tring to copy c = getchar() to c! ^ =EOF.
I tried shift+v & p, the code will appear right above the line, not in the line.
What should I do?
#include <stdio.h>
main()
{
int c;
c = getchar()
while (c != EOF {
putchar(c);
}
}
#include <stdio.h>
main()
{
int c;
while (c = getchar()!= EOF) {
putchar(c);
}
}
When you yank the c = getchar() line, the register is in linewise mode, so any pastes will also create a new line. My UnconditionalPaste plugin has mappings like gcp that force e.g. a characterwise paste. With that, you can insert the line after the while( statement, and have it stay in the same line.
But actually, you probably want to replace the c after the while( with the yanked text. For that, another of my plugins, the ReplaceWithRegister plugin comes handy. With it, you can either visually select the c or address it through a motion l, and use the plugin's gr mapping to replace the covered text with the register contents (again, sticking to the same line, so you only have to deal with the superfluous indent).
Place your cursor on the line you want to yank.
If you are not on the c, hit ^.
Cut until the end of line with d$.
Move to where you want to put. With /c, for example.
Enter visual mode and put, with vlp.
I usually do this kind of work with operations in movements over the same line with f and F. So I would do:
:20
to go to the line of c = getchar()!= EOF
fcdf)
to put cursor in first c letter and cut until next ) character.
:7
go to seventh line, and
f(p
to go to first ( character and paste.

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 & =/

Resources