首先,我要感谢@mike的回答,因为我使用的是它的修改版本。我想发布我的版本,以防有人感兴趣。我的主要功能区别在于,它将始终在射程的每一行上执行相同的动作。如果所选范围包含任何未注释的行,则每一行都会添加注释引线。这样,如果在未注释的代码块中有人类可读的注释,则它们不会变为未注释。然后,当您取消注释块时,人类可读的文本将保持注释状态,因为它有两个注释引线。完成后,它还会恢复光标位置。
ToggleComment函数:
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
键映射(注意,我将注释键更改为“k”):
noremap <Leader>k :call ToggleComment()<CR>
最后,我将autocmds放在下面的“if”语句和augroup中,但它们保持不变。它们大多只是供参考。
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
编辑:我从原始答案更新了ToggleComment函数。最重要的是,我修改了正则表达式。在许多情况下,如果字符串中有另一个注释引线实例,它将无法正常工作。我相信它可能必须在前面或后面加一个空格,但我记不起来了。不管怎样,下面是Python的错误示例。
print("Hello, World!") # Says hello to the world.
我已经解决了这个问题,并稍微简化了正则表达式。一个副作用是它不再在评论标题后面添加空格,但这并不困扰我。我在一些变量中添加了一个局部声明,我在最初的答案中忘记了这些变量。