如何在Vimscript中以原生方式保存符合条件的修改后缓冲区?
解决Vimscript中批量保存指定缓冲区的问题
你的需求很清晰:后台保存符合条件的缓冲区,不干扰当前编辑状态。先修正你代码里的几个小错误,再给你最贴合Vim原生逻辑的实现方式。
先修正原代码里的问题
- 拼写错误:
but.changed应该是buf.changed - 路径匹配逻辑不严谨:直接用
buf.name =~ getcwd()会因为路径中的正则特殊字符(比如.)导致误匹配,而且你需要的是路径以当前工作目录开头,不是简单包含,得用更可靠的判断方式。
优化后的完整函数
下面的函数完全满足你的需求,同时兼顾安全性和原生操作逻辑:
function! SaveChangedBuffers() " 提前记录当前活动缓冲区的编号,确保操作后不会改变当前编辑窗口 let current_buf = bufnr('%') " 遍历所有已列出的缓冲区 for buf in getbufinfo({'buflisted': 1}) " 过滤条件:缓冲区已修改、有有效文件名、绝对路径以当前工作目录开头 if buf.changed && !empty(buf.name) && startswith(fnamemodify(buf.name, ':p'), getcwd() . '/') " 静默写入指定缓冲区,用缓冲区编号而非文件名更可靠 silent execute 'bwrite ' . buf.bufnr endif endfor " 恢复到之前的活动缓冲区(保险操作,避免意外切换) execute 'buffer ' . current_buf endfunction
关键细节说明
- 用缓冲区编号操作:
buf.bufnr是每个缓冲区的唯一标识,比文件名更可靠,完全避免文件名包含空格、正则符号等特殊字符导致的命令执行失败。 - 严谨的路径判断:
fnamemodify(buf.name, ':p')会把缓冲区路径转为绝对路径,再用startswith判断是否以当前工作目录开头,确保不会误匹配其他目录下的同名文件。 - 静默后台执行:
silent关键字会抑制写入时的提示信息(比如"已写入xxx"),让操作在后台安静完成,完全不干扰当前编辑。 - 恢复当前缓冲区:提前记录当前活动缓冲区编号,操作结束后切回去,确保光标位置和当前编辑的内容完全不受影响。
可选扩展:强制写入只读文件
如果需要跳过Vim的只读保护,强制写入只读文件,可以把bwrite改成bwrite!,即:
silent execute 'bwrite! ' . buf.bufnr
注意:这个操作会绕过只读限制,使用前请确认操作的安全性。
内容的提问来源于stack exchange,提问作者Logan Reed
相关产品推荐
相关产品推荐

