How to replace the whole line with the text in the buffer in VIM? - vim

Here is the text I'm working on:
line1: website = "a.com";
...
line3: website = "b.com";
...
line5: website = "c.com";
Suppose I want to change all website to "stackoverflow.com", I can do:
- change "a.com" to "stackoverflow.com"
- yank the whole line (Y)
- go to line3, hit p, k, dd to paste from buffer and delete the old "b.com" line.
Now the problem is that since dd puts the "b.com" into the buffer, to replace line5 I'll have to yank the whole line again.
Is there any simple way so that I can replace line3 and line5 with the already yanked line quickly?
UPDATE:
Thanks for the answers, now there are several ways doing it: delete to black hole, yank from named buffer, etc. I found this being my favorite method ( I use key R instead r as sometime I need to replace a single character):
In Vim is there a way to delete without putting text in the register?
I put some links to similar SO questions below:
How to Delete (desired text), delete (undesired text), and paste (desired text) in Vim
In Vim is there a way to delete without putting text in the register?

First things first
You can go one better by not needing to explicitly delete the line:
yank the whole line into register x: "xY
go to the next line to replace
visually select the whole line: V
paste over the selection from register x: "xp
Now the deleted line is in register ", as always, but the yanked line is still in register x, so you can repeat steps 2 through 4 without having to yank over and over.
Repeated things repeated
Unfortunately you cannot use . to repeat steps 3+4. So if you have to do this for a lot of lines, insert a few more steps to record a macro:
yank the whole line into a register x: "xY
go to the next line to replace
record a macro into the w register: qw
visually select the whole line: V
paste over the selection from register x: "xp
stop recording: q
go to the next line to replace
replay the macro recorded into w: #w
go to the next line to replace
and now finally, you can replay same-as-last-time: ##
Then you can simply repeat steps 9 and 10 for the next 50 lines you need to replace.
Last (repeated) things last
In fact, if you find the next line by searching, then you should use that search to go to the first line as well. Because then the n that you use to go to the next line can be included as part of the macro – basically you just swap steps 6 and 7.
Then you don’t have to manually go to the next line to replace at all, because the macro will send you there as the last thing it does. You can just keep hitting ##, along with any occasional ns whenever you happen to want to skip a particular match.
References
help "
help registers
help complex-repeat

You can use named buffers for this instead of the default unnamed buffer: "lY then "lp to yank resp. paste from register l, then let the dd use the default buffer.

This is not an answer to your question as put but it is an answer to your real question, I think.
Technique 1: Are you aware of :s? If you are just wanting to replace all matches, you could do something like this:
:%s/^website = "\zs.*\ze\.com";$/stackoverflow/
As you haven't specified precise format of it all and whether or not you are wanting to replace all or only some, I can't say whether this is what you want or not.
Technique 1b: Even if you only want to replace some, there's a useful and not terribly widely known flag for :s: c, "confirm". (See :help :s_flags and more specifically :help :s_c.) Then you can decide with each one whether you want to replace it or not.
:%s/^website = "\zs.*\ze\.com";$/stackoverflow/c
Technique 2: You could also search, replace and then repeat. /^website = "\zs.*\ze\.com";$, then cwstackoverflowEsc to replace the word with "stackoverflow". Then n to go to the next match and if you want to replace it with "stackoverflow", use ..

Rereading this question I think this is closer to what you're after:
In Vim is there a way to delete without putting text in the register?
E.g. instead of using dd use "_dd

The "0 register always contain your last yanked text. Then you can do:
change "a.com" to "stackoverflow.com"
yank the whole line (Y)
go to line3, hit "0p, k, dd to paste from buffer and delete the old "b.com" line.
go to line5, hit "0p, k, dd to paste from buffer and delete the old "c.com" line.

ci" - change inside the ""
ctrl-r 0 - put default register
jj - move down two lines
. - repeat last command
jj
.

Related

How to select the similar text in gvim and modify them?

