当Vim失去焦点时,如何使其自动保存文件?

31

我习惯于我的编辑器在失去焦点时自动保存文件。最近我切换到了MacVim,但我无法再次实现这种行为。我尝试了以下方法:

autocmd BufLeave,FocusLost * wall

但是如果一个缓冲区在窗口或MacVim失去焦点时没有命名,则会出现以下错误:

Error detected while processing BufLeave Auto commands for "*":
E141: No file name for buffer 1

我感到困惑,因为:wall的文档描述如下:

Write all changed buffers.  Buffers without a file
name or which are readonly are not written.

我希望它可以跳过未命名的缓冲区。有更好的方法吗?

编辑:

我非常确定通过使用BufLeave实现我的目的的更好方式是设置'autowriteall' -- 当我在不同的缓冲区之间切换时保存缓冲区,这样我就不会得到“自上次更改以来未写入”错误消息。对于当MacVim失去焦点到其他应用程序(FocusLost)的情况,问题仍然存在。


关于在VIM中自动保存的问题,我只是想提出一个想法:交换文件不就足够了吗? - skippr
3
我并不是在备份我的工作资料,我需要把这个文件保存在磁盘上,以便于我转换到其他工具时使用,比如测试套件。 - Peeja
4个回答

44

在这种情况下,您不需要关心错误,因为无论如何您都无法合理地解决它们 - 特别是当失去重点时。因此,请忽略它们:

autocmd BufLeave,FocusLost * silent! wall

比起费力地跳舞来找到错误并避免它,这要简单得多了。


7
对于我而言,它需要一个 * ,就像 autocmd BufLeave,FocusLost * silent! wall 一样。 - pvinis
vim新手在这里...这行代码应该放在哪里?在.vimrc文件里面吗? - thefonso
它添加在 .vimrc 中的位置有关系吗?这一行对我来说没有消除警告。:( - Alisso
嗯,很难回答。它可能很重要,但在大多数情况下不会。你得到了什么警告?你的vimrc发布在哪里了? - Aristotle Pagaltzis

3

我猜测当wall的文档中提到“不带文件名”时,他们可能是在引用带有buftype=nofile属性的缓冲区。要实现您想要的效果的一种方法是让autocmd调用一个简单的函数。例如,以下未经测试的代码可以给出一个想法:

autocmd BufLeave,FocusLost * bufdo! call WriteFile()

function WriteFile()
   if (&buftype=="") && (expand("%:r") > "") && (&readonly==0)
      write
   endif
endfunction

我认为实现像自动保存缓冲区这样的功能的标准方法是在Vim中设置autosave选项。


bufdo会在当前窗口中切换缓冲区。你应该写成 let s:curbuf=bufnr('%') | try | execute 'bufdo! call WriteFile()' | finally | execute "buffer ".s:curbuf | endtry。但它仍然存在问题:由于某种原因,在此代码之后,帮助缓冲区中的list选项被重置,并且光标被定位在中心。在try之前添加wincmd v,在endtry之后添加wincmd q效果更好。 - ZyX
最好的选择可能是简单的 wincmd v | execute 'bufdo! call WriteFile()' | wincmd q - ZyX
@ZyX -- 感谢您的纠正;当我建议使用bufdo时,我没有考虑清楚。听起来您的第二个解决方案应该可以很好地工作,打开新窗口,循环浏览缓冲区,然后关闭窗口。我仍然认为只需使用autosave是最佳解决方案,或者可能编写一个更复杂的函数,由autocmd调用,在其中使用windo命令进行tabdo,以便永远不需要在窗口内切换缓冲区。 - Herbert Sitz

0

只需将此放入 .vimrc 文件中

set updatetime=1000
autocmd CursorHoldI * silent w

这有几个问题:首先,保存需要整整一秒钟的时间,在此期间我希望文件已经在磁盘上了;第二,只有在插入模式下才起作用;第三,:write 不能解决问题。@Aristotle Pagaltzis 的回答对我很有帮助。 - Peeja

0
autocmd BufLeave,FocusLost * bufdo! call WriteFile()

function WriteFile()
   if (&buftype=="") && (expand("%:r") > "") && (&readonly==0)
      write
   endif
endfunction

这种方法有一个副作用,即您只能打开一个未命名的缓冲区。如果您打开第二个,则会自动同步到第一个未命名缓冲区的内容。


这是Herbert Sitz上面的答案的副本,只是有不同的评论。这意味着这是对他的答案的评论吗? - Peeja

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