繁体   English   中英

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

[英]What's a quick way to comment/uncomment lines in Vim?

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

对于那些我大部分时间使用块选择的任务。

将光标放在第一个#字符上,按Ctrl V (或 gVim 的Ctrl Q ),然后向下直到最后一个注释行并按x ,这将垂直删除所有#字符。

注释一块文本几乎是一样的:

  1. 首先,转到您要评论的第一行,按Ctrl V 这会将编辑器置于VISUAL BLOCK模式。
  2. 然后使用箭头键并选择直到最后一行
  3. 现在按Shift I ,这会将编辑器置于INSERT模式,然后按# 这将在第一行添加一个哈希。
  4. 然后按Esc (稍等),它将在所有其他选定的行上插入一个#字符。

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

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

评论: 评论

取消注释: 取消注释

要在 vim 中注释掉块:

  • Esc (退出编辑或其他模式)
  • 点击ctrl + v (视觉块模式)
  • 使用 / 箭头键选择您想要的行(它不会突出显示所有内容 - 没关系!)
  • Shift + i (大写 I)
  • 插入你想要的文本,例如%
  • Esc Esc

要在 vim 中取消注释块:

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

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

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

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

有时我被困在一个远程盒子里,我的插件和.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 对这个答案的改进)

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

评论中所述:

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

我的.vimrc中有以下内容:

" Commenting blocks of code.
augroup commenting_blocks_of_code
  autocmd!
  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 = '" '
augroup END
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 中注释的行:

显示行号:

:set number

然后

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

或这个:

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

这是我的做法:

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

  2. 在 GVIM 中按 Ctrl + q或在 VIM 中按 Ctrl + v ,然后向下选择行上的第一个字符以注释掉。

  3. 然后按c ,并添加评论字符。

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

切换评论

如果您只需要切换评论,我宁愿使用tpopecommentary.vim

在此处输入图像描述

安装

病原:

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

vim 插件:

Plug 'tpope/vim-commentary'

包装:

Plugin 'tpope/vim-commentary'

进一步定制

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

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

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

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

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

评论:

如果该行的开头没有制表符/空格:
ctrl + V然后jjj然后shift + I (cappital i)然后//然后esc esc
如果该行开头有制表符/空格,您仍然可以执行上述操作或交换c
ctrl + V然后jjj然后c然后//然后esc esc

取消注释:

如果这些行的开头没有制表符/空格:
ctrl + V然后jjj然后ll (lower cap L)然后c

如果这些行的开头有制表符/空格,那么您将空格隔开并esc
ctrl + V然后jjj然后ll (lower cap L)然后c然后space然后esc

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

我结合了 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/\([^ ]\)/' . escape(b:comment_leader,'\/') . ' \1/'
    execute ':silent! s/^\( *\)' . escape(b:comment_leader,'\/') . ' \?' . escape(b:comment_leader,'\/') . ' \?/\1/'
endfunction
map <F7> :call CommentToggle()<CR>

这个怎么运作:

假设我们使用#-comments。

第一个命令s/\([^ ]\)/# \1/搜索第一个非空格字符[^ ]并将其替换为# + itself 自身替换由搜索模式中的\(..\)和替换模式中的\1完成。

第二个命令s/^\( *\)# \?# \?/\1/搜索以双注释开头的行^\( *\)# \?# \? (在注释之间接受 0 或 1 个空格)并简单地用非注释部分替换那些\( *\) (表示相同数量的前面空格)。

有关 vim 模式的更多详细信息,请查看内容。

Visual 和Shift-I不适合我。

没有任何插件的最简单的是


  1. 选择块 - V然后jk或任何相关动作(不要使用箭头键):)

  2. 然后点击:它提示命令:'<,'>

    评论

    Using # - `s/^/#/` Using `//` - `s/^/\/\//`

    取消注释

    Using # - `s/^#//` Using `//` - `s/^\/\//`

解释——

'<,'> - 应用于可视块

s - 替代品

^ - 以

/之后添加字符#在这种情况下为\/\/转义为//


更新

我写了一个函数来用<Space><Space>注释和取消注释当前行

