[英]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 ,这将垂直删除所有#
字符。
注释一块文本几乎是一样的:
VISUAL BLOCK
模式。INSERT
模式,然后按# 。 这将在第一行添加一个哈希。#
字符。 对于 debian/ubuntu 默认附带的精简版 vim,请在第三步中键入: s/^/#
(可以使用:nohl
删除每行第一个字符的任何剩余突出显示)。
这里有两个小屏幕录像供视觉参考。
%
如果要选择多个字符,请使用一种或组合以下方法:
有时我被困在一个远程盒子里,我的插件和.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
这是我的做法:
转到要注释掉的第一行的第一个字符。
在 GVIM 中按 Ctrl + q或在 VIM 中按 Ctrl + v ,然后向下选择行上的第一个字符以注释掉。
然后按c ,并添加评论字符。
取消注释的工作方式相同,只需键入空格而不是注释字符。
如果您只需要切换评论,我宁愿使用tpope的commentary.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
不适合我。
没有任何插件的最简单的是
选择块 - V
然后j
或k
或任何相关动作(不要使用箭头键):)
然后点击:
它提示命令:'<,'>
评论
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
该插件提供:
用法:
:<,'>
:<,'>Commentary
并按Enter 。我标记第一行和最后一行(ma 和 mb),然后执行 :'a,'bs/^# //
一些常规的 Vim 命令不适用于我在 Windows 上的设置。 Ctrl + v和Ctrl + q是其中的一部分。 后来我发现以下方法可以取消注释行。
给定
一些缩进的注释
# Practice in Vim
# Practice in Vim
# Practice in Vim
# Practice in Vim
# Practice in Vim
# Practice in Vim
# Practice in Vim
以下方法删除#
符号并保留缩进。
方法
将光标移动到第一个注释(箭头或h 、 j 、 k 、 l )。 然后应用以下技术之一:
视觉块模式(更快)
搜索/替换 + 正则表达式
:
。 你会得到这个提示'<,'>
。s/#//
将散列替换为空。s/# //
以包含空格)。 :norm
命令
:
。 你会得到这个提示'<,'>
。:norm ^x
以删除第一个非空白字符和下一个字符。 (可选:如果没有缩进,请尝试:norm x
或:norm ^xx
以包含空格)。 g
模式
:
。 你会得到这个提示'<,'>
。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
也可以看看
我使用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()
,我们必须再次点击它才能让我们的替代品一直通过(不太清楚为什么,但是无所谓)。
无论如何,希望这会有所帮助。 这将采用v
、 V
或Cv
突出显示的任何内容,检查第一行是否已注释,如果是,请尝试取消注释所有突出显示的行,如果没有,则在每行添加一层额外的注释字符。 这是我想要的行为; 我不只是希望它切换块中的每一行是否被评论,因此在就该主题提出多个问题后,它对我来说非常有效。
"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 和普通文件
它在正常和可视模式下对不同源文件中的行进行注释和取消注释
用法:
从这里的答案中的想法开始,我开始了自己的评论功能。 它打开和关闭评论。 它可以处理像//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 。
其中最快和最直观的方法是重新映射)
用于逐行注释行,然后(
用于逐行取消注释。试试吧,你不会回去的。
在Ruby或Bash中,使用 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
重做自动换行结合得很好。
这是一个基于Cv
和I
方法的基本单线。
此命令 ( :Comment
) 将选定的字符串添加到任何选定行的开头。
command! -range -nargs=1 Comment :execute "'<,'>normal! <C-v>0I" . <f-args> . "<Esc><Esc>"
将此行添加到您的.vimrc
以创建一个接受单个参数的命令,并将该参数放在当前选择的每一行的开头。
例如,如果选择了以下文本:
1
2
然后运行: :Comment //
,结果将是:
//1
//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 */
最好将其保存为.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 + k 、 ctrl + c进行注释或按 Ctrl + k 、 Ctrl + 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>
ctrl + v
进入可视块。 现在使用j
(向下)或k
(向上)导航到需要注释的行。c
进行切插测试。 现在键入“#”进行注释,然后键入esc
以反映您在选定行上的插入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.