I want to map \c to comment the current line in vim (add '// ' to before the first non-blank to the line) and \d to delete the '// ' at the beginning of line(uncomment).
I've added these two lines in my vimrc:
imap \c <Esc>:s/^/\/\/ <CR>j$a
imap \d <Esc>:s/^\/\/ /<CR>j$a
but when I call this in this line:
for (int i = 0; i < n; i++)
then it is converted to:
// for (int i = 0; i < n; i++)
but I want to convert it to:
// for (int i = 0; i < n; i++)
one of the reasons I want this is that when I want vim to indent this line, it will add an extra tab at the beginning of the line and convert it to:
// for (int i = 0; i < n; i++)
what should I do? I thought that ^ refers to first non-blank character of line but it wasn't true.
P.S: I've found these two commands, but I don't know what are they doing. could you please explain them to me (because I need to remember them and they're easier to remember when I know what are they). if any part of them is unnecessary please tell me:
imap \c <ESC>:s,^\(\s*\)[^/ \t]\@=,\1// ,e<CR>j$a
imap \d <ESC>:s,^\(\s*\)// \s\@!,\1,e<CR>j$a
I recommend using the Enhanced Commentify plugin. You can then add this to your
~/.vimrc
file:and it will give you the behaviour you are after. In visual mode, select the area of code that you want to comment and then type
\c
. To uncomment use\C
.Even though the
^
normal mode command goes to the first non-blank,^
in a pattern (so in the:s
,:g
,:v
,:sort
commands) means start of line. See:help /^
Use
I
to insert at first non-blank, andA
to append after last character.Use:
There are, however, good plugins that do the job. commentary by Tim Pope, or the NERD Commenter. See their documentation.
About those commands you found:
Let's start with the pattern match, comparing it with your
:s/^/\/\/ <CR>j$a
.:s,
is exactly equivalent to:s/
- you can choose a nonstandard seperator where it makes the expression more readable, so here using,
instead of/
means less escaping, and no confusion between the comment//
and the seperator^(\s*)
matches the beginning of the line (same as yours) and any leading whitespace, capturing the whitespace so we can reuse it later[^# \t]\@=
just requires some character other than space, tab or#
before the line end, but doesn't capture it (ie, that character won't be replaced),\1// ,
replaces the matched string with the leading whitespace (\1
is whatever was captured by the(\s*)
group) followed by//
For example:
should match like so:
^(\s*)[^# \t]\@=
->^( )(v@=)void foo();
, ie, the first group matches the leading whitespace, and the next expression matches but doesn't consume thev
fromvoid
. Then,\1//
expands to:and the final substitution result is:
(I've marked the start of line with
^
since the indentation is ambiguous otherwise)