How I can select all the text start with foo_list starting from line 4 (see. below code) and rename them with list_values or any other preferred name ? Please note, I don't want to change in the first line.
Thanks in advance !
foo_list = [5, 2, 3, 1, 4]
def reverse_list_1():
foo_list=[0,10,20,40]
for i in reversed(foo_list):
print i,
foo_list=[0,10,20,40]
print foo_list[::-1]
for i in reversed(foo_list):
print i,
length = len(foo_list)
for i in range(length):
print foo_list[length-i-1],
Preferable solution: key map in the .vimrc or .gvimrc file, don't want to use any plugin.
That's a job for :substitute. You can specify the range with explicit line numbers (here: 4 to end of buffer $, or maybe next empty line /^$/):
:4,$substitute/\<foo_list\>/list_values/g
You can also first move to the first line and use the .,$ range.
Since that's still a lot of typing, you can pull in the current word (assuming you first position the cursor on the foo_list occurrence in line 4) into the command line via <C-R><C-W>.
Or, for a plugin solution, my ChangeGlobally plugin provides a mapping that avoids the use of :s.
:%s/foo_list/list_values/gc
This command says to replace the word foo_list with list_values in the whole document, asking for confirmation each time. Then for the first occurrence of foo_list on line 1, press n (to indicate NO) , and press y (to indicate YES) for all further occurrences to replace them. This solution works when you have to replace a few words. You can read the command as follows:
In the whole document (%), substitute (s) the word foo_list with list_values and do this globally (g), asking for confirmation (c) each time. For more options in the substitute command type :help :s in vim.
Solution 2 :
When there are thousands of words to replace, you surely don't want to type a y/n confirmation each time (which is enabled by the c flag in the end in the above command).
Take your cursor to line 4 and run
:.,$s/foo_list/list_values/g
Read the above command as from here (.) to the end of file (,$)
replace (s) the word foo_list with list_values
globally (g).
For small changes like this I like to use the gn motion. The gn motion visually selects the current search pattern. This makes for a powerful search/replace method when combining the gn motion with the change, c, operator and the repeat command, ..
Basic steps:
Make foo_list your search pattern. e.g. /foo_list or via *
Use c and gn to change the first foo_list. e.g. cgnbar_list<esc>
Now repeat that change on the next search result via .
Use n to advance to the next search results. (Hit n twice to skip an occurrence)
Keep using n and . until done
There is a nice Vimcasts episode on this topic: Operating on search matches using gn
For more information see:
:h gn
:substitute is the 'correct' way, but if you're only making a few changes, and you are not very experienced with ex commands, sometimes it takes longer to think through the command than to bounce through the list of changes you want to make using motions.
If you start with your cursor on the first instance of foo_list, hit '*' to jump to the next occurrence in the file. Hit 'ce' to delete to the end of the word and enter insert mode. Type in your new variable name and return to normal mode. Now you can jump through the rest of the file using 'n' to jump to the next occurrence (or 'N' to go back), and '.' to repeat your last edit action.

VIM Select Entire Line

How do you select a single line in VIM, when your cursor as at some random point along that line?
I know you can do (v, $) to get to the end of the line, or (v, ^) to get to the start, but when you do (v,$,^) it logically doesn't select the whole line, it selects from cursor, until end, then switches it to cursor until beginning... So this approach fails of course.
Capital V selects the current line in one key stroke; two, if you include the "shift" in shift+v.
V would be direct answer. However, I rarely need to do this because "selecting the current line" is generally part of a larger task. Example of such tasks includes copying the line and deleting the line. There's generally a better way to accomplish the task as a whole. The following are some of the tasks I can think of:
copy the line: yy
delete the line: dd
indent the line: >> or <<
select the current paragraph: vap or vip
delete from the current line to the end of the file 0dG
highlight the current line to see where my cursor is: use :set cursorline in .vimrc file
One case in which I do use V is to select multiple lines that are not a paragraph or some other text object. In this case, there's a tip that might be useful for you: once in the selection mode, you can use o to jump the cursor between the start and the end of the selection.
While this might be more keystrokes.
If you are already in visual mode you can use o to go to the other end of the visual selection.
So you can type
v0o$
To select the whole line. Take a look at :h visual-change
However from the comments it seems you just want to copy the whole line.
Which would just be yy
Just change your order of operations. You almost have it.
^,v,$
Or as suggested by #Kent: because ^ goes to the first non-empty char, if the line has leading spaces:
0,v,$
I know this thread is super old, but I just had the same question. This thread came up first, but I found a different answer than any found here. Use 'V' to select whole lines. That easy. One character to select the whole current line.

What is the best way to refactor a Ruby ‘if’ statement into one-line shorthand form in Vim?

