Merge line by line in vimdiff? - vim

while giving the dp command in vimdiff it replaces the entire block(2 lines) with pink colour on left hand side file to right hand side file.
In that block if i want to merge only the second line. First line should not be Merged.

You can just copy the part of the code you want to copy over using:
Hit the V key and then select just the text you want to move; and then hit yy to yank it.
Press CTRL+ww to switch windows, and then move your cursor to the desired location
Finally, press p to paste it in the desired location.

Go to the one line that you need to be overwritten:
:.diffget
Or just:
:.diffg
If you want to re-calculate the "pink areas" now:
:diffu
If the line is absent, it's best to hit O to add an empty line and then do a :.diffg
Just adding it as an answer, so people can vote on it. For me it works better (when bound to a key combo) than do or dp.

Related

Vim duplicate with same cursor position

I want to duplicate a line with Vim. Every time when I use yyp or any other command, I have to jump the cursor to the position where it was. Is there any trick to duplicate a line and jump the cursor to its position, like maybe using a macro to save current the cursor position, duplicate, and then jump to the required position?
The only solution I'd see to do what you want, given you only use it for yyp (i.e. copy currentline and paste it below), is to record in a macro:
mmyyp`mj
what that does is:
to record a mark m,
copy current line
paste it
jump to col+row location of the mark m
move the cursor one line down
ideally what you'd want is a jump to a column, not changing the row. I'm not sure if it's possible, I never needed that before.
Maybe you are looking for ctrl-o and ctrl-i to jump back and forth.

VIM to delete a range of lines into a register

I am trying to delete a range of lines into a register a. Is this the easiest way to achieve this?
:5,10d a
The definition of "easiest" depends on what do you have, and what do you want to do
if you have a start line number and end number, e.g.
:2349,5344d a
is the easiest way.
You don't have to consider the questions like
"where is my cursor?"
"how many lines would be removed?"
...
If you are about to remove a small amount of lines, particularly they are on same screen. (You could use relative-linenumber.) for example: "a5dd but you have to move your cursor to the first line you want to delete. And this could be done by option 1 too: 5:d a<CR> (vim will automatically translate it into .,.+5d a<CR>)
If you just know the 1st line of deletion, and find the last line you want to delete by reading your text, (of course, small amount of lines) you could press V, and press j by reading, when it reaches the deletion ending border, press "ad
If the "range" in your question is the "range" concept in vim, The first option would be better. since it could be 234,540, it could be 1;/foo, /foo/,/bar/... :h range see detail
so back to the first sentence in my answer, There is no absolutely easiest way. It all depends on what do you have, and what do you want to do.
The other way to achieve this would be to highlight the range of lines in visual line mode. (Shift-V)
Then type "ad while in visual line mode. This will put the deleted lines into the a register.
" followed by a register puts the next delete, yank or put into that register.
Below is the documentation for " (quote)
*quote*
"{a-zA-Z0-9.%#:-"} Use register {a-zA-Z0-9.%#:-"} for next delete, yank
or put (use uppercase character to append with
delete and yank) ({.%#:} only work with put).
Another example of deleting multiple lines and putting it in a register. To delete 6 lines and put them in a register you can got to the line and type "a6dd. This puts the 6 deleted lines into register a.

Placing characters at a specific column in vi

Is there a way to place a character at a specific line in vim, even if the line is short?
For example, I'm contributing to a project which has a comment block style which is 79 columns wide, with a comment character at either end e.g.
!--------------!
! Comment !
! More Comment !
!--------------!
but it's really annoying to space over to it, even with guessing large numbers (35i< SPACE>< ESC>)
Is there a simple command which will do this for me, or a macro or something I could write?
set ve=all
then you could move (h,j,k,l) to anywhere you want. no matter how short your line is.
there are 4 options block, all, insert, onemore for details:
check :h virtualedit
in this way, after you typed short comment, then type <ESC>080l to go to the right place to the tailing !
you can map it too, if it is often used
then it works like this:
Put this in your .vimrc file and restart vim:
inoremap <F1> <C-r>=repeat(' ', 79-virtcol('.'))<CR>!<CR>
With this just press F1 (or whatever key you map) in insert mode after entering comment text to automatically pad with spaces and insert a ! in column 79.
Another simple way is to keep an empty comment box of the correct size somewhere, yank/paste it where needed and just Replace the spaces in it with your comment each time.
If you want to reformat a box that is too short, one way is to start from the comment in your example, make a Visual Block (Ctrl+v) selecting the single column just to the left of its right-hand edge, yank it (y), then repeatedly paste it (p). This will successively move the entire right-hand side of the comment one step, extending the box rightward. Repeat until it has the desired length.
If you already entered the comment text, you can use a macro to add the right-hand ! mark at the correct place. For example, record a macro (qa) that appends more characters than are needed for any line (e.g. 80ASpaceEsc), then use the goto column (|) to go to the correct place (79|) and replace the excess characters from there (C!Esc), then move down one line (j), and stop recording (q). Repeating this macro (#a) then "fixes" each line in turn and moves to the next. In total: qa80A<space><esc>79|C!<esc>jq and then #a whenever needed. Sounds complex but is convenient once you have it.
There are certainly good answers here already, particularly the virtualedit answer. However, I don't see the method which seems most intuitive to me. I would create an empty line for the last row of the comment which is just surrounded by the exclamation points. Then I would yank and paste a new copy of the empty line, go to the old empty line and go to the point at which I want to edit and use overstrike mode (R) to add my text without affecting the placement of the ending exclamation point.
Sometimes the simplest methods, while slightly more clunky, are the easiest to use and remember.
I usually just copy and paste an existing line in the comment block (or copy one from another file) and then modify it. If the text you're replacing is about the same size as what you want to write (e.g., if you're changing the author's name), you probably only need to add or delete a few spaces to make everything line up. It's a lot less painful than spacing out to the desired width.
If you ever have a block that gets too long this way, a neat trick is to place the cursor on the 79th column and press dw. That will clear all spaces up to the ! at the end.
My AlignFromCursor plugin offers commands and mappings that align only the text to the right of the cursor, and keep the text to the left unmodified. So, with the cursor in the whitespace left of the trailing !, you can align it with <Leader>ri.

Vim: insert the same characters across multiple lines

Sometimes I want to edit a certain visual block of text across multiple lines.
For example, I would take a text that looks like this:
name
comment
phone
email
And make it look like this
vendor_name
vendor_comment
vendor_phone
vendor_email
Currently the way I would do it now is...
Select all 4 row lines of a block by pressing V and then j four times.
Indent with >.
Go back one letter with h.
Go to block visual mode with Ctrlv.
Select down four rows by pressing j four times. At this point you have selected a 4x1 visual blocks of whitespace (four rows and one column).
Press C. Notice this pretty much indented to the left by one column.
Type out a " vendor_" without the quote. Notice the extra space we had to put back.
Press Esc. This is one of the very few times I use Esc to get out of insert mode. Ctrlc would only edit the first line.
Repeat step 1.
Indent the other way with <.
I don't need to indent if there is at least one column of whitespace before the words. I wouldn't need the whitespace if I didn't have to clear the visual block with c.
But if I have to clear, then is there a way to do what I performed above without creating the needed whitespace with indentation?
Also why does editing multiple lines at once only work by exiting out of insert mode with Esc over Ctrlc?
Here is a more complicated example:
name = models.CharField( max_length = 135 )
comment = models.TextField( blank = True )
phone = models.CharField( max_length = 135, blank = True )
email = models.EmailField( blank = True )
to
name = models.whatever.CharField( max_length = 135 )
comment = models.whatever.TextField( blank = True )
phone = models.whatever.CharField( max_length = 135, blank = True )
email = models.whatever.EmailField( blank = True )
In this example I would perform the vertical visual block over the ., and then reinsert it back during insert mode, i.e., type .whatever.. Hopefully now you can see the drawback to this method. I am limited to only selecting a column of text that are all the same in a vertical position.
Move the cursor to the n in name.
Enter visual block mode (Ctrlv).
Press j three times (or 3j) to jump down by 3 lines; G (capital g) to jump to the last line
Press I (capital i).
Type in vendor_. Note: It will only update the screen in the first line - until Esc is pressed (6.), at which point all lines will be updated.
Press Esc.
An uppercase I must be used rather than a lowercase i, because the lowercase i is interpreted as the start of a text object, which is rather useful on its own, e.g. for selecting inside a tag block (it):
Another approach is to use the . (dot) command in combination with i.
Move the cursor where you want to start
Press i
Type in the prefix you want (e.g. vendor_)
Press esc.
Press j to go down a line
Type . to repeat the last edit, automatically inserting the prefix again
Alternate quickly between j and .
I find this technique is often faster than the visual block mode for small numbers of additions and has the added benefit that if you don't need to insert the text on every single line in a range you can easily skip them by pressing extra j's.
Note that for large number of contiguous additions, the block approach or macro will likely be superior.
Select the lines you want to modify using CtrlV.
Press:
I: Insert before what's selected.
A: Append after what's selected.
c: Replace what's selected.
Type the new text.
Press Esc to apply the changes to all selected lines.
I would use a macro to record my actions and would then repeat it.
Put your cursor on the first letter in name.
Hit qq to start recording into the q buffer.
Hit i to go into insert mode, type vector_, and then hit Esc to leave insert mode.
Now hit 0 to go back to the beginning of the line.
Now hit j to go down.
Now hit q again to stop recording.
You now have a nice macro.
Type 3#q to execute your macro three times to do the rest of the lines.
:%s/^/vendor_/
or am I missing something?
Updated January 2016
Whilst the accepted answer is a great solution, this is actually slightly fewer keystrokes, and scales better - based in principle on the accepted answer.
Move the cursor to the n in name.
Enter visual block mode (ctrlv).
Press 3j
Press I.
Type in vendor_.
Press esc.
Note, this has fewer keystrokes than the accepted answer provided (compare Step 3). We just count the number of j actions to perform.
If you have line numbers enabled (as illustrated above), and know the line number you wish to move to, then step 3 can be changed to #G where # is the wanted line number.
In our example above, this would be 4G. However when dealing with just a few line numbers an explicit count works well.
An alternative that can be more flexible:
Example: To enter the text XYZ at the beginning of the line
:%norm IXYZ
What's happening here?
% == Execute on every line
norm == Execute the following keys in normal mode (short for normal)
I == Insert at beginning of line
XYZ == The text you want to enter
Then you hit Enter, and it executes.
Specific to your request:
:%norm Ivendor_
You can also choose a particular range:
:2,4norm Ivendor_
Or execute over a selected visual range:
:'<,'>norm Ivendor_
Or execute for each line that matches a 'target' regex:
:%g/target/norm Ivendor_
I wanted to comment out a lot of lines in some config file on a server that only had vi (no nano), so visual method was cumbersome as well
Here's how i did that.
Open file vi file
Display line numbers :set number! or :set number
Then use the line numbers to replace start-of-line with "#", how?
:35,77s/^/#/
Note: the numbers are inclusive, lines from 35 to 77, both included will be modified.
To uncomment/undo that, simply use :35,77s/^#//
If you want to add a text word as a comment after every line of code, you can also use:
:35,77s/$/#test/ (for languages like Python)
:35,77s/;$/;\/\/test/ (for languages like Java)
credits/references:
https://unix.stackexchange.com/questions/84929/uncommenting-multiple-lines-of-code-specified-by-line-numbers-using-vi-or-vim
https://unix.stackexchange.com/questions/120615/how-to-comment-multiple-lines-at-once
You might also have a use case where you want to delete a block of text and replace it.
Like this
Hello World
Hello World
To
Hello Cool
Hello Cool
You can just visual block select "World" in both lines.
Type c for change - now you will be in insert mode.
Insert the stuff you want and hit escape.
Both get reflected vertically. It works just like 'I', except that it replaces the block with the new text instead of inserting it.
Suppose you have this file:
something
name
comment
phone
email
something else
and more ...
You want to add "vendor_" in front of "name", "comment", "phone", and "email", regardless of where they appear in the file.
:%s/\<\(name\|comment\|phone\|email\)\>/vendor_\1/gc
The c flag will prompt you for confirmation. You can drop that if you don't want the prompt.
Use Ctrl+V to enter visual block mode
Move Up/Down to select the columns of text in the lines you want to comment.
Then hit Shift+i and type the text you want to insert.
Then hit Esc, wait 1 second and the inserted text will appear on every line
Ctrl + v to go to visual block mode
Select the lines using the up and down arrow
Enter lowercase 3i (press lowercase I three times)
I (press capital I. That will take you into insert mode.)
Write the text you want to add
Esc
Press the down arrow
I came here to paste in many lines an already copied string. When copy with y we can paste, in the INSERT MODE, pressing Ctrl+r and right after press ''. This will have the same result as being in NORMAL MODE and press p. This is called paste from registry.
Suppose the following text in the buffer:
vendor_something
text
to_receive
the_paste
pattern
Then we can put the cursor pointing to v in vendor_ and press v, move to right using l until select the underscore symbol we want to paste in the text bellow. After that, we can point the cursor at the beginning of "text" (two lines bellow vendor_something) and press Ctrl+v. Then I to go into INSERT MODE where we press 3j Ctrl+r '' Esc. The result of this sequence will be:
vendor_something
vendor_text
vendor_to_receive
vendor_the_paste
vendor_pattern
:.,+3s/^/vendor_/
Another example, I needed to just add two spaces to a block of 125 lines, so I used (with cursor positioned at the beginning of the first line of the block):
:.,+125s/^/ /
Worked great.
If the change is required in the entire file,
:1,$s/^/vendor_/
If the change is required for only a few lines,
Go to the first line where change is required, and either give the command
:.,ns/^/vendor_/
Substitute n with the line number of the last line in the block.
Or,
:.,+ns/^/vendor_/
Substitute n with number of lines minus 1 in which the change is required.

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