Vim 宏非常慢

发布于 2024-12-19 15:35:31 字数 197 浏览 0 评论 0原文

我将一个非常简单的 vim 宏保存到一个键:qa$pjq,然后使用 40000@a 执行它 40000 次。这非常慢。我肯定做错了什么,因为虽然它确实有效,但需要大约 60-90 秒。这和 vim 一样快吗?是否有一些设置可以加速这一过程?是否有混合插件会导致宏执行速度变慢?

我使用的是 Mac 并使用 MacVim。它是一个纯文本文件,确实没有比这更简单的了。

I'm saving a very simple vim macro to a key: qa$pjq and then executing it 40000 times with 40000@a. This is very slow. I must be doing something wrong, because while it does work it takes something like 60-90 seconds. Is this as fast as vim goes? Are there some settings that can accelerate this? Is there a mixture of plugins that make macro execution slow?

I'm using a Mac and using MacVim. It is a plain text file, it really doesn't get any simpler than this.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

最丧也最甜 2024-12-26 15:35:31

粘贴 40,000 行并不需要很长时间,但如果您像在宏中经常做的那样不断更新屏幕,则会减慢速度。

首先,关于你的宏应该做什么的问题。如果只是粘贴默认寄存器的内容,那么正确的宏定义就是qapjq。无需将光标定位在上一行的特定位置。 [编辑:抱歉,我假设您正在进行逐行粘贴,如果您要在行尾粘贴逐字符寄存器,则需要定位。 。 .. ]

其次,您可以通过设置lazyredraw(:setlazyredraw)来加快当前宏的速度,这样屏幕就不会随之更新。可能不会加快速度很多,像这样的键盘宏不像直接处理缓冲区。

第三,这是另一种方法,大约需要一秒钟:
.,+40000g/.*/正常! $p

It doesn't take long to paste 40,000 lines, but if you've got the screen constantly updating as you often do in a macro that slows things down.

First, a question about what your macro is supposed to be doing. If it's simply pasting contents of default register, then proper macro definition is just qapjq. There is no need to position the cursor in a specific spot on previous line. [EDIT: sorry, I was assuming you were doing linewise paste, positioning is needed if you're pasting character-wise register at end of line. . .. ]

Second, you can speed up your current macro by setting lazyredraw (:set lazyredraw), so screen doesn't update as it goes. Probably won't speed things up a whole lot, keyboard macros like this aren't like direct processing of the buffer.

Third, here's another method that should take about a second:
.,+40000g/.*/normal! $p

甜是你 2024-12-26 15:35:31

我建议使用“vim -u NONE”启动一个空白的 vim。
插件通常会减慢速度。
您会发现这种方式运行得更快。
然后你需要找出是什么插件导致了这种减速。
另请参阅 如何查看哪些插件导致 Vim 变慢?

I would recommend to start a blank vim with 'vim -u NONE '.
Often plugins are slowing down things.
You will see that it works much faster this way.
Then you need to find out what plugin causes this slowdown.
See also How to see which plugins are making Vim slow?

贱贱哒 2024-12-26 15:35:31

这是正常的。正如 Herbert Sitz 所写,屏幕更新速度很慢。

您可能只想运行替换命令::.,+40000s/.*/&"

  • .,+40000 是一个范围,包括当前行和模式中的 40000 后面的
  • .* 匹配整行
  • & 字符串中的就是匹配的行
  • " 粘贴未命名寄存器的内容

This is normal. As Herbert Sitz wrote, updating the screen is slow.

You might want to just run a substitution command: :.,+40000s/.*/&<c-r>".

  • .,+40000 is a range including the current line and the 40000 following
  • .* in the pattern matches a whole line
  • & in the string is the line that was matched
  • <c-r>" pastes the contents of the unnamed register
纸短情长 2024-12-26 15:35:31

使用 40000@a 执行宏 40,000 次非常慢,大约需要 60-90 秒。我一定是做错了什么。

其他答案都没有解决主要问题。宏执行性能缓慢主要受系统剪贴板访问和插件注册的事件挂钩影响,而不是屏幕重绘。

使用 filetype 语法和 lazyredraw 的影响非常小。真正的解决方案在于识别并禁用在插入模式下阻碍编辑速度的插件。