适用于接下来的 10 行,例如10<Space><Space>

将其粘贴到 .vimrc

function CommentUncomment()
  let line = getline('.')
  if line[:1] == "//"
      norm ^2x
  else 
      norm I//
  endif
endfunction

nnoremap <Space><Space> :call CommentUncomment()<CR>

如果您已经知道行号,那么n,ms/# //就可以了。

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

#code code
#code
#code code code

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

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

code code
code
code code code

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

// Esc _

那是大写字母 I、// 和 Escape。

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

前面有 30 个答案,我将尝试提供一个更简单的解决方案:在行首插入# 然后下一行并按点 ( . )。 要重复,请执行j , . , j , . 等...要取消注释,请删除# (您可以在#上点击x ),然后使用k执行相反的操作, . ,ETC...

我喜欢使用 tcomment 插件: http ://www.vim.org/scripts/script.php?script_id=1173

我已经映射 gc 和 gcc 来注释一行或突出显示的代码块。 它检测文件类型并且工作得非常好。

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

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

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

  • 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

修改上面的正则表达式以适应您对#应该在哪里的口味:

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

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

该插件提供

  • 理智
  • 正确缩进的注释
  • 不注释掉空/不必要的行

用法

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

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

一些常规的 Vim 命令不适用于我在 Windows 上的设置。 Ctrl + vCtrl + q是其中的一部分。 后来我发现以下方法可以取消注释行。

给定

一些缩进的注释

   # Practice in Vim
   # Practice in Vim
   # Practice in Vim
   # Practice in Vim
   # Practice in Vim
   # Practice in Vim
   # Practice in Vim

以下方法删除#符号并保留缩进。

方法

将光标移动到第一个注释(箭头或hjkl )。 然后应用以下技术之一:

视觉块模式(更快)

  • Ctrl + Shift + v进入可视块模式
  • j s 选择垂直线。
  • l包括水平字符(可选)
  • x删除块

