Skip to content

Instantly share code, notes, and snippets.

@adscriven
Last active May 4, 2018 06:26
Show Gist options
  • Save adscriven/79d6c60bbd01f47432221a405c071f30 to your computer and use it in GitHub Desktop.
Save adscriven/79d6c60bbd01f47432221a405c071f30 to your computer and use it in GitHub Desktop.
Define :SessionRestore and :SessionSave commands for Vim.
" sessions.vim -- Define :SessionSave and :SessionRestore.
" SUMMARY
" $ mkdir ~/.vim/session
" :SessionSave save the current session
" :SessionSave {name} save a session as g:sessions_dir/{name}
" :SessionRestore restore the current session
" :SessionRestore {name} restore the session from g:sessions_dir/{name}
"
" There is tab completion for {name}.
" :mksession! is always used; sessions are overwritten without warning.
" The current session is always saved as 'last' by default when
" exiting Vim, even if there was no session active at the time.
" That way you can always get back to what you were doing when you
" last exited Vim by typing :SessionRestore last on startup.
" Obviously if you have multiple Vims running, the last one wins.
" This is just a convenience; use named sessions otherwise.
" REQUIREMENTS
" Vim 8 (Probably just because of the map() call.)
" INSTALLATION
" Chuck this file in ~/.vim/plugin
" CONFIGURATION
" Use these optional global variables in your vimrc.
" To specify the directory for session files (optional trailing slash),
" let g:sessions_dir = '~/.vim/jam/'
" Default: '~/.vim/session/'
" To prompt to save a named session when leaving Vim, e.g. after :qa,
" let g:sessions_prompt_on_exit = 1
" Default: 0
" When prompted press 'y' to save. Any other key means 'no'.
" To set the default last session name,
" let g:sessions_default_name = 'Margaret'
" Default: 'last'
" To warn if there are modified buffers when restoring a session, even
" if you have 'hidden' set,
" let g:sessions_warn_modified = 1
" Default: 0
" To define abbreviated command names, :SR and :SS,
" let g:sessions_abbreviated_commands = 1
" Default: 0
" Alternatively create some mappings in your vimrc, such as
" nnoremap \ss :<c-u>SessionSave |
" nnoremap \sr :<c-u>SessionRestore |
" To skip autosaving the current session as 'last' for a regexp
" matching the current file name,
" let g:sessions_dont_autosave_pattern = '\.config\|\.vimrc'
" Default: 'COMMIT_EDITMSG\|MERGE_MSG\|TAG_EDITMSG'
let s:cpo = &cpo
set cpo&vim
let s:thisfile = expand('<sfile>:t')
fun! s:err(msg)
echohl errormsg
echomsg '(' . s:thisfile . ') ' . a:msg
echohl None
endfun
if !has('mksession')
call s:err('Sessions aren''t supported in this build of Vim.')
finish
endif
let s:dir = get(g:, 'sessions_dir', '~/.vim/session')
let s:dir = fnamemodify(expand(s:dir), ':p')
if !isdirectory(s:dir)
call s:err('Non-existent sessions directory: ' . s:dir)
finish
endif
let s:defaultname = get(g:, 'sessions_default_name', 'last')
let s:defaultfile = s:dir . s:defaultname
let s:dontautosavepat = get(g:, 'sessions_dont_autosave_pattern',
\ 'COMMIT_EDITMSG\|MERGE_MSG\|TAG_EDITMSG')
fun! s:savesession(name)
if a:name == '' && v:this_session == ''
call s:err('Can''t save: no session name.')
return
endif
let file = a:name != '' ? s:dir . a:name : v:this_session
execute 'mksession! ' . file
redraw!
endfun
fun! s:aremodifiedbufs()
for buf in getbufinfo()
if buf.changed
return 1
endif
endfor
return 0
endfun
fun! s:restoresession(name)
if a:name == '' && v:this_session == ''
call s:err('Can''t restore: no session name.')
return
endif
let file = a:name != '' ? s:dir . a:name : v:this_session
if !filereadable(file)
call s:err('Can''t restore from file: ' . file)
return
endif
if s:aremodifiedbufs() && (!&hidden || get(g:, 'sessions_warn_modified', 0))
call s:err('Write modified buffers before restoring a session.')
return
endif
let v:this_session = ""
silent tabnew
silent tabonly
silent! execute 'source ' . file
redraw
endfun
fun! s:save_on_exit()
" If you want a prompt to save the session, and you actually have
" a current session, and it isn't the default one, ...
if get(g:, 'sessions_prompt_on_exit', 0) && v:this_session != '' &&
\ v:this_session != s:defaultfile
echo 'Save session ''' . fnamemodify(v:this_session, ':t') . '''? (n)'
let c = getchar()
if nr2char(c) == 'y'
call s:savesession('')
endif
endif
" Save the current session as s:default name, if it wasn't saved
" above. But skip this if the current filename matches s:dontautosavepat.
if expand('%') !~# s:dontautosavepat
call s:savesession(s:defaultname)
endif
endfun
augroup sessions_save_on_exit
autocmd!
autocmd VimLeave * call s:save_on_exit()
augroup end
fun! s:complete(a, l, p)
let files = glob(s:dir . a:a . '*', 0, 1)
call map(files, {k, v -> fnamemodify(v, ':t')})
return files
endfun
command! -nargs=* -complete=customlist,s:complete SessionSave
\ call s:savesession(<q-args>)
command! -nargs=* -complete=customlist,s:complete SessionRestore
\ call s:restoresession(<q-args>)
if get(g:, 'sessions_abbreviated_commands', 0)
command! -nargs=* -complete=customlist,s:complete SS
\ call s:savesession(<q-args>)
command! -nargs=* -complete=customlist,s:complete SR
\ call s:restoresession(<q-args>)
endif
let &cpo = s:cpo
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment