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


当前回答

你可以使用tpope的vim评论(https://github.com/tpope/vim-commentary)您可以按如下方式使用它:

按进入视觉模式

'v'

然后按

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

现在,您所要做的选择就是输入键:

'gc'

这将注释掉所有选择,以取消注释repead键:

'gc'

其他回答

我在.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静态函数/map更慢Vim的启动速度,但这只是我的偏好。我也试图保持它的简单和性能。如果确实使用了自动命令,则需要确保将它们放入自动命令组中,否则每次加载文件时,回调都会多次添加到文件类型中,从而导致性能下降。

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

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

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

我个人不喜欢注释“切换”功能,因为它会破坏代码中已经包含的注释。此外,我希望注释字符始终显示在最左边,这样我可以很容易地看到注释块。此外,我希望这是嵌套的(如果我首先注释掉一个块,然后是一个封闭块)。因此,我稍微改变了其中一个解决方案。我使用F5注释,使用Shift-F5取消注释。此外,我在s/命令末尾添加了/g:

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 = '"'
autocmd FileType nasm             let b:comment_leader = ';'

function! CommentLine()
    execute ':silent! s/^\(.*\)/' . b:comment_leader . ' \1/g'
endfunction

function! UncommentLine()
    execute ':silent! s/^' . b:comment_leader . ' //g'
endfunction

map <F5> :call CommentLine()<CR>
map <S-F5> :call UncommentLine()<CR>

所有这些方法中最快、最直观的方法是重新映射()行的逐步注释,然后()逐步取消注释。尝试一下,你就不会再回去了。

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

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

在C/C++或PHP中,使用4空间缩进:

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

缺点是你在句子移动时会丢失(和)(但das可以在其中填充),而且你偶尔会在处理长段时使用select and replace或CtrlV。但这很罕见。

对于C样式,长注释最好用以下方式处理:

set cindent
set formatoptions=tcqr

…这与使用V[move]gq重新进行单词换行结合得很好。

在VIM中:

1-按v进入视觉模式。

2-使用箭头选择要注释的块。

3-按下:

4-类型“s/^/#”

要删除注释,只需将步骤4替换为:

4-类型's/^#//'