1517

I have a Ruby code file open in vi, there are lines commented out with #:

class Search < ActiveRecord::Migration
  def self.up
    # create_table :searches do |t|
    #   t.integer :user_id
    #   t.string :name
    #   t.string :all_of
    #   t.string :any_of
    #   t.string :none_of
    #   t.string :exact_phrase
    # 
    #   t.timestamps
    # end
  end

  def self.down
    # drop_table :searches
  end
end

Say I want to uncomment all the lines in the first def ... end section. What's an efficient way to do that in Vim?

In general, I'm looking for an easy and fluid way to comment and uncomment lines. Here I'm dealing with Ruby code, but it could be JavaScript (//) or Haml (-#).

Eric Leschinski
  • 146,994
  • 96
  • 417
  • 335
Ethan
  • 57,819
  • 63
  • 187
  • 237
  • 49
    The accepted answer should be changed to one of the answers that has detailed instructions on how to accomplish commenting/uncommenting blocks without using a plugin. The [current accepted answer](https://stackoverflow.com/a/1676775/3303195) is basically just a link to a third-party plugin. – faintsignal Sep 07 '17 at 22:13
  • The best rated answer does not mention any plugins, @rationalis your comment is misleading, could you please either correct it or remove it, thank you. – bonobo Jun 09 '19 at 13:57
  • Accpted Answer should be [Magnus answer](https://stackoverflow.com/a/23063140/3313834) – user3313834 Apr 18 '21 at 08:31
  • An ideal solution would be where one hotkey can toggle comments both "off" and "on" for either "the line the cursor is resting on" or "the selection of lines selected". Anything else is too many steps in my book. – Lonnie Best Aug 03 '22 at 11:52

53 Answers53

3208

For those tasks I use most of the time block selection.

Put your cursor on the first # character, press CtrlV (or CtrlQ for gVim), and go down until the last commented line and press x, that will delete all the # characters vertically.

For commenting a block of text is almost the same:

  1. First, go to the first line you want to comment, press CtrlV. This will put the editor in the VISUAL BLOCK mode.
  2. Then using the arrow key and select until the last line
  3. Now press ShiftI, which will put the editor in INSERT mode and then press #. This will add a hash to the first line.
  4. Then press Esc (give it a second), and it will insert a # character on all other selected lines.

For the stripped-down version of vim shipped with debian/ubuntu by default, type : s/^/# in the third step instead (any remaining highlighting of the first character of each line can be removed with :nohl).

Here are two small screen recordings for visual reference.

Comment: Comment

Uncomment: Uncomment

Eric O. Lebigot
  • 91,433
  • 48
  • 218
  • 260
Christian C. Salvadó
  • 807,428
  • 183
  • 922
  • 838
  • 101
    By default it's CTRL+V. The windows version of gvim uses Ctrl+Q because Ctrl+V is already used for paste. – R. Martinho Fernandes Nov 04 '09 at 21:40
  • Note the uncommenting only works for single-character comments – amindfv Dec 10 '12 at 19:03
  • 8
    @amindfv Ctrl+V, `n` (where n is num lines - 1), j, `n` (where n num number of length of comment character sequence - 1), l, x. – michael.bartnett Dec 15 '12 at 21:09
  • 5
    @michael.bartnett: Nice! Also, for anyone else: note that you can move the cursor with arrow keys instead of `(n-1)-l` – amindfv Dec 16 '12 at 03:52
  • 38
    How would you do this with '//'? – AustinT Jan 28 '14 at 04:27
  • 3
    to uncomment do `:s/^#/` – pixel 67 Feb 23 '14 at 10:26
  • 4
    I needed to hit `Esc` twice. – Aditya M P Jun 14 '14 at 13:55
  • 2
    @AustinTruong If you want to insert another string, just type that instead of `#` in the second step. It can be anything you want. – Mike Jul 02 '14 at 02:24
  • 1
    This answer does not seem to work in VIM 7.2 (i.e. default Vim on OS X 10.6.8). However, it does work in VIM 7.4 :) –  Aug 12 '14 at 14:53
  • Go to the beginning of a line, press «Ctrl-v», go to the last line to be commented, press «I», enter a comment, press «ESC». Versus: press «v», go to the last line to be commented, press a hotkey. The last **much** faster, and since vim is all about a speed it is surely should have something to comment a lines. – Hi-Angel Oct 09 '14 at 06:52
  • 3
    +1 for Ctrl+V; honestly it was one of the only things about sublime I thought ViM was missing. Boy was I wrong. – Qix - MONICA WAS MISTREATED Nov 08 '14 at 19:45
  • 88
    You can click Esc two times to not wait that second ;) – Ahmed Hegazy Jan 15 '15 at 12:40
  • 5
    Why does it only work in Visual Block, not in Visual Line mode? What's the difference conceirning the selection? Using Line mode only the first line is edited. – inVader Feb 19 '15 at 14:52
  • 4
    Why is it so slow at updating the text after inserting in visual mode? Is this a temporary bug in the current vim? – Thomas Ahle Mar 10 '15 at 22:40
  • @AustinT and 6+ others, get Vim 7.4 and try michael.bartnett's comment at which point you'll realize that 'j' and 'l' are just arrow keys – Colin Apr 19 '15 at 13:56
  • 1
    I was wondering the same, @inVader. Because I was trying to practice between this answer and the one by @ Magnus – DrBeco Jun 30 '15 at 15:53
  • 1
    I had the same issue @ThomasAhle and thought it wasn't working because I kept undoing. I'm running VI in Tmux on a local cluster. – ekangas Aug 06 '15 at 19:32
  • @Ethan: Judging by the popular vote, you might want to change this to be the accepted answer. – jvriesem Sep 13 '15 at 18:10
  • 89
    This didn't work for me. Shift-I went into simple insertion mode. – Geremia Feb 14 '16 at 01:55
  • 2
    Any simple way to upgrade the "stripped-down" version? I'm using a MacBook Air and can't use `shift I`. – Alexander Feb 29 '16 at 12:44
  • Elementary OS users: The pantheon terminal maps ctrl+v to paste, which might result in this answer not working at first try. This (retarded) mapping can be turned off by running `gsettings set org.pantheon.terminal.settings natural-copy-paste false`, or disabling the equivalent setting from `dconf-editor`. – Jishnu Oct 04 '16 at 16:57
  • to set single "fast escape" you can add this line to .vimrc file: set timeoutlen=1000 ttimeoutlen=0 – Zhorzh Alexandr Oct 25 '16 at 20:57
  • 1
    @Alexander You can get the full version of Vim by uninstalling your current vim version and (on _apt_ systems) using `apt-get install vim-nox` – forresthopkinsa Dec 11 '16 at 17:32
  • Hmmm.... how could we store this in our vimrc in a way that let's you comment regardless of the language? That would be a fun afternoon's worth of work... – Costa Michailidis Dec 28 '16 at 17:52
  • `CTRL-V` on gvim in windows here. – dylnmc Jul 07 '17 at 19:10
  • 2
    The inverse would be to use shift + "X" to remove the first line in the visual block. – shdobxr Jul 18 '17 at 15:32
  • @AustinT just escape the backslashes twice as `s/^/\/\/` to add `//` to the lines. – Gideon Maina Jul 20 '17 at 10:02
  • why using ```shift+I``` ? I think it's better using the change command ```c``` or ```s``` instead of shift+I – SdSaati Aug 21 '17 at 04:37
  • the rumor is true, vim has everything and the plugin usually is just a wrapper of vim functions. – buncis Dec 08 '17 at 12:27
  • If this is not working on windows have a look at this http://pjerald.blogspot.in/2010/08/how-to-enable-visual-block-mode-in-gvim.html – Sunil Kumar Jan 22 '18 at 09:22
  • 1
    just for future reference: the documentation for the `shift-I` from visual block mode can be found with `:help v_b_I` – glS Mar 11 '18 at 16:09
  • 3
    This should definitely be the accepted answer. No plugins or external scripts, just vim's embedded power – MariusPontmercy Mar 19 '18 at 09:45
  • This seems not to work when using backspace during the insert part – lucidbrot Apr 28 '18 at 18:02
  • 1
    @lucidbrot you can use `c` at step three to replace instead of insert. – JazZ Jun 25 '18 at 17:12
  • Does this work for remapped command for Visual Block mode? For example `v`. For me it didn't work – Suncatcher Mar 04 '19 at 05:01
  • @Geremia did you find a solution for this? Maybe the OS I'm doing this on is too old? – Nict Aug 22 '19 at 12:19
  • 18
    For people that `shif-i` didn't work for them: you should press `ESC` to see the pasted text in the other lines. – Yar Sep 30 '19 at 00:25
  • 10
    If "shift-i" goes to the regular one line insertion mode, it means you're not done yet! I had the same problem. if you follow the steps, it will seem like only the first line of your visual block is getting the comment, that is fine. Once you add the comment, ***press esc twice*** and the rest of the lines will magically get the comments as well! :) – Angel Garcia Jan 06 '20 at 16:57
  • 2
    @Geremia it did not work for me because I had the habit of just using `V`. You should use `Ctrl` + `V` first. – baptx Apr 25 '20 at 20:08
  • 3
    @Geremia You are right. After editing the first line, press ESC to quit insert mode, then you will see that it is applied to the rest of selected line.(Double ESC should work) – Kevin Jun 22 '20 at 13:02
  • @CMS Sorry kind sir, but what is the name of that font. It's so beautiful ❤ – Godstime Osarobo Aug 23 '20 at 08:24
  • To clarify, `Ctrl` + `V` = `Ctrl` + `Shift` + `v` worked with my setup on Windows. – pylang Oct 14 '20 at 15:41
  • Bingo! Why is this not the accepted answer? – Kiran Dec 10 '20 at 15:17
  • To avoid counting the lines or holding `j`, one should enable `relativenumber` (`:h relativenumber`), this way you immediately know your motion target is 9 lines below and you can type `9j`. If it's at more than one screen, use `Ctrl+F` to go forward one page and `Ctrl+B` to go one page back. Once you see your target, you can use relative motion again. – liberforce Feb 04 '21 at 13:55
  • If you have space after the commenting character e.g. `# this is a comment` and you want to remove that space while uncommenting, use two columns while selecting the blocks in visual-block mode and then delete. Check @amelias's answer – Deepam Gupta May 07 '21 at 19:57
  • Dont think comments mentioned for `//`. Basically press `Ctrl+V` select your lines, and then `Shift+I` and just type `//`. If you prefer regex you press `Ctrl+V` then `:'<,'>s/^/\/\/ /` . A similar thing for removing. Quite cool. – Minsky Feb 07 '22 at 11:20
  • ctrl + v was bound to paste on mine. Had to go into settings.json and comment out the block { "command": "paste", "keys": "ctrl+v" }, and then it worked – scrow Jul 19 '22 at 10:09
  • You can add '//' the same way. Just CTRL+V, go down to the last line you want to comment out, and type SHIFT+I, then type // and hit Esc, wait a split second and all lines will be prepended with //. – papashou Dec 02 '22 at 09:25
  • I'm using `VIM - Vi IMproved 8.0` on `AlmaLinux - 8.6 (Sky Tiger)` and the only solution mentioned in 'For the stripped-down version of vim shipped with debian/ubuntu by default, type : s/^/# in the third step instead' part, worked for me. – Vahid F Dec 06 '22 at 10:41
  • On Windows Terminal `Ctrl` `Shift` `v` (or the same as `Ctrl` `V`) is assigned to paste. Thus Vim doesn't go in Visual block mode. After deleting the shortcut, it works for me. – Maxim Suslov Jan 20 '23 at 07:04
  • stop recommending arrow keys, use target line number for example 12, then press J or K to move 12 lines down or up. – Lem Feb 11 '23 at 12:12
  • this is perfect. now I am free from stupid :norm thing – SpookyJelly Jul 20 '23 at 02:28
1054

To comment out blocks in vim:

  • press Esc (to leave editing or other mode)
  • hit ctrl+v (visual block mode)
  • use the / arrow keys to select lines you want (it won't highlight everything - it's OK!)
  • Shift+i (capital I)
  • insert the text you want, e.g. %
  • press EscEsc

To uncomment blocks in vim:

  • press Esc (to leave editing or other mode)
  • hit ctrl+v (visual block mode)
  • use the / arrow keys to select the lines to uncomment.

    If you want to select multiple characters, use one or combine these methods:

    • use the left/right arrow keys to select more text
    • to select chunks of text use shift + / arrow key
    • you can repeatedly push the delete keys below, like a regular delete button

  • press d or x to delete characters, repeatedly if necessary
amelia
  • 10,670
  • 1
  • 12
  • 6
  • 2
    This answer does not seem to work in VIM 7.2 (i.e. default Vim on OS X 10.6.8). However, it does work in VIM 7.4 :) –  Aug 12 '14 at 14:52
  • 72
    @amelia : The commenting shortcut doesn't work for me. Shift + i takes me to insert mode. Does it depend on vim version? – user3527975 Jan 19 '16 at 19:20
  • 3
    @user3527975 I'm in the same boat. Previous poster said it doesn't work in vim 7.2. That's what I have on my cluster as well. – abalter Jan 22 '16 at 07:00
  • 2
    @user3527975 It is working for me, have you pressed Esc in the end ? – StrawhatLuffy Jan 22 '16 at 10:47
  • @StrawhatLuffy yes I pressed Esc – proxy Jan 24 '16 at 07:15
  • 1
    @proxy I am using gVim 7.4 in Windows and it is working for me. – StrawhatLuffy Jan 25 '16 at 05:55
  • 3
    I wish this answer would be promoted. As it currently stands it's like if you asked how to i get all rows from a table and someone posted a link to an ORM and said just install this and use this command. – michael.schuett Jan 26 '16 at 00:11
  • 8
    Why does it take a second? – Conor Patrick Feb 22 '16 at 22:36
  • @user3527975 it might depend on version as another commenter has noted. However, you do want to be in insert mode as the goal is to insert commenting text (or remove it). What happens after you follow the other steps? – amelia Mar 03 '16 at 12:54
  • @ConorPatrick dunno, but here's a start http://stackoverflow.com/questions/9341768/vim-response-quite-slow – amelia Mar 03 '16 at 13:01
  • 2
    Using Vim 7.2 on RHEL 6 - this does not work. Inserts command on first line only – dcompiled Mar 15 '16 at 13:54
  • 61
    The only issue I have with this answer is that it tells you to use *arrow keys*. – cozyconemotel May 11 '16 at 10:38
  • 7
    Hit Esc twice instead. :) – Aaron Feb 11 '17 at 00:43
  • 2
    @ConorPatrick it's waiting to see if you're using the Esc in combination with anything else – forresthopkinsa Nov 17 '17 at 17:42
  • 1
    @AaronAlphonsus edited the answer to remove the comment about waiting to reflect your feedback. – pneumatics Dec 07 '17 at 18:46
  • You need to use Esc, not Ctrl+C (twice), otherwise you it will only alter the first line. – Sebastian Graf Jan 23 '18 at 15:59
  • 66
    At first enabling comments didn't work for me but after reading that once again worked fine: 1. make sure you use Ctrl-V, not V for selection 2. when inserting it will appear as you are modifying only a single line 3. all inserts happen when you hit Esc in the end – timurb Feb 26 '18 at 14:42
  • @chase It IS a feature. Hit Esc twice and you'll see it will insert the characters instantly. – tiktak Feb 27 '18 at 00:08
  • 4
    Also most of you guys need to learn how to read. I've used this longer than I can remember, so it definitely worked with ViM 7.2 and 7.4. Maybe you are expecting ViM to behave differently? It's normal the characters appear only on the first line before you press Esc. Maybe your terminal is not sending the keys (typical with arrow keys especially over SSH)? – tiktak Feb 27 '18 at 00:11
  • 1
    @shxfee: I think one should know the builtin way but also not be ignorant of what plugins can offer for your personal dev environment. The plugin approach makes the "damn simple thing" even simpler. It is just a task I simply do so often that I will benefit from any improvement. Using an operator on a textobject is IMHO the true vim way (e.g. `gcip`). This is why I use vim not because it has visual-block mode aka rectangular block selection: [most editor nowadays offer this](https://en.wikipedia.org/wiki/Comparison_of_text_editors#Basic_features). – Hotschke Mar 26 '18 at 09:35
  • 3
    This totally does NOT work for me in MacVim 8.0. Hitting shit-i puts it into insert mode and only fixes the line the cursor is on. hitting esc twice doesn't change anything – jaydel Mar 29 '18 at 13:15
  • For me the arrow keys don't work, I'm using j and k and it works (MacVim). – scravy Jul 30 '18 at 13:16
  • 1
    Why doesn't this work with Shift-V? I use Shift-V way more and always forget – GameKyuubi Jan 22 '19 at 04:08
  • 1
    For macbook users, it might be helpful to make sure that you actually press control, not fn. That was my problem. – Homper Jul 06 '20 at 10:58
  • 1
    What exactly does the esc, esc at the end do? – xotix Sep 12 '20 at 07:43
  • If you're having trouble with this, make sure you hit that double escape! – safay Jun 23 '21 at 20:52
  • 1
    I also though that the comment does not work, but **it actually does**! It **looks like** Shift+i gets you to the insert mode, but if you type `# ` and press Esc twice, it magically applies that to all lines! – Ben Usman Jun 25 '21 at 20:28
430

Sometimes I'm shelled into a remote box where my plugins and .vimrc cannot help me, or sometimes NerdCommenter gets it wrong (eg JavaScript embedded inside HTML).

In these cases a low-tech alternative is the built-in norm command, which just runs any arbitrary vim commands at each line in your specified range. For example:

Commenting with #:

1. visually select the text rows (using V as usual)
2. :norm i#

This inserts "#" at the start of each line. Note that when you type : the range will be filled in, so it will really look like :'<,'>norm i#

Uncommenting #:

1. visually select the text as before (or type gv to re-select the previous selection)
2. :norm x

This deletes the first character of each line. If I had used a 2-char comment such as // then I'd simply do :norm xx to delete both chars.

If the comments are indented as in the OP's question, then you can anchor your deletion like this:

:norm ^x

which means "go to the first non-space character, then delete one character". Note that unlike block selection, this technique works even if the comments have uneven indentation!

Note: Since norm is literally just executing regular vim commands, you're not limited to comments, you could also do some complex editing to each line. If you need the escape character as part of your command sequence, type ctrl-v then hit the escape key (or even easier, just record a quick macro and then use norm to execute that macro on each line).

Note 2: You could of course also add a mapping if you find yourself using norm a lot. Eg putting the following line in ~/.vimrc lets you type ctrl-n instead of :norm after making your visual selection

vnoremap <C-n> :norm

Note 3: Bare-bones vim sometimes doesn't have the norm command compiled into it, so be sure to use the beefed up version, ie typically /usr/bin/vim, not /bin/vi

(Thanks to @Manbroski and @rakslice for improvements incorporated into this answer)

Magnus
  • 10,736
  • 5
  • 44
  • 57
  • I thought this was the way to go until I scrolled to read this answer http://stackoverflow.com/a/1676690/850996 The block selection using CTRL + V (as opposed to line selection with SHIFT + V) gives much nicer control over where the comment character insertion takes place. – Shyam Habarakada Aug 01 '14 at 18:03
  • 4
    @Shyam The ctrl-v technique combined with special block-selection-only commands is what most of the other answers recommend; however I personally find the "norm" technique I've described to be easier because it doesn't introduce any new syntax besides the norm command itself, so I can reuse what I already know about vim. – Magnus Sep 02 '14 at 17:40
  • 3
    For uncommenting an indented block, it is useful to say `:norm ^x`. This method in general has the advantage of working with region selections (e.g. `vi{` will select inside curly braces). Such _text object selectors_ do not work with `Visual Block`. – ivan-k Dec 24 '14 at 08:20
  • Does this only work on certain versions of `vim`? I'm trying to do this on 7.2 on a centos box and it displays the `:'<,'>norm i#` as expected, but when I press enter it doesn't make any change to the lines that were selected. – rakslice Oct 07 '15 at 22:23
  • 1
    Ah, I just figured it out -- on centos 6 the `/bin/vi` is vim 7.2, but it's a different build than `/usr/bin/vim`, and it has features like this turned off. – rakslice Oct 07 '15 at 22:34
  • 1
    You can also select the lines, then :s/^/# or :s/^# or :s@^@// ... etc. (All of which will similarly become :'<,'>s...) – DimeCadmium Aug 07 '18 at 19:22
  • 11
    This is by far the best answer. Especially when combined with `vip` to select a whole paragraph. – meh Oct 09 '18 at 17:05
  • Note that `norm` is short for `normal`. – ritiek Jan 18 '19 at 13:58
  • 3
    This is so awesome. I am an AVID macro user. I create macros (often times recursive) on the fly for keystrokes that I am going to have to repeat even once. I just think in macros now. I never knew about `:normal`. I'm going to use the heck out of it. – Bruno Bronosky Jun 14 '20 at 20:22
  • This offers better visual feedback than solutions based on visual blocks (ctrl+v). Also, it works when comments are/should not be aligned vertically. Thanks for sharing! – nimser Jan 12 '21 at 06:27
  • The very best answer by far ! – user3313834 Apr 18 '21 at 08:12
199

I use the NERD Commenter script. It lets you easily comment, uncomment or toggle comments in your code.

As mentioned in the comments:

for anyone who is confused by the usage, default leader is "\" so 10\cc will comment ten lines and 10\cu will uncomment those ten lines

Bhargav Rao
  • 50,140
  • 28
  • 121
  • 140
Manuel Ceron
  • 8,268
  • 8
  • 31
  • 38
  • Interesting! I read the Doc and find there is a "sexy comment" -- just use "\cs". For Ruby, it will use `=begin` and `=end` to comment multiple lines instead of hash tags. – Hegwin Aug 11 '17 at 03:59
  • I think that it isn't the quickest way to do it with vim since it requires to install a plugin. Also the best answer has already received more votes but it hasn't been marked as solution. – whirmill Jul 10 '18 at 10:17
  • 360
    **Don't stop here.** Most voted answers are below without the requirement of any plugins. https://stackoverflow.com/a/15588798/2117868 and https://stackoverflow.com/a/1676690/2117868 – kuttumiah Jul 24 '18 at 00:13
  • 3
    @whirmill I think "best" really depends on use case. Visual block mode is faster if I want to toggle comments once in my life. But if I don't mind installing a plugin and want to make as few keystrokes as possible to toggle comments and not have to differentiate operation between adding or removing comments - then this here might be the "best answer". – Carolus Nov 07 '19 at 13:53
  • @Carolus I would have agreed with you if the question had begun with "what's the best way" instead of "what's a quick way". – whirmill Nov 11 '19 at 13:51
  • 1
    @whirmill Great point. Though I *could* argue that "quickest" might have those multiple interpretations as well. Though yours would be more common/likely. :) – Carolus Nov 11 '19 at 14:13
  • Accepted answers should be the one with block selection Christian C. Salvadó – user3313834 Apr 18 '21 at 08:05
