Cut and paste multiple lines in vim - vim

I'm running vim 7.3 on a Mac 10.7.2 and I'm having some trouble cutting and pasting several lines.
On my old Linux setup (which was stolen so I don't know versions), I could type "dd" multiple times and then "p" would yank all of them back. For example: type: "dd dd" and two lines would be deleted. Now type "p" and both lines are pasted back into the buffer.
I know I can accomplish what I want by typing "2dd", and then "p" - but I would like to be able to "dd"-out lines without counting the number of lines ahead of time.
Any ideas?

Have you considered using visual mode?
You could just go:
Press V
Select everything you want to cut without counting
Press d
Go to where you want to paste
Press p
This should yield approximately half as many keystrokes as the dd method since you press one key per line rather than two. Bonus points if you use 5j (or similar) to select multiple lines at a time.

You could type:
d<n>d
where <n> is the number of lines that you want to cut, and then you could paste them with:
p
For example, to cut and paste 3 lines:
d3d
p

To cut and paste by line numbers (do :set number to see the line numbers), for lines x to y do:
:x,yd
or if your cursor is already on line x, do
:,yd
Then go to where you want to paste and press p

Not sure if this is close enough to what you're trying, but one thing you could do is use a specific register, and capitalize your register name. That tells vim to append to the register rather than replace it, so if you have the lines:
one
two
three
you can enter
"qdd
"Qdd
"Qdd
and then subsequently if you enter
"qp
it will paste back the original lines

To copy and paste 4 lines:
y4y (with the cursor on the starting line you wanna copy)
p (with cursor on the line you wanna paste after)

I agree with #Ben S. that this is the preferred way to accomplish this but if you are just looking to replicate your old behavior you can remap dd to append to a specified register, and then map p to paste from that register and clear it.
This will have the disadvantage of causing p to only work with things deleted using dd (using d} to delete to the end of the paragraph would not put the text in the correct register to be pasted later).
Add the following to your vimrc
noremap dd "Ddd "Appends the contents of the current line into register d
noremap p "dp:let #d=""<CR> "Pastes from register d and then clears it out
if you don't want pasting to clear out the contents of the register
noremap p "dp "Paste from register d
but this will cause that register to grow without ever clearing it out

Related

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

vi/vim editor, copy a block (not usual action)

