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


1167

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


20
可接受的答案应更改为其中一个详细说明了如何不使用插件即可完成注释/取消注释块的答案之一。在目前接受的答案基本上是一个以第三方插件的链接。
faintsignal

评分最高的答案没有提及任何插件,@ rationalis您的评论具有误导性,请您更正或删除它,谢谢。
no黑猩猩

Answers:


180

我使用NERD Commenter脚本。它使您可以轻松地在代码中注释,取消注释或切换注释。

评论中所述:

对于任何对用法感到困惑的人,默认领导者为“ \”,因此10 \ cc将注释十行,而10 \ cu将取消注释这十行


有趣!我阅读了文档,发现有一个“性感的评论”-只需使用“ \ cs”即可。对于Ruby,它将使用=begin=end注释多行而不是哈希标签。
Hegwin '17

我认为这不是用vim最快的方法,因为它需要安装插件。此外,最佳答案已经获得更多投票,但尚未被标记为解决方案。
whirmill '18

136
不要在这里停下来。以下是大多数投票表决的答案,不需要任何插件。stackoverflow.com/a/15588798/2117868stackoverflow.com/a/1676690/2117868
kuttumiah

@whirmill我认为“最佳”确实取决于用例。如果我一生中想切换一次注释,则可视块模式会更快。但是,如果我不介意安装插件,并希望进行尽可能少的击键来切换评论,而不必在添加或移除评论之间进行区分,那么这可能是“最佳答案”。
卡洛斯(Carolus),

@Carolus如果问题开始于“什么是最好的方法”而不是“什么是快速的方法”,我会同意你的看法。
whirmill '19

2539

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

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

注释一段文本几乎是相同的:

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

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

这是两个小屏幕录像,仅供参考。

评论: 评论

取消注释: 取消评论


87
默认情况下为CTRL + V。Windows版本的gvim使用Ctrl + Q,因为Ctrl + V已用于粘贴。
R. Martinho Fernandes 2009年

8
@amindfv Ctrl + V,n(其中n为数字行-1),j n(其中n num个注释字符序列的长度数-1),l,x。
michael.bartnett 2012年

27
您将如何使用“ //”来做到这一点?
AustinT 2014年

74
您可以单击两次Esc来不等待第二秒;)
Ahmed Hegazy 2015年

44
这对我不起作用。Shift-I进入简单插入模式。
Geremia

826

注释掉vim中的块:

  • Esc(退出编辑或其他模式)
  • ctrl+ v(视觉遮挡模式)
  • 使用/ 箭头键选择所需的行(它不会突出显示所有内容-可以!)
  • Shift+ i(大写字母I)
  • 插入您想要的文本,例如 %
  • EscEsc

取消注释vim中的块:

  • Esc(退出编辑或其他模式)
  • ctrl+ v(视觉遮挡模式)
  • 使用/ 箭头键选择要取消注释的行。

    如果要选择多个字符,请使用一个或组合以下方法:

    • 使用左/右箭头键选择更多文本
    • 选择文本块,使用shift+ / 方向键
    • 您可以像常规的删除按钮一样反复按下下面的删除键

  • dx删除字符,必要时重复

33
@amelia:评论快捷方式对我不起作用。Shift + I带我进入插入模式。它取决于vim版本吗?
user3527975 '16

7
为什么要花一秒钟?
科纳·帕特里克

24
我对此答案的唯一问题是,它告诉您使用箭头键
cozyconemotel

6
按两次Esc键。:)
亚伦·阿方索斯

21
起初,启用注释对我不起作用,但在阅读后再次可以正常工作:1.确保您使用Ctrl-V而不是V进行选择2.插入时将出现,因为您只修改了一行3。当您最终按下Esc时,所有插入都会发生
timurb

333

有时我被装进一个远程盒中,我的插件和.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个字符的注释,例如//,那么我只需:norm xx删除两个字符。

如果评论像OP的问题一样缩进,那么您可以像这样锚定删除:

:norm ^x

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

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

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

vnoremap <C-n> :norm

注3:准系统vim有时没有norm编译命令,因此请确保使用功能更强大的版本,即通常是/ usr / bin / vim,而不是/ bin / vi

(感谢@Manbroski和@rakslice将此答案纳入了改进)


我认为这是直到我滚动阅读此答案之前要走的路stackoverflow.com/a/1676690/850996使用CTRL + V进行块选择(而不是使用SHIFT + V进行行选择)可以更好地控制注释的位置字符插入发生。
Shyam Habarakada 2014年

