Vim命令如何注释掉一段代码?

3

假设我有一堆行:

@Override
public void draw(Graphics g) {
    g.setColor(Color.MAGENTA);
    g.fillRect(rectangle.x, rectangle.y, rectangle.width, rectangle.height);
    g.setColor(Color.BLACK);
    g.drawRect(rectangle.x, rectangle.y, rectangle.width, rectangle.height);
}

当我想用//来注释它们时(我更喜欢使用行注释而不是块注释),我的做法是:
  • 将光标放在@符号前面
  • Ctrl-V:切换到进入块选择模式
  • 使用多次按下j选择到}闭合括号的列
  • Shift-I:进入块插入模式
  • 输入//
  • ESC退出
  • Enter完成命令
--> 现在这些行已被注释掉。
有没有更简单的方法,不需要进行块选择操作?我发现我可以使用替换命令,例如:'<, '>s/^/\/\///g,但这有两个问题:
  1. 打字很笨拙容易出错(需要转义多个正斜杠)
  2. 它将注释符号(//)放在行的开头(位置0),而不是首字符所在的位置(所以缩进会丢失)。
如何在Vi中选定的行的每行第一个字符所处的位置插入//

我同意你使用插件会更开心,但是我想告诉你 :s 命令在分隔符方面非常灵活,所以你可以选择 # 而不是 /;另外,由于你每行只替换一次(在行首),g 标志没有起到任何作用;因此,这个简单的语句就可以工作了,而且不需要转义任何字符::'<,'>s#^#// - undefined
5个回答

3

您可以为您的:substitute定义自定义映射或命令。

但是,有几个注释插件非常出色,它们是通用的(通常可扩展),因此适用于任何文件类型:

我强烈建议您使用其中一个插件,而不是尝试重新发明一个不好的解决方案。


我喜欢Commentary:它非常简单,而且能满足我所有的需求。选择gc - 已注释。选择gc - 未注释。(你也可以使用gcu来取消当前所在的注释块,而无需选择)。 - undefined
@Amadan gc也适用于文本对象,因此gcap比如vapgc更容易。它也是一个文本对象,所以dgc会按预期执行! - undefined
1
@D.BenKnoble 是的,我知道。我只是指的是,唯一需要记住的序列是gc(和gcu);其他所有内容都可以从gc中派生出来:gcgc(类似于dd),gcG(类似于dG),v...gc(类似于v...d)... 只是ap通常不是我在代码中使用的,因为我经常在函数内部有换行符。对于一般情况,va{okgc会更好,除非我确定可以缩短它。 - undefined
谢谢提供参考。这个功能是否也可以在Intellij IDEA的Vim插件中启用? - undefined
Vim插件通常只支持简单的映射,而不是整个Vimscript,所以不行。但是你可以利用IDEA内置的快捷键(例如Ctrl-/)来注释行。 - undefined

1
如何在Vi中在选定行的每行第一个字符位置插入//?尽管我同意其他人并认为专门的插件是必须的,但是根据OP的表述,这是一个相当简单的任务,可以实现为一行代码。
vnoremap <silent>gc :call setline(".", printf("%*s" . &cms, indent("."), "", trim(getline("."))))<CR>

现在选择一些文本,按下“gc”,然后,哇,它就起作用了。要强制使用//而不是默认的/**/,请为您的缓冲区设置以下选项:setlocal cms=//\ %s。请参见:h 'cms'

1
I希望您能像其他答案一样使用Commentary,但是有几点需要注意:
  • <C-v>jjjjj可以替换为<C-v>}<C-v>/}<CR>
  • :substitute不必使用/作为分隔符::'<,'>s-^-//
  • 通过可视选择,您还可以执行:'<,'>normal! I//

0

q制作一个宏,将其放入a缓冲区中,在给定行上按下qa。然后按下I//跳转到行的开头,并注释掉它。按下Escq,现在你的宏就完成了。这个宏将注释掉当前行。
完整的命令是qaI//Escq

现在使用V可视选择一堆行,并输入:norm!@a来运行你的a宏。这将注释掉一堆行。

记录另一个宏来执行相反操作,使用qb^xx。可以通过可视选择要取消注释的行并键入norm!@b来调用它。

如果你想要"保存"这些命令,可以将这些宏保存在你的.vimrc文件中,并将特定的宏映射到一个键组合。


0
我有一个看起来像这样的“切换注释功能” 参考:https://dev59.com/wHI-5IYBdhLWcg3wxrqQ#24652257
" these lines are needed for ToggleComment()
" Reference: https://dev59.com/wHI-5IYBdhLWcg3wxrqQ#24652257
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 = '"'

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>
" vnoremap <Leader>t :call ToggleComment()<CR>

所以,一旦你在你的~/.vimrc中有了这个函数,你可以这样做:
vip ...................... visual inner paragraph
<leader>t ................ in order to call the function

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接