163

I have the following in my .vimrc:

" Commenting blocks of code.
augroup commenting_blocks_of_code
  autocmd!
  autocmd FileType c,cpp,java,scala let b:comment_leader = '// '
  autocmd FileType sh,ruby,python   let b:comment_leader = '# '
  autocmd FileType conf,fstab       let b:comment_leader = '# '
  autocmd FileType tex              let b:comment_leader = '% '
  autocmd FileType mail             let b:comment_leader = '> '
  autocmd FileType vim              let b:comment_leader = '" '
augroup END
noremap <silent> ,cc :<C-B>silent <C-E>s/^/<C-R>=escape(b:comment_leader,'\/')<CR>/<CR>:nohlsearch<CR>
noremap <silent> ,cu :<C-B>silent <C-E>s/^\V<C-R>=escape(b:comment_leader,'\/')<CR>//e<CR>:nohlsearch<CR>

Now you can type ,cc to comment a line and ,cu to uncomment a line (works both in normal and visual mode).

(I stole it from some website many years ago so I can't completely explain how it works anymore :). There is a comment where it is explained.)

Bruno Bronosky
  • 66,273
  • 12
  • 162
  • 149
jqno
  • 15,133
  • 7
  • 57
  • 84
  • what is the shortcut I should use? I can't quite make sure from the vim code itself! – gideon Aug 23 '13 at 17:34
  • in normal or visual mode, use ",cc" (3 character sequence) to comment the current line, and ",cu" to uncomment the current line. – Dan Sep 13 '13 at 08:26
  • 9
    i like it :)! thanks! On a side note i don't find it to hard to explain. a) it remaps a command (non recursively [see this ](http://stackoverflow.com/questions/3776117/vim-what-is-the-difference-between-the-remap-noremap-nnoremap-and-vnoremap-ma) so now when you press ,cc the :... thing gets executed. b) now this is basically a sed (s/what/towhat/where) command changing ^ (start of line) to the correctly set comment character based on the type of file you have opened c) as for the silent thingies they just suppress output from commands. d):nohlsearch stops it from highlighting the sed search – ramrunner Sep 22 '13 at 12:05
  • 14
    Note, this is not the correct way to load autocommands. They should be inside an augroup or else they will be added to vim multiple times and cause a lot of slow down. See: http://learnvimscriptthehardway.stevelosh.com/chapters/14.html. I've added my answer to this question. –  Jun 04 '14 at 20:28
  • Nice. This is an actual answer to question I had on how to (un)comment while you have a block selection. – user2609980 Aug 29 '14 at 22:27
  • My version of this(conceived as more general, don't know if it has bugs) https://gist.github.com/Bad-ptr/c880141ad3a68e4e4bc0/218e249f4c3f24efcaacf3eca037e77145993bf9#file-vimrc-L249 – Bad_ptr Apr 29 '15 at 12:01
  • 2
    My mod which defaults to // for unlisted filetypes and uses `` (default `\ `) instead of `,` and adds/removes the comment character after any indentation: https://gist.github.com/zonidjan/7fc11c2e9574c84383a87a8fcbe4b1ca – DimeCadmium Aug 07 '18 at 19:34
  • not sure why this isn't top ans. Most idiomatic way, no plugin required, supports motions – Darren Brien Apr 24 '20 at 14:59
  • Thanks @user427390, I corrected it. Does it look right now? – Bruno Bronosky Jun 14 '20 at 20:15
  • @user427390 thanx for the tutorial, I've read it all up. One question tho, in which case would vim re-source the ~/.vimrc script? – SimZhou Mar 06 '22 at 11:08
  • @DimeCadmium that link is broken. If it works, that should be the #1 answer for this question. Anyone using vim should have this. – Ralph Oct 11 '22 at 21:56
  • @Ralph yeah, I don't use GitHub anymore. It looks like I just removed `autocmd FileType c,cpp,java,scala` from the front of that line, and change `,cc` to `cc` in the noremap line. – DimeCadmium Dec 14 '22 at 00:24
  • @DimeCadmium not sure what you mean but I don't think that would help – Ralph Dec 14 '22 at 22:30
  • Today vim allows `autocmd FileType * let b:comment_leader = (split(&commentstring, '%s')+['//'])[0]`. Check :set cms? under different filetypes. Please note that the resulting string doesn't include the trailing space character. Also it may not work without +folding or in older versions. Not sure if I should edit the answer myself, so I'll leave it as a comment. tpope/vim-commentary seems to use 'commentstring' it as well. (Reposted with fix for empty cms) – user3125367 Aug 13 '23 at 16:06
153

Specify which lines to comment in vim:

Reveal the line numbers:

:set number

then

:5,17s/^/#/     this will comment out line 5-17

or this:

:%s/^/#/        will comment out all lines in file
JonnyRaa
  • 7,559
  • 6
  • 45
  • 49
Carlos
  • 1,539
  • 1
  • 9
  • 2
65

Here is how I do it:

  1. Go to first character on the first line you want to comment out.

  2. Hit Ctrl+q in GVIM or Ctrl+v in VIM, then go down to select first character on the lines to comment out.

  3. Then press c, and add the comment character.

Uncommenting works the same way, just type a space instead of the comment character.

isomorphismes
  • 8,233
  • 9
  • 59
  • 70
Marcin
  • 12,245
  • 9
  • 42
  • 49
65

Toggle comments

If all you need is toggle comments I'd rather go with commentary.vim by tpope.

enter image description here

Installation

Pathogen:

cd ~/.vim/bundle
git clone git://github.com/tpope/vim-commentary.git

vim-plug:

Plug 'tpope/vim-commentary'

Vundle:

Plugin 'tpope/vim-commentary'

Further customization

Add this to your .vimrc file: noremap <leader>/ :Commentary<cr>

You can now toggle comments by pressing Leader+/, just like Sublime and Atom.

Flavio Wuensche
  • 9,460
  • 1
  • 57
  • 54
46

I've come up with a simple addition to my .vimrc file which works pretty well and can be extended easily. You simply add a new filetype to the comment_map and its comment leader.

I added a mapping to normal and visual modes, but you can remap to anything you like. I prefer only to have a 'toggle' style function. One bears having multiple mappings etc.

let s:comment_map = { 
    \   "c": '\/\/',
    \   "cpp": '\/\/',
    \   "go": '\/\/',
    \   "java": '\/\/',
    \   "javascript": '\/\/',
    \   "lua": '--',
    \   "scala": '\/\/',
    \   "php": '\/\/',
    \   "python": '#',
    \   "ruby": '#',
    \   "rust": '\/\/',
    \   "sh": '#',
    \   "desktop": '#',
    \   "fstab": '#',
    \   "conf": '#',
    \   "profile": '#',
    \   "bashrc": '#',
    \   "bash_profile": '#',
    \   "mail": '>',
    \   "eml": '>',
    \   "bat": 'REM',
    \   "ahk": ';',
    \   "vim": '"',
    \   "tex": '%',
    \ }

function! ToggleComment()
    if has_key(s:comment_map, &filetype)
        let comment_leader = s:comment_map[&filetype]
        if getline('.') =~ "^\\s*" . comment_leader . " " 
            " Uncomment the line
            execute "silent s/^\\(\\s*\\)" . comment_leader . " /\\1/"
        else 
            if getline('.') =~ "^\\s*" . comment_leader
                " Uncomment the line
                execute "silent s/^\\(\\s*\\)" . comment_leader . "/\\1/"
            else
                " Comment the line
                execute "silent s/^\\(\\s*\\)/\\1" . comment_leader . " /"
            end
        end
    else
        echo "No comment leader found for filetype"
    end
endfunction


nnoremap <leader><Space> :call ToggleComment()<cr>
vnoremap <leader><Space> :call ToggleComment()<cr>

Note:

I don't use any callbacks or hooks into the file types/loading, because I find they slow down Vim's startup more than the .vimrc static function/map does but that's just my preference. I've also tried to keep it simple and performant. If you do use autocommands you need to be sure to put them in an autocommand group or else the callbacks get added to the filetype multiple times per-file loaded and cause a lot of performance degradation.

ideasman42
  • 42,413
  • 44
  • 197
  • 320
  • 1
    I'm completely new to vim, what button should I press to toggle the mapped function? What's that `` declaration at the bottom? – Jens Kohl Jun 16 '14 at 12:11
  • 2
    You can replace with a key like <,>. Then you press ,SPACE and it will toggle the line's comment state. Leader is whatever your leader is, Vim's default is \, but you can set your own like "let mapleader = ','" –  Jun 16 '14 at 23:36
  • Great answer, one annoyance though, commenting blocks that already have some comments, will swap commented for un-commented lines. QtCreator for eg only removes comments if all non-empty lines have leading comments, else add a leading comment. – ideasman42 Sep 24 '16 at 02:57
  • 1
    I have made a slightly different version using `\zs` and `\ze` regex trick, the code became a little smaller. you can see it [here](https://gist.github.com/voyeg3r/223f148a115c17a02a15660cc7335f4c) – SergioAraujo Mar 04 '18 at 22:34
  • This is the method that I use. If you're running it on an older version of vim, you might need to remove any trailing spaces in code lines to get it to work properly. I used `` to match Control-/ to match most other line comment keybinds. – Marthinwurer Jun 15 '21 at 21:04
26

Use Control-V to select rectangles of text: go to the first # character, type Ctrl+V, move right once, and then down, up to the end of the comments. Now type x: you're deleting all the # characters followed by one space.

R. Martinho Fernandes
  • 228,013
  • 71
  • 433
  • 510
Arthur Reutenauer
  • 2,622
  • 1
  • 17
  • 15
20

Here is a section of my .vimrc:

"insert and remove comments in visual and normal mode
vmap ,ic :s/^/#/g<CR>:let @/ = ""<CR>
map  ,ic :s/^/#/g<CR>:let @/ = ""<CR>
vmap ,rc :s/^#//g<CR>:let @/ = ""<CR>
map  ,rc :s/^#//g<CR>:let @/ = ""<CR>

In normal and in visual mode, this lets me press ,ic to insert comments and,rc to remove comments.

innaM
  • 47,505
  • 4
  • 67
  • 87
20

I use vim 7.4 and this works for me.
Assuming we are commenting/uncommenting 3 lines.

To comment:

if the line has no tab/space at the beginning:
ctrl + V then jjj then shift + I (cappital i) then //then esc esc
if the line has tab/space at the beginning you still can do the above or swap for c:
ctrl + V then jjj then c then //then esc esc

To uncomment:

if the lines have no tab/space at the beginning:
ctrl + V then jjj then ll (lower cap L) then c

if the lines have tab/space at the beginning, then you space one over and esc
ctrl + V then jjj then ll (lower cap L) then c then space then esc

Andy
  • 1,190
  • 1
  • 11
  • 25
20

Visual and Shift-I did not worked for me.

Simplest that worked without any plugins is


  1. Select block - V then j or k or any relevant motion (Don't use arrow keys) :)

  2. Then hit : it prompts command to :'<,'>

    To Comment

    Using #  - `s/^/#/` 
    
    Using `//` - `s/^/\/\//`
    

    To Uncomment

    Using #  - `s/^#//` 
    
    Using `//` - `s/^\/\//`
    

Exaplanation -

'<,'> - Apply to visual block

s - substitute

^ - starts with

after / add character # in this case of \/\/ escaped for //


Update

I wrote a function to comment and uncomment current line with <Space><Space>

Works for next 10 lines for example 10<Space><Space>

Paste it to .vimrc

function CommentUncomment()
  let line = getline('.')
  if line[:1] == "//"
      norm ^2x
  else 
      norm I//
  endif
endfunction

nnoremap <Space><Space> :call CommentUncomment()<CR>
Yugandhar Chaudhari
  • 3,831
  • 3
  • 24
  • 40
  • 3
    This is far the easiest way I found. In this case the full command to insert command would be `'<,'>s/^/#/g`. For me, it wouldn't work if not add `/g at the end, which indicates the cursor to move at the end of the `'<,'>` range – RicHincapie Aug 03 '21 at 22:25
  • 1
    If you have number lines enabled, you can do this: `:1,10 s/^/#/` to comment lines 1 to 10. – tomato Oct 12 '21 at 17:41
  • 1
    No need to escape the slashes, just use a different separator charakter: `:s#^#//` – Alexander Stumpf Mar 22 '22 at 20:42
18

I combined Phil and jqno's answer and made untoggle comments with spaces:

autocmd FileType c,cpp,java,scala let b:comment_leader = '//'
autocmd FileType sh,ruby,python   let b:comment_leader = '#'
autocmd FileType conf,fstab       let b:comment_leader = '#'
autocmd FileType tex              let b:comment_leader = '%'
autocmd FileType mail             let b:comment_leader = '>'
autocmd FileType vim              let b:comment_leader = '"'
function! CommentToggle()
    execute ':silent! s/\([^ ]\)/' . escape(b:comment_leader,'\/') . ' \1/'
    execute ':silent! s/^\( *\)' . escape(b:comment_leader,'\/') . ' \?' . escape(b:comment_leader,'\/') . ' \?/\1/'
endfunction
map <F7> :call CommentToggle()<CR>

how it works:

Lets assume we work with #-comments.

The first command s/\([^ ]\)/# \1/ searches for the first non-space character [^ ] and replaces that with # +itself. The itself-replacement is done by the \(..\) in the search-pattern and \1 in the replacement-pattern.

The second command s/^\( *\)# \?# \?/\1/ searches for lines starting with a double comment ^\( *\)# \?# \? (accepting 0 or 1 spaces in between comments) and replaces those simply with the non-comment part \( *\) (meaning the same number of preceeding spaces).

For more details about vim patterns check this out.

Markus Dutschke
  • 9,341
  • 4
  • 63
  • 58
mathewguest
  • 630
  • 5
  • 10
11

If you already know the line numbers, then n,ms/# // would work.

uckelman
  • 25,298
  • 8
  • 64
  • 82
  • really that should probably be: n,ms/^\s.#// Because you might have leading white space and might not follow the hash with one – Skip Huffman Jan 08 '13 at 14:25
11

With 30 answers ahead of me, I'll try to give an even easier solution: Insert a # at the beginning of the line. Then go down a line and press dot (.). To repeat, do j,.,j,., etc...To uncomment, remove a # (you can hit x over the #), and do the reverse using k,.,etc...

imagineerThat
  • 5,293
  • 7
  • 42
  • 78
  • 1
    It's a very simple answer even beginner can understand and use. However, it works pretty slowly on big amounts of lines to comment. To work around that you can write `I#j` to the buffer - say, `c` - and then do `10@c`, or whatever number of lines suits you. – Daerdemandt Jun 20 '17 at 06:19
  • Pretty cumbersome key combination for such simple task :( I am commenting and uncommenting stuff a lot using cmd+/ and lack of that function built-in is the reason I am not using vim for serious work – Sebastian Sep 28 '20 at 09:52
10

How to uncomment the following three lines in vi:

#code code
#code
#code code code

Place the cursor over the upper left # symbol and press CtrlV. This puts you in visual block mode. Press the down arrow or J three times to select all three lines. Then press D. All the comments disappear. To undo, press U.

How to comment the following three lines in vi:

code code
code
code code code

Place the cursor over the upper left character, press CtrlV. This puts you in visual block mode. Press or J three times to select all three lines. Then press:

I//Esc

That's a capital I, //, and Escape.

When you press ESC, all the selected lines will get the comment symbol you specified.

K.Dᴀᴠɪs
  • 9,945
  • 11
  • 33
  • 43
Ivor Scott
  • 159
  • 3
  • 12
9

I like to use the tcomment plugin: http://www.vim.org/scripts/script.php?script_id=1173

I have mapped gc and gcc to comment a line or a highlighted block of code. It detects the file type and works really well.

Rick
  • 15,484
  • 5
  • 25
  • 29
8

Yes, there are 33 (mostly repetitive) answers already to this question.

Here is another approach to how to comment lines out in Vim: motions. The basic idea is to comment or uncomment lines out using the same method as yanking a paragraph by typing yip or deleting 2 lines by typing dj.

This approach will let you do things like:

  • ccj to comment the next 2 lines out, and cuk to uncomment them;

  • cci{ to comment a block out, and cui{ to uncomment it;

  • ccip to comment a whole paragraph out, and cuip to uncomment it.

  • ccG to comment everything out down to the last line, and cugg to uncomment everything up to the first line.

All you need are 2 functions that operate over motions, and 2 mappings for each function. First, the mappings:

nnoremap <silent> cc  :set opfunc=CommentOut<cr>g@
vnoremap <silent> cc  :<c-u>call  CommentOut(visualmode(), 1)<cr>
nnoremap <silent> cu  :set opfunc=Uncomment<cr>g@
vnoremap <silent> cu  :<c-u>call  Uncomment(visualmode(), 1)<cr>

(See the manual about the g@ operator and the operatorfunc variable.)

And now the functions:

function! CommentOut(type, ...)
  if a:0
    silent exe "normal!  :'<,'>s/^/#/\<cr>`<"
  else
    silent exe "normal!  :'[,']s/^/#/\<cr>'["
  endif
endfunction

function! Uncomment(type, ...)
  if a:0
    silent exe "normal!  :'<,'>s/^\\(\\s*\\)#/\\1/\<cr>`<"
  else
    silent exe "normal!  :'[,']s/^\\(\\s*\\)#/\\1/\<cr>`["
  endif
endfunction

Modify the regular expressions above to suit your taste as to where the # should be:

Rich
  • 7,348
  • 4
  • 34
  • 54
n.r.
  • 1,900
  • 15
  • 20
  • "completely new [...] motions" seems a bit over the top: the t_comment and vim-commentary plugins, both of which predate this answer, allow you to comment out using motions. – Rich Nov 21 '16 at 17:06
  • Good stuff! Upvoted. (I also think I might start using this approach instead of the plugin I was using previously, so thanks for writing it!) – Rich Nov 22 '16 at 09:34
8

There is this life changing plugin by tpope called vim-commentary

https://github.com/tpope/vim-commentary

This plugin provides:

  • Sanity
  • Properly indented comments
  • Does not comment out empty/unnecessary lines

Usage:

  • Install via Vundle (or Pathogen I guess).
  • Highlight your text and press : which will show as :<,'>
  • Type Commentary here :<,'>Commentary and press Enter.
  • Boom. Your done bud.
fugu
  • 6,417
  • 5
  • 40
  • 75
Weston Ganger
  • 6,324
  • 4
  • 41
  • 39
8

A few regular Vim commands do not work with my setup on Windows. Ctrl + v and Ctrl + q are some of them. I later discovered the following methods worked to uncomment lines.

Given

Some indented comments

   # Practice in Vim
   # Practice in Vim
   # Practice in Vim
   # Practice in Vim
   # Practice in Vim
   # Practice in Vim
   # Practice in Vim

The following approaches remove the # symbol and preserve indents.

Approaches

Move the cursor to the first comment (arrows or h, j, k, l). Then apply one of the following techniques:

Visual Block Mode (faster)

  • Ctrl + Shift + v to enter VISUAL BLOCK mode
  • js to choose the vertical lines.
  • l to include horizontal characters (optional)
  • x to delete the block

Substitution

  • Highlight text in VISUAL mode: Shift + v
  • Type a command+:
    • :s/#// to substitute the hash with nothing
    • :s/# // to include the space (optional)
  • Enter

:norm command

  • Highlight text in VISUAL mode: Shift + v

  • Type a command+:

    • :norm ^x to remove the first non-whitespace character
    • :norm ^xx to include the space (optional)
  • Enter

g mode

  • Highlight text in VISUAL mode: Shift + v
  • Type a command+:
    • :g/#/norm! ^x.
    • :g/#/norm! ^xx to include the space (optional)
  • Enter

dgn

  • Search the symbol: \# Enter
  • Delete word under cursor: dgn
  • Repeat n times: ......

Results

    Practice in Vim
    Practice in Vim
    Practice in Vim
    Practice in Vim
    Practice in Vim
    Practice in Vim
    Practice in Vim

See Also

  • Post on removing indented comments
  • Post on how to quickly comment w/Vim
  • ThePrimeagen's tutorial on g commands.
  • VimTrick's tutorial on Commenting code

+Typing : in VISUAL mode with create a :'<,'> prompt.

pylang
  • 40,867
  • 14
  • 129
  • 121
7

I mark the first and last lines (ma and mb), and then do :'a,'bs/^# //

SDGator
  • 2,027
  • 3
  • 21
  • 25
6

I use EnhancedCommentify. It comments everything I needed (programming languages, scripts, config files). I use it with visual-mode bindings. Simply select text you want to comment and press co/cc/cd.

vmap co :call EnhancedCommentify('','guess')<CR>
vmap cc :call EnhancedCommentify('','comment')<CR>
vmap cd :call EnhancedCommentify('','decomment')<CR> 
qba
  • 1,291
  • 3
  • 15
  • 22
6

This answer is most useful if you are unable to install plugins but you still want your comment characters to follow existing indentation levels.

This answer is here to 1) show the correct code to paste into a .vimrc to get vim 7.4+ to do block commenting/uncommenting while keeping indentation level with 1 shortcut in visual mode and 2) to explain it. Here is the code:

let b:commentChar='//'
autocmd BufNewFile,BufReadPost *.[ch]    let b:commentChar='//'
autocmd BufNewFile,BufReadPost *.cpp    let b:commentChar='//'
autocmd BufNewFile,BufReadPost *.py    let b:commentChar='#'
autocmd BufNewFile,BufReadPost *.*sh    let b:commentChar='#'
function! Docomment ()
  "make comments on all the lines we've grabbed
  execute '''<,''>s/^\s*/&'.escape(b:commentChar, '\/').' /e'
endfunction
function! Uncomment ()
  "uncomment on all our lines
  execute '''<,''>s/\v(^\s*)'.escape(b:commentChar, '\/').'\v\s*/\1/e'
endfunction
function! Comment ()
  "does the first line begin with a comment?
  let l:line=getpos("'<")[1]
  "if there's a match
  if match(getline(l:line), '^\s*'.b:commentChar)>-1
    call Uncomment()
  else
    call Docomment()
  endif
endfunction
vnoremap <silent> <C-r> :<C-u>call Comment()<cr><cr>

How it works:

  • let b:commentChar='//' : This creates a variable in vim. the b here refers to the scope, which in this case is contained to the buffer, meaning the currently opened file. Your comment characters are strings and need to be wrapped in quotes, the quotes are not part of what will be substituted in when toggling comments.

  • autocmd BufNewFile,BufReadPost *... : Autocommands trigger on different things, in this case, these are triggering when a new file or the read file ends with a certain extension. Once triggered, the execute the following command, which allows us to change the commentChar depending on filetype. There are other ways to do this, but they are more confusing to novices (like me).

  • function! Docomment() : Functions are declared by starting with function and ending with endfunction. Functions must start with a capital. the ! ensures that this function overwrites any previous functions defined as Docomment() with this version of Docomment(). Without the !, I had errors, but that might be because I was defining new functions through the vim command line.

  • execute '''<,''>s/^\s*/&'.escape(b:commentChar, '\/').' /e' : Execute calls a command. In this case, we are executing substitute, which can take a range (by default this is the current line) such as % for the whole buffer or '<,'> for the highlighted section. ^\s* is regex to match the start of a line followed by any amount of whitespace, which is then appended to (due to &). The . here is used for string concatenation, since escape() can't be wrapped in quotes. escape() allows you to escape character in commentChar that matches the arguments (in this case, \ and /) by prepending them with a \. After this, we concatenate again with the end of our substitute string, which has the e flag. This flag lets us fail silently, meaning that if we do not find a match on a given line, we won't yell about it. As a whole, this line lets us put a comment character followed by a space just before the first text, meaning we keep our indentation level.

  • execute '''<,''>s/\v(^\s*)'.escape(b:commentChar, '\/').'\v\s*/\1/e' : This is similar to our last huge long command. Unique to this one, we have \v, which makes sure that we don't have to escape our (), and 1, which refers to the group we made with our (). Basically, we're matching a line that starts with any amount of whitespace and then our comment character followed by any amount of whitespace, and we are only keeping the first set of whitespace. Again, e lets us fail silently if we don't have a comment character on that line.

  • let l:line=getpos("'<")[1] : this sets a variable much like we did with our comment character, but l refers to the local scope (local to this function). getpos() gets the position of, in this case, the start of our highlighting, and the [1] means we only care about the line number, not other things like the column number.

  • if match(getline(l:line), '^\s*'.b:commentChar)>-1 : you know how if works. match() checks if the first thing contains the second thing, so we grab the line that we started our highlighting on, and check if it starts with whitespace followed by our comment character. match() returns the index where this is true, and -1 if no matches were found. Since if evaluates all nonzero numbers to be true, we have to compare our output to see if it's greater than -1. Comparison in vim returns 0 if false and 1 if true, which is what if wants to see to evaluate correctly.

  • vnoremap <silent> <C-r> :<C-u>call Comment()<cr><cr> : vnoremap means map the following command in visual mode, but don't map it recursively (meaning don't change any other commands that might use in other ways). Basically, if you're a vim novice, always use noremap to make sure you don't break things. <silent> means "I don't want your words, just your actions" and tells it not to print anything to the command line. <C-r> is the thing we're mapping, which is ctrl+r in this case (note that you can still use C-r normally for "redo" in normal mode with this mapping). C-u is kinda confusing, but basically it makes sure you don't lose track of your visual highlighting (according to this answer it makes your command start with '<,'> which is what we want). call here just tells vim to execute the function we named, and <cr> refers to hitting the enter button. We have to hit it once to actually call the function (otherwise we've just typed call function() on the command line, and we have to hit it again to get our substitutes to go through all the way (not really sure why, but whatever).

Anyway, hopefully this helps. This will take anything highlighted with v, V, or C-v, check if the first line is commented, if yes, try to uncomment all highlighted lines, and if not, add an extra layer of comment characters to each line. This is my desired behavior; I did not just want it to toggle whether each line in the block was commented or not, so it works perfectly for me after asking multiple questions on the subject.

jeremysprofile
  • 10,028
  • 4
  • 33
  • 53
5
"comment (cc) and uncomment (cu) code 
noremap   <silent> cc      :s,^\(\s*\)[^# \t]\@=,\1# ,e<CR>:nohls<CR>zvj
noremap   <silent> cu      :s,^\(\s*\)# \s\@!,\1,e<CR>:nohls<CR>zvj

You can comment/uncomment single or multiple lines with #. To do multiple lines, select the lines then type cc/cu shortcut, or type a number then cc/cu, e.g. 7cc will comment 7 lines from the cursor.

I got the orignal code from the person on What's the most elegant way of commenting / uncommenting blocks of ruby code in Vim? and made some small changes (changed shortcut keys, and added a space after the #).

Community
  • 1
  • 1
konyak
  • 10,818
  • 4
  • 59
  • 65
5

I use Tim Pope's vim-commentary plugin.

Jim Stewart
  • 16,964
  • 5
  • 69
  • 89
5

Starting with the ideas in answers here, I started my own comment function. It toggles comments on and off. It can handle things like //print('blue'); //this thing is blue and just toggles the first comment. Furthermore it adds comments and a single space just where the first non whitespace is and not at the very start of the line. Aditionally it doesn't unnecessarily copy the whitespaces, but uses zooms (:h \zs for help) to avoid this extra work, when commenting and indented line. Hope it helps some minimalists out there. Suggestions are welcome.

" these lines are needed for ToggleComment()
autocmd FileType c,cpp,java      let b:comment_leader = '//'
autocmd FileType arduino         let b:comment_leader = '//'
autocmd FileType sh,ruby,python  let b:comment_leader = '#'
autocmd FileType zsh             let b:comment_leader = '#'
autocmd FileType conf,fstab      let b:comment_leader = '#'
autocmd FileType matlab,tex      let b:comment_leader = '%'
autocmd FileType vim             let b:comment_leader = '"'

" l:pos   --> cursor position
" l:space --> how many spaces we will use b:comment_leader + ' '

function! ToggleComment()
    if exists('b:comment_leader')
        let l:pos = col('.')
        let l:space = ( &ft =~ '\v(c|cpp|java|arduino)' ? '3' : '2' )
        if getline('.') =~ '\v(\s*|\t*)' .b:comment_leader
            let l:space -= ( getline('.') =~ '\v.*\zs' . b:comment_leader . '(\s+|\t+)@!' ?  1 : 0 )
            execute 'silent s,\v^(\s*|\t*)\zs' .b:comment_leader.'[ ]?,,g'
            let l:pos -= l:space
        else
            exec 'normal! 0i' .b:comment_leader .' '
            let l:pos += l:space
        endif
        call cursor(line("."), l:pos)
    else
        echo 'no comment leader found for filetype'
    end
endfunction

nnoremap <Leader>t :call ToggleComment()<CR>
inoremap <Leader>t <C-o>:call ToggleComment()<CR>
xnoremap <Leader>t :'<,'>call ToggleComment()<CR>
SergioAraujo
  • 11,069
  • 3
  • 50
  • 40
mike
  • 791
  • 11
  • 26
  • 1
    I have made a slightly different version of your solution that also restores the cursor position, I would like your opinion on that. [on github](https://gist.github.com/voyeg3r/1c589b685e9568125038d4d4035af656) – SergioAraujo Mar 23 '18 at 13:53
  • Cool. You can edit my post and add your solution (because of similarity)! – mike Mar 23 '18 at 15:50
  • It has changed to avoid backslashing c,cpp,java and using another separator in substitutions to avoid E488. Also the spacing changes for java, cpp because the comments have three chars, // plus space, this is done by l:space. – SergioAraujo Mar 24 '18 at 10:27
5

You can use vim-commentary by tpope (https://github.com/tpope/vim-commentary) you can use it as following:

Enter visual mode by pressing

'v'

Then press

'j' repeatedly or e.g 4j to select 4 row

Now all you have to do with the selection is enter keys:

'gc'

This will comment out all the selection, to uncomment repead keys:

'gc'
Kingsley Ijomah
  • 3,273
  • 33
  • 25
4

This simple snippet is from my .vimrc:

function! CommentToggle()
    execute ':silent! s/\([^ ]\)/\/\/ \1/'
    execute ':silent! s/^\( *\)\/\/ \/\/ /\1/'
endfunction

map <F7> :call CommentToggle()<CR>

It's for //-Comments, but you can adapt it easily for other characters. You could use autocmd to set a leader as jqno suggested.

This is a very simple and efficient way working with ranges and visual mode naturally.

Phil
  • 3,282
  • 1
  • 20
  • 16
4

I use comments.vim from Jasmeet Singh Anand (found on vim.org),

It works with C, C++, Java, PHP[2345], proc, CSS, HTML, htm, XML, XHTML, vim, vimrc, SQL, sh, ksh, csh, Perl, tex, fortran, ml, caml, ocaml, vhdl, haskel, and normal files

It comments and un-comments lines in different source files in both normal and visual mode

Usage:

  • CtrlC to comment a single line
  • CtrlX to un-comment a single line
  • ShiftV and select multiple lines, then CtrlC to comment the selected multiple lines
  • ShiftV and select multiple lines, then CtrlX to un-comment the selected multiple lines
K.Dᴀᴠɪs
  • 9,945
  • 11
  • 33
  • 43
Ronan
  • 4,311
  • 3
  • 19
  • 14
4

I use vim-multiple-cursors for this.

  1. To select the region, go to the first character of the first or last line of the region to be commented out by pressing 0 (it's zero, not letter "o"). Then press V and select the region using J, K or up and down arrow keys.
  2. Then put a virtual cursor on each line of the selection by pressing CtrlN.
  3. Then press I to simultaneously edit each line of the selection.
nrz
  • 10,435
  • 4
  • 39
  • 71
  • It doesn't work here, when I press `Ctrl` + `N` it selects the line bellow. –  Aug 10 '15 at 17:09
  • 2
    @Gerep Do you have [vim-multiple-cursors](http://www.vim.org/scripts/script.php?script_id=4523) installed? If yes, do you have the latest version of vim-multiple-cursors? Did you move to the first character of the first or the last line to be commented out/uncommented by pressing `0`? Did you then select the lines to be commented out/uncommented using Visual mode (by pressing `V` or `Ctrl`+`V` to enter Visual mode, then `J` or `K` to select all the lines you want to comment out/uncomment) before you pressed `Ctrl`+`N`? – nrz Aug 11 '15 at 06:19
  • 1
    Oh!!! I'm really sorry, I thought vim-multiple-cursors was a built in functionality, it is working now, thank you =) –  Aug 11 '15 at 10:05
  • Just for me works with: `\di#`. Thank you for advice. – Alexander Borisov Aug 22 '16 at 11:43
4

The quickest and the most intuitive method of them all is to remap ) for walk-down-commenting of lines, and then ( for walk-up-uncommenting. Try it and you won't go back.

In Ruby or Bash, with 2-space indents:

map ) I# <Esc>j
map ( k^2x

In C/C++ or PHP, with 4-space indents:

map ) I//  <Esc>j
map ( k^4x

Downsides are that you lose ( and ) for sentence-movement (but das can fill in there), and you'll occasionally fall back on select-and-replace or CtrlV for handling long sections. But that's pretty rare.

And for C-style, the long comments are best handled with:

set cindent
set formatoptions=tcqr

... Which combines well with using V[move]gq to redo the word-wrapping.

K.Dᴀᴠɪs
  • 9,945
  • 11
  • 33
  • 43
eukras
  • 869
  • 7
  • 4
4

To uncomment the whole file:

  1. Esc exits insert mode
  2. gg goes to first char on first line
  3. ctrl+V or ctrl+shift+v selects current char
  4. G or shift+g goes to last line
  5. x deletes selection
JSON C11
  • 11,272
  • 7
  • 78
  • 65
3

I like /* ... */ (C ansi comments), so here it is my trick for you. You can adapt it to use in different cases, of course.


Comment with /* ... */

Select the text (go to the begin, start visual block, jump with }):

<c-V>}

Type the command to be applied in the selection

:norm i/* <c-v><esc>$a */

Command will look like: :'<,'>norm i /* ^[$a */

See (i*) for details.


Uncomment the /* ... */

Select the text (as before, or other way you like):

<c-V>}

Type the command to be applied in the selection

:norm :s-\s*/\*\s*-<c-v><enter>$bbld$

Command will look like: :'<,'>norm :s-\s*/\*\s*-^M$bbld$

See (ii*) for details.


Result

Effect is comments line by line:

Comment block
Comment block
Comment block

Becomes (and vice-versa):

/* Comment block */
/* Comment block */
/* Comment block */

Its better to save it as some map or @reg in your .vimrc, because it's a lot to type. If you prefer a single /* and */ to the whole block, use:

Comment with a single /* */ the whole block

Save it in a register by recording with, say, qc, then, at the beginning of a paragraph to comment:

v}di/*  */<esc>hhhp

and don't forget q again, to finish the record.

See (iii*) for details.


Uncomment a single /* */ from a block

Save it in register, say, @u. Put your cursor anywhere inside the block, and:

?/\*<enter>xx/\*/<enter>xx

Save the register by finishing q command.

See (iv*) for details.


Result

Effect is a single comment for multiple lines:

Comment block
Comment block
Comment block

Becomes (and vice-versa):

/* Comment block
Comment block
Comment block */

Explanations

(i*) It works by using norm which applies the same command repeatedly in every selected line. The command simply insert a /*, finds the end of that line and finishes by inserting a */

:norm i/* <c-v><esc>$a */

(ii*) It also uses norm to repeat the search/replace on every line. Search for spaces /* spaces and replace by nothing. After that, finds the end of the line, back two words, right a letter, delete to the end.

:norm :s-\s*/\*\s*-<c-v><enter>$bbld$

(iii*) Selects the paragraph by v}, delete it, insert a comment open and close, move to its middle and paste the deleted block.

v}di/*  */<esc>hhhp

(iv*) Anywhere in the middle, finds backwards a /*, deletes it; finds forward a */, deletes it.

?/\*<enter>xx/\*/<enter>xx
DrBeco
  • 11,237
  • 9
  • 59
  • 76
3

Here's a basic one-liner based on the C-v followed by I method outlined above.

This command (:Comment) adds a chosen string to the beginning of any selected lines.

command! -range -nargs=1 Comment :execute "'<,'>normal! <C-v>0I" . <f-args> . "<Esc><Esc>"

Add this line to your .vimrc to create a command that accepts a single argument and places the argument at the beginning of every line in the current selection.

E.g. if the following text is selected:

1
2

and you run this: :Comment //, the result will be:

//1
//2
bgran
  • 867
  • 6
  • 12
3

I like short, integrated and memorable methods to not be dependent on externals scripts an fancy fuss...

TLDR:
press gI (capital i) to place the cursor in insert mode on the beginning of the line (regardless if it is space or non-space character and preventing automatic indention)

Use this to fastly comment (e.g.) non-consecutive lines with the comment-sigil (e.g. # or //) as first character and without indention, by pressing the . (dot) --> but if there is still an auto-indention mechanism, while in insert mode press and to correct indention and after action escape to normal mode. Now . is usable to comment out lines...

long:
I realized now (after years), that pressing gI (capital i) will place the cursor at column 1 in insert mode (meaning: at the beginning of the line no matter if it's a word or non-word character).

Inserting the commenting sigil (like #) and pressing escape - now it's possible to comment single, non-consecutive lines (with the comment-sigil as first character and no indention) while just pressing the . (dot) on the keyboard.

In contrast to pressing 0i or just I where it's placing the commenting sigil at the first word-character, partly also with unwanted indention

MacMartin
  • 2,366
  • 1
  • 24
  • 27
  • And for uncommenting, you'd repeat the steps but with removing the comment sigil. Also, be wary of any auto-indent settings you have that may add leading space before the comment sigil. Otherwise, the "undo" function is a bit more tedious. – Jonathan E. Landrum Jul 11 '22 at 15:52
2

In VIM:

1- Enter visual mode by presssing v.

2- Use arrows to select the block you want to comment.

3- Press :

4- Type 's/^/#'

To remove comments just replace step 4 with:

4- Type 's/^#//'

BOUKANDOURA Mhamed
  • 941
  • 1
  • 9
  • 25
2
  1. One way to comment the lines is using visual block selection
  • Place your cursor on the 0th location of the line which needs to be commented, then ctrl + v to enter visual block. Now use j (downwards) or k (upwards) to navigate to the lines that need to be commented.
  • Then use c to cut and insert test. Now type "#" to comment and esc to reflect your insertion on the selected lines
  1. Using command mode
  • Select the line with V, then select all the lines that need to be commented using j (downawrds) k (upwards) and hit : to enter into command mode which looks like ":<,>" then insert the "#" in the beginning of each line selected
:'<,'>s/^/#
Karthik MB
  • 21
  • 2
1

There are several vim plugins like Tcomment and nerdcommenter available.

I use tcomment for commenting purposes.

gcc: It will will toggle comment on the current line. v{motion}gc: It will toggle commenting a range of lines visually selected

Example: v3jgc will toggle region of 3 lines.

These commands can work for working with comments in any language.

dvk317960
  • 672
  • 5
  • 10
1

@CMS's solution is the most "vim native" way to comment in/out lines. In @CMS's second step, after CtrlV, you could also use r# to add comments or x to delete them. Drew Neil's Practical Vim, page 46, explains this technique well.

Another good option is to use an ex mode command. :[range]normali##. Obviously, to save keystrokes with this one, you'll need to comment out 15+ lines.

jfmercer
  • 3,641
  • 3
  • 29
  • 35
1

Even though this question already has a ton of answers I still thought I would give a shoutout to a small plugin I wrote: commentify.

Commentify uses the commentstring setting to decide how to comment out a block of code, so you don't have to keep a mapping of different comment types in your configuration, and supports both line based comments (eg, //) and block comments (eg, /* */).

It also maps the same shortcut (defaults to ctrl+c) for both commenting and uncommenting the block, so you don't have to remember two mappings or a complex set of commands.

Jaymon
  • 5,363
  • 3
  • 34
  • 34
1
" comments
augroup comment_like_a_boss
    autocmd!
    autocmd FileType c,cpp,go                let b:comment_leader = '// '
    autocmd FileType ruby,python             let b:comment_leader = '# '
    autocmd FileType conf,fstab,sh,bash,tmux let b:comment_leader = '# '
    autocmd FileType tex                     let b:comment_leader = '% '
    autocmd FileType mail                    let b:comment_leader = '> '
    autocmd FileType vim                     let b:comment_leader = '" '
augroup END
noremap <silent> ,cc :<C-b>silent <C-e>norm ^i<C-r>=b:comment_leader<CR><CR>
noremap <silent> ,uc :<C-b>silent <C-e>norm ^xx<CR>
moeabdol
  • 4,779
  • 6
  • 44
  • 43
  • 1
    Works like a charm, is short and adapts to your filetype. __Instructions__: Put this in your `~/.vimrc`. Mark region w/ `v` + cursor of jk keys. Use `,cc` to comment, `,uc` to uncomment regions. – count0 Sep 12 '22 at 13:54
1

First, I'd like to thank @mike for his answer, as I'm using a modified version of it. I wanted to post my version, in case anyone is interested. The main functional difference for mine is that it will always perform the same action on every line of the range. If the selected range contains any uncommented lines, then every line has a comment leader added to it. This way, if you have human-readable comments in your otherwise uncommented code block, they don't become uncommented. Then, when you uncomment the block, the human-readable text will remain commented, since it has 2 comment leaders. It also restores the cursor position when done.

The ToggleComment function:

function! ToggleComment() range
    "Ensure we know the comment leader.
    if !exists('b:comment_leader')
        echo "Unknown comment leader."
        return
    endif
    "Save the initial cursor position, to restore later.
    let l:inipos = getpos('.')
    "Make a list of all of the line numbers in the range which are already commented.
    let l:commented_lines = []
    for i in range(a:firstline, a:lastline)
        if getline(i) =~ '^\s*' . b:comment_leader
            let l:commented_lines = add(l:commented_lines, i)
        endif
    endfor
    "If every line in the range is commented, set the action to uncomment.
    "  Otherwise, set it to comment.
    let l:i1 = index(l:commented_lines, a:firstline)
    let l:i2 = index(l:commented_lines, a:lastline)
    if l:i1 >= 0 && l:i2 >= 0 && (l:i2 - l:i1) == (a:lastline - a:firstline)
        let l:action = "uncomment"
    else
        let l:action = "comment"
    endif
    "Loop through the range, commenting or uncommenting based on l:action.
    for i in range(a:firstline, a:lastline)
        "Move to line i.
        exec "exe " . i
        "Perform the action.
        if l:action == "comment"
            exec 'normal! 0i' . b:comment_leader
        else
            execute 'silent s,' . b:comment_leader . ',,'
        endif
    endfor
    "Restore the initial position.
    call setpos('.', l:inipos)
endfunction

The key mapping (note that I changed the comment key to 'k'):

noremap <Leader>k :call ToggleComment()<CR>

Lastly, I put the autocmds inside the "if" statement and augroup below, but they are unchanged. They are mostly just there for reference.

if has("autocmd")
    augroup autocmds
        autocmd!
        autocmd FileType c,cpp,java      let b:comment_leader = '//'
        autocmd FileType arduino         let b:comment_leader = '//'
        autocmd FileType sh,ruby,python  let b:comment_leader = '#'
        autocmd FileType zsh             let b:comment_leader = '#'
        autocmd FileType conf,fstab      let b:comment_leader = '#'
        autocmd FileType matlab,tex      let b:comment_leader = '%'
        autocmd FileType vim             let b:comment_leader = '"'
    augroup END
endif

EDIT: I updated the ToggleComment function from my original answer. Most importantly, I modified the regular expressions. In many cases, it would not work correctly if there was another instance of a comment leader in the string. I believe it may have had to be preceded or followed by a space, but I can't remember. Either way, an example error case for Python is below.

print("Hello, World!") # Says hello to the world.

I've fixed this, and simplified the regular expressions a bit. One side effect is that it no longer adds a space after the comment leader, but this does not bother me. I've added a local declaration to a few variables that I forgot in my original answer.

0

I personally don't like a comment "toggle" function, as it will destroy comments wich are already included in the code. Also, I want to have the comment char appear on the far left, always, so I can easily see comment blocks. Also I want this to work nested (if I first comment out a block and later an enclosing block). Therefore, I slightly changed one of the solutions. I use F5 to comment and Shift-F5 to uncomment. Also, I added a /g at the end of the s/ command:

autocmd FileType c,cpp,java,scala let b:comment_leader = '//'
autocmd FileType sh,ruby,python   let b:comment_leader = '#'
autocmd FileType conf,fstab       let b:comment_leader = '#'
autocmd FileType tex              let b:comment_leader = '%'
autocmd FileType mail             let b:comment_leader = '>'
autocmd FileType vim              let b:comment_leader = '"'
autocmd FileType nasm             let b:comment_leader = ';'

function! CommentLine()
    execute ':silent! s/^\(.*\)/' . b:comment_leader . ' \1/g'
endfunction

function! UncommentLine()
    execute ':silent! s/^' . b:comment_leader . ' //g'
endfunction

map <F5> :call CommentLine()<CR>
map <S-F5> :call UncommentLine()<CR>
Flo
  • 421
  • 4
  • 6
0

Very good question, but not so many good answers imho. First, I would say, using block insert mode is not an easy solution here, just too many keystrokes, so obviously it must work on selected lines to improve performance of code editing. Another point which nobody mentions : where the comment sign should be put - in the very beginning of the line or before actual text? It is a matter of taste probably, but my opinion, it should be put before the text to keep the code readable: when the comment sign is put in the very line beginning it breaks the visual consistence of indented code, so it looks like a bulleted list. With that in mind, I've ended up with following solution (I make example for # comment). In my vimrc:

vnoremap 1 :s:^\(\s*\)\([^#\t ]\):\1#\2:e<CR>
vnoremap 2 :s:^\(\s*\)#\(\s*\):\1\2:e<CR>

Key 1 inserts # before the text (after white space) in every selected line. It checks if there is already #, not to insert # twice. And also ignores empty lines.
Key 2 deletes one #. It also keeps the comments on the right side of line safe.


Update: here is an example, how to make file type dependent toggle comment command. To learn more about these thing read: http://learnvimscriptthehardway.stevelosh.com/chapters/14.html

Just to make it work, put the following lines in your .vimrc file.

" build the whole regex search/replace command
function! Build()
    let b:Comment_ON='''<,''>s:^\(\s*\)\([^\t ]\):\1' . b:cs . '\2:e'
    let b:Comment_OFF='''<,''>s:^\(\s*\)' . b:cs . '\(\s*\):\1\2:e'
endfunction

" run this group on Filetype event
augroup SetCS
    autocmd!
    "default comment sign
    autocmd FileType * let b:cs='--'
    "detect file type and assign comment sign
    autocmd FileType python,ruby let b:cs='#'
    autocmd FileType c,cpp,java,javascript,php let b:cs = '\/\/'
    autocmd FileType vim let b:cs='"'
    autocmd FileType * call Build()
augroup END

vnoremap 1 :<C-u>execute b:Comment_ON<CR>
vnoremap 2 :<C-u>execute b:Comment_OFF<CR>
Mikhail V
  • 1,416
  • 1
  • 14
  • 23
  • Block inserts _is_ a good solution for editing files on remote servers. If most of your edits are local you might look into other approaches — snippets (like yours) or plugins. – timurb Feb 26 '18 at 14:50
0

This solution maps / to commenting and ? to uncommenting (comment toggling using the single mapping is too complex to implement properly). It takes comment strings from VIM's builtin commentstring option which is populated from files like /usr/share/vim/vim*/ftplugin/*.vim if filetype plugin on is declared.

filetype plugin on
autocmd FileType * let b:comment = split(&commentstring, '%s', 1)
autocmd FileType * execute "map <silent> <Leader>/ :normal 0i" . b:comment[0] . "<C-O>$" . b:comment[1] . "<C-O>0<CR>"
autocmd FileType * execute "map <silent> <Leader>? :normal $" . repeat('x', strlen(b:comment[1])) . "0" . strlen(b:comment[0]) . "x<CR>"
sgtpep
  • 819
  • 1
  • 7
  • 3
0

I personally wanted commenting a-la Visual Studio. I've gotten so used to it at work that it has taken over my muscle memory (using vsvim). Use shift+v select lines you want and then press ctrl+k, ctrl+c to comment or Ctrl+k, Ctrl+u to uncomment.

:vnoremap <C-k><C-c> :norm i//<Cr>
:vnoremap <C-k><C-u> :s/\/\///g<Cr>:noh<Cr>
scx
  • 3,221
  • 1
  • 19
  • 37
0

Here's a new method that extends very generally to other Bash aliases and functions:

  • use this to add a line to .vimrc echo 'let $BASH_ENV = "~/.bash_aliases"' >> .vimrc (change to ~/.bashrc or ~/.profile if desired). Now add this alias or function to that file:
    function cmt { while read -r line; do echo "${1:-#} $line"; done; } or..
    alias cmt='while read -r line; do echo "# $line"; done';shopt -s expand_aliases and use "${line/\#\ /}" to remove.
    Now type !! and cmt to run the alias on the line (:.!cmt), or !} to run it on a paragraph (:.,$!cmt) or with line numbers (:3,5!cmt), or use Visual mode crtl-V (:'<,'>!cmt).

You can transform lines with any function or even Bash script with this. Very powerful.. it can send lines to files, use lines as arguments, endless possibilities!

  • or use F4 in Visual mode with these lines in .vimrc:
    "comment"
    vnoremap <F4> :s/^/# <CR>:set hlsearch!<CR>
    nnoremap <F4> :s/^/# <CR>:set hlsearch!<CR>
    "uncomment"
    nnoremap <F6> :s/^# //<CR>
    vnoremap <F6> :s/^# //<CR>

Here's a few from above I also like for single lines or multiple with Visual mode:

  • use map ) I# <Esc>j and map ( k^2x to comment and goto next line. This can be saved in .vimrc with keymapping.

  • use :s/^/#/ in command mode. and :s/^# //

  • use gI for insert mode at line beginning.

  • remap ctrl-k and crtl-u to comment and uncomment, like in VSCode.
    :vnoremap <C-k><C-c> :norm i//<Cr>
    :vnoremap <C-k><C-u> :s/\/\///g<Cr>:noh<Cr>

alchemy
  • 954
  • 10
  • 17
-1

: %s/^/ \ / \ / /g

remove the sapces between the characters and Use this command to comment .C or CPP files

-1

To Comment A Line (For All Languages):

  • noremap <silent> ,// :call CommentLine() <CR>

We can call it with number of lines and in visual mode too, it works. Like : To comment four lines use 4,// and to uncomment use 4,/.

To Uncomment A Line (For All Languages):

  • noremap <silent> ,/ :call UnCommentLine() <CR>

If You want to add new symbol[comment] then add a list and add some lines in function. If you want to add a language that has the comment symbol that already defined in one of the lists just add your language name in the corresponding list (To Get correct name: Open your file in vim and use :set ft to get the correct name for your language).

Definition of CommentLine()

function! CommentLine() let slash_ft_list = ['c' , 'cpp', 'java', 'scala' , 'systemverilog' , 'verilog' , 'verilog_systemverilog'] let hash_ft_list = ['sh' , 'ruby' , 'python' , 'csh' , 'conf' , 'fstab' , 'perl'] let perct_ft_list = ['tex'] let mail_ft_list = ['mail'] let quote_ft_list = ['vim'] if (index(slash_ft_list, &ft) != -1) :norm I// elseif (index(hash_ft_list, &ft) != -1) :norm I# elseif (index(perct_ft_list, &ft) != -1) :norm I% elseif (index(mail_ft_list, &ft) != -1) :norm I> elseif (index(quote_ft_list, &ft) != -1) :norm I" endif endfunction

Definition of UnCommentLine()

function! UnCommentLine() let slash_ft_list = ['c' , 'cpp', 'java', 'scala' , 'systemverilog' , 'verilog' , 'verilog_systemverilog'] let hash_ft_list = ['sh' , 'ruby' , 'python' , 'csh' , 'conf' , 'fstab' , 'perl'] let perct_ft_list = ['tex'] let mail_ft_list = ['mail'] let quote_ft_list = ['vim'] if (index(slash_ft_list, &ft) != -1) :norm ^2x elseif (index(hash_ft_list, &ft) != -1) :norm ^x elseif (index(perct_ft_list, &ft) != -1) :norm ^x elseif (index(mail_ft_list, &ft) != -1) :norm ^x elseif (index(quote_ft_list, &ft) != -1) :norm ^x endif endfunction

AnuragChauhan
  • 143
  • 1
  • 15
-1
:g/.spare[1-9].*/,+2s/^/\/\//

The above code will comment out all the lines that contain "spare" and a number after that plus it will comment two lines more from the line in which that was found. For more such uses visit : http://vim.wikia.com/wiki/Search_and_replace#Details

-2

mark a text area by mark command say ma and mb type command: :'a,'bg/(.*)/s////\1/

You can see an example of this kind of test manipulation at http://bknpk.ddns.net/my_web/VIM/vim_shell_cmd_on_block.html

-3

Press ctrl+v then use or to select the number of lines to comment. Then press shift+I, press # and then ESC. This will comment out the number of lines you have selected.

The opposite for uncomment lines.

Diego C Nascimento
  • 2,801
  • 1
  • 17
  • 23
Ravikumar
  • 57
  • 3
  • 2
    Welcome to StackOverflow Ravikumar. Note that your answer is an exact duplicate of an existing answer (http://stackoverflow.com/a/15588798/430128). Your efforts will be more appreciated if you do not copy the substance of an existing answer without contributing any new ideas. – Raman Jan 08 '14 at 06:44
  • 3
    Instead of posting the same answer as others, you could rather try on your own. – Santhosh Jan 08 '14 at 06:46