【问题标题】:Stop vim from dynamically updating folds阻止 vim 动态更新折叠
【发布时间】:2014-01-22 10:36:12
【问题描述】:

有什么方法可以阻止 vim 自动更新折叠?我真的很喜欢 vim 的折叠,而且我更喜欢在语法模式下使用它,以便在我键入时创建折叠。但是例如,当我编写 C++ 代码并编写一个括号 { 它会自动关闭所有后续折叠,然后当我再次用 } 关闭括号时,vim 会自动展开所有后续折叠,这意味着我必须重新折叠所有内容。

另一个相关的问题,如果我在不同的缓冲区中打开了相同的文档,假设我运行了“:split”,那么写一个左括号 { 会将缓冲区中的所有折叠嵌套在我打开括号的折叠下, 关闭它将取消嵌套折叠但也会关闭所有折叠。如果我使用“。”或“->”来访问成员函数/变量,它将缓冲区中的所有折叠重置为当前折叠级别,无论我自己打开/关闭了哪些折叠。

当我在两个缓冲区中打开同一个文档时,这有点令人沮丧,因此我可以在编写另一个函数时读取一个函数的内容,因为我必须经常切换缓冲区并重新打开我的折叠。

在我的 .vimrc 中有

set foldmethod=syntax

就是这样。对于自动补全,我使用 clang-complete 和 supertab:

let g:SuperTabDefaultCompletionType = "<c-x><c-u><c-p>"

我认为这就是可能影响这一点的一切。

编辑:

Added some pictures to help illustrate the problem

【问题讨论】:

    标签: vim


    【解决方案1】:

    这两个问题都可以通过以下两个autocmds 解决:

    autocmd InsertLeave,WinEnter * setlocal foldmethod=syntax
    autocmd InsertEnter,WinLeave * setlocal foldmethod=manual
    

    当进入插入模式或离开其窗口(缓冲区显示)时,这会将缓冲区本地'foldmethod' 设置为manual,并在离开插入模式或进入其窗口时将其设置为syntax。

    之所以可行,是因为将'foldmethod' 设置为manual 将保留syntax 自动创建的折叠,就像您自己(手动)设置它们一样,并且手动折叠不会根据文件的语法进行更新。

    我发现这个解决方案有两个错误:

    1. 在插入模式下切换窗口时,autocmd 会将新窗口的'foldmethod' 设置为syntax,即使它处于插入模式并应设置为manual。

      这对我来说不是问题,因为我像一个文明人一样使用 Vim,并且默认在正常模式下运行。

    2. 什么时候

      • 创建了一个新缓冲区(例如通过读取文件)
      • 和'foldlevel' 是0
      • 并且使用了特定的语法(我可以用 C 文件复制问题)
      • 并且o 或O 命令用于在该缓冲区中第一次进入插入模式(执行i&lt;esc&gt;o 不会重复该错误),

      然后将打开光标下方的所有折叠。

      我在测试上述解决方案时偶然发现了这一点,现在回想起来我很惊讶我发现了它;这几乎不值得一提。我不打算尝试编写具有复制错误所需的确切语法的测试文件,因此这可能会在另一个 eon 中被忽视。


    实际上,我几个月前就发现了这个问题,并使用了 Ben linked to 的解决方案一段时间,最终对一个缓冲区问题(您的第二个问题)的多窗口解决方案感到厌烦。

    感谢 Ben 的解决方案,感谢您提出这个问题!

    【讨论】:

    • 乍一看,经过一些测试,这似乎确实解决了我的问题。当然,在处理拆分和多个缓冲区时,模 vim 有点奇怪,但这是我学会的。
    • “在插入模式下切换窗口时”......这甚至可能吗?!?!哦,我的...为什么有人会做这样的事情? O.o
    【解决方案2】:

    我对 user4830797 的回答做了一些修改,这有助于处理您正在编辑的文件不使用 foldmethod=syntax 的情况(例如,可能使用 foldmethod=marker 的 .vimrc 文件):

    autocmd InsertLeave,WinEnter * let &l:foldmethod=g:oldfoldmethod
    autocmd InsertEnter,WinLeave * let g:oldfoldmethod=&l:foldmethod | setlocal foldmethod=manual
    

    【讨论】:

    • 处理“*”的 WinEnter 自动命令时检测到错误:E121:未定义变量:g:oldfoldmethod
    【解决方案3】:

    我认为您需要检查:h 'foldlevel。您也许还应该使用:mkview,可能在autocmd 中,它可以恢复手动打开和关闭的折叠。

    除此之外,您可能应该在不同的文件类型上设置不同的折叠方法(例如在 C 上,您可以将其设置为手动或标记)

    【讨论】:

    • 我更愿意继续使用语法折叠,因为它通常工作得很好,而且我认为 foldlevel 与此无关。问题是每当我写一些会创建折叠的东西时,无论折叠级别如何,所有后续折叠都会打开
    • 你可以尝试在 startinsert 上 mkview 并在 end insert 上恢复视图吗?
    • 除了看起来有点作弊之外,它的效果略有不同。首先,它似乎将括号后面的所有东西都折叠一次(但不是一直折叠),我猜这是一种改进,但仍然无法正常工作。另外,如果我写一个括号,在里面写一些东西,然后在我的新括号内停止编辑,当我退出插入模式时,它将被折叠,这不太理想。
    • 后面的部分很容易通过在退出时恢复视图后添加zv 来解决(打开足够多的折叠以查看光标)。看起来很作弊? :) 它要么有效,要么无效。
    • 好吧,我猜。只是在自动创建新折叠时关闭所有后续折叠(如果发生这种情况)并不是完全预期的行为,因此人们会认为有一个一般性的修复,或者至少是一个解释。原来的问题仍然存在,因为唯一的区别是它只折叠一次,但这仍然会迫使我重新打开折叠。
    【解决方案4】:

    如果你暂时将 foldmethod 设置为 manual,那么 Vim 将保留当前由语法定义的所有折叠,并将它们保持在你现在拥有的确切的打开/关闭状态。这可以使用 InsertEnter 自动命令自动完成,并在 InsertLeave 上恢复以在单个窗口中保护您的折叠状态。不幸的是,我还没有花时间尝试让它在拆分窗口中工作,但是使用窗口局部变量很容易甚至可以在不离开插入模式的情况下考虑用户切换窗口或其他东西。有关详细信息和讨论,请参阅http://vim.wikia.com/wiki/Keep_folds_closed_while_inserting_text。

    【讨论】:

    • 谢谢,在进入和退出时更改 foldmethod 解决了第一个问题,但我非常想解决第二个问题以及拆分窗口以一次读取文件的多个部分非常方便.
    猜你喜欢
    • 2011-01-09
    • 2010-11-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-07-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多