2
@Shyam ctrl-v技术与特殊的仅块选择命令相结合是大多数其他答案所建议的。但是我个人发现我描述的“规范”技术更容易,因为它除了规范命令本身之外没有引入任何新的语法,因此我可以重用我对vim已有的了解。
Magnus

2
对于取消注释缩进的块,说很有用:norm ^x。通常,此方法具有处理区域选择的优点(例如,vi{将选择大括号内的内容)。此类文本对象选择器不适用于Visual Block
ivan-k 2014年

1
啊,我刚刚弄清楚了-在centos 6上/bin/vi是vim 7.2,但它与的版本不同/usr/bin/vim,并且它具有类似这样的功能。
rakslice 2015年

3
到目前为止,这是最好的答案。尤其是与结合在一起vip以选择整个段落时。
meh,

121

我的内容如下.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取消注释行(在普通和可视模式下均可)。

(很多年前,我从某个网站上偷了它,所以我无法完全解释它是如何工作的:)。有评论说明。)


我应该使用什么快捷方式?我不能完全确定vim代码本身!
gideon

在普通或可视模式下,使用“,cc”(3个字符序列)注释当前行,使用“,cu”取消注释当前行。
2013年

8
我喜欢 :)!谢谢!附带一提,我觉得很难解释。a)它重新映射命令(非递归[参见此](stackoverflow.com/questions/3776117/…),因此现在当您按,cc:...东西被执行时。b)现在这基本上是一个sed(s / what / towhat / where)命令根据您打开的文件类型将^(行首)更改为正确设置的注释字符c)至于无声的东西,它们只是抑制命令的输出。d):nohlsearch阻止它突出显示sed搜索
ramrunner 2013年

14
注意,这不是加载自动命令的正确方法。它们应该在一个augroup内部,否则它们将被多次添加到vim中,并导致很多速度变慢。请参阅:learnvimscriptthehardway.stevelosh.com/chapters/14.html。我已经将我的答案添加到了这个问题。

真好 这是对您在选择块时如何(取消)注释的问题的实际答案。
Erwin Rooijakkers 2014年

119

指定在vim中注释的行:

显示行号:

:set number

然后

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

或这个:

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

11
由于您只是更改每行的第一个字符,因此不需要结尾处的“ g”
Magnus

1
嵌入式盒子上的某些vim(例如openwrt)没有可视模式..所以这真是
太厉害了

您能解释一下为什么:%s/^/#/g要注释掉所有内容吗?我想知道百分号%

18
要取消注释这些行,您可以编写:5,17s / ^#/
Iraklis Moutidis '16

