├── .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 |
--------------------------------------------------------------------------------