我将一个非常简单的vim宏保存到键上:qa$pjq,然后使用40000@a执行它40000次。这非常缓慢。我一定做错了什么,因为虽然它确实能够工作,但大约需要60-90秒时间。vim的速度就是这样快吗?有哪些设置可以加速它?有哪些插件组合会使宏执行变慢吗?
我正在使用Mac和MacVim。这是一个纯文本文件,真的没有比这更简单的了。
把 40,000 行代码粘贴进去并不需要很长时间,但是如果你的屏幕一直更新,就像宏常常做的那样,这会拖慢速度。
首先,关于你的宏应该做什么的问题。如果只是要粘贴默认寄存器的内容,那么正确的宏定义只是 qapjq
。没有必要在上一行的特定位置放置光标。[编辑:抱歉,我假设你要进行行复制,如果你要复制字符寄存器到行尾,则需要定位.. ..]
第二,你可以通过设置 lazyredraw (:set lazyredraw
) 来加速当前的宏,这样屏幕在执行过程中就不会更新了。这可能不会大幅提高速度,像这样的键盘宏不像直接处理缓冲区。
第三,这里有另一种方法,大约需要一秒钟:.,+40000g/.*/normal! $p
我建议使用“vim -u NONE”启动空白的vim。 通常插件会拖慢速度。 你会发现这样可以更快地工作。 然后,你需要找出是哪个插件导致了这种减速。 参见如何查看哪些插件使Vim变慢?
这是正常现象。如Herbert Sitz所述,更新屏幕的速度较慢。
您可能只想运行替换命令::.,+40000s/.*/&<c-r>"
。
.,+40000
是一个范围,包括当前行和接下来的40000行.*
匹配整行&
是被匹配的行<c-r>"
粘贴未命名寄存器的内容我使用40000@a的方式执行宏,但速度非常慢,大约需要60-90秒。我肯定做错了什么,因为虽然它可以工作,但速度太慢了。
其他答案都没有针对主要原因进行解释。宏运行缓慢主要是由插件和粘贴板引起的,与屏幕重绘无关。
filetype
语法和lazyredraw
功能只会带来非常小的影响。正确的解决方法是找出并禁用那些在插入模式下导致编辑缓慢的插件。
宏只是将记录在寄存器中的操作重放到所选区域。宏的运行环境与录制宏的环境相同。插件可能会在编辑时增加额外的开销。通常这不是问题。但将代价乘以40000倍会极大地增加影响。
下面是我得到的宏运行影响因素:
system clipboard >> plugins >> filetype, syntax
避免在宏中访问系统剪贴板。
与访问内部寄存器相比,访问外部系统剪贴板+
、*
会增加额外的成本。在测试中,运行6000行的宏可能会永远冻结宏重放。
禁用影响编辑速度的插件
imap
<CR>
<Tab>
...
jiangmiao/auto-pairs
Raimondi/delimitMate
:noautocmd :norm @q
临时禁用事件运行宏。或者在运行宏之前设置set eventignore=all
,并在运行后将其设置回来。CursorMoved(I)
,CursorHold(I)
InsertCharPre
,InsertEnter
,InsertLeave(Pre)
neoclide/coc.nvim
brglng/vim-im-select
chrisbra/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
se synmaxcol=1
和se ft=txt
和se foldmethod=manual
可以很大程度上帮助解决这个问题。VIM似乎不够智能,无法等待宏完成后再更新语法高亮和折叠等其他更改。说实话,这是VIM的缺点。
a
中。不过屏幕更新做得很好。 - Don Reba