搜索/替换 + 正则表达式

  • 选择具有常规视觉模式的文本,即Shift + v
  • 类型: 你会得到这个提示'<,'>
  • 键入正则表达式,例如s/#//将散列替换为空。
    (可选:键入s/# //以包含空格)。
  • 进入

:norm命令

  • 选择具有常规视觉模式的文本,即Shift + v
  • 类型: 你会得到这个提示'<,'>
  • 发出命令。 键入:norm ^x以删除第一个非空白字符和下一个字符。 (可选:如果没有缩进,请尝试:norm x:norm ^xx以包含空格)。
  • 进入

g模式

  • 选择具有常规视觉模式的文本,即Shift + v
  • 类型: 你会得到这个提示'<,'>
  • 发出命令。 输入g/#/norm! ^x g/#/norm! ^x
    (可选:输入g/#/norm! ^xx以包含空格)。
  • 进入

结果

    Practice in Vim
    Practice in Vim
    Practice in Vim
    Practice in Vim
    Practice in Vim
    Practice in Vim
    Practice in Vim

也可以看看

  • 发布删除缩进评论
  • 发布如何使用 Vim 快速评论
  • ThePrimeagen 的g命令教程
  • VimTrick 关于注释代码教程

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

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

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

这个答案在这里 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*/\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! Docomment() :以function开头并以endfunction结尾来声明函数。 函数必须以大写字母开头。 ! 确保此函数使用此版本的Docomment()覆盖任何先前定义为Docomment()的函数。 没有! ,我有错误,但这可能是因为我正在通过 vim 命令行定义新函数。

  • execute '''<,''>s/^\s*/&'.escape(b:commentChar, '\/').' /e' execute '''<,''>s/^\s*/&'.escape(b:commentChar, '\/').' /e' :执行调用命令。 在这种情况下,我们正在执行substitute ,它可以采用一个范围(默认情况下这是当前行),例如整个缓冲区的%或突出显示部分'<,'> ^\s*是正则表达式,用于匹配行首后跟任意数量的空格,然后将其附加到(由于& )。 . 这里用于字符串连接,因为escape()不能用引号引起来。 escape()允许您通过在前面加上\来转义与参数(在本例中为\/ )匹配的commentChar字符。 在此之后,我们再次与具有e标志的substitute字符串的末尾连接。 这个标志让我们静默失败,这意味着如果我们在给定的行上找不到匹配项,我们就不会大喊大叫。 总的来说,这一行让我们在第一个文本之前放置一个注释字符,后跟一个空格,这意味着我们保持缩进级别。

  • 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()返回为 true 的索引,如果未找到匹配项,则返回-1 由于if评估所有非零数字为真,我们必须比较我们的输出以查看它是否大于 -1。 vim中的比较如果为假则返回 0,如果为真则返回 1,这就是if希望看到正确评估的结果。

  • vnoremap <silent> <Cr> :<Cu>call Comment()<cr><cr> : vnoremap表示在可视模式下映射以下命令,但不要递归映射它(意思是不要更改任何其他可能以其他方式使用)。 基本上,如果您是 vim 新手,请始终使用noremap来确保您不会破坏任何东西。 <silent>的意思是“我不想要你的话,只想要你的行动”,并告诉它不要在命令行中打印任何内容。 <Cr>是我们正在映射的东西,在这种情况下是 ctrl+r(请注意,您仍然可以使用 Cr 在正常模式下通过此映射正常“重做”)。 Cu有点令人困惑,但基本上它确保你不会忘记你的视觉突出显示(根据这个答案,它使你的命令以我们想要'<,'>开头)。 这里的call只是告诉 vim 执行我们命名的函数,而<cr>是指点击enter按钮。 我们必须点击一次才能真正调用该函数(否则我们只是在命令行上输入了call function() ,我们必须再次点击它才能让我们的替代品一直通过(不太清楚为什么,但是无所谓)。

无论如何,希望这会有所帮助。 这将采用vVCv突出显示的任何内容,检查第一行是否已注释,如果是,请尝试取消注释所有突出显示的行,如果没有,则在每行添加一层额外的注释字符。 这是我想要的行为; 我不只是希望它切换块中的每一行是否被评论,因此在就该主题提出多个问题后,它对我来说非常有效。

"comment (cc) and uncomment (cu) code 
noremap   <silent> cc      :s,^\(\s*\)[^# \t]\@=,\1# ,e<CR>:nohls<CR>zvj
noremap   <silent> cu      :s,^\(\s*\)# \s\@!,\1,e<CR>:nohls<CR>zvj

您可以使用 # 注释/取消注释单行或多行。 要执行多行,请选择行然后键入 cc/cu 快捷方式,或键入一个数字然后 cc/cu,例如 7cc 将注释从光标开始的 7 行。

我从这个人那里得到了原始代码, 什么是在 Vim 中注释/取消注释 ruby​​ 代码块的最优雅的方式? 并进行了一些小改动(更改了快捷键,并在 # 后添加了一个空格)。

我使用 Tim Pope 的vim-commentary插件。

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

按 进入可视模式

'v'

然后按

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

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

'gc'

这将注释掉所有选择,取消注释重复键:

'gc'

这个简单的片段来自我的 .vimrc:

function! CommentToggle()
    execute ':silent! s/\([^ ]\)/\/\/ \1/'
    execute ':silent! s/^\( *\)\/\/ \/\/ /\1/'
endfunction

map <F7> :call CommentToggle()<CR>

它用于 //-Comments,但您可以轻松地将其调整为其他字符。 您可以按照 jqno 的建议使用 autocmd 设置领导者。

这是自然地使用范围和视觉模式的一种非常简单有效的方式。

我使用 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 和普通文件

它在正常和可视模式下对不同源文件中的行进行注释和取消注释

用法:

  • Ctrl C注释一行
  • Ctrl X取消注释一行
  • Shift V并选择多行,然后Ctrl C注释选定的多行
  • Shift V并选择多行,然后Ctrl X取消注释选定的多行

从这里的答案中的想法开始,我开始了自己的评论功能。 它打开和关闭评论。 它可以处理像//print('blue'); //this thing is blue这样的事情 //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>

为此,我使用vim-multiple-cursors

  1. 要选择区域,请通过按0转到要注释掉的区域的第一行或最后一行的第一个字符(它是零,而不是字母“o”)。 然后按V并使用JK或上下箭头键选择区域。
  2. 然后按Ctrl N将虚拟光标放在所选内容的每一行上。
  3. 然后按I同时编辑选择的每一行。

其中最快和最直观的方法是重新映射)用于逐行注释行,然后(用于逐行取消注释。试试吧,你不会回去的。

RubyBash中,使用 2 个空格缩进:

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

C/C++PHP中,使用 4 个空格缩进:

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

缺点是你会因为句子移动而丢失() (但das可以在那里填写),并且你偶尔会求助于选择和替换或Ctrl V来处理长部分。 但这非常罕见。

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

set cindent
set formatoptions=tcqr

...这与使用V[move]gq重做自动换行结合得很好。

这是一个基于CvI方法的基本单线。

此命令 ( :Comment ) 将选定的字符串添加到任何选定行的开头。

command! -range -nargs=1 Comment :execute "'<,'>normal! <C-v>0I" . <f-args> . "<Esc><Esc>"

将此行添加到您的.vimrc以创建一个接受单个参数的命令,并将该参数放在当前选择的每一行的开头。

例如,如果选择了以下文本:

1
2

然后运行: :Comment // ,结果将是:

//1
//2

要取消注释整个文件:

  1. Esc退出插入模式
  2. g g转到第一行的第一个字符
  3. ctrl + Vctrl + shift + v选择当前字符
  4. Gshift + g转到最后一行
  5. x删除选择

我喜欢/* ... */ (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 */

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

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

通过使用qc记录将其保存在寄存器中,然后在段落的开头进行评论:

v}di/*  */<esc>hhhp

并且不要再次忘记q ,完成记录。

详见 (iii*)。


从块中取消注释单个 /* */

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

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

完成q命令保存寄存器。

详见 (iv*)。


结果

Effect 是多行的单个注释:

Comment block
Comment block
Comment block

变成(反之亦然):

/* Comment block
Comment block
Comment block */

解释

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

: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*)在中间的任何地方,向后找到/* ,将其删除; 找到转发*/ ,将其删除。

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

在 VIM 中:

1- 按v进入视觉模式。

2- 使用箭头选择要评论的块。

3- 按:

4-键入's/^/#'

要删除评论,只需将步骤 4 替换为:

4-键入's/^#//'

我喜欢简短集成令人难忘的方法,不要依赖外部脚本而大惊小怪......

TLDR
gI (大写 i)以插入模式将光标置于行首(无论它是空格还是非空格字符并防止自动缩进

使用它来快速注释(例如)不连续的行,其中注释符号(例如#// )作为第一个字符并且没​​有缩进,通过按. (点)-->但如果仍然存在自动缩进机制,则在插入模式下按 和 纠正缩进并在操作后转义到正常模式。 现在. 可用于注释行...


我现在(多年后)意识到,按gI (大写 i)会将光标置于插入模式下的第 1 列(意思是:无论是单词还是非单词字符,都位于行首)。

插入注释符号(如# )并按下escape键 - 现在可以在按下. (点)在键盘上。

与按0i或仅按I将评论符号放在第一个单词字符处相反,部分还带有不需要的缩进

有几个 vim 插件,如 Tcomment 和 nerdcommenter 可用。

我使用 tcomment 进行评论。

gcc:它将切换当前行的注释。 v{motion}gc:它将切换评论一系列视觉选择的行

示例:v3jgc 将切换 3 行的区域。

这些命令可用于处理任何语言的注释。

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

另一个不错的选择是使用 ex 模式命令。 : [范围]正常i # # . 显然,要使用此键节省击键,您需要注释掉 15 行以上。

首先,我要感谢@mike 的回答,因为我正在使用它的修改版本。 我想发布我的版本,以防有人感兴趣。 我的主要功能差异是它总是在范围的每一行上执行相同的操作。 如果所选范围包含任何未注释的行,则每行都会添加一个注释前导。 这样,如果您在其他未注释的代码块中有人类可读的注释,它们就不会被取消注释。 然后,当您取消注释该块时,人类可读的文本将保持注释状态,因为它有 2 个评论领导者。 完成后它还会恢复光标位置。

切换评论功能:

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.

我已经解决了这个问题,并稍微简化了正则表达式。 一个副作用是它不再在评论领导者之后添加一个空格,但这并不困扰我。 我已在原始答案中忘记的一些变量中添加了本地声明。

我个人不喜欢注释“切换”功能,因为它会破坏已经包含在代码中的注释。 另外,我想让评论字符总是出现在最左边,这样我就可以很容易地看到评论块。 我也希望它可以嵌套工作(如果我先注释掉一个块,然后再注释掉一个封闭块)。 因此,我稍微改变了其中一种解决方案。 我使用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>

很好的问题,但恕我直言,没有那么多好的答案。 首先,我想说,在这里使用块插入模式并不是一个简单的解决方案,只是击键太多,所以显然它必须在选定的行上工作以提高代码编辑的性能。 没有人提到的另一点:注释符号应该放在哪里 - 在行的最开始还是在实际文本之前? 这可能是一个口味问题,但我认为,它应该放在文本之前以保持代码可读性:当注释符号放在最开始的行时,它会破坏缩进代码的视觉一致性,所以它看起来像一个项目符号列表。 考虑到这一点,我最终得到了以下解决方案(我以#comment 为例)。 在我的vimrc中:

vnoremap 1 :s:^\(\s*\)\([^#\t ]\):\1#\2:e<CR>
vnoremap 2 :s:^\(\s*\)#\(\s*\):\1\2:e<CR>

1在每个选定行的文本之前(空格之后)插入# 它检查是否已经存在# ,而不是插入#两次。 并且还忽略空行。
2删除一个# 它还可以保证行右侧的注释安全。


更新:这是一个示例,如何使文件类型相关的切换注释命令。 要了解有关这些内容的更多信息,请阅读:http: //learnvimscriptthehardway.stevelosh.com/chapters/14.html

只是为了让它工作,把下面几行放在你的.vimrc文件中。

" build the whole regex search/replace command
function! Build()
    let b:Comment_ON='''<,''>s:^\(\s*\)\([^\t ]\):\1' . b:cs . '\2:e'
    let b:Comment_OFF='''<,''>s:^\(\s*\)' . b:cs . '\(\s*\):\1\2:e'
endfunction

" run this group on Filetype event
augroup SetCS
    autocmd!
    "default comment sign
    autocmd FileType * let b:cs='--'
    "detect file type and assign comment sign
    autocmd FileType python,ruby let b:cs='#'
    autocmd FileType c,cpp,java,javascript,php let b:cs = '\/\/'
    autocmd FileType vim let b:cs='"'
    autocmd FileType * call Build()
augroup END

vnoremap 1 :<C-u>execute b:Comment_ON<CR>
vnoremap 2 :<C-u>execute b:Comment_OFF<CR>

该解决方案将 / 映射到评论和 ? 取消注释(使用单个映射进行注释切换太复杂而无法正确实现)。 它从 VIM 的内置commentstring字符串选项中获取注释字符串,如果声明了filetype plugin on则该选项从/usr/share/vim/vim*/ftplugin/*.vim之类的文件中填充。

filetype plugin on
autocmd FileType * let b:comment = split(&commentstring, '%s', 1)
autocmd FileType * execute "map <silent> <Leader>/ :normal 0i" . b:comment[0] . "<C-O>$" . b:comment[1] . "<C-O>0<CR>"
autocmd FileType * execute "map <silent> <Leader>? :normal $" . repeat('x', strlen(b:comment[1])) . "0" . strlen(b:comment[0]) . "x<CR>"

我个人想评论 a-la Visual Studio。 我在工作中已经习惯了它,它已经接管了我的肌肉记忆(使用 vsvim)。 使用shift + v选择您想要的行,然后按ctrl + kctrl + c进行注释或按 Ctrl + kCtrl + u取消注释。

:vnoremap <C-k><C-c> :norm i//<Cr>
:vnoremap <C-k><C-u> :s/\/\///g<Cr>:noh<Cr>

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

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

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

" comments
augroup comment_like_a_boss
    autocmd!
    autocmd FileType c,cpp,go                let b:comment_leader = '// '
    autocmd FileType ruby,python             let b:comment_leader = '# '
    autocmd FileType conf,fstab,sh,bash,tmux 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 = '" '
augroup END
noremap <silent> ,cc :<C-b>silent <C-e>norm ^i<C-r>=b:comment_leader<CR><CR>
noremap <silent> ,uc :<C-b>silent <C-e>norm ^xx<CR>
  1. 注释行的一种方法是使用可视块选择
  • 将光标放在需要注释的行的第 0 处,然后ctrl + v进入可视块。 现在使用j (向下)或k (向上)导航到需要注释的行。
  • 然后用c进行切插测试。 现在键入“#”进行注释,然后键入esc以反映您在选定行上的插入
  1. 使用命令模式
  • 选择带有V的行,然后使用j (downawrds) k (向上)选择所有需要注释的行并点击:进入看起来像“: <, >”的命令模式,然后在所选行的开头
:'<,'>s/^/#

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

删除字符之间的空格并使用此命令注释 .C 或 CPP 文件

要评论一行(适用于所有语言):

  • noremap <silent> ,// :call CommentLine() <CR>

我们可以用行数来调用它,在可视模式下也可以。 喜欢:评论四行使用4,//取消评论使用4,/

取消注释一行(适用于所有语言):

  • noremap <silent> ,/ :call UnCommentLine() <CR>

如果您想添加新符号 [comment] ,请添加一个列表并在函数中添加一些行 如果要添加具有已在其中一个列表中定义的注释符号的语言,只需在相应列表中添加您的语言名称(获取正确名称:在 vim 中打开文件并使用:set ft获取正确名称为您的语言)。

CommentLine() 的定义

function! CommentLine() let slash_ft_list = ['c' , 'cpp', 'java', 'scala' , 'systemverilog' , 'verilog' , 'verilog_systemverilog'] let hash_ft_list = ['sh' , 'ruby' , 'python' , 'csh' , 'conf' , 'fstab' , 'perl'] let perct_ft_list = ['tex'] let mail_ft_list = ['mail'] let quote_ft_list = ['vim'] if (index(slash_ft_list, &ft) != -1) :norm I// elseif (index(hash_ft_list, &ft) != -1) :norm I# elseif (index(perct_ft_list, &ft) != -1) :norm I% elseif (index(mail_ft_list, &ft) != -1) :norm I> elseif (index(quote_ft_list, &ft) != -1) :norm I" endif endfunction

UnCommentLine() 的定义

function! UnCommentLine() let slash_ft_list = ['c' , 'cpp', 'java', 'scala' , 'systemverilog' , 'verilog' , 'verilog_systemverilog'] let hash_ft_list = ['sh' , 'ruby' , 'python' , 'csh' , 'conf' , 'fstab' , 'perl'] let perct_ft_list = ['tex'] let mail_ft_list = ['mail'] let quote_ft_list = ['vim'] if (index(slash_ft_list, &ft) != -1) :norm ^2x elseif (index(hash_ft_list, &ft) != -1) :norm ^x elseif (index(perct_ft_list, &ft) != -1) :norm ^x elseif (index(mail_ft_list, &ft) != -1) :norm ^x elseif (index(quote_ft_list, &ft) != -1) :norm ^x endif endfunction

:g/.spare[1-9].*/,+2s/^/\/\//

上面的代码将注释掉所有包含“备用”的行和后面的一个数字,再加上它会在找到的那一行多注释两行。 有关更多此类用途,请访问:http: //vim.wikia.com/wiki/Search_and_replace#Details

用mark命令标记文本区域say ma and mb type command: :'a,'bg/(.*)/s////\1/

您可以在http://bknpk.ddns.net/my_web/VIM/vim_shell_cmd_on_block.html看到这种测试操作的示例

ctrl + v然后使用选择要评论的行数。 然后按shift + I ,按# ,然后按ESC 这将注释掉您选择的行数。

取消注释行相反。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM