501

In Vim, how do I insert characters at the beginning of each line in a selection?

For instance, I want to comment out a block of code by prepending // at the beginning of each line assuming my language's comment system doesn't allow block commenting like /* */. How would I do this?

the Tin Man
  • 158,662
  • 42
  • 215
  • 303
Jordan Parmer
  • 36,042
  • 30
  • 97
  • 119

14 Answers14

904
  1. Press Esc to enter 'command mode'
  2. Use Ctrl+V to enter visual block mode
  3. Move Up/Downto select the columns of text in the lines you want to comment.
  4. Then hit Shift+i and type the text you want to insert.
  5. Then hit Esc, wait 1 second and the inserted text will appear on every line.

For further information and reading, check out "Inserting text in multiple lines" in the Vim Tips Wiki.

cody.codes
  • 1,384
  • 1
  • 18
  • 24
pixelbeat
  • 30,615
  • 9
  • 51
  • 60
  • 7
    The only bummer with this is that it appears Ctrl+V is overridden in GVIM. – Jordan Parmer Oct 31 '08 at 13:04
  • 18
    Not for me (on linux) it's not – pixelbeat Oct 31 '08 at 13:07
  • 25
    You can use Ctrl-Q as a replacement in gVim (as :help Ctrl-V explains) but you need to use hjkl to navigate in this mode rather than the arrow keys – Gareth Oct 31 '08 at 13:07
  • 1
    To be able to use the arrow keys in visual mode on windows just add "set keymodel-=stopsel" to your _vimrc. More at http://vim.wikia.com/wiki/Make_arrow_keys_work_in_visual_mode_under_Windows – agnul Oct 31 '08 at 23:12
  • 10
    If your ctrl-v is overridden in windows gvim, you should edit the global vimrc to stop including mswin.vim. – graywh Jan 04 '09 at 21:20
  • This worked for me. I had to press escape twice though (on mac terminal) – jimiyash Dec 07 '10 at 01:03
  • Ctrl+Shift+V works for me in GVIM, but I might have set that by hand...don't actually remember. – Cheezmeister Oct 04 '12 at 19:59
  • 2
    If anyone else got confused like me... That's Shift + i, not a lowercase l. – strongriley Nov 15 '12 at 12:28
  • 1
    Don't forget to install the REAL Vim on Ubuntu since the default Vi editor is vim-tiny and it does not work the same. $ sudo apt-get install vim – user57359 Nov 27 '13 at 16:52
  • 3
    Shift+i takes me back into insert mode and I lose the block selection that I get through CTRL+V. Any reasons? – vkaul11 Jan 17 '14 at 22:22
  • 5
    The "wait one second" part was what was confusing me on previous attempts to discover this method. – Patrick Sanan Mar 06 '14 at 19:21
  • 22
    Any idea why this wouldn't do anything after pushing esc? I waited like 10 seconds for something to happen on less than a hundred lines -- Never mind, I was pushing `Shift + v` not `CTRL + v`. @vkaul11 Probably the same thing what you did lol – Tek Jan 16 '15 at 22:31
  • 1
    :help visual-operators -> I = block insert , A = block append – here Aug 25 '16 at 19:54
  • 1
    Sorry if not related, but anyone knows how to paste something at the beginning of lines in a block. Basically same steps as mentioned in the answer, but instead of typing at step 3, pasting an already yanked text (let's say too complex to type in full again)? – mgouin May 29 '17 at 21:16
  • 2
    CTRL not shift! That's what I had confused so watch out! Now then could you please tell me how to uncomment a selection of lines? – alienCY Jul 21 '17 at 15:34
  • 1
    Does anyone know why it takes exactly one second between escaping Visual mode and inserting the characters on subsequent lines? I'm just curious. – StockB Mar 02 '18 at 22:33
  • 2
    @mgouin Hopefully you figured this out over the past year, but I'll leave this here in case anyone sees your question - you can always use `Ctrl-R (register)` to put (paste) while in insert mode. So, something like `Ctrl-V` `Shift-I` `Ctrl-R` `"` `Esc`. – brhfl May 30 '18 at 16:35
  • @brhfl Thanks you for taking the time to put the trick to my old question... It's funny, I found about the Ctrl-R in search mode (/) but I did not realize I could use it in that case also. Thanks! – mgouin May 31 '18 at 01:27
  • @alienCY yes, it must be visual block selection so do it with `Ctrl-v`. To uncomment, select in the same way and then hit `x` to delete them. – karakays Dec 25 '18 at 07:08
  • 1
    The confusing bit for me was that in Step 2 you have to press Ctrl + "Uppercase V", so in effect Ctrl + Shift + v to enter Visual block mode. – ankur_kachru Mar 04 '19 at 22:55
  • 1
    @ankur_kachru : for me ctrl+v (lower case) works just fine. tested on Ubuntu 18.04 LTS and VIM - Vi IMproved 8.0 (2016 Sep 12, compiled Jun 06 2019 17:31:41). – alphaGeek Nov 01 '19 at 10:22
  • Took me a while to figure out that you really have to press `Esc`, and not the command mode-key (which is `Ctrl-C` for me), when exiting VISUAL BLOCK. – user228395 Mar 14 '20 at 19:17
  • Works in Emacs Evil mode. Thanks! – Lino Ferreira May 18 '22 at 15:00
  • Doesn't work in vim 7.4.629. Shift + i doesn't take me to --INSERT-- mode – Alecz Nov 30 '22 at 21:38
  • @Alecz it's not supposed to show you that mode, but you will be able to insert just like it says. – robrecord Dec 13 '22 at 12:43
  • this works for me on debian 11. – kevin Dec 17 '22 at 04:24
  • The "wait 1 second" step is useless, the modification is done as soon as the final Esc is typed. At least on neovim, would the behavior different with vim? – COil Feb 16 '23 at 16:26
  • OMG!!! This is magic :) – Satish Apr 24 '23 at 20:19
218

This replaces the beginning of each line with "//":

:%s!^!//!

This replaces the beginning of each selected line (use visual mode to select) with "//":

:'<,'>s!^!//!

Note that gv (in normal mode) restores the last visual selection, this comes in handy from time to time.

Tomalak
  • 332,285
  • 67
  • 532
  • 628
  • 4
    Thanks! Makes total sense. And removing the text goes as follows: '<,'>s!^//!! – Jordan Parmer Oct 31 '08 at 13:08
  • 4
    What is the meaning of the exclamation marks in the above answer? (:%s!^!//!) – Henrik K May 31 '11 at 08:57
  • 21
    @HKK, normally one uses the forward slash character / as a delimeter for the search and replace command. In this case we are inserting a forward slash as part of the search and replace so we use an alternative delimeter, namely the exclamation character ! – cyber-monk Jun 07 '11 at 20:46
  • +1 This works in VsVim where (Ctrl+V) (Shiift+I) Esc doesn't. – Seth Reno Jan 24 '12 at 15:03
  • Thanks! Also, to replace the END of each line you might write: %s!$!//! – MigDus Apr 08 '12 at 21:32
  • 4
    +1, had no idea you could use something else as the regex delimiter (here I was using `/` and having to escape the `//` in `:s/^/\/\/` instead of writing `:s!^!//`) – Hashbrown Dec 18 '13 at 06:19
  • This actually works. Commonly here, the 2nd highest vote tally is actually the correct answer... – Chris Jan 29 '20 at 21:38
99

The general pattern for search and replace is:

:s/search/replace/

Replaces the first occurrence of 'search' with 'replace' for current line

:s/search/replace/g

Replaces all occurrences of 'search' with 'replace' for the current line, 'g' is short for 'global'

This command will replace each occurrence of 'search' with 'replace' for the current line only. The % is used to search over the whole file. To confirm each replacement interactively, append a 'c' for confirm:

:%s/search/replace/c

Interactive confirm replacing 'search' with 'replace' for the entire file

Instead of the % character you can use a line number range (note that the '^' character is a special search character for the start of line):

:14,20s/^/#/

Inserts a '#' character at the start of lines 14-20

If you want to use another comment character (like //), then change your command delimiter:

:14,20s!^!//!

Inserts a '//' character sequence at the start of lines 14-20

Or you can always escape the // characters like:

:14,20s/^/\/\//

Inserts a '//' character sequence at the start of lines 14-20

If you are not seeing line numbers in your editor, simply type the following:

:set nu
cyber-monk
  • 5,470
  • 6
  • 33
  • 42
49

Another way that might be easier for newcomers:

 some█
 code
 here

Place the cursor on the first line, e.g. by

gg

and type the following to get into insert mode and add your text:

I / / Space

 // █some
 code
 here

Press Esc to get back to command mode and use the digraph:

j . j .

 // some
 // code
 //█here

j is a motion command to go down one line and . repeats the last editing command you made.

lbonn
  • 2,499
  • 22
  • 32
ninegrid
  • 1,791
  • 14
  • 17
  • 3
    Thats really simple :). If you are having trouble with it may be because you are typing a bar (the other symbol with your \ ) `|` instead of a capital `I`. I thought it was a `|` at first. – cokedude Feb 28 '14 at 17:30
  • 1
    If I do "5." it deletes 5 character from same line. How do I make it delete 5 character at once from each line ? – Rahul Prasad Jun 24 '15 at 06:58
  • 1
    @RahulPrasad Let's say you have 25 lines, then beginning at the front of the first line just record 5xj into a register and play that register 24 times, for example: qa5xjq25@a But it would be better if you posted this as an actual question if it doesnt exist already... – ninegrid Mar 01 '16 at 07:03
29

And yet another way:

  • Move to the beginning of a line
  • enter Visual Block mode (CTRL-v)
  • select the lines you want (moving up/down with j/k, or jumping to a line with [line]G)
  • press I (that's capital i)
  • type the comment character(s)
  • press ESC
Hulk1991
  • 3,079
  • 13
  • 31
  • 46
Yewge
  • 1,894
  • 2
  • 15
  • 15
27

This adds # at the beginning of every line:

:%s/^/#/

And people will stop complaining about your lack of properly commenting scripts.

Alper Turan
  • 1,220
  • 11
  • 24
Jar-jarhead
  • 279
  • 3
  • 2
16

If you want to get super fancy about it, put this in your .vimrc:

vmap \c :s!^!//!<CR>
vmap \u :s!^//!!<CR>

Then, whenever in visual mode, you can hit \c to comment the block and \u to uncomment it. Of course, you can change those shortcut keystrokes to whatever.

Lucas Oman
  • 15,597
  • 2
  • 44
  • 45
14

Yet another way:

:'<,'>g/^/norm I//

/^/ is just a dummy pattern to match every line. norm lets you run the normal-mode commands that follow. I// says to enter insert-mode while jumping the cursor to the beginning of the line, then insert the following text (two slashes).

:g is often handy for doing something complex on multiple lines, where you may want to jump between multiple modes, delete or add lines, move the cursor around, run a bunch of macros, etc. And you can tell it to operate only on lines that match a pattern.

Brian Carper
  • 71,150
  • 28
  • 166
  • 168
7

To insert "ABC" at the begining of each line:

  1. Go to command mode

  2. % norm I ABC

rafaelvalle
  • 6,683
  • 3
  • 34
  • 36
Mac
  • 71
  • 1
  • 1
3

For commenting blocks of code, I like the NERD Commenter plugin.

Select some text:

Shift-V
...select the lines of text you want to comment....

Comment:

,cc

Uncomment:

,cu

Or just toggle the comment state of a line or block:

,c<space>
Kevin
  • 1,170
  • 2
  • 8
  • 10
2

I can recommend the EnhCommentify plugin.

eg. put this to your vimrc:

let maplocalleader=','
vmap <silent> <LocalLeader>c <Plug>VisualTraditional
nmap <silent> <LocalLeader>c <Plug>Traditional
let g:EnhCommentifyBindInInsert = 'No'
let g:EnhCommentifyMultiPartBlocks = 'Yes'
let g:EnhCommentifyPretty = 'Yes'
let g:EnhCommentifyRespectIndent = 'Yes'
let g:EnhCommentifyUseBlockIndent = 'Yes'

you can then comment/uncomment the (selected) lines with ',c'

Benedikt Waldvogel
  • 12,406
  • 8
  • 49
  • 61
1

Mark the area to be comment as a visual block (<C-V)

and do c#<ESC>p

  1. change it to "#"
  2. put it back

If you do it often, define a short cut (example \q) in your .vimrc

:vmap \q c#<ESC>p
JJoao
  • 4,891
  • 1
  • 18
  • 20
1

In case someone's multi-line-selection is actually a paragraph, there is no need to manually select the lines. vim can do that for you:

  1. vip: select and mark the whole paragraph
  2. shift-i: insert text at line beginning
  3. escape: leave insert mode/enter normal mode [line beginnings still selected]
  4. escape: unselect line beginnings
TheUnseen
  • 314
  • 2
  • 6
0

Mapping of most voted answer:

1st visual select the desired lines, then execute <leader>zzz, which values:

vnoremap <leader>zzz <C-V>^I-<Space><Esc>
  • <C-V> to enter visual mode
  • ^ goes to start of line ( or use '0' to 1st non blank)
  • I to insert in block mode
  • -<Space> to insert '- ' (for example, edit as you need)
  • <Esc> to apply same insert to all visual block lines

Or of last visual selection from normal mode:

nnoremap <leader>zzz gv<C-V>^I-<Space><Esc>
Xopi García
  • 359
  • 1
  • 2
  • 9