created 2008 · complexity basic · author Jlepak · version 7.0
This tip uses the opfunc option to define two operators. Assuming the default backslash leader key, the operators are:
\cto comment lines (insert a comment string before each line)\Cto uncomment lines
Usage[]
For example, put the cursor anywhere in the def block in the following Python code:
class Example:
def f(self, x):
if x < 5:
print "Pointless function."
return 0
The command yip (yank inner paragraph) would copy the block. In a similar manner, the command \cip will comment-out the block, resulting in:
class Example:
# def f(self, x):
# if x < 5:
# print "Pointless function."
# return 0
Later, you could remove the comment signifiers with \Cip.
An operator can be used in two ways:
- Invoke the operator, then enter a movement command. or
- Visually select a block, then invoke the operator.
Examples:
\ciBcomment inner block (between braces)\c}comment to end paragraph\cGcomment to end bufferVjjj\ccomment visually-selected lines
Script[]
Here's the code. It only handles linewise comments.
" Comment or uncomment lines from mark a to mark b.
function! CommentMark(docomment, a, b)
if !exists('b:comment')
let b:comment = CommentStr() . ' '
endif
if a:docomment
exe "normal! '" . a:a . "_\<C-V>'" . a:b . 'I' . b:comment
else
exe "'".a:a.",'".a:b . 's/^\(\s*\)' . escape(b:comment,'/') . '/\1/e'
endif
endfunction
" Comment lines in marks set by g@ operator.
function! DoCommentOp(type)
call CommentMark(1, '[', ']')
endfunction
" Uncomment lines in marks set by g@ operator.
function! UnCommentOp(type)
call CommentMark(0, '[', ']')
endfunction
" Return string used to comment line for current filetype.
function! CommentStr()
if &ft == 'cpp' || &ft == 'java' || &ft == 'javascript'
return '//'
elseif &ft == 'vim'
return '"'
elseif &ft == 'python' || &ft == 'perl' || &ft == 'sh' || &ft == 'R'
return '#'
elseif &ft == 'lisp'
return ';'
endif
return ''
endfunction
nnoremap <Leader>c <Esc>:set opfunc=DoCommentOp<CR>g@
nnoremap <Leader>C <Esc>:set opfunc=UnCommentOp<CR>g@
vnoremap <Leader>c <Esc>:call CommentMark(1,'<','>')<CR>
vnoremap <Leader>C <Esc>:call CommentMark(0,'<','>')<CR>
Explanation[]
A custom operator can be defined using visual-mode maps (to apply the operator to a selection), and using the operatorfunc (opfunc) option (to apply the operator to a movement).
The g@ operator can be used in a map to define your own operator. When g@ is invoked, the function defined by the opfunc option is called with an argument indicating the type of motion ("line", "char" or "block"). In addition, the '[ and '] marks identify the start and end positions of the motion.
You can let the script determine the comment string from the filetype, or you can define the buffer-local variable comment, for example:
:let b:comment='#---'