大!它确实可以很好地与块选择(如:va{var红宝石)一起使用。
ArturMałecki17年

58

这是我的方法:

  1. 转到要注释掉的第一行上的第一个字符。

  2. 命中Ctrl+ q在GVIM或Ctrl+ v在VIM,然后再往上选择行第一个字符注释掉。

  3. 然后按c,并添加注释字符。

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


44
c也删除第一个字符。CMS的答案正确,即按I然后输入注释字符,然后Esc(在Windows vim上)
Samaursa 2012年

6
这是可行的,除了需要在第三步中按“ r”而不是“ c”。
David Baucum 2014年

或者,您也可以在按下ESC后再按两次c,这应该可以解决问题
nihiser

所有这些选项都破坏了该行的第一个字符。
约西亚

36

我已经为.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>

注意:

我不对文件类型/加载使用任何回调或钩子,因为我发现它们使Vim的启动比.vimrc静态函数/映射更慢,但这只是我的偏爱。我还尝试使其保持简单和高效。如果确实使用自动命令,则需要确保将它们放入自动命令组中,否则每个加载的文件多次将回调添加到文件类型中,这会导致很多性能下降。


1
我是vim的新手,应该按哪个按钮切换映射功能?<leader><Space>底部的声明是什么?
Jens Kohl 2014年

2
您可以用<,>之类的键替换<leader>。然后,按SPACE键,它将切换该行的注释状态。Leader是您的领导者,Vim的默认<leader>是\,但是您可以设置自己的名称,例如“ let mapleader =','”

很好的答案,但很烦人的是,已经有一些注释的注释块将注释替换为未注释的行。例如,QtCreator仅在所有非空行都有前导注释时才删除注释,否则添加前导注释。
ideaman42

1
我已经使用了一个稍微不同的版本\zs\ze正则表达式的把戏,代码变得有点小。您可以在这里
SergioAraujo,

33

切换评论

如果你需要的是拨动意见我会跟宁愿去commentary.vim通过tpope

在此处输入图片说明

安装

病原:

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

vim-plug:

Plug 'tpope/vim-commentary'

Vundle:

Plugin 'tpope/vim-commentary'

进一步定制

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

现在,您可以按Leader+ 来切换评论/,就像Sublime和Atom一样。


谢谢!将来是否会支持在HTML内的CSS注释?
丹·奥克

25

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


18

这是我的一部分.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删除评论。


这对于初学者如何学习写作很有帮助.vimrc
最酷的2011年

3
map涵盖了普通模式和可视模式,因此您不需要vmap线条
doubleDown 2013年

更好的地方在after/ftplugin/ruby.vim
Santosh Kumar

也使用<leader>ic<leader>rc
Hans Kristian

15

我使用vim 7.4,这对我有效。
假设我们要注释/取消注释3行。

评论:

如果行的开头有没有标签/空间:
ctrl + V那么jjj然后shift + I (cappital i)//然后esc esc
,如果行有标签/空间一开始你仍然可以做上面或交换为c
ctrl + V然后jjjc然后//esc esc

取消注释:

如果线必须在开始时没有标签/空间:
ctrl + V然后jjjll (lower cap L)然后c

如果线必须在开始选项卡/空间,在那你空间之一,esc
ctrl + V然后jjjll (lower cap L)然后cspace然后esc



9

在我前面有30个答案的情况下,我将尝试给出一个更简单的解决方案:#在行首插入a 。然后下一行并按点(.)。要重复,不j.j.,等...要取消注释,删除#(你能打到x#),并做反向使用k.等...


1
即使是初学者也可以理解和使用,这是一个非常简单的答案。但是,在大量要注释的行上,它的工作相当缓慢。要解决此问题,您可以写入I#<Esc>j缓冲区-说,c-然后执行10@c,或者选择适合您的行数。
Daerdemandt

9

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

#code code
#code
#code code code

将光标放在左上方的#符号上,然后按CtrlV。这使您进入可视块模式。按向下箭头或J三下选择所有三行。然后按D。所有评论消失。要撤消,请按U

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

code code
code
code code code

将光标放在左上角的字符上,按CtrlV。这使您进入可视块模式。按J三下选择所有三行。然后按:

I//Esc

这是大写字母I,//和Escape。

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


1
如果您错过了“左上”哈希,则可以按o 以便在可视模式下将光标移动到“另一侧”。
dylnmc '16

我认为这是最好的用法。不需要任何第三方,只需使用本地vim
Ardi Nusawan

最佳答案,简单且没有任何第三方
aze

8

是的,这个问题已经有33个(大多数是重复的)答案。

这是另一种在Vim中注释行的方法:motions。基本思想是使用与键入yip或删除两行来取消段落相同的方法来注释或取消注释行dj

这种方法可以让您执行以下操作:

  • 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

修改上面的正则表达式以适合您的口味#


“全新的动作”似乎有点过头了:t_comment和vim-commentary插件(都早于此答案)允许您使用动作来注释掉。
丰富

好东西!已投票。(我也认为我可能会开始使用此方法,而不是以前使用的插件,因此感谢您编写它!)
2016年

7

如果您已经知道行号,则n,ms/# //可以使用。


确实应该是:n,ms / ^ \ s。#//因为您可能有前导空格,并且可能不会跟上一个哈希值
Skip Huffman 2013年

7

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


6

我使用EnhancedCommentify。它注释了我需要的所有内容(编程语言,脚本,配置文件)。我将其与可视模式绑定一起使用。只需选择要注释的文本,然后按co / cc / cd。

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

5

我结合了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>

5

有一个改变生活的插件,tpope称为vim-commentary

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

该插件提供

  • 理智
  • 适当缩进的注释
  • 不注释掉空/不必要的行

用法

  • 通过Vundle安装(或者我猜是Pathogen)。
  • 突出显示您的文字,然后按:,将显示为:<,'>
  • 在此处键入Commentary :<,'>Commentary,然后按Enter
  • 繁荣。你完成了芽。

vim-commentary(像所有tpope的插件一样)具有惯用vim的优点。gc=“发表评论”,gcap=“发表评论”,等等
goldenratio '18

难道这只是吉姆·斯图尔特(Jim Stewart)对蒂姆·波普(Tim Pope)答案的编辑?
jdk1.0

5

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

这个答案在这里是:1)显示正确的代码以粘贴到.vimrcvim 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则返回true的索引。由于if评估所有非零数字为真,因此我们必须比较输出以查看其是否大于-1。vim如果为false,则in的比较返回0,如果为true,则返回1,这是if希望正确评估的结果。

  • vnoremap <silent> <C-r> :<C-u>call Comment()<cr><cr>vnoremap表示在可视模式下映射以下命令,但不要以递归方式映射(表示不要更改可能以其他方式使用的任何其他命令)。基本上,如果您是vim新手,请务必使用noremap以确保您不会破坏事物。<silent>意思是“我不想你的话,只是你的行动”,并告诉它不要在命令行上打印任何内容。<C-r>是我们要映射的东西,在这种情况下为ctrl + r(请注意,通过此映射,您仍可以在正常模式下将Cr正常用于“重做”)。C-u有点令人困惑,但是基本上可以确保您不会丢失视觉突出显示的内容(根据此答案,它使您的命令从'<,'>我们想要的开始)。call这里只是告诉vim执行我们命名的函数,<cr>指的是enter按下按钮。我们必须打一下它才能实际调用该函数(否则,我们只需call function()在命令行上键入,然后我们必须再次打它才能使我们的替代品一路遍历(不确定原因,但无论如何)。

无论如何,希望这会有所帮助。这将使用vV或突出显示的内容C-v,检查第一行是否已注释,如果是,请尝试取消注释所有突出显示的行,如果没有注释,请在每行中添加额外一层注释字符。这是我想要的行为;我不仅希望它能切换块中的每一行是否都被注释,因此在对这个问题问了 多个问题之后,它对我来说是完美的。



3

您可以通过tpope(https://github.com/tpope/vim-commentary)使用vim-commentary,可以按以下方式使用它:

按下即可进入视觉模式

'v'

然后按

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

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

'gc'

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

'gc'

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>

1
我为您的解决方案制作了一个略有不同的版本,该版本也恢复了光标位置,我希望您对此表示意见。在github上
SergioAraujo,

凉。您可以编辑我的帖子并添加您的解决方案(因为相似)!
迈克,

它已更改为避免反斜杠c,cpp,java并在替换中使用另一个分隔符以避免E488。同样,java,cpp的间距也会更改,因为注释具有三个字符,//加上空格,这是由l:space完成的。
SergioAraujo

3

我使用Jasmeet Singh Anand的 comment.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取消注释选定的多行

3

所有这些方法中最快,最直观的方法是重新映射)以对行进行下移注释,然后(进行上移不注释。尝试一下,您将不会再回来。

RubyBash中,具有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

我喜欢/* ... */(C ansi评论),所以这是我的招数。当然,您可以使其适应不同情况的使用。


用/ * ... * /注释

选择文本(转到开头,开始可视块,使用跳转}):

<c-V>}

