如何在可视模式下选择多行注释掉?如何使它特定于语言?例如,如果选择了前4行:

def foo(a,b):
    for each in (a,b):
        print each
    return a+b
print "2"


命令的操作/宏应导致以下情况(在python中):

#def foo(a,b):
#    for each in (a,b):
#        print each
#    return a+b
print "2"


#1 楼

如果您想要特定语言的注释,则需要一个类似nerdcommenter的插件。

或者,尽管它不能回答您的实际问题,但是您可以使用内置的vim操作和您对每种语言的注释字符的了解。 。

选项1:V形块



:1输入(转到第1行)

Ctrl- V(V块模式)

jjj(下3行)


# (插入'#')

Esc(返回正常模式)

选项2:替换

:1,4s/^/#/


故障:




: Ex命令遵循

1,4从1到4行

s替代

/替换命令的分隔符。
(也可以使用其他字符,例如:

^行首

/分离器

# python的注释字符

/最终分隔符

选项3:重复应用宏(源)




:1输入(转到第1行)

qa(开始在寄存器a上记录)

Shift-I(在行的开头进入插入模式

#(在行首添加'#')

Esc(返回正常模式)
q(停止记录)

:2,4 normal @a(重新运行记录的宏以在2到4之间的行上注册a



您可以在可视模式下选择行并按:自动
:'<,'>(从视觉选择的开始到结尾的范围)填充Ex行,然后键入normal @a并按Enter(源)。


现在,每当您要注释一些行时,只需重新运行记录的宏
在这些行上注册a

:9,22 normal @a (comment out lines 9-22)


评论


选项4:插件

–科迪民意测验
15年2月4日在18:25

我不明白为什么您可以在单个命令中使用宏,但根据我的回答,您可以执行:9,22正常的I#。

–本
15年2月19日在9:53

当可以使用gg时,为什么还要使用:1

–塔娜丝
15年2月19日在17:12

@Tanath从第一行开始注释是针对此示例的。如果作者想在第9至22行发表评论,他们将无法使用gg。

–bsmith89
2015年2月19日在22:53



@ bsmith89然后您将使用9gg。少一个字符,更易于键入。

–塔娜丝
2015年2月20日,下午3:27

#2 楼

使用可视块模式(CtrlV),选择行的开头。然后按I#(这是一个大写字母I),以在每个行上插入井号。然后按Esc键从插入模式返回到普通模式。

评论


它对我不起作用。它仅在第一行中插入注释。

–gon1332
15年2月4日在17:38

您要按ctrl吗?因为ctrl + v与v不同。

–科迪民意测验
15年2月4日在17:40

@CodyPoll我知道。 I一切正常。当我按I时,#将仅放在第一行的前面。

–gon1332
2015年2月5日在20:43



@CodyPoll好吧..我只是住院。在执行完上述步骤后,我没有按Esc键。

–gon1332
2015年2月5日在22:07



据我所知@ gon1332,您需要在末尾按Esc。

–贡萨洛·里贝罗(GonçaloRibeiro)
2015年2月5日在22:07

#3 楼

如果您只需要快速解决当前使用的任何语言,并且已经在可视模式下选择了文本,那么

:norm 0i#


就可以了。
(对于每一行,在正常模式下,请转到第一列并插入#。使用:norm I#会将其插入第一个非空白字符之前,这可能不是您想要的。)
使用:norm i#将也可以使用,因为:norm从该行的开头开始,但是如果您不知道的话,它就不太明确,也不太清楚。

当然,如果您打算经常这样做,想要设置映射或寻找插件。

评论


不需要为0,因为默认情况下,正常命令在行的开头用光标执行。

–nitishch
15年2月19日在10:28

当然,可以在此命令前加上行号,%,标记。示例::1,5norm i#(或):'a,'bnorm i#(或):10%norm i#

– SibiCoder
16年5月28日在8:40



#4 楼

自动执行此操作将需要您在vimrc文件(源)中添加以下内容:

au FileType haskell,vhdl,ada let b:comment_leader = '-- '
au FileType vim let b:comment_leader = '" '
au FileType c,cpp,java let b:comment_leader = '// '
au FileType sh,make let b:comment_leader = '# '
au FileType tex let b:comment_leader = '% '
noremap <silent> ,c :<C-B>sil <C-E>s/^/<C-R>=escape(b:comment_leader,'\/')<CR>/<CR>:noh<CR>
noremap <silent> ,u :<C-B>sil <C-E>s/^\V<C-R>=escape(b:comment_leader,'\/')<CR>//e<CR>:noh<CR>


使用,c注释区域,使用,u取消注释a地区。这将手动设置不同语言的注释符号。

第二个选项是使用诸如tcomment,vim-commentary或comments.vim之类的插件。我自己用tcomment。请相信,请阅读他们页面上的使用和安装说明,因为我认为这超出了问题的主题。

我建议您使用一个插件(上面链接中的一个或另一个)作为这比在vimrc文件中维护一段代码要容易得多。

编辑:问题被更改后,我删除了手动方式,并且200_success回答了正确的方式。

评论


另一个插件建议:NERD Commenter-vim.org/scripts/script.php?script_id=1218

– gaveen
15年2月3日在20:33

注意:这仅支持逐行注释。例如,ANSI C不能识别//(仅/ * * /)。

– wchargin
2015年2月3日在21:35

当我喜欢这种方法时,是否有办法使其切换评论?

–ideasman42
2015年9月23日下午5:18

@ ideasman42您必须改用一个函数,并检查当前行是否以注释开头,然后根据该调用选择答案中摘录中显示的:s命令之一。检查本身将类似于getline('。')=〜“ ^”。转义(b:comment_leader,'\ /')。如果确实没有评论,请发表评论。这未经测试,仅应作为示例。

–tokoyami
15年9月23日在18:26

#5 楼

选择行之后,只需键入

:norm I#


:会自动将'<,'>放在命令行上,该范围是从选择开始到结束的范围; norm执行正常模式命令,并将作用于该范围; I#是普通模式命令,该命令在行的开头插入一个“#”。

#6 楼

我为此使用scrooloose / nerdcommenter。

使用此插件,您可以直观地选择行并点击Leader + c来切换注释。根据文件类型,它将使用不同的符号进行注释。

#7 楼

为此,我是TComment的忠实粉丝;我不仅可以执行文件类型特定的注释样式,还可以为支持块注释的语言指定逐行还是逐行。

    gc{motion}   :: Toggle comments (for small comments within one line 
                    the &filetype_inline style will be used, if 
                    defined)
    gcc          :: Toggle comment for the current line

Explicit commenting/uncommenting:

    g<{motion}   :: Uncomment region
    g<c          :: Uncomment the current line
    g<b          :: Uncomment the current region as block

    g>{motion}   :: Comment region
    g>c          :: Comment the current line
    g>b          :: Comment the current region as block

In visual mode:

    gc           :: Toggle comments
    gC           :: Comment selected text


评论


感谢您的回答!您可以扩大它吗?提供插件答案很好,但是现在它只是插件的链接。至少应该在答案中对它做什么以及如何使用它进行基本描述。另请参阅此元信息。

–马丁·图尔诺伊(Martin Tournoij)
15年2月19日在10:09

复制/粘贴键绑定似乎很愚蠢,但是您就可以了。我已经描述了它的作用。

–科林·格雷迪
15年2月19日在17:07

#8 楼

我发现vim注释插件是迄今为止最简单的方法。选择行的范围,然后单击gc。它将为您打开的文件类型使用适当的注释字符。甚至可能没有任何视觉选择就可以用gcu或gcgc取消注释相邻的注释行。

#9 楼

假设您想在行首添加前缀到5行,则可以使用Search and replace:

:.,+5s/^/prefix_/g


或行尾:

:.,+5s/$/suffix_/g


或使用视觉模式(Ctrl + v)选择垂直文本块,然后进入插入模式(I)并键入内容,然后按Esc确认并将更改应用到其他行。

相关内容:




如何在Vim中将文本添加到多行?在stackoverflow

创建Vim函数以在stackoverflow的所有行加上前缀在超级用户处插入视觉块


#10 楼

这个答案在这里是: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*//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*//e',它确保我们不必逃避我们的\v(),这是指我们用1组成的组。基本上,我们匹配的行以任意数量的空格开头,然后匹配注释字符,其后跟随任意数量的空格,并且我们仅保留第一组空白。同样,如果我们在该行上没有注释字符,则()让我们默默地失败。功能)。在这种情况下,e获得突出显示位置的位置,而let l:line=getpos("'<")[1]意味着我们只关心行号,而不关心列号之类的其他内容。
l:您知道getpos()的工作原理。 [1]检查第一件事是否包含第二件事,因此我们抓住了开始突出显示的行,并检查它是否以空格开头,后跟注释字符。 if match(getline(l:line), '^\s*'.b:commentChar)>-1返回正确的索引,如果未找到匹配项,则返回if。由于match()评估所有非零数字为true,因此我们必须比较输出以查看其是否大于-1。 match()中的比较如果为false则返回0,如果为true则返回1,这是-1希望看到以正确评估的结果。
ifvim意味着以可视模式映射以下命令,但不要以递归方式映射它(意味着不要t更改可能以其他方式使用的任何其他命令)。基本上,如果您是vim新手,请务必使用if来确保您不会摔碎东西。 vnoremap <silent> <C-r> :<C-u>call Comment()<cr><cr>的意思是“我不要你的话,只是你的行动”,并告诉它不要在命令行中打印任何内容。 vnoremap是我们要映射的东西,在这种情况下为ctrl + r(请注意,通过此映射,您仍可以在正常模式下将C-r正常用于“重做”)。 noremap有点令人困惑,但基本上可以确保您不会丢失视觉突出显示的内容(根据此答案,它使您的命令以<silent>开始,这正是我们想要的)。 <C-r>在这里只是告诉vim执行我们命名的函数,而C-u则是指点击'<,'>按钮。我们必须打一下它才能实际调用该函数(否则,我们只是在命令行上键入了call,我们必须再次打它才能使我们的替代品一路遍历(不确定为什么,但是无论如何) 。

无论如何,希望这会有所帮助。这将使用<cr>entercall function()突出显示的内容,检查第一行是否已注释,如果是,请尝试取消注释所有突出显示的行,如果没有注释,请为每行添加额外一层注释字符。这是我想要的行为;我不仅希望它切换是否注释了每一行,因此在对这个问题提出了多个问题之后,它对我来说非常理想。

#11 楼

这是对以下内容的扩展:命令并允许使用“ set filetype = X”可以轻松切换的文件类型字典
粘贴以下内容,在字典中声明缺少的文件类型(默认注释字符为“#”),并使用Ctrl-m切换注释在一行或多行上。

let commentTextMap = {
        \'c': '\/\/',
        \'h': '\/\/',
        \'cpp': '\/\/',
        \'java': '\/\/',
        \'php': '\/\/',
        \'javascript': '\/\/',
        \'groovy': '\/\/',
        \'python': '#',
        \'sh': '#',
        \'vim': '"',
        \'make': '#',
        \'conf': '#',
\}
noremap <silent> <expr> <C-m> ((synIDattr(synID(line("."), col("."), 0), "name") =~ 'comment\c') ?
        \ ':<S-Right>:s/^\([ \t]*\)' . get(commentTextMap, &filetype, '#') . '//<CR>' :
        \ ':<S-Right>:s/^/' . get(commentTextMap, &filetype, '#') . '/<CR>:nohl<CR>'
        \ ) . ':nohl<CR>:call histdel("/", -1)<CR>'