Vim:如何恢复光标的逻辑和物理位置?

14
如何在打开文件时恢复光标的“逻辑”和“物理”位置?
即:
1. 光标应该位于文件中上一次所在的逻辑行。 2. 光标应该位于 Vim 窗口中上一次所在的物理行。
我注意到了这篇帖子。它确实将光标放在了正确的逻辑行上。但是,窗口中光标的物理位置却是第一行或中间位置。
更新: @sehe 提到的解决方案是使用 mkview 和 loadview 命令。
为了使其与其他插件(例如我的情况下,LaTeX 文件 + latex-box)配合使用,可以使用以下命令:
au BufWinLeave *.tex mkview
au VimEnter *.tex loadview
根据 Vim 的文档,VimEnter 命令的作用是:
  • 在完成所有启动工作,包括加载.vimrc文件、执行“-c cmd”参数、创建所有窗口并在其中加载缓冲区之后。

更新2:为了更好地组织“查看快照文件”

通过创建一个名为~/.vim/view的文件夹,您可以将所有“查看快照文件”保存在那里。

如果您正在使用git同步跨计算机使用的~/.vim,也许您想要

  • 忽略~/.vim/view中的文件,
  • 但保留空文件夹在您的repo中。

然后您需要(根据here中的答案进行调整)

  • 创建一个空文件:~/.vim/view/.gitignore
  • ~/.vim/.gitignore中放置view/*!.gitignore

另一种表达第二个要求的方式是窗口的顶部行也应该相同。(如果可能的话!考虑光标在屏幕的最后一行的情况,然后你再在一个较小的窗口中打开文件。)我认为这不是viminfo可以完成的事情,但是通过一些脚本/自动命令是可能实现的。 - Cascabel
感谢@Jefromi。也许你是对的。这是不可能的。(虽然我知道插件会做到这一点,但我确实期望viminfo的某些设置和vimrc中的一些短函数。) - ying17zi
我并没有说这是不可能的!只是不是一个快速内置的东西。 - Cascabel
@Jefromi:我认为这是可能的,并且是内置的。请看我的回答。 - sehe
@sehe:啊,很酷。它仍然需要自动命令(即不只是翻转“恢复位置”配置开关),但我没有意识到它会这么简单! - Cascabel
1个回答

25

好消息,:mkview 已经有了这个功能(请参阅下面的文档摘录)。

更具体地说,如果 viewoptions 包括 cursor,folds:loadview 将恢复滚动位置以及折叠状态。

更好的消息是,如果您希望,可以为所有打开的文件透明地启用视图。例如,要为所有 C 源文件启用视图保存,请将以下内容添加到 $MYVIMRC:

au BufWinLeave *.c mkview
au BufWinEnter *.c silent loadview

编辑 根据Hongying的评论,结合某些插件使用VimEnter自动命令加载视图可能效果更好。

可选地,使用viewdir选项定义保存视图的位置。

一定要看看:mksession,因为它更加强大,可以恢复多个窗口、标签及其位置、映射、寄存器、选项、折叠状态等等。

工作原理

Vim :mkview 保存恢复位置的ex命令如下:

silent! normal! zE
let s:l = 88 - ((4 * winheight(0) + 4) / 9)
if s:l < 1 | let s:l = 1 | endif
exe s:l
normal! zt
88
normal! 025l

:loadview 就像任何 vimscript 一样源这些命令。

来自文档

注意 这是从文档中 剪裁 的内容,请确保阅读更多的内容执行 he :mkview

                            *:mkvie* *:mkview*
:mkvie[w][!] [file] Write a Vim script that restores the contents of the
            current window.
            When [!] is included an existing file is overwritten.
            When [file] is omitted or is a number from 1 to 9, a
            name is generated and 'viewdir' prepended.  When the
            last directory name in 'viewdir' does not exist, this
            directory is created.
            An existing file is always overwritten then.  Use
            |:loadview| to load this view again.
            When [file] is the name of a file ('viewdir' is not
            used), a command to edit the file is added to the
            generated file.

The output of ":mkview" contains these items:
1. The argument list used in the window.  When the global argument list is
   used it is reset to the global list.
   The index in the argument list is also restored.
2. The file being edited in the window.  If there is no file, the window is
   made empty.
3. Restore mappings, abbreviations and options local to the window if
   'viewoptions' contains "options" or "localoptions".  For the options it
   restores only values that are local to the current buffer and values local
   to the window.
   When storing the view as part of a session and "options" is in
   'sessionoptions', global values for local options will be stored too.
4. Restore folds when using manual folding and 'viewoptions' contains
   "folds".  Restore manually opened and closed folds.
5. The scroll position and the cursor position in the file.  Doesn't work very
   well when there are closed folds.
6. The local current directory, if it is different from the global current
   directory.

哦,谢谢!@sehe。如果我自己输入命令,它能很好地工作,但它仍然把光标放在窗口的第一行。你有注意到吗?(我已经测试了 tex 文件。在我的 .vimrc 中,我添加了“au BufWinLeave *.tex mkview au BufWinEnter *.tex silent loadview ”) - ying17zi
这是因为其他的 LaTeX 插件。 - ying17zi
我该如何在其他tex插件之后运行"loadview"?(如果有影响的话:我正在使用latex-box。) - ying17zi
@Hongying:我真的不知道。但是通过查看视图文件,您可以看到latex可能在SessionLoadPost自动命令中'撤销'某些操作,该命令在最后触发。通常情况下,尝试使用noautocmd loadview。但无法保证;您可以使用:verbose autocmd:debug ...查找从哪里触发了什么(以及自动命令的最后定义位置)。哦,如果_latex_插件通过运动命令覆盖了光标位置,请查看是否按下“``”可以让您回到想要的位置 - sehe
4
我找到了一个解决方案:将"au BufWinLeave *.tex mkview"和"au VimEnter *.tex loadview"替换进去即可。 - ying17zi

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接