键入要在选择中应用的命令

:norm i/* <c-v><esc>$a */

命令将如下所示: :'<,'>norm i /* ^[$a */

有关详细信息,请参见(i *)。


取消注释/ * ... * /

选择文本(与以前一样,或按其他方式选择):

<c-V>}

键入要在选择中应用的命令

:norm :s-\s*/\*\s*-<c-v><enter>$bbld$

命令将如下所示: :'<,'>norm :s-\s*/\*\s*-^M$bbld$

有关详细信息,请参见(ii *)。


结果

效果是逐行注释:

Comment block
Comment block
Comment block

成为(反之亦然):

/* Comment block */
/* Comment block */
/* Comment block */

最好将其另存为您的map或,因为要输入的内容很多。如果您更喜欢单个块而不是整个块,请使用:@reg.vimrc/**/

用一个/ * * /整个块注释

将其保存在寄存器中,方法是使用,qc然后在段落的开头进行注释:

v}di/*  */<esc>hhhp

别忘q了完成记录。

有关详细信息,请参见(iii *)。


取消注释单个/ * * /

将其保存在寄存器中,例如@u。将光标放在块内的任何位置,然后:

?/\*<enter>xx/\*/<enter>xx

通过完成q命令保存寄存器。

有关详细信息,请参见(iv *)。


结果

效果是多行的单个注释:

Comment block
Comment block
Comment block

成为(反之亦然):

/* Comment block
Comment block
Comment block */

说明

(i *)通过使用norm在每个选定的行中重复应用相同的命令来工作。该命令只需插入a /*,找到该行的末尾并通过插入a结束*/

:norm i/* <c-v><esc>$a */

(ii *)它还用于norm在每一行上重复搜索/替换。搜索spaces /* spaces并替换为空。之后,找到该行的末尾,退回两个单词,对一个字母,删除到末尾。

:norm :s-\s*/\*\s*-<c-v><enter>$bbld$

(iii *)通过选择段落v},将其删除,在打开和关闭处插入注释,移至其中间并粘贴已删除的块。

v}di/*  */<esc>hhhp

(iv *)在中间的任何地方,向后查找a /*,将其删除;找到一个*/,将其删除。

?/\*<enter>xx/\*/<enter>xx
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.