说明

宏只是在选定区域上重播存储在寄存器中的操作。宏运行的环境与录制宏的环境相同。

这意味着监听 Vim 事件的插件在宏重播时继续运行。在此过程中影响性能的相关挂钩和事件包括:

  • CursorMoved(I)
  • CursorHold(I)
  • InsertCharPre
  • InsertEnter
  • InsertLeave(Pre)
  • ...

移动光标或编辑文本时会发生其他操作。

解决方案

  1. 录制宏时避免访问系统剪贴板。
  2. 在录制宏之前抑制 autocmd (事件/挂钩),然后重新启用它们。以下函数由 m 触发,使用 Vim 设置 eventignore 切换此“宏增强”:
function! <SID>ToggleMacro(...)
  if get(g:, '_macro', {}) ==# {}
    let g:_macro = {'state': 1}
    let g:_macro.eventignore = &eventignore
    set eventignore=all
  else
    let g:_macro.state = 0
    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>)

注意:使用 :noautocmd当重播宏不够时。由于在宏录制期间不会抑制自动命令,因此录制和重放的环境不同。这可能会导致意外的行为。例如,jianmiao/auto-pairs 插件可以帮助插入配对引号,但在使用 :noautocmd 重播宏时,它无法正常工作。

" q is register for macro
" noa is short for noautocmd
:noa '<,'>norm! @q

参考文献

  • :h autocmd
  • :h noautocmd
  • :h eventignore

特别感谢 Christian Brabandt 提到了 :noautocmdeventignore

Executing the macro 40,000 times with 40000@a is extremely slow, taking around 60-90 seconds. I must be doing something wrong.

None of the other answers addressed the primary issue. The slow performance of macro execution is mainly influenced by system clipboard access and event hooks registered by plugins, rather than by screen redrawing.

Using filetype syntax and lazyredraw only has a very minimal impact. The real solution lies in identifying and disabling the plugins that hinder your editing speed in insert mode.

Explanation

A macro simply replays actions stored in a register over the selected region. The environment in which the macro runs is the same as the environment used to record it.

This means that plugins listening to Vim events continue to operate while the macro is replayed. The relevant hooks and events affecting performance during this process include:

  • CursorMoved(I)
  • CursorHold(I)
  • InsertCharPre
  • InsertEnter
  • InsertLeave(Pre)
  • ...

Additional actions occur when moving the cursor or editing text.

Solution

  1. Avoid accessing the system clipboard when recording the macro.
  2. Suppress autocmd (event/hooks) before recording the macro, and re-enable them afterward. The following function, triggered by <F3>m, toggles this "macro boost" using the Vim setting eventignore:
function! <SID>ToggleMacro(...)
  if get(g:, '_macro', {}) ==# {}
    let g:_macro = {'state': 1}
    let g:_macro.eventignore = &eventignore
    set eventignore=all
  else
    let g:_macro.state = 0
    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>)

Note: Using :noautocmd when replaying the macro is insufficient. Since autocmds are not suppressed during macro recording, the environments for recording and replaying differ. This can lead to unexpected behavior. For example, the jiangmiao/auto-pairs plugin assists with inserting paired quotes, but it won't function correctly when replaying a macro with :noautocmd.

" q is register for macro
" noa is short for noautocmd
:noa '<,'>norm! @q

References

  • :h autocmd
  • :h noautocmd
  • :h eventignore

Special thanks to Christian Brabandt for mentioning :noautocmd and eventignore.

那些过往 2024-12-26 15:35:31

我遇到了一些问题,即使在少量行上操作时,VIM 宏也非常慢(尽管更改很复杂)。 se synmaxcol=1se ft=txtse Foldmethod=manual 可以提供很大帮助。 VIM 似乎不够智能,无法等到宏完成后才更新语法突出显示和折叠以及其他此类更改。老实说,这是 VIM 的失败。

I have had some problems with VIM macros being very slow even when operating on a small number of lines (although the changes are complex). se synmaxcol=1 and se ft=txt and se foldmethod=manual can help a lot. VIM does not seem smart enough to wait until after the macro is done to update syntax highlighting and folding and other such changes. It's a failing of VIM to be honest.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文