In vi/vim editor, I need to copy a block. There are many ways, but one way is very quick.
label the first line by some way,
then label the end line by some way,
then put some command to copy the labeled lines.
then copy, may using 'p', but not sure.
Anybody know the commands (not yy or 10yy)?
just use V to select lines or v to select chars or Ctrlv to select a block.
When the selection spans the area you'd like to copy just hit y and use p to paste it anywhere you like...
Their Documentation says:
Cut and paste:
Position the cursor where you want to begin cutting.
Press v to select characters (or uppercase V to select whole lines).
Move the cursor to the end of what you want to cut.
Press d to cut (or y to copy).
Move to where you would like to paste.
Press P to paste before the cursor, or p to paste after.
Copy and paste is performed with the same steps except for step 4 where you would press y instead of d:
d = delete = cut
y = yank = copy
Another option which may be easier to remember would be to place marks on the two lines with ma and mb, then run :'a,'byank.
Many different ways to accomplish this task, just offering another.
I found the below command much more convenient. If you want to copy lines from 6 to 12 and paste from the current cursor position.
:6,12 co .
If you want to copy lines from 6 to 12 and paste from 100th line.
:6,12t100
Source: https://www.reddit.com/r/vim/comments/8i6vbd/efficient_ways_of_copying_few_lines/
It sounds like you want to place marks in the file.
mx places a mark named x under the cursor
y'x yanks everything between the cursor's current position and the line containing mark x.
You can use 'x to simply move the cursor to the line with your mark.
You can use `x (a back-tick) to move to the exact location of the mark.
One thing I do all the time is yank everything between the cursor and mark x into the clipboard.
You can do that like this:
"+y'x
NOTE: In some environments the clipboard buffer is represented by a * in stead of a +.
Similar questions with some good answers:
How to copy/paste text from vi to different applications
How to paste from buffer in ex mode of vim?
Keyboard shortcuts to that are:
For copy: Place cursor on starting of block and press md and then goto end of block and press y'd. This will select the block to paste it press p
For cut: Place cursor on starting of block and press ma and then goto end of block and press d'a. This will select the block to paste it press p
You can do it as you do in vi, for example to yank lines from 3020 to the end, execute this command (write the block to a file):
:3020,$ w /tmp/yank
And to write this block in another line/file, go to the desired position and execute next command (insert file written before):
:r /tmp/yank
(Reminder: don't forget to remove file: /tmp/yank)

How can I highlight multiple lines in gVim without using the mouse?

Vim noob here. I am trying to select multiple lines of code to copy and paste in other areas. Is there a way to do this without using the mouse?
A few other ways that don't use visual mode at all:
using marks
leave a mark somewhere with ma
move somewhere else
yank from here to there with y'a
using search motions
localize some unique token at the end of the part you want to yank
yank from here to there with y/foo<cr> (forward search) or y?bar<cr> (backward search)
using text-objects
determine what text-object would map to what you want to yank:
inner/outer word, iw/aw
inner/outer pair, i'"([{</a'"([{<
inner/outer html tag, it/at
sentence, s
paragraph, p
"block", ]
…
yank that text-object with, say, yip
using other motions
yank to end of function: y]}
yank to end of file: yG
all of the above solutions with visual mode
V'ay
V/foo<cr>y
V?bar<cr>y
Vipy, etc.
V]}y
VGy
:h motion.txt will hopefully blow your mind, like it did to mine.
You can place your cursor in the first line you want to copy and then type nyy where n is the number of lines you want to copy. For example, type 2yy to copy the two lines under the cursor.
Then, you can paste them using p.
You can also select multiple lines by placing your cursor somewhere and keeping Shift pressed. Move your cursor to the end of the desired selection and stop pressing Shift. Then copy using just y (and not yy) and paste with p.
Yep, in normal mode type V[direction] and you will highlight multiple lines. If you don't want whole lines, use v instead of V. To copy it, hit y and move to the area which you want to paste in and hit p. To delete it, instead of y use x.
Alternatively, you can simply use [number of lines]yy to yank some number of lines or [number of lines]dd to cut some number of lines. In this case pasting is the same.

How to insert a block of white spaces starting at the cursor position in vi?

Suppose I have the piece of text below with the cursor staying at the first A currently,
AAAA
BBB
CC
D
How can I add spaces in front of each line to make it like, and it would be great if the number of columns of spaces can be specified on-the-fly, e.g., two here.
AAAA
BBB
CC
D
I would imagine there is a way to do it quickly in visual mode, but any ideas?
Currently I'm copying the first column of text in visual mode twice, and replace the entire two column to spaces, which involves > 5 keystrokes, too cumbersome.
Constraint:
Sorry that I didn't state the question clearly and might create some confusions.
The target is only part of a larger file, so it would be great if the number of rows and columns starting from the first A can be specified.
Edit:
Thank both #DeepYellow and #Johnsyweb, apparently >} and >ap are all great tips that I was not aware of, and they both could be valid answers before I clarified on the specific requirement for the answer to my question, but in any case, #luser droog 's answer stands out as the only viable answer. Thank you everyone!
I'd use :%s/^/ /
You could also specify a range of lines :10,15s/^/ /
Or a relative range :.,+5s/^/ /
Or use regular expressions for the locations :/A/,/D/>.
For copying code to paste on SO, I usually use sed from the terminal sed 's/^/ /' filename
Shortcut
I just learned a new trick for this. You enter visual mode v, select the region (with regular movement commands), then hit : which gives you this:
:'<,'>
ready for you to type just the command part of the above commands, the marks '< and '> being automatically set to the bounds of the visual selection.
To select and indent the current paragraph:
vip>
or
vip:>
followed by enter.
Edit:
As requested in the comments, you can also add spaces to the middle of a line using a regex quantifier \{n} on the any meta-character ..
:%s/^.\{14}/& /
This adds a space 14 chars from the left on each line. Of course % could be replaced by any of the above options for specifying the range of an ex command.
When on the first A, I'd go in block visual mode ctrl-v, select the lines you want to modify, press I (insert mode with capital i), and apply any changes I want for the first line. Leaving visual mode esc will apply all changes on the first line to all lines.
Probably not the most efficient on number of key-strokes, but gives you all the freedom you want before leaving visual mode. I don't like it when I have to specify by hand the line and column range in a regex command.
I'd use >}.
Where...
>: Shifts right and
}: means until the end of the paragraph
Hope this helps.
Ctrl + v (to enter in visual mode)
Use the arrow keys to select the lines
Shift + i (takes you to insert mode)
Hit space keys or whatever you want to type in front of the selected lines.
Save the changes (Use :w) and now you will see the changes in all the selected lines.
I would do like Nigu. Another solution is to use :normal:
<S-v> to enter VISUAL-LINE mode
3j or jjj or /D<CR> to select the lines
:norm I<Space><Space>, the correct range ('<,'>) being inserted automatically
:normal is probably a bit overkill for this specific case but sometimes you may want to perform a bunch of complex operations on a range of lines.
You can select the lines in visual mode, and type >. This assumes that you've set your tabs up to insert spaces, e.g.:
setl expandtab
setl shiftwidth=4
setl tabstop=4
(replace 4 with your preference in indentation)
If the lines form a paragraph, >ap in normal mode will shift the whole paragraph above and below the current position.
Let's assume you want to shift a block of code:
setup the count of spaces used by each shift command, :set shiftwidth=1, default is 8.
press Ctrl+v in appropriate place and move cursor up k or down j to select some area.
press > to shift the block and . to repeat the action until desired position (if cursor is missed, turn back with h or b).
Another thing you could try is a macro. If you do not know already, you start a macro with q and select the register to save the macro... so to save your macro in register a you would type qa in normal mode.
At the bottom there should be something that says recording. Now just do your movement as you would like.
So in this case you wanted 2 spaces in front of every line, so with your cursor already at the beginning of the first line, go into insert mode, and hit space twice. Now hit escape to go to normal mode, then down to the next line, then to the beginning of that line, and press q. This ends and saves the macro
(so that it is all in one place, this is the full list of key combinations you would do, where <esc> is when you press the escape key, and <space> is where you hit the space bar: qai<space><space><esc>j0q This saves the macro in register a )
Now to play the macro back you do # followed by the register you saved it in... so in this example #a. Now the second line will also have 2 spaces in front of them.
Macros can also run multiple times, so if I did 3#a the macro would run 3 times, and you would be done with this.
I like using macros for this like this because it is more intuitive to me, because I can do exactly what I want it to do, and just replay it multiple times.
I was looking for similar solution, and use this variation
VG:norm[N]I
N = numbers of spaces to insert.
V=Crtl-V
*** Notice *** put space immediate after I.

How do I select a chunk of text and paste it to the current cursor position w/o using mouse in vim?

I want to give up using mouse for selecting and pasting chunks of text within a buffer. Whats the most efficient way to do this with just kb? I mean navigate to arbitrary line, copy the substring, return to the previous position and paste.
Very simple method:
Select the lines with Shift-V
"Yank" (=copy) the text with y
Paste the text with p at the position you want to.
There are of course many other ways to copy and paste, yy copies the current line for example.
Do the some VIM tutorials, it is better than learning everything bit by bit.
If you want to go quickly to a line use the search by typing
/SUBSTRING and then Enter after you have found the correct substring.
Make sure to use hlsearch and incsearch
:set incsearch and :set hlsearch
When you are at the correct line, yank the whole line with yy or the whole word with yaw.
Then go back to where you started the search by typing two backticks ``
Then you can paste your yanked line/string with p
Mark your current position by typing ma (you can use any other letter instead of a, this is just a "named position register".
navigate to the line and substring for example by using a / search
yank text with y<movement> or mark it with shift/ctrl-v and then y
move back to your previously marked position with ```a`` (backtick)
paste your buffer with p or P
My normal method would be:
Use visual mode to select the text with v, V, or Ctrl+v
Yank using y
Go to the line you want to be on using 123G or :123
Navigate where I want to be within that line with t or f
Put the text with p or P
If you need to jump back and forth between the spots, I'd cycle through jumps using g, and g;.
Use "p" to paste after the current line, and "P" to paste above the current line.
Not sure what you mean by 'the substring'. If you want to copy line 50 to the current position, use:
:50t.
If you want to move line 50 to the current cursor position, use:
:50m.

Resources