什么是在Vim中评论/取消注释行的快速方法?

问题描述 投票:984回答:45

我在vi中打开了一个Ruby代码文件,有一些用#注释掉的行:

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

假设我想取消注释第一个def ... end部分中的所有行。在Vim中这样做的有效方法是什么?

一般来说,我正在寻找一种简单流畅的方式来评论和取消注释。在这里,我正在处理Ruby代码,但它可能是JavaScript(//)或Haml(-#)。

vim comments
45个回答
166
投票

我用的是NERD Commenter script。它可以让您轻松评论,取消注释或切换代码中的注释。

comments中所述:

对于任何对使用感到困惑的人,默认的领导者是“\”所以10 \ cc将评论十行,10 \ cu将取消注释这十行


22
投票

使用Control-V选择文本的矩形:转到第一个#字符,键入Ctrl + V,向右移动一次,然后向下移动,直到注释结束。现在输入x:你要删除所有#字符后跟一个空格。


14
投票

这是我的.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>

在正常和可视模式下,这让我按,ic插入注释,和rc删除注释。


12
投票

我使用vim 7.4,这对我有用。 假设我们正在评论/取消注释3行。

评论:

如果该行在开头没有制表符/空格: ctrl + V然后jjj然后shift + I (cappital i)然后//then esc esc 如果该行在开头有标签/空格,您仍然可以执行上述操作或交换cctrl + V然后jjj然后c然后//then esc esc 取消注释:

如果行开头没有制表符/空格: ctrl + V然后jjj然后ll (lower cap L)然后c

如果线条在开头有空格/空格,那么你将空格一个和esc ctrl + V然后jjj然后ll (lower cap L)然后c然后space然后esc


9
投票

我喜欢使用tcomment插件:http://www.vim.org/scripts/script.php?script_id=1173

我已经映射了gc和gcc来评论一行或突出显示的代码块。它检测文件类型并且工作得很好。


9
投票

在我前面有30个答案,我将尝试提供一个更简单的解决方案:在行的开头插入一个#。然后沿着一条线按下点(.)。重复,做j.j.等...要取消注释,删除#(你可以在x上击中#),并使用k.等反向...


9
投票

如何在vi中取消注释以下三行:

#code code
#code
#code code code

将光标放在左上方的#符号上,然后按CtrlV。这使您处于可视阻止模式。按向下箭头或J三次以选择所有三条线。然后按D.所有评论都消失了。要撤消,请按U.

如何在vi中评论以下三行:

code code
code
code code code

将光标放在左上角,按CtrlV。这使您处于可视阻止模式。按↓或J三次以选择所有三条线。然后按:

我// Esc

这是资本I,//和Escape。

按ESC键时,所有选定的行都将获得您指定的注释符号。


7
投票

是的,这个问题已经有33个(主要是重复的)答案。

这是另一种如何在Vim中评论线条的方法:运动。基本思想是使用与通过键入yip或通过键入dj删除2行来删除段落相同的方法来注释或取消注释行。

这种方法可以让你做到这样的事情:

  • ccj评论接下来的两行,并且cuk取消注释;
  • cci{评论一个区块,并且cui{取消注释;
  • ccip评论整个段落,cuip取消注释。
  • ccG将所有内容评论到最后一行,并且cugg将所有内容取消注释到第一行。

您只需要2个在运动中运行的功能,以及每个功能的2个映射。首先,映射:

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>

(参见有关g@运算符和operatorfunc变量的手册。)

而现在的功能:

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

修改上面的正则表达式,以满足您对#应该在哪里的品味:


6
投票

如果您已经知道行号,那么n,ms/# //就可以了。


6
投票

我用EnhancedCommentify。它评论我需要的一切(编程语言,脚本,配置文件)。我使用它与视觉模式绑定。只需选择要评论的文本,然后按co / cc / cd即可。

vmap co :call EnhancedCommentify('','guess')<CR>
vmap cc :call EnhancedCommentify('','comment')<CR>
vmap cd :call EnhancedCommentify('','decomment')<CR> 

6
投票

我标记了第一行和最后一行(ma和mb),然后执行:'a,'bs / ^#//


2179
投票

对于那些我大多数时间使用block selection的任务。

将光标放在第一个#字符上,按CtrlV(或CtrlQ for gVim),然后向下直到最后一个注释行并按x,这将垂直删除所有#字符。

对于评论文本块几乎是相同的:

  1. 首先,转到要评论的第一行,按CtrlV。这将使编辑器处于VISUAL BLOCK模式。
  2. 然后使用箭头键并选择直到最后一行
  3. 现在按ShiftI,将编辑器置于INSERT模式,然后按#。这将向第一行添加哈希。
  4. 然后按Esc(给它一秒钟),它将在所有其他选定的行上插入一个#字符。

对于debian / ubuntu默认附带的精简版vim,请在第三步中键入: s/^/#

这是两个用于视觉参考的小屏幕录音。

评论:Comment

取消注释:Uncomment


4
投票

我使用Tim Pope的vim-commentary插件。


4
投票

我结合了Phil和jqno的答案,并用空格做了无聊的评论:

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/\([^ ]\)/' . b:comment_leader . ' \1/'
    execute ':silent! s/^\( *\)' . b:comment_leader . ' \?' . b:comment_leader . ' \?/\1/'
endfunction
map <F7> :call CommentToggle()<CR>

4
投票

这个改变生命的插件由tpope称为vim-commentary

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

这个插件提供:

  • 明智
  • 正确缩进评论
  • 不会注释掉空/不必要的行

用法:

  • 通过Vundle(或我猜的病原体)安装。
  • 突出显示您的文字并按:这将显示为:<,'>
  • 在此处输入评论:<,'>Commentary并按Enter键。
  • 繁荣。你的成就了。

4
投票

这个答案在这里1)显示正确的代码粘贴到.vimrc以获得vim 7.4+进行块注释/取消注释,同时在视觉模式中保持缩进级别1个快捷方式和2)解释它。

这是代码:

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>

这个怎么运作:

  • let b:commentChar='//':这在vim中创建了一个变量。这里的b指的是范围,在这种情况下包含在缓冲区中,意味着当前打开的文件。您的注释字符是字符串,需要用引号括起来,引号不是切换注释时要替换的内容的一部分。
  • autocmd BufNewFile,BufReadPost *...:自动命令触发不同的东西,在这种情况下,这些是在新文件或读取文件以某个扩展名结束时触发。触发后,执行以下命令,允许我们根据文件类型更改commentChar。还有其他方法可以做到这一点,但它们对新手(比如我)更容易混淆。
  • function! Docomment():函数通过从function开始并以endfunction结尾来声明。功能必须以资本开头。 !确保此函数使用此版本的Docomment()覆盖任何以前定义为Docomment()的函数。没有!,我有错误,但那可能是因为我通过vim命令行定义了新函数。
  • execute '''<,''>s/^\s*/&'.escape(b:commentChar, '\/').' /e':执行调用命令。在这种情况下,我们正在执行substitute,它可以取一个范围(默认情况下这是当前行),例如整个缓冲区的%或突出显示部分的'<,'>^\s*是正则表达式,用于匹配行的开头,后跟任意数量的空格,然后附加到(由于&)。这里的.用于字符串连接,因为escape()不能用引号括起来。 escape()允许你通过在commentChar前加上\中与角色匹配的字符(在本例中为/\)。在此之后,我们再次与我们的substitute字符串的结尾连接,该字符串具有e标志。这个标志让我们无声地失败,这意味着如果我们在给定的行上找不到匹配,我们就不会对此大喊大叫。总的来说,这一行让我们在第一个文本之前放置一个注释字符后跟一个空格,这意味着我们保持缩进级别。
  • execute '''<,''>s/\v(^\s*)'.escape(b:commentChar, '\/').'\v\s*/\1/e':这与我们上一次巨大的长命令类似。这个独特,我们有\v,这确保我们不必逃避我们的()1,这是指我们用()制作的组。基本上,我们匹配一个以任意数量的空格开头的行,然后我们的注释字符后跟任意数量的空格,我们只保留第一组空格。再次,如果我们在该行上没有评论字符,e会让我们无声地失败。
  • let l:line=getpos("'<")[1]:这设置了一个变量,就像我们使用注释字符一样,但是l指的是本地范围(此函数的本地范围)。在这种情况下,getpos()获得了我们突出显示的开始位置,而[1]意味着我们只关心行号,而不是列号等其他内容。
  • if match(getline(l:line), '^\s*'.b:commentChar)>-1:你知道if是如何工作的。 match()检查第一件事是否包含第二件事,所以我们抓住我们开始突出显示的行,并检查它是否以空格开头,后跟我们的注释字符。 match()返回这个为真的索引,如果找不到匹配则返回-1。由于if评估所有非零数字是真的,我们必须比较我们的输出以查看它是否大于-1。 vim中的比较如果为false则返回0,如果为true则返回1,这是if想要正确评估的结果。
  • vnoremap <silent> <C-r> :<C-u>call Comment()<cr><cr>vnoremap表示在可视模式下映射以下命令,但不要递归映射它(意味着不要更改可能以其他方式使用的任何其他命令)。基本上,如果你是一个vim新手,总是使用noremap确保你不会破坏东西。 <silent>的意思是“我不想要你的话,只是你的行为”,并告诉它不要在命令行上打印任何内容。 <C-r>是我们映射的东西,在这种情况下是ctrl + r(请注意,在这种映射的情况下,你仍然可以正常模式下使用C-r进行“重做”)。 C-u有点令人困惑,但基本上它确保你不会忘记你的视觉突出显示(根据this answer它使你的命令从'<,'>开始,这是我们想要的)。 call这里只是告诉vim执行我们命名的函数,而<cr>指的是按下enter按钮。我们必须打一次实际调用函数(否则我们只是在命令行上键入call function(),我们必须再次点击它以让我们的替代品一直通过(不确定为什么,但无论如何) 。

无论如何,希望这会有所帮助。这将使用vVC-v突出显示任何内容,检查第一行是否已注释,如果是,则尝试取消注释所有突出显示的行,如果没有,则为每行添加额外的注释字符层。这是我理想的行为;我不只是想让它切换块中的每一行是否被评论,所以在asking multiple关于这个主题的问题之后,它对我来说是完美的。


3
投票

这是基于C-v的基本单线程,然后是上面概述的I方法。

此命令(:Comment)将所选字符串添加到任何选定行的开头。

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

将此行添加到.vimrc以创建接受单个参数的命令,并将参数放在当前选择中每行的开头。

例如。如果选择以下文本:

1
2

你运行这个::Comment //,结果将是:

//1
//2

3
投票

从这里的答案中的想法开始,我开始自己的评论功能。它会打开和关闭评论。它可以处理像//print('blue'); //this thing is blue这样的东西,只是切换第一条评论。此外,它添加了注释和单个空格,就在第一个非空白区域而不是行的最开头。另外,它不会不必要地复制空白,但是在评论和缩进行时使用缩放(:h \ zs求助)来避免这种额外的工作。希望它有助于一些极简主义者。欢迎提出建议。

" 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>

3
投票

我使用comments.vim from Jasmeet Singh Anand(在vim.org上找到),

它适用于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和普通文件

它在普通模式和可视模式下对不同源文件中的行进行注释和取消注释

用法:

  • CtrlC注释单行
  • CtrlX取消注释单行
  • ShiftV并选择多行,然后按CtrlC注释所选的多行
  • ShiftV并选择多行,然后按CtrlX取消注释所选的多行

3
投票

它们中最快捷,最直观的方法是重新映射)以便对行进行逐行评论,然后将(重新表示为行走 - 取消注释。尝试一下,你就不会回去了。

在Ruby或Bash中,使用2空格缩进:

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

在C / C ++或PHP中,带有4个空格的缩进:

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

缺点是你因为句子移动而失去了()(但das可以在那里填补),你偶尔会选择替换或CtrlV来处理长段。但这非常罕见。

对于C风格,长评论最好用以下方式处理:

set cindent
set formatoptions=tcqr

...结合使用V[move]gq重做自动换行。


2
投票

这个简单的片段来自我的.vimrc:

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

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

它适用于// - 评论,但您可以轻松地适应其他角色。您可以使用autocmd将领导者设置为jqno建议。

这是一种非常简单有效的方式,可以自然地使用范围和视觉模式。


2
投票

您可以使用tpope(https://github.com/tpope/vim-commentary)的vim-comment来使用它,如下所示:

按下进入可视模式

'v'

然后按

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

现在您只需输入键即可完成选择:

'gc'

这将注释掉所有选择,取消注释重复键:

'gc'

751
投票

在vim中注释掉块:

  • 按Esc(退出编辑或其他模式)
  • 点击ctrl + v(可视块模式)
  • 使用向上/向下箭头键选择你想要的行(它不会突出显示所有内容 - 没关系!)
  • Shift + i(大写I)
  • 插入你想要的文字,即%
  • 按EscEsc

要在vim中取消注释块:

  • 按Esc(退出编辑或其他模式)
  • 点击ctrl + v(可视块模式)
  • 使用↑/↓箭头键选择要取消注释的行。 如果要选择多个字符,请使用一个或组合这些方法: 使用左/右箭头键选择更多文本 选择文本块使用shift +←/→箭头键 您可以反复按下面的删除键,就像常规删除按钮一样
  • 如有必要,请按d或x删除字符

2
投票

我使用vim-multiple-cursors

  1. 要选择区域,请按0(它为零,不是字母“o”)转到要注释掉的区域的第一行或最后一行的第一个字符。然后按V并使用J,K或向上和向下箭头键选择区域。
  2. 然后按Ctrl键将虚拟光标放在选择的每一行上。
  3. 然后按I同时编辑选择的每一行。

292
投票

有时候我被绑在一个远程盒子里,我的插件和.vimrc无法帮助我,或者有时候NerdCommenter错了(例如嵌入HTML中的JavaScript)。

在这些情况下,低技术替代方案是内置的norm命令,它只在指定范围内的每一行运行任意vim命令。例如:

评论#

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

这会在每行的开头插入“#”。请注意,当您键入时:范围将被填充,因此它看起来真的像:'<,'>norm i#

取消注释#

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

这将删除每行的第一个字符。如果我使用了诸如//之类的2-char注释,那么我只需要执行:norm xx删除两个字符。

如果评论在OP的问题中缩进,那么您可以锚定您的删除,如下所示:

:norm ^x

这意味着“转到第一个非空格字符,然后删除一个字符”。请注意,与块选择不同,即使注释具有不均匀的缩进,此技术也可以工作!

注意:由于norm实际上只是执行常规vim命令,因此您不仅限于注释,还可以对每一行进行一些复杂的编辑。如果您需要将转义字符作为命令序列的一部分,请键入ctrl-v然后点击转义键(或者更简单,只需记录一个快速宏,然后使用norm在每一行上执行该宏)。

注意2:如果你发现自己经常使用norm,你当然也可以添加一个映射。例如,在〜/ .vimrc中放入以下行,可以在进行视觉选择后输入ctrl-n而不是:norm

vnoremap <C-n> :norm

注3:Bare-bones vim有时没有编译成norm命令,所以一定要使用增强版本,即通常是/ usr / bin / vim,而不是/ bin / vi

(感谢@Manbroski和@rakslice对此答案的改进)


113
投票

我在.vimrc中有以下内容:

" Commenting blocks of code.
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 = '" '
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>

现在你可以输入,cc来评论一条线,然后输入,cu来取消注释一条线(在普通模式和可视模式下都能正常工作)。

(我多年前从某个网站偷了它,所以我不能完全解释它是如何工作的:)。有一个comment解释。)


102
投票

指定要在vim中注释的行:

显示行号:

:set number

然后

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

或这个:

:%s/^/#/        will comment out all lines in file

54
投票

我是这样做的:

  1. 转到要注释掉的第一行的第一个字符。
  2. 在GVIM中按Ctrl + q或在VIM中按Ctrl + v,然后向下选择要注释掉的行上的第一个字符。
  3. 然后按c,添加注释字符。

取消注释以相同的方式工作,只需键入空格而不是注释字符。


28
投票

我已经提出了一个简单的添加到我的.vimrc文件,该文件非常好用,并且可以轻松扩展。您只需向comment_map及其评论标题添加新的文件类型即可。

我添加了正常和可视模式的映射,但您可以重新映射到您喜欢的任何内容。我更喜欢只有'切换'风格的功能。一个人有多个映射等。

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>

注意:

我没有在文件类型/加载中使用任何回调或挂钩,因为我发现它们比.vimrc静态函数/映射更慢地减慢了Vim的启动速度,但这只是我的偏好。我也试图保持简单和高效。如果您确实使用自动命令,则需要确保将它们放在自动命令组中,否则回调会在每个文件加载时多次添加到文件类型,并导致大量性能下降。


28
投票

Toggle comments

如果你需要的只是切换评论,我宁愿和commentary.vim一起去tpope

enter image description here

Installation

病原:

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

VIM插头:

Plug 'tpope/vim-commentary'

对角:

Plugin 'tpope/vim-commentary'

Further customization

将其添加到.vimrc文件:noremap <leader>/ :Commentary<cr>

您现在可以通过按Leader + /来切换注释,就像Sublime和Atom一样。

© www.soinside.com 2019 - 2024. All rights reserved.