在使用Teamocil后,我的项目工作区是能在瞬间准备好了,但是编辑器部分(Vim)还是很弱。能不能让它直接载入上次会话(session)呢?
经过一番折腾后,我不仅实现的Vim全功能的会话的自动保存及载入,而且顺便设置了持久化的undo机制——也就是连撤消/重做都能保存下来。
Talk is cheap. Show me the code!
" Auto Session Save/Restore function GetProjectName() " Get the current editing file list, Unix only let edit_files = split(system("ps -o command= -p " . getpid())) if len(edit_files) >= 2 let project_path = edit_files[1] if project_path[0] != '/' let project_path = getcwd() . project_path endif else let project_path = getcwd() endif return shellescape(substitute(project_path, '[/]', '', 'g')) endfunction function SaveSession() "NERDTree doesn't support session, so close before saving execute ':NERDTreeClose' let project_name = GetProjectName() execute 'mksession! ~/.vim/sessions/' . project_name endfunction function RestoreSession() let session_path = expand('~/.vim/sessions/' . GetProjectName()) if filereadable(session_path) execute 'so ' . session_path if bufexists(1) for l in range(1, bufnr('$')) if bufwinnr(l) == -1 exec 'sbuffer ' . l endif endfor endif endif "Make sure the syntax is on syntax on endfunction nmap ssa :call SaveSession() smap SO :call RestoreSession() autocmd VimLeave * call SaveSession() autocmd VimEnter * call RestoreSession() " Persistent undo set undodir=~/.vim/undodir set undofile set undolevels=1000 "maximum number of changes that can be undone set undoreload=10000 "maximum number lines to save for undo on a buffer reload
简单的介绍一下。
GetProjectName 这个函数主要的作用是取得当前正在编辑的文件(或文件夹)的ProjectName,它的效果是:
- 当在一个文件夹如「/home/tualatrix/imtx」直接执行vim时,就返回「hometualatriximtx」作为项目名;
- 当在一个文件夹如「/home/tualatrix/imtx」执行「vim test.py」时,就返回「hometualatriximtxtest.py」作为项目名;
为什么要这样区分?这样有时我需要临时单独编辑一个文件时,Session就不必和Project Level的混合起来。
接下来在SaveSession和RestoreSession这两个函数里,就可以调用GetProjectName这个函数来进行会话(session)的操作了,然后利用Vim的autocmd特性,在VimLeave和VimEnter这两个事件中分别调用SaveSession及RestoreSession,就这样无缝的做到了打开Vim时自动根据当前编辑的文件或文件夹载入会话,在退出Vim时自动保存会话。
而下面的undo区块相对简单一点,不需要自己写函数,只需要设置一下全局文件夹,然后设置启动undofile和相关的level就可以了。
这样,在没有给自己增加一点额外操作的情况下,Vim的全自动会话保存/还原及持久化的undo功能就这样搞定了,这一切对编辑者来说是完全无缝的。
第一次写代码的时候,打开Vim等写完一些然后退出以后,此次的会话就自动保存下来了;下次在同一地方打开Vim后,上次的会话就会自动载入了,包括正在编辑的文件、光标正在哪行、undo/redo的历史纪录,一切都会恢复如初…
当然,有时候还会有清空会话的需求, 这时只要来到~/.vim/sessions,删除掉对应路径的文件就可以了,可以看出,文件本身也是Vim Script:
再附加一些写Vim Script的心得:
- 通过「 exexcute “!pwd” 」可以执行一条shell指令不返回output但返回退出码,通过system(‘pwd’)可以返回output,但是要注意最后可能有换行;
- Vim的List、String,对于用动态语言如Python的很容易理解;
- shellescape函数可以让包含空格或其他特殊字符的文件名escape出来,在操作时就可以避免异常,比如:「Hello World.py」就变成了「Hello World.py」
- NERDTree这个Vim插件会造成Session还原时的一点小问题,所以保存会话之前先关闭它,或者有谁可以推荐更好的替代品吗?
- Is it possible to access vim’s command-line arguments in vimscript?
- auto save vim session on quit and auto reload session on start
- Vim 7.3: Persistent undo and encryption!
转载请注明:爱开源 » 打造Vim之自动会话载入/保存和持久化undo