I have the following Ruby code:
if some_cond && another
foo_bar
end
and I want to change it to:
foo_bar if some_cond && another
What are the most idiomatic ways to do that in Vim?
Assuming that the cursor is located at the if-line prior to
refactoring (not necessarily at the beginning of that line),
I would use the following sequence of Normal-mode commands:
ddjVpkJ<<
or this chain of Ex commands:
:m+|-j|<|+d
Here the if-line is first moved down one line by the :move + command.
The :move command cuts a given range of lines (the current line, if
not specified) and pastes it below the line addressed by the argument.
The + address is a shorthand for .+1 referring to the next line
(see :help {address}).
Second, the line containing the body of the conditional statement is
joined with the just moved if-line. The :join command concatenates
a given range of lines into a single line. The - range is a shortened
form of the .-1 address referring to the line just above the cursor
(see :help {address}).
Third, the newly joined line is unindented by one shiftwidth using
the :< command.
Finally, the remaining end-line, which can now be addressed as +,
is removed by the :delete command.
I see few (probably non-optimal) solutions:
cursor in first character in first line:
D - remove if condition but leave cursor in same position (don't delete line)
J - join next line to current
A <Space> <ESC> - append space and exit to Normal mode
p - paste if condition
and then remove remaining end with jdd
cursor in first character in first line, as previously:
j - move to next line
dd - remove this line
k - move back to if condition
P - paste removed line before actual line, cursor should be placed to pasted line
J - join next line to current
== or << - unindent current line
and then remove remaining end with jdd
another solution:
j - move to second line
JD - join line with next, remove what was joined
dd - remove current line
k - step to previous line
PJ<< - paste, join and unshift
It's probably not optimal, but I do it without thinking, because most of this commands are in my muscle memory (you don't think how to move around you, how to yank/delete and paste most of the time, and joining line is also helpful to remember).
If you have virtualedit enabled in config, instead of A <Space> <Esc> you can $ <Space>, but I find $ harder to use than A followed by Ctrl-[ (it's simmilar to ESC).
As an advice: if you use some upper letter commands, try to chain them if it's possible, so you only need to keep Shift pressed and then execute some commands, instead of mixing upper and lower letter commands and pressing two keys at a time (upper letter is 2 key press, one is Shift). Once I found combo helpful for restarting server in console Ctrl+cpj, which sends Ctrl+c, Ctrl+p (previous command) and Ctrl+j (Enter key) with single Ctrl press. Since then I try to find simmilar time-saving combination in Vim too mostly with Shift, as Ctrl is not much used in Vim.
Yet another way:
ddpkJjdd
ddp swap the two lines
kJ move up and join the lines
== re-indent the line
jdd move down and delete the last line
There are probably 30 ways to do this.
Here is one, assuming you are starting from the end of the word end in normal mode:
dd (delete last line)
"aD (delete and copy foo_bar to buffer a)
dd (delete now-empty line 2)
"aP (paste from buffer a before caret)
aSpaceEsc (insert space and return to normal mode)
Again, "properly" rarely applies in Vim because there are so many ways to accomplish something. This is so small a change that even re-typing foo_bar could be justifiable.

Append general buffer to the end of every line in VI

I'm trying to add the contents of the general buffer to the end of every line. I'm sure this is fairly simple, however, an hour of google searches have lead me nowhere.
This is what my file looks like
::Things to bring camping
--matches
--tent
--sleeping bags
--inflatable bed
--firewood
--camping stove
--skillet
I want to add "::Things to bring camping" to the end of every line.
This is i have figured out so far.
/:: -> brings me to the line in question
Y -> yanks the entire line to the general buffer
I tried :%s/$/\p -> this added a "p" to the end of every line.
My problem is with step 3. How do I tell the "search and replace command" to used the "p" (the contents of the general buffer) instead of the "p" the character
Thank you so much for your help.
Just a suggestion: If you try doing it with a macro, you will be able to use 'p' to add the contents of the general buffer.
Sorry, I had to go into vim and find out.
The way to copy your entire line while in command mode, is:
^r "
(that's CTRL and r, then " )
That should paste the entire line you yanked into your search and replace command
For step three, instead of \p, you should use ctrl-R-a. Hold down the control key and type an uppercase "R", continue holding control, and type a lowercase "a".
For a line with multiple words, use ctrl-R-" instead.
I agree with using a macro - they're very powerful.
In this case I took your list example and positioned it at the first colon.
I used y$ to grab the remainder of the line in the buffer.
Then I recorded the macro - I chose 1.
q1
j$pq
Then you can call it for any number of rows in your list. E.g. 10#1
Learned something figuring this one out ...
:%s/$/\=getreg()/
The \= says that what follows is an expression to be evaluated, and the getreg() call gets the contents of the register, by default the "general buffer" as it used to be called by vi.

Vim yanking range of lines

I'm a C# developer who has just recently decided to expand my knowledge of the tools available to me. The first tool I've decided to learn is Vi/Vim. Everything has been going well so far, but there are a couple of questions I can't seem to find the answer to:
Lets say I wanted to yank a range of lines. I know there are many ways of doing so, but I would like to do it by line number. I figured it would be similar to how the substitute commands work, something like 81,91y. Is there a way to do this?
I'm a little confused about the g command in normal mode. It seems to do a myriad of things and I can't really determine what the g command does at its core. I'm confused on whether or not it's a motion command or a kind of "catch all" for other commands ran through normal mode. Can someone please explain this or point me to a reference that gives a good explanation of the g command?
Yank lines 81-91
:81,91y<enter>
If your fingers don't like to find the : and , keys, this would work as well (go to line 81, yank 11 lines)
81gg11yy
My only use of g is 5gg. To go to the 5th line. 22gg: 22nd line. As jimbo said, it's really only a modifier for some other commands.
For completeness, (http://vim.wikia.com/wiki/Power_of_g) explains a lot of how g works in command mode.
You can also copy the current lines to your present cursor location using 't'.
:81,91t.<enter>
This will paste the lines 81-91 under the line the cursor is on.
I learned this from http://vimcasts.org which is an excellent resource on VIM.
I also like to use vim's relative line number option which means I can just enter:
:-10,-7ya a
to yank the text into named buffer a.
N.B. Specifying A will append what you're yanking to the current contents of buffer a.
Don't forget you can also copy blocks of text and move blocks of text around as well with the similar commands:
:-10,-7co .
means copy the four lines of text 10 lines above to below the current line, and
:-10,-7mo .
means move the four lines of text 10 lines above to below the current line.
The G command goes to a certain line number, if it's accompanied by a count value. 81G puts you on line 81.
The y command can be combined with a movement, like G. So to yank everything until line 91 you can use y91G.
Together you get:
81Gy91G
Go to line 81, then yank while going to line 91.
g doesn't do anything by itself. It's one of a couple meta-commands that holds a bunch of sorta-unrelated commands.
z is yet another command like that.
In addition to :91,96y a which yanks (y) lines 91 through 96 into register a, (pasted with "ap), the yanked lines can be appended to the register with:
:91,96y A
I.e. the capitalization of the A register causes an appending operation into register a instead of an overwrite. Capitalization of the register always works like this, e.g. :let #A=';' appends a ; to register a.
Using plus (+) or minus (-) references lines relative to the current cursor position:
:-10,+10y b
I.e. it would yank(y) 21 lines around the current cursor position and put them in register b.
An absence of input actually represents the current cursor position as well, which means that this:
:-5,y a
would yank the text from 5 lines above to current cursor position into named buffer a, and:
:,+5y a
would yank the 5 lines after the current cursor position into buffer a.
Note: If you have a macro in buffer a it was just overwritten by the previous yank, as yank registers and macro registers are really the same thing. Which is why, coincidentally, you can paste a macro, edit it, and then yank it back into it's register. I personally use letters reached by my left hand for yanks, and letters reached by my right hand for macros.
Moving blocks of text around, looks like this:
:+10,+13m.
which means move the four lines positioned 10 lines ahead of current cursor, to below the current line.
Addendum
I previously confused ya in :91,95ya a to be somehow synonymous with ya{motion} where the motion was supplied by 91,95. This was incorrect and the "a" in ya is completely unnecessary. In my defense, my help yank does not convey that ya is a possible alias of yank.
The best solution would be to enter "visual mode", by pressing v. And after selecting lines just copy them by pressing y. Then paste copied lines by pressing p.
Vim's :help index describes g as:
|g| g{char} extended commands, see |g| below
Scroll down (or :help g) for a list.
As a long time Vi/Vim user I tend to use 'marks' instead of line numbers (or 'line markers'). It works like this: m is the 'mark' character; then use any letter to identify/name the mark. To return to a mark preface the named mark with a single quote ( 'a)These marks can be used as the range. Examples:
File:
<line 1>
<line 2>
<line 3>
<line 4>
<line 5>
When in command mode move cursor to line 2, typema. scroll to line 4, typemb.
To yank from mark a to mark b type:
:'a,'byank
To delete from mark a to mark b type:
:'a,'bdel
To search from mark a to mark b and replace 'ine' with 'ink':
:'a,'bs/ine/ink/g
To copy mark a through mark b and paste below the current position (the 'dot' always references the line where the cursor currently is positioned):
:'a,'bco .
Shift lines of code, between mark a through mark b, one tab to the right (use opposite chevron, <, to move left):
:'a,'b>
In command mode you can move back to marks by simply typing 'a to move back to the line marked a. Typing '' moves you back to previous position (unfortuantely only remembers the previous position, not two back).
You can yank to named buffers, copy, delete lines, search&replace just portions of your code, etc. without needing to know the line numbers.
To yank lines from line number 81 to 91 :
approach 1: 81gg11yy
not bad but you have to do little bit of math to find out how many lines to yank
approach 2: 81gg then shift+v then 91gg then y
BEST IN MY OPINION because this is straight forward, you only have to know the obvious thing i.e from which line number to which line number you want to yank

Resources