我在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(-#)。


当前回答

:%s/^/\/\//g

删除角色和使用此命令注释.C或CPP文件

其他回答

首先,我要感谢@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.

我已经解决了这个问题,并稍微简化了正则表达式。一个副作用是它不再在评论标题后面添加空格,但这并不困扰我。我在一些变量中添加了一个局部声明,我在最初的答案中忘记了这些变量。

对于这些任务,我使用了大部分时间块选择。

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

对于注释文本块几乎是相同的:

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

默认情况下,对于debian/ubuntu附带的精简版vim,请在第三步中键入:s/^/#(可以使用:nohl删除每行第一个字符的任何剩余突出显示)。

这里有两个小屏幕录音,供视觉参考。

注释:

取消注释:

我使用Jasmeet Singh Anand的comments.vim(在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取消注释所选多行

我使用NERD评论员脚本。它允许您在代码中轻松注释、取消注释或切换注释。

如评论中所述:

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

@CMS的解决方案是注释输入/输出行的最“vim原生”方式。在@CMS的第二步中,在CtrlV之后,您还可以使用r#添加注释或使用x删除注释。Drew Neil的《实用Vim》(第46页)很好地解释了这一技术。

另一个好的选择是使用ex模式命令[范围]归一化##⌴。显然,要用这个保存击键,您需要注释掉15+行。