最新消息:

打造Vim之自动会话载入/保存和持久化undo

未分类 admin 3144浏览 0评论

在使用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-session-folder

再附加一些写Vim Script的心得:

  • 通过「 exexcute “!pwd” 」可以执行一条shell指令不返回output但返回退出码,通过system(‘pwd’)可以返回output,但是要注意最后可能有换行;
  • Vim的List、String,对于用动态语言如Python的很容易理解;
  • shellescape函数可以让包含空格或其他特殊字符的文件名escape出来,在操作时就可以避免异常,比如:「Hello World.py」就变成了「Hello World.py」
  • NERDTree这个Vim插件会造成Session还原时的一点小问题,所以保存会话之前先关闭它,或者有谁可以推荐更好的替代品吗?
参考资料:

 

转载请注明:爱开源 » 打造Vim之自动会话载入/保存和持久化undo

您必须 登录 才能发表评论!