Avoid extra whitespace when pasting vertical selection - vim

I often need to copy larger vertical selections e.g. when working with
(let's stay civilized) "getter/setter"-rich interfaces, e.g
A very long line with something I would like to copy: ABC$
A short line with nothing$
A very long line with something I would like to copy: ABC$
Here I have used $ to indicated the end of the line. I now make a visual
vertical selection on e.g. the A in the column 55 across all lines, yank it
and paste it with P before that column and get extra whitespace inserted in
the second line.
A very long line with something I would like to copy: AABC$
A short line with nothing $
A very long line with something I would like to copy: AABC$
Is there a way to avoid the extra whitespace? Changing characters in the vertical visual
selection doesn't seem to suffer from this issue.

This is how visual-block move works. You are copying column 55. Then pasting with P. Your second line does not extend as far as column 55. So when you paste it will extend that line for you.
Use :reg to look at your register. You will noticed A^J ^JA as the value for "", the unnamed register. The ^J symbolize line breaks. Notice the space between ^J's. This is how a visual-block mode yank works with empty space, by filling it in with spaces.

Related

vim, duplicate whole line to the end of each line?

How to copy the current line content to the end of each line for the whole file ?
For example:
From
hello
world
!
To
hello hello
world world
! !
Handling text in columns is what Visual-Block mode is made for!
You can create a blockwise Visual selection for all your text with:
gg to go to the Top; then
Ctrl+V to start Visual Block mode. (You might see -- VISUAL BLOCK -- at the last line of the screen.)
G to go to the last line of the buffer.
$ to select until the end of each line. This is pretty important! Since lines might have different number of characters, the $ behaves in a special way, in that instead of forcing a rectangle format to the selection, it extends it to the longest line, whatever number of columns it has.
Once you got everything selected in a Visual Block, you can use y to yank it into the unnamed register.
At that point, when you put it, it will come back as a block, as a column.
Go back to the first line, using gg, then append a certain number of spaces to get you to the column where you want your second copy to appear. For example, for 20 spaces, you can use 20A then Space and Esc.
At that point, you can go to the end of that line with $ and simply put with p. Sine the register was yanked in Visual Block mode, Vim will remember that and put the contents as a column. Lines that need to be extended with spaces to make it to allow for the pasted text to start in the later column will get extended automatically.
Also useful (with the Visual Block mode) is the 'virtualedit' option, which lets you navigate the cursor past the end of lines. If you enable it with :set virtualedit=all, then you can skip the part about adding enough spaces to the first line, since you can simply navigate to the appropriate column and the act of pasting the Visual Block contents with p will extend the first line with spaces as well.
:%s/^\(.*\)$/\1 \1
% - whole file
s/^\(.*\)$ - match line from the beginning to end
/\1 \1 - replace it with matched text two times.
There may be a problem with formatting those lines in columns.
Here is an example:
hello hello
hello hello
world world
! !
This can be solved with addition of trailing spaces, the the shorter lines, like this: (. - denotes trailing space)
hello hello
hello hello
world world
!.... !....
As mentioned by #mattb in the comment, column formatting issue can be fixed with column command (it has to be on your PATH though):
:%s/^\(.*\)$/\1 \1/ | %!column -t

How to append each line from 11-20 to each line from 1-10 in VIM

I have a file in which first 10 lines are the columns of a table and the rest 10 lines are the values of each column.
How can I use norm in VIM to append the values after each column names like this:
column1
...
column10
value1
...value10
-->
column1: value1
...
column10: value10
It is a little similar with this(Vim - Copy Nth word of each line, from line 10-100, to end of line), but I don't know how to go to line 1:10 and append the copied lines.
Any idea will be appreciated!
Fairly naive and crude way to do this, but:
:1,10norm! 10j0d$10kA: ^[p
Explanation:
1,10norm!: for lines 1 to 10, do the following (the ! means any custom mapping you have will be ignored, thanks to D. Ben Knoble for reminding of this):
10j: move down 10 lines
0d$: delete the whole line (not including newline)
10k: move back up 10 lines
A:: append (at the end of the line) ': ' (note the trailing space)
^[: input escape character, going back to normal mode. This (^[) is a single character and is inputted by typing Ctrl-v then escape, not by typing ^[.
p: paste the line deleted in step 3
Another (copy-pastable) way, (ab)using the substitute command:
:1,10s/\v(.*)\ze(.*\n){10}(.*)/\1: \3/ | 11,20d
which does:
1,10s/: for lines 1 to 10, execute the following substitution:
\v: use very-magic regex mode (see :help \v)
(.*): capture the entire current line (eg column1)
\ze: signal the end of the match. This way everything read (and captured) afterwards will not be affected (but can still be read)
(.*\n){10}: skip 10 (including current) lines, ie skip selector to 10 lines below
(.*): capture the line (eg value1)
/: end the 'select' part of the substitute command
\1: \3: replace with captured groups (eg column1: value1)
|: command separator
11,20d: delete lines 11 to 20
Use blockwise-visual mode to perform the operations.
You can enter visual block mode with Ctrl-V and it allows you to select and operate on columns. It also allows you to perform the same action on a block, which you can use to add the : to the lines with the column names.
I'll use normal Vim syntax for keystrokes in my examples, <C-v> means Ctrl-V.
Start by deleting the values into the default register, using a visual block:
11G<C-v>9j$d
Then Add the : to the column lines, also using a visual block:
1G<C-v>9j$A: <Esc>
Then add some more spaces to the first line, to ensure there's room for all the column names to fit:
A <Esc>
Finally, put the visual block at the end of the first line:
$p
It will actually put it on all lines all the way to the end.
This is slightly different from what you specified, since the values are all aligned on the same column. If you want different spacing, you can perhaps use a :s operation to fix spacing.
10:s/: */: /<cr>
Depending on where you pasted (if some column names had more trailing spaces than the first one), you might have some trailing spaces after the pasted values to fix as well, but that should be easy to do using a similar procedure.
Visual block operations are really powerful, it's a great feature to learn and keep in your "toolbox" in Vim. They're really handy with this kind of problem where thinking in "columns" makes the most sense.

vim: copy and paste text without looking into the line number

For example, I want to copy the line 5~15 and paste it in another place. I find several methods:
Move your cursor to the line 5, then 11yy, and p
Command: 5,15y and p
Ctrl + V, select the block within line 5~15, then go the place you want to paste in, leave enough blank lines for pasting(or it would be overlap with the current text), and p
I'm not satisfied with any of these methods, for method 1 and 2, I would have to bother to see the line number or count how many lines I want to copy, when the text covers many lines, it becomes quite tricky. For method 3, I would have to allow enough space ahead, which also acquires me to count the lines I want to paste. So is there any method that is just like method 3, only that I don't need to leave enough space beforehand?
EDIT: Method 2, the original 5,15yy is wrong. Has been corrected.
When you want to copy entire lines, use linewise visual mode, entered via V. With this, the register contents will shift existing lines automatically when pasted, unlike the blockwise selection you've used via <C-V>.
You can also use :put to paste as whole lines (even if you've (mistakenly) make a blockwise selection). For more such tricks and handy mappings, there's my UnconditionalPaste plugin.
A method similar to your 3. would be:
Go to Line-5, then V15Gy or V10jy or Vjjj...jy (V is Visual Mode linewise. You can see your selected lines without bodhering about the line numbers)
Go to Line-40(or somewhere else) and p. That would put the yanked lines after Line-40. Or use P to put it before Line-40.
Or you can use the Ex-command :t (the same as :copy but shorter)
:5,15t 40

In vim, how do I paste a column of text to the end of irregular length lines?

I would like to paste a column of text at the end of irregular-length lines.
For example, I would like to paste the following:
SRR447882.fastq.gz
SRR447883.fastq.gz
SRR447944.fastq.gz
at the end of these lines:
TIL01_
TIL01_
TIL04-TIP285_
Many times in the past, I simply create enough space on the first line that pasting will not come before the end of the existing text in the longest line. But then I need to go back and remove whitespace.
I have tried googling "vim column paste irregular length rows" and similar queries.
You could try to do the following four steps:
block-wise select the first 3 lines (you want to paste later), and press y
line-wise select (V) the 3 lines ending with _, press :right
then move cursor to the end of the first line($), paste the yanked text
gv re-select the lines, press :left
It looks like this:
You can do it like this:
Start on the first line of the second block
qq, start recording the q macro
4k, go up four lines
d$, delete till the end of line
4j, go back to the previous line
$p, paste the line at the end of the line
q, stop recording the macro
jVG, go down one line and select the remaining lines
:norm! #q, apply the macro to the selection
It does however leave space where the previous text was. #Kent one's is still easier.
My UnconditionalPaste plugin has (among others) gBp / gBP mappings that paste register contents as a minimal fitting (not rectangular) block with a jagged right edge.
demo
Step 1 - goto to the start of the SPP... lines, then start Visual mode linewise with V (capital V), press j two times to get the desired lines selected then press y.
Step 2 - goto the start of the TIL0... lines, then start Visual mode linewise with V (capital V), press j two times to get the desired lines selected then type...
:s;$;\=' ' . split(#")[line('.')-line("'<")];g`
and press Enter.
Here's another way to do it with a different feel to it:
set ve=all to permit insert/paste at arbitrary columns past eol. Block-copy your source text, then at your first target line paste it with 100|P (100 being any column number longer than your target lines), then :'[,']s, *\%100c,,
If you do p instead of P you'll get a space separator.

Difference between cutting lines with 10dd and d9 in vim?

If I understand correctly both commands cut 10 lines and allow you to paste them anywhere.
Are they both the same as (n-1)dd and dn+enter where n is the number of lines to be cut?
The two relevant help section are copied below.
d
["x]d{motion} Delete text that {motion} moves over [into register
x]. See below for exceptions.
dd
["x]dd Delete [count] lines [into register x] linewise.
10dd is the second one which deletes 10 lines from you current position.
d9 does nothing. d9j (or d9<CR>) is delete from the cursor to where the cursor ends up (which is9j) is nine lines below the current one. However the j or <CR> makes it linewise so the same thing is deleted.
Both of these commands delete 10 lines. so ndd is equivalent to d(n-1)j.
d9j might be easier to type than 10dd if you have set relativenumber turned on because the difference between the line you are on and the line you want to delete to are on the left hand side of your screen.
You can use d9k to delete 10 lines up from your cursor line which you can't do with dd. Or you can use dfa to delete upto and including the next a. d{motion} is more powerful than dd because it isn't restricted to only linewise deletions.
Which one you use is up to you but certain combinations are easier depending on where your cursor is.

Resources