├── .github └── FUNDING.yml ├── .gitignore ├── CONTRIBUTING.markdown ├── README.markdown ├── doc └── obsession.txt └── plugin └── obsession.vim /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | github: tpope 2 | custom: ["https://www.paypal.me/vimpope"] 3 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /doc/tags 2 | -------------------------------------------------------------------------------- /CONTRIBUTING.markdown: -------------------------------------------------------------------------------- 1 | See the [contribution guidelines for pathogen.vim](https://github.com/tpope/vim-pathogen/blob/master/CONTRIBUTING.markdown). 2 | -------------------------------------------------------------------------------- /README.markdown: -------------------------------------------------------------------------------- 1 | # obsession.vim 2 | 3 | Vim features a `:mksession` command to write a file containing the current 4 | state of Vim: window positions, open folds, stuff like that. For most of my 5 | existence, I found the interface way too awkward and manual to be useful, but 6 | I've recently discovered that the only thing standing between me and simple, 7 | no-hassle Vim sessions is a few tweaks: 8 | 9 | * Instead of making me remember to capture the session immediately before 10 | exiting Vim, allow me to do it at any time, and automatically re-invoke 11 | `:mksession` immediately before exit. 12 | * Also invoke `:mksession` whenever the layout changes (in particular, on 13 | `BufEnter`), so that even if Vim exits abnormally, I'm good to go. 14 | * If I load an existing session, automatically keep it updated as above. 15 | * If I try to create a new session on top of an existing session, don't refuse 16 | to overwrite it. Just do what I mean. 17 | * If I pass in a directory rather than a file name, just create a 18 | `Session.vim` inside of it. 19 | * Don't capture options and maps. Options are sometimes mutilated and maps 20 | just interfere with updating plugins. 21 | 22 | Use `:Obsess` (with optional file/directory name) to start recording to a 23 | session file and `:Obsess!` to stop and throw it away. That's it. Load a 24 | session in the usual manner: `vim -S`, or `:source` it. 25 | 26 | There's also an indicator you can put in `'statusline'`, `'tabline'`, or 27 | `'titlestring'`. See `:help obsession-status`. 28 | 29 | ## Installation 30 | 31 | If you don't have a preferred installation method, I recommend 32 | installing [pathogen.vim](https://github.com/tpope/vim-pathogen), and 33 | then simply copy and paste: 34 | 35 | cd ~/.vim/bundle 36 | git clone https://github.com/tpope/vim-obsession.git 37 | vim -u NONE -c "helptags vim-obsession/doc" -c q 38 | 39 | ## Self-Promotion 40 | 41 | Like obsession.vim? Follow the repository on 42 | [GitHub](https://github.com/tpope/vim-obsession) and vote for it on 43 | [vim.org](http://www.vim.org/scripts/script.php?script_id=4472). And if 44 | you're feeling especially charitable, follow [tpope](http://tpo.pe/) on 45 | [Twitter](http://twitter.com/tpope) and 46 | [GitHub](https://github.com/tpope). 47 | 48 | ## License 49 | 50 | Copyright © Tim Pope. Distributed under the same terms as Vim itself. 51 | See `:help license`. 52 | -------------------------------------------------------------------------------- /doc/obsession.txt: -------------------------------------------------------------------------------- 1 | *obsession.txt* Continuously updated session files 2 | 3 | Author: Tim Pope 4 | Repo: https://github.com/tpope/vim-obsession 5 | License: Same terms as Vim itself (see |license|) 6 | 7 | USAGE *obsession* *:Obsession* 8 | 9 | :Obsession {file} Invoke |:mksession| on {file} and continue to keep it 10 | updated until Vim exits, triggering on the |BufEnter| 11 | and |VimLeavePre| autocommands. If the file exists, 12 | it will be overwritten if and only if it looks like a 13 | session file. 14 | 15 | Set `g:obsession_no_bufenter` to disable saving the 16 | session on |BufEnter|, improving performance at the 17 | expense of safety. 18 | 19 | :Obsession {dir} Invoke |:Obsession| on {dir}/Session.vim. Use "." to 20 | write to a session file in the current directory. 21 | 22 | :Obsession If session tracking is already in progress, pause it. 23 | Otherwise, resume tracking or create a new session in 24 | the current directory. 25 | 26 | :Obsession! Stop obsession and delete the underlying session file. 27 | 28 | Loading a session created with |:Obsession| automatically resumes updates to 29 | that file. 30 | 31 | STATUS INDICATOR *obsession-status* 32 | 33 | *ObsessionStatus()* 34 | Add %{ObsessionStatus()} to 'statusline', 'tabline', or 'titlestring' to get 35 | an indicator when Obsession is active or paused. Pass an argument to override 36 | the text of the active indicator and a second argument to override the text of 37 | the paused indictor. By default, the active indicator is `[$]`, and the 38 | paused indicator is `[S]`. 39 | 40 | vim:tw=78:et:ft=help:norl: 41 | -------------------------------------------------------------------------------- /plugin/obsession.vim: -------------------------------------------------------------------------------- 1 | " obsession.vim - Continuously updated session files 2 | " Maintainer: Tim Pope 3 | " Version: 1.0 4 | " GetLatestVimScripts: 4472 1 :AutoInstall: obsession.vim 5 | 6 | if exists("g:loaded_obsession") || v:version < 704 || &cp 7 | finish 8 | endif 9 | let g:loaded_obsession = 1 10 | 11 | command! -bar -bang -complete=file -nargs=? Obsession 12 | \ execute s:dispatch(0, ) 13 | 14 | function! s:dispatch(bang, file) abort 15 | let session = get(g:, 'this_obsession', v:this_session) 16 | try 17 | if a:bang && empty(a:file) && filereadable(session) 18 | echo 'Deleting session in '.fnamemodify(session, ':~:.') 19 | call delete(session) 20 | unlet! g:this_obsession 21 | return '' 22 | elseif empty(a:file) && exists('g:this_obsession') 23 | echo 'Pausing session in '.fnamemodify(session, ':~:.') 24 | unlet g:this_obsession 25 | return '' 26 | elseif empty(a:file) && !empty(session) 27 | let file = session 28 | elseif empty(a:file) 29 | let file = getcwd() . '/Session.vim' 30 | elseif isdirectory(a:file) 31 | let file = substitute(fnamemodify(expand(a:file), ':p'), '[\/]$', '', '') 32 | \ . '/Session.vim' 33 | else 34 | let file = fnamemodify(expand(a:file), ':p') 35 | endif 36 | if !a:bang 37 | \ && file !~# 'Session\.vim$' 38 | \ && filereadable(file) 39 | \ && getfsize(file) > 0 40 | \ && readfile(file, '', 1)[0] !=# 'let SessionLoad = 1' 41 | return 'mksession '.fnameescape(file) 42 | endif 43 | let g:this_obsession = file 44 | let error = s:persist() 45 | if empty(error) 46 | echo 'Tracking session in '.fnamemodify(file, ':~:.') 47 | let v:this_session = file 48 | return '' 49 | else 50 | return error 51 | endif 52 | finally 53 | let &l:readonly = &l:readonly 54 | endtry 55 | endfunction 56 | 57 | function! s:doautocmd_user(arg) abort 58 | if !exists('#User#' . a:arg) 59 | return '' 60 | else 61 | return 'doautocmd User ' . fnameescape(a:arg) 62 | endif 63 | endfunction 64 | 65 | function! s:persist() abort 66 | if exists('g:SessionLoad') 67 | return '' 68 | endif 69 | let sessionoptions = &sessionoptions 70 | if exists('g:this_obsession') 71 | let tmp = g:this_obsession . '.' . getpid() . '.obsession~' 72 | try 73 | set sessionoptions-=blank sessionoptions-=options sessionoptions+=tabpages 74 | exe s:doautocmd_user('ObsessionPre') 75 | execute 'mksession!' fnameescape(tmp) 76 | let v:this_session = g:this_obsession 77 | let body = readfile(tmp) 78 | call insert(body, 'let g:this_session = v:this_session', -3) 79 | call insert(body, 'let g:this_obsession = v:this_session', -3) 80 | if type(get(g:, 'obsession_append')) == type([]) 81 | for line in g:obsession_append 82 | call insert(body, line, -3) 83 | endfor 84 | endif 85 | call writefile(body, tmp) 86 | call rename(tmp, g:this_obsession) 87 | let g:this_session = g:this_obsession 88 | exe s:doautocmd_user('Obsession') 89 | catch /^Vim(mksession):E11:/ 90 | return '' 91 | catch 92 | unlet g:this_obsession 93 | let &l:readonly = &l:readonly 94 | return 'echoerr '.string(v:exception) 95 | finally 96 | let &sessionoptions = sessionoptions 97 | call delete(tmp) 98 | endtry 99 | endif 100 | return '' 101 | endfunction 102 | 103 | function! ObsessionStatus(...) abort 104 | let args = copy(a:000) 105 | let numeric = !empty(v:this_session) + exists('g:this_obsession') 106 | if type(get(args, 0, '')) == type(0) 107 | if !remove(args, 0) 108 | return '' 109 | endif 110 | endif 111 | if empty(args) 112 | let args = ['[$]', '[S]'] 113 | endif 114 | if len(args) == 1 && numeric == 1 115 | let fmt = args[0] 116 | else 117 | let fmt = get(args, 2-numeric, '') 118 | endif 119 | return substitute(fmt, '%s', get(['', 'Session', 'Obsession'], numeric), 'g') 120 | endfunction 121 | 122 | augroup obsession 123 | autocmd! 124 | autocmd VimLeavePre * exe s:persist() 125 | autocmd BufEnter * 126 | \ if !get(g:, 'obsession_no_bufenter') | 127 | \ exe s:persist() | 128 | \ endif 129 | autocmd User Flags call Hoist('global', 'ObsessionStatus') 130 | augroup END 131 | 132 | " vim:set et sw=2: 133 | --------------------------------------------------------------------------------