在我的vimrc中,此刻我有以下自动命令:
autocmd Bufwritepre,filewritepre *.py exe ":silent! 1," . 20 . "g/Last Modified :.*/s/Last Modified :.*/Last Modified : " .strftime("%Y-%m-%d %H:%M:%S %z(%Z)")
基本上,替换我标题中的某个字符串。它将最后一次修改的日期写在文件的标题中。
它可以工作,但是很烦人,因为每次我保存文件时都会触发它。我只想在保存并离开文件时触发它。
此问题:autocmd event to execute a command on :wq - vimscript?
我有类似的东西:
:autocmd BufWritePost *.py :autocmd VimLeave *.py :! exe ":silent! 1," . 20 . "g/Last Modified :.*/s/Last Modified :.*/Last Modified : " .strftime("%Y-%m-%d %H:%M:%S %z(%Z)")
它不起作用,退出vim时收到一些错误消息。可能是因为字符串替换最初是使用vim命令在“内部”完成的,而现在我尝试使用bash命令进行替换?
您能帮我解决这个问题吗?
编辑:
这是我的标题的样子:
#!/usr/bin/python
# coding: utf-8
"""
------------------------------------------------------------------------------
* Creation Date : 2018-11-27 14:55:00 +0100(CET)
* Last Modified : 2018-11-27 15:52:57 +0100(CET)
* Created By : JPFrancoia https://github.com/JPFrancoia
* Description :
------------------------------------------------------------------------------
"""
答案 0 :(得分:1)
这里的问题是,当当前缓冲区处于活动状态时(如您目前处于BufWritePre
的情况下,总是触发:write
之类的事件,而VimLeave
之类的事件却被触发) (或更确切地说,取决于您退出Vim的方式)在当前缓冲区范围之外触发。您可能已经在选项卡,参数列表,分割窗口等中编辑了多个(Python或其他)文件。在VimLeave
上,您将不得不再次找到所有这些缓冲区,并显式地遍历它们; :autocmd
机制不会为您做到这一点。
更好的触发器是BufUnload
或BufDelete
,因为每个缓冲区都会触发一次。但是,甚至有些并发症,如:help BufUnload
所述:
注意:执行此自动命令时,当前缓冲区
%
可能与正在卸载的缓冲区<afile>
不同。不要更改到另一个缓冲区或窗口,这会导致问题!
虽然无法:write
而不切换到另一个缓冲区,但是您可以很好地退出其他缓冲区(例如,通过:[N]bdelete
或:qall
)。由于不允许切换到受影响的(即将死去的)缓冲区,因此无法使用:substitute
。您可以使用较低级别的readfile()
和writefile()
,并通过expand('<afile>:p')
获取缓冲区的文件规范,并通过substitute()
进行操作。或完全通过system()
和外部shell命令在Vim外部进行时间戳操作。
如您所见,从每次保存的更新切换到仅在离开Vim时才更新/听起来听起来很简单,但是很难实现(正确完成-如果您只在其中编辑单个文件,则可以将某些东西捆绑在一起)例如Vim会话)。我宁愿保留原始设计,而是从事“烦人”的工作。有了可靠的实现(例如,不会像您的简单解决方案那样破坏当前的搜索模式和窗口视图),这是很自然的,许多人都在使用这种功能。实际上,您可以使用我的AutoAdapt plugin或其插件页面上列出的任何替代方法(或在vim.org或其他地方找不到的其他插件)。
答案 1 :(得分:0)
您可以尝试以下代码:
augroup monitor_python_change
au!
au QuitPre *.py call s:update_timestamp('now', 'on_QuitPre')
au BufWritePre,FileWritePre *.py call s:update_timestamp('later', 'on_BufLeave')
augroup END
fu! s:update_timestamp(when, on_what) abort
if a:when is# 'now'
sil! au! update_timestamp
sil! aug! update_timestamp
if a:on_what is# 'on_QuitPre' && !&l:modified
return
endif
sil! 1/Last Modified : \zs.*/s//\=strftime('%Y-%m-%d %H:%M:%S %z(%Z)')/
else
augroup update_timestamp
au!
au BufLeave * call s:update_timestamp('now', 'on_BufLeave')
augroup END
endif
endfu
如果代码未更新您的时间戳,则可能需要更改替换命令:
" ┌ pattern used in the next substitution command (`//` = last used pattern)
" ├───────────────────┐
sil! 1/Last Modified : \zs.*/s//\=strftime("%Y-%m-%d %H:%M:%S %z(%Z)")/
" ├──────────────────────┘
" └ range of the substitution command
" (after the first line of the buffer,
" look for the next line containing `Last Modified : `)
也许会替换其样式和/或其范围。
如果代码有时会更新您的时间戳,而实际上不会,则您可能需要更改s:update_timestamp()
中的条件:
if a:on_what is# 'on_QuitPre' && !&l:modified
return
endif
当前条件阻止从QuitPre
(a:on_what is# 'on_QuitPre'
)调用函数并且未修改缓冲区(!&l:modified
)时执行替换。