【发布时间】:2012-01-12 22:10:28
【问题描述】:
我将一个非常简单的 vim 宏保存到一个键中:qa$pjq,然后使用 40000@a 执行 40000 次。这很慢。我一定做错了什么,因为虽然它确实有效,但它需要大约 60-90 秒。这和vim一样快吗?是否有一些设置可以加速这一点?是否存在使宏执行变慢的插件组合?
我正在使用 Mac 并使用 MacVim。这是一个纯文本文件,真的没有比这更简单的了。
【问题讨论】:
我将一个非常简单的 vim 宏保存到一个键中:qa$pjq,然后使用 40000@a 执行 40000 次。这很慢。我一定做错了什么,因为虽然它确实有效,但它需要大约 60-90 秒。这和vim一样快吗?是否有一些设置可以加速这一点?是否存在使宏执行变慢的插件组合?
我正在使用 Mac 并使用 MacVim。这是一个纯文本文件,真的没有比这更简单的了。
【问题讨论】:
然后用 40000@a 执行 40000 次。这是非常缓慢的。我一定是做错了什么,因为虽然它确实有效,但它需要大约 60-90 秒。
其他答案均未针对主要原因。宏运行缓慢主要受插件影响、粘贴,而不是屏幕重绘。
filetype 语法和lazyredraw 只会产生非常、非常、非常最小的影响。正确的解决方案应该是找出并禁用那些在插入模式下减慢编辑速度的插件。
宏只是将存储在寄存器中的动作重播到所选区域。运行宏的环境和你录制宏的环境是一样的。插件可能会在编辑过程中引入额外的成本。通常这不是问题。但将成本乘以 40,000 会显着放大影响。
这是我得到的对宏运行的影响因子:
system clipboard >> plugins >> filetype, syntax
避免在宏中访问系统剪贴板。
与访问内部寄存器相比,访问外部系统剪贴板+、* 会带来额外的成本。它甚至可能永远冻结宏重播(在我的测试中运行 6000 行宏)。
禁用影响编辑速度的插件
imap <CR> <Tab> ...
jiangmiao/auto-pairsRaimondi/delimitMate:noautocmd :norm @q 在宏运行期间暂时禁用事件。
或者在宏运行之前set eventignore=all,之后再设置。CursorMoved(I), CursorHold(I)
InsertCharPre, InsertEnter, InsertLeave(Pre)
neoclide/coc.nvimbrglng/vim-im-selectchrisbra/Colorizer注意:
auto-pairs 的插入模式映射,
这也是我切换到delimitMate 的原因之一。:noautocmd。范围应放在norm 之前::noa '<,'>norm! @q
这是我在运行宏之前禁用上述插件的切换功能。
使用<F3>m 在录制宏之前禁用插件。运行宏后,
<F3>m 再次重置这些插件的状态。
(我把我所有的切换都归为<F3>,m 代表宏。您可以根据需要调整映射。)
function! <SID>ToggleMacro(...)
" Optimize macro running by disable some plugins.
if get(g:, '_macro', {}) ==# {}
let g:_macro = {'state': 1}
let g:_macro.auto_pairs = get(b:, 'autopairs_enabled')
if g:_macro.auto_pairs
let b:autopairs_enabled = 0
endif
let g:_macro.delimit_mate = get(b:, 'delimitMate_enabled')
if g:_macro.delimit_mate
DelimitMateOff
endif
let g:_macro.eventignore = &eventignore
set eventignore=all
else
let g:_macro.state = 0
let b:autopairs_enabled = g:_macro.auto_pairs
if g:_macro.delimit_mate
DelimitMateOn
endif
let &eventignore = g:_macro.eventignore
endif
if g:_macro.state
echo 'Macro boost: On'
else
echo 'Macro boost: Off'
unlet g:_macro
endif
endfunction
nnoremap <F3>m :call <SID>ToggleMacro()<CR>
command! -nargs=? ToggleMacro call <SID>ToggleMacro(<f-args>)
:h autocmd, :h noautocmd, :h eventignore
:noautocmd,eventignore
【讨论】:
我遇到了一些问题,即即使在少量行上操作时,VIM 宏也很慢(尽管更改很复杂)。 se synmaxcol=1 和 se ft=txt 和 se foldmethod=manual 可以提供很多帮助。 VIM 似乎不够聪明,无法等到宏完成后才更新语法高亮和折叠以及其他此类更改。老实说,这是 VIM 的失败。
【讨论】:
set syntax= 在我的情况下帮助了我。
我建议使用 'vim -u NONE' 启动一个空白 vim。 通常插件会减慢速度。 您会看到它以这种方式运行得更快。 然后你需要找出是什么插件导致了这种减速。 另见How to see which plugins are making Vim slow?
【讨论】:
粘贴 40,000 行并不需要很长时间,但是如果您像经常在减慢速度的宏中那样让屏幕不断更新。
首先,关于您的宏应该做什么的问题。如果只是粘贴默认寄存器的内容,那么正确的宏定义就是qapjq。无需将光标定位在前一行的特定位置。 [编辑:对不起,我假设您正在执行逐行粘贴,如果您在行尾粘贴逐字符寄存器,则需要定位。 . ..]
其次,您可以通过设置lazyredraw (:set lazyredraw) 来加速您当前的宏,因此屏幕不会随其更新。可能不会大大加快速度,像这样的键盘宏不像直接处理缓冲区。
第三,这是另一种需要大约一秒钟的方法:
.,+40000g/.*/normal! $p
【讨论】:
a中。不过,屏幕更新很好。
这是正常的。正如 Herbert Sitz 所写,更新屏幕很慢。
您可能只想运行一个替换命令::.,+40000s/.*/&<c-r>"。
.,+40000 是一个范围,包括当前行和后面的 40000 行.* 匹配整行& 是匹配的行<c-r>"粘贴未命名寄存器的内容【讨论】: