我在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

假设我想取消注释第一个定义中的所有行。。。端部。在Vim中有什么有效的方法可以做到这一点?

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


当前回答

尽管这个问题已经有了很多答案,但我仍然认为我会对我写的一个小插件大声叫好:commentify。

Commentify使用commentstring设置来决定如何注释掉代码块,因此您不必在配置中保留不同注释类型的映射,并且支持基于行的注释(例如,//)和块注释(例如/**/)。

它还为注释和取消注释块映射了相同的快捷方式(默认为ctrl+c),因此您不必记住两个映射或一组复杂的命令。

其他回答

尽管这个问题已经有了很多答案,但我仍然认为我会对我写的一个小插件大声叫好:commentify。

Commentify使用commentstring设置来决定如何注释掉代码块,因此您不必在配置中保留不同注释类型的映射,并且支持基于行的注释(例如,//)和块注释(例如/**/)。

它还为注释和取消注释块映射了相同的快捷方式(默认为ctrl+c),因此您不必记住两个映射或一组复杂的命令。

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

tpope有一个改变生活的插件,叫做vim comments

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

此插件提供:

神志正常正确缩进注释不注释空/不必要的行

用法:

通过Vundle(我猜是病原体)安装。突出显示文本并按:,将显示为:<,'>在此处键入注释:<,'>注释,然后按Enter键。繁荣你做的花蕾。

指定要在vim中注释的行:

显示行号:

:set number

然后

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

或者:

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

如果您无法安装插件,但仍希望注释字符遵循现有缩进级别,则此答案非常有用。

这里的答案是: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。有其他方法可以做到这一点,但对新手(像我)来说,它们更容易混淆。作用Docomment():函数以函数开头,以endfunction结尾。函数必须以大写开头。这个确保此函数使用此版本的Doccomment()覆盖以前定义为Doccomment)的任何函数。没有!,我有错误,但这可能是因为我通过vim命令行定义了新函数。执行“”<,“”>s/^\s*/&'.escape(b:commentChar,'\/')。“/e':Execute调用命令。在这种情况下,我们正在执行替换,它可以取一个范围(默认情况下,这是当前行),例如整个缓冲区的%或突出显示部分的“<,”>^\s*是正则表达式,以匹配一行的开头,后跟任意数量的空格,然后将其附加到(由于&)。这个这里用于字符串连接,因为escape()不能用引号括起来。escape()允许您转义commentChar中与参数(在本例中,\和/)匹配的字符,方法是在它们前面加上\。之后,我们再次用替换字符串的结尾连接,该字符串带有e标志。这个标志让我们无声地失败,这意味着如果我们在给定的行上找不到匹配项,我们就不会对它大喊大叫。作为一个整体,这一行允许我们在第一个文本之前放置一个注释字符,后跟一个空格,这意味我们保持缩进级别。执行“”<,“”>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()返回索引,如果为true,则返回-1。因为if计算所有非零数字为真,所以我们必须比较输出,看看它是否大于-1。vim中的比较如果为false,则返回0,如果为true,则返回1,这就是if希望看到的正确评估结果。vnoremap<silent><C-r>:<C-u>调用Comment()<cr><cr>:vnoremap意味着在视觉模式下映射以下命令,但不要递归映射(意味着不要更改可能以其他方式使用的任何其他命令)。基本上,如果你是一个vim新手,请始终使用noremap来确保你不会破坏东西<silent>的意思是“我不需要你的言语,只需要你的行动”,并且告诉它不要向命令行打印任何内容<C-r>是我们正在映射的对象,在这种情况下是ctrl+r(注意,在正常模式下,使用此映射,您仍然可以正常使用C-r进行“重做”)。C-u有点让人困惑,但基本上它可以确保你不会忘记视觉高亮显示(根据这个答案,它会让你的命令以“<,”>开头,这就是我们想要的)。这里的调用只是告诉vim执行我们命名的函数,<cr>是指点击enter按钮。我们必须点击它一次才能真正调用该函数(否则我们只是在命令行上键入了call function(),我们必须再次点击它以让替代品一直执行(不确定为什么,但无论如何)。

无论如何,希望这能有所帮助。这将接受用v、v或C-v突出显示的任何内容,检查第一行是否有注释,如果有,尝试取消注释所有突出显示的行,如果没有,则为每行添加一层注释字符。这是我想要的行为;我不只是想让它切换块中的每一行是否有评论,所以在问了多个关于这个主题的问题后,它非常适合我。