PageRenderTime 45ms CodeModel.GetById 20ms RepoModel.GetById 0ms app.codeStats 0ms

/plugin/autosession.vim

https://github.com/serebrov/vimrc
Vim Script | 400 lines | 319 code | 33 blank | 48 comment | 38 complexity | 097f6d4165c61ce07813340ca529aabf MD5 | raw file
  1. " Vim tab session manager.
  2. "
  3. " Based on sessionman.vim by Yuri Klubakov (see
  4. " http://www.vim.org/scripts/script.php?script_id=2010)
  5. "
  6. " Author: Boris Serebrov <serebrov at gmail dot com>
  7. " License: GPL (same as original plugin)
  8. "
  9. " Description:
  10. "
  11. " Plugin wraps ':mksession' to add following features:
  12. "
  13. " * :SessionSave command to create and name a new session or rename existing
  14. " * :SessionOpen to open session
  15. " * :SessionList to show the list of sessions
  16. " * Keep list of sessions (see default locations below)
  17. " * Multiple sessions - one session per tab
  18. " * Note: since tab is used as a session container the session itself
  19. " will not save tabs
  20. " * Automatically load last sessions when Vim starts
  21. "
  22. " On Windows, DOS and OS2 sessions are saved in:
  23. " "$HOME/vimfiles/sessions" if $HOME is defined
  24. " "$APPDATA/Vim/sessions" if $APPDATA is defined
  25. " "$VIM/sessions" otherwise
  26. " On Unix sessions are saved in:
  27. " "$HOME/.vim/sessions"
  28. " If this directory does not exist, it will be created by the :SessionSave
  29. " command.
  30. " Disable it, testing the vim-session plugin
  31. finish
  32. if !has('mksession') || exists('loaded_autosession')
  33. finish
  34. endif
  35. if !exists('debug_autosession')
  36. let debug_autosession = 0
  37. let debug_autosession_file = ''
  38. endif
  39. if !exists('autosession_load_after')
  40. let autosession_load_after = ''
  41. endif
  42. let s:cpo_save = &cpo
  43. set cpo&vim
  44. let s:et_save = &et
  45. let s:sw_save = &sw
  46. let s:ts_save = &ts
  47. function! s:session_restore_defaults()
  48. let &et = s:et_save
  49. let &sw = s:sw_save
  50. let &ts = s:ts_save
  51. endfunction
  52. let loaded_autosession = 1
  53. let s:num_sessions = 0
  54. let s:sessions = {}
  55. let s:session = ''
  56. command! -nargs=1 -complete=custom,s:session_open_complete SessionOpen call s:session_open(<f-args>)
  57. command! -nargs=0 SessionClose call s:session_close()
  58. command! -nargs=0 SessionList call s:session_list()
  59. command! -nargs=? SessionSave call s:session_save_ask(<f-args>)
  60. command! -nargs=0 SessionShow call s:session_show()
  61. augroup autosession
  62. "autocmd!
  63. " autosave session
  64. autocmd VimLeavePre * call s:session_vim_leave()
  65. " load last session on start
  66. " Note: without 'nested' filetypes are not restored.
  67. autocmd VimEnter * nested call s:session_vim_enter()
  68. augroup END
  69. if !exists('autosession_path')
  70. if has("win32") || has("dos32") || has("dos16") || has("os2")
  71. let s:sessions_path = ($HOME != '') ? $HOME . '/vimfiles' : ($APPDATA != '') ? $APPDATA . '/Vim' : $VIM
  72. let s:sessions_path = substitute(s:sessions_path, '\\', '/', 'g') . '/sessions'
  73. else
  74. let s:sessions_path = $HOME . '/.vim/sessions'
  75. endif
  76. else
  77. let s:sessions_path = g:autosession_path
  78. endif
  79. let s:sessions_file = s:sessions_path . '/.sessions.vim'
  80. function! s:session_vim_enter()
  81. if bufnr('$') == 1 && bufname('%') == '' && !&mod && getline(1, '$') == ['']
  82. call s:session_debug_message('vim enter - restore all')
  83. call s:session_load(s:get_session())
  84. "execute 'windo filtype detect'
  85. redraw | echom 'Loaded last session(s)'
  86. " Without this after vim restart there is no syntax highlight in
  87. " restored buffers
  88. " windo filetype detect
  89. else
  90. " remove last session, so actual session will not be changed when
  91. " we open vim like `vim .` or `vim file_name` for quick edit.
  92. call s:remove_session()
  93. endif
  94. endfunction
  95. function! s:session_vim_leave()
  96. call s:session_debug_message('vim leave - save all')
  97. call s:session_save()
  98. endfunction
  99. function! s:session_open(name)
  100. if s:has_session()
  101. call s:session_debug_message('Session open has: '.s:get_session())
  102. call s:session_save()
  103. call s:remove_session()
  104. endif
  105. call s:session_debug_message('Session open wipe buffers ')
  106. let buf_count = s:_wipe_buffers()
  107. if buf_count == -1
  108. "if there is a modified buffer - exit
  109. return
  110. endif
  111. call s:session_load(a:name)
  112. endfunction
  113. function! s:session_load(name)
  114. if a:name != '' && a:name[0] != '"'
  115. call s:session_restore_defaults()
  116. execute 'silent so ' . s:sessions_path . '/' . a:name
  117. call s:set_session(a:name)
  118. call s:session_call_load_after()
  119. endif
  120. endfunction
  121. function! s:session_call_load_after()
  122. echom 'Session load after ' . g:autosession_load_after
  123. if empty(g:autosession_load_after)
  124. return
  125. endif
  126. execute 'call '.g:autosession_load_after
  127. endfunction
  128. function! s:session_close()
  129. if s:has_session()
  130. call s:session_restore_defaults()
  131. call s:session_debug_message('Session close has: '.s:get_session())
  132. call s:session_save()
  133. call s:remove_session()
  134. call s:_wipe_buffers()
  135. endif
  136. endfunction
  137. function! s:session_delete(name)
  138. if a:name != '' && a:name[0] != '"'
  139. let save_go = &guioptions
  140. set guioptions+=c
  141. if confirm('Are you sure you want to delete "' . a:name . '" session?', "&Yes\n&No", 2) == 1
  142. setlocal modifiable
  143. d
  144. setlocal nomodifiable
  145. if delete(s:sessions_path . '/' . a:name) != 0
  146. redraw | echohl ErrorMsg | echom 'Error deleting "' . a:name . '" session file' | echohl None
  147. endif
  148. endif
  149. let &guioptions = save_go
  150. endif
  151. endfunction
  152. function! s:session_edit(name)
  153. if a:name != '' && a:name[0] != '"'
  154. bwipeout
  155. execute 'silent edit ' . s:sessions_path . '/' . a:name
  156. set ft=vim
  157. endif
  158. endfunction
  159. function! s:session_edit_extra(name)
  160. if a:name != '' && a:name[0] != '"'
  161. bwipeout
  162. let n = substitute(a:name, "\\.[^.]*$", '', '')
  163. execute 'silent edit ' . s:sessions_path . '/' . n . 'x.vim'
  164. endif
  165. endfunction
  166. function! s:session_list()
  167. let w_sl = bufwinnr("__SessionList__")
  168. if w_sl != -1
  169. execute w_sl . 'wincmd w'
  170. return
  171. endif
  172. silent split __SessionList__
  173. " Mark the buffer as scratch
  174. setlocal buftype=nofile
  175. setlocal bufhidden=wipe
  176. setlocal noswapfile
  177. setlocal nowrap
  178. setlocal nobuflisted
  179. nnoremap <buffer> <silent> q :bwipeout<CR>
  180. nnoremap <buffer> o :call <SID>session_open(getline('.'))<CR>
  181. nnoremap <buffer> <CR> :call <SID>session_open(getline('.'))<CR>
  182. nnoremap <buffer> <2-LeftMouse> :call <SID>session_open(getline('.'))<CR>
  183. nnoremap <buffer> <silent> d :call <SID>session_delete(getline('.'))<CR>
  184. nnoremap <buffer> <silent> e :call <SID>session_edit(getline('.'))<CR>
  185. nnoremap <buffer> <silent> x :call <SID>session_edit_extra(getline('.'))<CR>
  186. syn match Comment "^\".*"
  187. silent put ='\"-----------------------------------------------------'
  188. silent put ='\" q - close session list'
  189. silent put ='\" o, <CR>, <2-LeftMouse> - open session'
  190. silent put ='\" d - delete session'
  191. silent put ='\" e - edit session'
  192. silent put ='\" x - edit extra session script'
  193. silent put ='\"-----------------------------------------------------'
  194. silent put =''
  195. let l = line(".")
  196. let sessions = substitute(glob(s:sessions_path . '/*'), '\\', '/', 'g')
  197. let sessions = substitute(sessions, "\\(^\\|\n\\)" . s:sessions_path . '/', '\1', 'g')
  198. let sessions = substitute(sessions, "\n[^\n]\\+x\\.vim\n", '\n', 'g')
  199. if sessions == ''
  200. syn match Error "^\" There.*"
  201. let sessions = '" There are no saved sessions'
  202. endif
  203. silent put =sessions
  204. silent 0,1d
  205. execute l
  206. setlocal nomodifiable
  207. setlocal nospell
  208. endfunction
  209. function! s:session_save_ask(...)
  210. if a:0 != 0
  211. let name = a:1
  212. else
  213. let name = s:get_session()
  214. if !empty(name)
  215. let name = input('Save session as: ', name)
  216. else
  217. let name = input('Save session as: ')
  218. endif
  219. endif
  220. call s:session_save(name)
  221. endfunction
  222. function! s:session_save(...)
  223. if a:0 != 0
  224. let name = a:1
  225. call s:session_debug_message('Will save session : ' . name)
  226. elseif s:has_session()
  227. let name = s:get_session()
  228. call s:session_debug_message('Will save current session : ' . name)
  229. else
  230. call s:session_debug_message('Will not save session')
  231. return
  232. endif
  233. if v:version >= 700 && finddir(s:sessions_path, '/') == ''
  234. call mkdir(s:sessions_path, 'p')
  235. endif
  236. "silent! argdel *
  237. call s:set_session(name)
  238. let sessionoptions = &sessionoptions
  239. try
  240. set sessionoptions-=options
  241. set sessionoptions+=tabpages
  242. call s:session_debug_message('Saving a session')
  243. execute 'mksession! ' . s:sessions_path . '/' . name
  244. call s:set_session(name)
  245. "call writefile(insert(readfile(g:this_obsession), 'let g:this_obsession = v:this_session', -2), g:this_obsession)
  246. call s:session_debug_message('Writing sessions')
  247. redraw | echom 'Saved session "' . name . '"'
  248. catch
  249. redraw | echom 'Error saving session "' . string(v:exception) . '"'
  250. finally
  251. let &sessionoptions = sessionoptions
  252. endtry
  253. endfunction
  254. " function! s:session_save(do_save_as)
  255. " let name = s:get_session()
  256. " if name != 0 && name != ''
  257. " call s:session_save_as(substitute(name, '.*\(/\|\\\)', '', ''))
  258. " else
  259. " if a:do_save_as
  260. " call s:session_save_as()
  261. " endif
  262. " endif
  263. " endfunction
  264. function! s:session_show()
  265. if s:has_session()
  266. echom 'Current session is "' . substitute(s:get_session(), '.*\(/\|\\\)', '', '') . '"'
  267. else
  268. echom 'Current session is empty'
  269. endif
  270. " echom ', sessions are "' . string(s:sessions) . '"'
  271. endfunction
  272. function! s:set_session(name)
  273. let g:LAST_SESSION = a:name
  274. endfunction
  275. function! s:has_session()
  276. return exists('g:LAST_SESSION')
  277. endfunction
  278. function! s:remove_session()
  279. unlet! g:LAST_SESSION
  280. endfunction
  281. function! s:get_session()
  282. return g:LAST_SESSION
  283. endfunction
  284. function! s:session_open_complete(A, L, P)
  285. let sessions = substitute(glob(s:sessions_path . '/*'), '\\', '/', 'g')
  286. return substitute(sessions, '\(^\|\n\)' . s:sessions_path . '/', '\1', 'g')
  287. endfunction
  288. function! s:_wipe_buffers()
  289. call s:session_debug_message('Wipe buffers')
  290. " if index(split(&sessionoptions,','), 'tabpages') == -1
  291. " " tabpages are not saved into the session, so
  292. " " we assume that sessions will be loaded inside tabs
  293. " " and wipe only current tab buffers
  294. " call s:_wipe_tab_buffers()
  295. " else
  296. call s:_wipe_all_buffers()
  297. " endif
  298. endfunction
  299. function! s:_wipe_all_buffers()
  300. let last_buffer = bufnr('$')
  301. let delete_count = 0
  302. let n = 1
  303. while n <= last_buffer
  304. if buflisted(n)
  305. if getbufvar(n, '&modified')
  306. echohl ErrorMsg
  307. echomsg 'No write since last change for buffer'
  308. echohl None
  309. return -1
  310. else
  311. silent exe 'bwipeout ' . n
  312. if ! buflisted(n)
  313. let delete_count = delete_count+1
  314. endif
  315. endif
  316. endif
  317. let n = n+1
  318. endwhile
  319. return delete_count
  320. endfunction
  321. function! s:_wipe_tab_buffers()
  322. let buflist = tabpagebuflist()
  323. let delete_count = 0
  324. for i in buflist
  325. if buflisted(i)
  326. if getbufvar(i, '&modified') && getbufvar(i, '&filetype') != "netrw"
  327. echohl ErrorMsg
  328. echomsg 'No write since last change for buffer'
  329. echohl None
  330. return -1
  331. else
  332. silent exe 'bwipeout ' . i
  333. if ! buflisted(i)
  334. let delete_count = delete_count+1
  335. endif
  336. endif
  337. endif
  338. endfor
  339. return delete_count
  340. endfunction
  341. function! s:session_debug_message(message)
  342. " can log messages to file if run vim as vim - V0/home/user/vim.log
  343. " or set debug_autosession_file to log file name
  344. if !g:debug_autosession
  345. return
  346. endif
  347. let sess = ''
  348. if s:has_session()
  349. let sess = '. Current session: ' . s:get_session()
  350. endif
  351. let buflist = tabpagebuflist()
  352. let msg = 'tsdebug: ' . a:message . sess . ' , tab: ' . tabpagenr() . ' number of buffers: ' . len(buflist)
  353. echom msg
  354. if !empty(g:debug_autosession_file)
  355. execute 'silent !echo "' . msg . '" >> '. g:debug_autosession_file .' &'
  356. endif
  357. endfunction
  358. let &cpo = s:cpo_save
  359. unlet s:cpo_save