Related
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
I have a list of products to place on a rails seed and I would like to instead of put brackets one by one on the list with a command place the brackets on the whole list?
for example:
1. Dakine
2. Dale of Norway
3. Dan Post
1. ["Dakine"],
2. ["Dale of Norway"],
3. ["Dan Post"],
I searched on the help but did not find any about. Thanks.
You can record a macro in Vim and repeat that.
If you are on number 1, you can do following:
qqf a["Esc$a"],Esc0jq
Explanation:
qq: Start recording macro in register q
f: Go to first space character
a: : Insert after (the space character from above)
\[": Insert those characters
Esc: Back to normal mode
$: Go to end of line
a: Insert after (end of line)
"],: Insert the characters
Esc: Back to normal mode
0: Jump to start of line
j: Go down one line
If you have 100 such lines, you can do 100#q to achieve your result.
With vim substitute command:
:%s/.*/["&"]/
If you don't want to operate on all lines, then select the ones you want to transform or note the related line numbers, and then type :s/..... without the %. You'll see actually :'<,'>s this range represent the visually selected lines, and vim adds it automatically in visual mode.
On Atom you can enable the find to use Regex in the search(there is a button next to the search field)
Then you can search for something like (^.*$) to get every line separated by groups and in the Replace field you use ["$1"],. The $1 represents the value matched by the Regex.
Then just do a Replace All and remove the last comma in your list if needed.
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.
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.
What's the easiest way to delete the first 2 spaces for each line using VIM? Basically it's repeating "2x" for each line.
Clarification: here the assumption is the first 2 characters are spaces. So the question is about doing indentation for multiple lines together.
Enter visual block mode with Ctrl-V (or Ctrl-Q if you use Ctrl-V for paste);
Select the area to delete with the arrows;
Then press d to delete the selected area.
Press Esc
Some more options. You can decided which is the "easiest way".
Remove the first 2 characters of every line:
:%normal 2x
Remove first 2 characters of every line, only if they're spaces:
:%s/^ /
Note that the last slash is optional, and is only here so that you can see the two spaces. Without the slash, it's only 7 characters, including the :.
Move indentation to left for every line:
:%normal <<
You could also use a search and replace (in the ex editor, accessed via the : character):
Remove first two characters no matter what:
%s/^.\{2}//
Remove first two white space characters (must be at the beginning and both must be whitespace... any line not matching that criteria will be skipped):
%s/^\s\{2}//
Assuming a shiftwidth=2, then using shift with a range of %
:%<
Two spaces, or two characters? (2x does the latter.)
:[range]s/^ //
deletes two blanks at the beginning of each line; use % (equivalent to 1,$) as [range] do to this for the entire file.
:[range]s/^..//
deletes the first two characters of each line, whatever they are. (Note that it deletes two characters, not necessarily two columns; a tab character counts as one character).
If what you're really doing is changing indentation, you can use the < command to decrease it, or the > command to increase it. Set shiftwidth to control how far it shifts, e.g.
:set shiftwidth=2
I'd try one of two approaches:
Do column editing on the block to delete using Ctrl+V (often mapped to Ctrl+Q).
Record a macro on the first row using q1 (or any other number/letter you want to denote the recording register), then replay that macro multiple times using #1 (to use my previous example. Even better, use a preceding number to tell it how many times to run - 10#1 to run that macro 10 times, for example. It does, however, depends on what you recorded - make sure to rewind the cursor 0 or drop one line j, if that's relevant.
I'd also add: learn how to configure indentation for vim. Then a simple gg=G will do the trick.