xtabline.vim 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404
  1. """"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
  2. " xTabline - Reduced version for vim-airline
  3. " Plugin: https://github.com/mg979/vim-xtabline
  4. " MIT License Copyright (C) 2018-2021 Gianmaria Bajo <mg1979.git@gmail.com>
  5. " tabpagecd:
  6. " expanded version by mg979
  7. " MIT License Copyright (C) 2012-2013 Kana Natsuno <http://whileimautomaton.net/>
  8. " MIT License Copyright (C) 2018-2021 Gianmaria Bajo <mg1979.git@gmail.com>
  9. """"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
  10. function! airline#extensions#tabline#xtabline#init()
  11. let s:state = 0
  12. " initialize mappings
  13. call airline#extensions#tabline#xtabline#maps()
  14. """"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
  15. " Variables
  16. """"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
  17. let g:loaded_xtabline = 1
  18. let s:most_recent = -1
  19. let s:xtabline_filtering = 1
  20. let t:xtl_excluded = get(g:, 'airline#extensions#tabline#exclude_buffers', [])
  21. let t:xtl_accepted = []
  22. let g:xtabline_include_previews = get(g:, 'xtabline_include_previews', 1)
  23. let g:xtabline_alt_action = get(g:, 'xtabline_alt_action', "buffer #")
  24. """"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
  25. " Autocommands
  26. """"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
  27. augroup plugin-xtabline
  28. autocmd!
  29. autocmd TabNew * call s:Do('new')
  30. autocmd TabEnter * call s:Do('enter')
  31. autocmd TabLeave * call s:Do('leave')
  32. autocmd TabClosed * call s:Do('close')
  33. autocmd BufEnter * if exists('#airline') | let g:xtabline_changing_buffer = 0 | endif
  34. autocmd BufAdd,BufDelete,BufWrite * call airline#extensions#tabline#xtabline#filter_buffers()
  35. augroup END
  36. """"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
  37. " Commands
  38. """"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
  39. com! XTabReopen call airline#extensions#tabline#xtabline#reopen_last_tab()
  40. endfunction
  41. """"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
  42. " Mappings
  43. """"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
  44. function! airline#extensions#tabline#xtabline#maps()
  45. if !exists('g:xtabline_disable_keybindings')
  46. fun! s:mapkeys(keys, plug)
  47. if empty(mapcheck(a:keys)) && !hasmapto(a:plug)
  48. silent! execute 'nmap <unique> '.a:keys.' '.a:plug
  49. endif
  50. endfun
  51. call s:mapkeys('<F5>','<Plug>XTablineToggleTabs')
  52. call s:mapkeys('<leader><F5>','<Plug>XTablineToggleFiltering')
  53. call s:mapkeys('<BS>','<Plug>XTablineSelectBuffer')
  54. call s:mapkeys(']l','<Plug>XTablineNextBuffer')
  55. call s:mapkeys('[l','<Plug>XTablinePrevBuffer')
  56. call s:mapkeys('<leader>tr','<Plug>XTablineReopen')
  57. endif
  58. nnoremap <unique> <script> <Plug>XTablineToggleTabs <SID>ToggleTabs
  59. nnoremap <silent> <SID>ToggleTabs :call airline#extensions#tabline#xtabline#toggle_tabs()<cr>
  60. nnoremap <unique> <script> <Plug>XTablineToggleFiltering <SID>ToggleFiltering
  61. nnoremap <silent> <SID>ToggleFiltering :call airline#extensions#tabline#xtabline#toggle_buffers()<cr>
  62. nnoremap <unique> <script> <Plug>XTablineSelectBuffer <SID>SelectBuffer
  63. nnoremap <silent> <expr> <SID>SelectBuffer g:xtabline_changing_buffer ? "\<C-c>" : ":<C-u>call airline#extensions#tabline#xtabline#select_buffer(v:count)\<cr>"
  64. nnoremap <unique> <script> <Plug>XTablineNextBuffer <SID>NextBuffer
  65. nnoremap <silent> <expr> <SID>NextBuffer airline#extensions#tabline#xtabline#next_buffer(v:count1)
  66. nnoremap <unique> <script> <Plug>XTablinePrevBuffer <SID>PrevBuffer
  67. nnoremap <silent> <expr> <SID>PrevBuffer airline#extensions#tabline#xtabline#prev_buffer(v:count1)
  68. nnoremap <unique> <script> <Plug>XTablineReopen <SID>ReopenLastTab
  69. nnoremap <silent> <SID>ReopenLastTab :XTabReopen<cr>
  70. if get(g:, 'xtabline_cd_commands', 0)
  71. map <unique> <leader>cdc <Plug>XTablineCdCurrent
  72. map <unique> <leader>cdd <Plug>XTablineCdDown1
  73. map <unique> <leader>cd2 <Plug>XTablineCdDown2
  74. map <unique> <leader>cd3 <Plug>XTablineCdDown3
  75. map <unique> <leader>cdh <Plug>XTablineCdHome
  76. nnoremap <unique> <script> <Plug>XTablineCdCurrent :cd %:p:h<cr>:call airline#util#doautocmd('BufAdd')<cr>:pwd<cr>
  77. nnoremap <unique> <script> <Plug>XTablineCdDown1 :cd %:p:h:h<cr>:call airline#util#doautocmd('BufAdd')<cr>:pwd<cr>
  78. nnoremap <unique> <script> <Plug>XTablineCdDown2 :cd %:p:h:h:h<cr>:call airline#util#doautocmd('BufAdd')<cr>:pwd<cr>
  79. nnoremap <unique> <script> <Plug>XTablineCdDown3 :cd %:p:h:h:h:h<cr>:call airline#util#doautocmd('BufAdd')<cr>:pwd<cr>
  80. nnoremap <unique> <script> <Plug>XTablineCdHome :cd ~<cr>:call airline#util#doautocmd('BufAdd')<cr>:pwd<cr>
  81. endif
  82. endfunction
  83. """"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
  84. " Commands functions
  85. """"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
  86. function! airline#extensions#tabline#xtabline#toggle_tabs()
  87. """Toggle between tabs/buffers tabline."""
  88. if tabpagenr("$") == 1 | call airline#util#warning("There is only one tab.") | return | endif
  89. if g:airline#extensions#tabline#show_tabs
  90. let g:airline#extensions#tabline#show_tabs = 0
  91. call airline#util#warning("Showing buffers")
  92. else
  93. let g:airline#extensions#tabline#show_tabs = 1
  94. call airline#util#warning("Showing tabs")
  95. endif
  96. doautocmd BufAdd
  97. endfunction
  98. """"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
  99. function! airline#extensions#tabline#xtabline#toggle_buffers()
  100. """Toggle buffer filtering in the tabline."""
  101. if s:xtabline_filtering
  102. let s:xtabline_filtering = 0
  103. let g:airline#extensions#tabline#exclude_buffers = []
  104. call airline#util#warning("Buffer filtering turned off")
  105. doautocmd BufAdd
  106. else
  107. let s:xtabline_filtering = 1
  108. call airline#extensions#tabline#xtabline#filter_buffers()
  109. call airline#util#warning("Buffer filtering turned on")
  110. doautocmd BufAdd
  111. endif
  112. endfunction
  113. """"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
  114. function! airline#extensions#tabline#xtabline#reopen_last_tab()
  115. """Reopen the last closed tab."""
  116. if !exists('s:most_recently_closed_tab')
  117. call airline#util#warning("No recent tabs.")
  118. return
  119. endif
  120. let tab = s:most_recently_closed_tab
  121. tabnew
  122. let empty = bufnr("%")
  123. let t:cwd = tab['cwd']
  124. cd `=t:cwd`
  125. let t:name = tab['name']
  126. for buf in tab['buffers'] | execute "badd ".buf | endfor
  127. execute "edit ".tab['buffers'][0]
  128. execute "bdelete ".empty
  129. endfunction
  130. """"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
  131. function! airline#extensions#tabline#xtabline#filter_buffers()
  132. """Filter buffers so that only the ones within the tab's cwd will show up.
  133. " 'accepted' is a list of buffer numbers, for quick access.
  134. " 'excluded' is a list of buffer numbers, it will be used by Airline to hide buffers.
  135. if !exists('#airline')
  136. " airline disabled
  137. return
  138. endif
  139. if !s:xtabline_filtering | return | endif
  140. let g:airline#extensions#tabline#exclude_buffers = []
  141. let t:xtl_excluded = g:airline#extensions#tabline#exclude_buffers
  142. let t:xtl_accepted = [] | let accepted = t:xtl_accepted
  143. let previews = g:xtabline_include_previews
  144. " bufnr(0) is the alternate buffer
  145. for buf in range(1, bufnr("$"))
  146. if !buflisted(buf) | continue | endif
  147. " get the path
  148. let path = expand("#".buf.":p")
  149. " confront with the cwd
  150. if !previews && path =~ "^".getcwd()
  151. call add(accepted, buf)
  152. elseif previews && path =~ getcwd()
  153. call add(accepted, buf)
  154. else
  155. call add(t:xtl_excluded, buf)
  156. endif
  157. endfor
  158. call s:RefreshTabline()
  159. endfunction
  160. """"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
  161. function! airline#extensions#tabline#xtabline#next_buffer(nr)
  162. """Switch to next visible buffer."""
  163. if ( s:NotEnoughBuffers() || !s:xtabline_filtering ) | return | endif
  164. let accepted = t:xtl_accepted
  165. let ix = index(accepted, bufnr("%"))
  166. let target = ix + a:nr
  167. let total = len(accepted)
  168. if ix == -1
  169. " not in index, go back to most recent or back to first
  170. if s:most_recent == -1 || s:most_recent >= total
  171. let s:most_recent = 0
  172. endif
  173. elseif target >= total
  174. " over last buffer
  175. while target >= total | let target -= total | endwhile
  176. let s:most_recent = target
  177. else
  178. let s:most_recent = target
  179. endif
  180. return ":buffer " . accepted[s:most_recent] . "\<cr>"
  181. endfunction
  182. """"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
  183. function! airline#extensions#tabline#xtabline#prev_buffer(nr)
  184. """Switch to previous visible buffer."""
  185. if ( s:NotEnoughBuffers() || !s:xtabline_filtering ) | return | endif
  186. let accepted = t:xtl_accepted
  187. let ix = index(accepted, bufnr("%"))
  188. let target = ix - a:nr
  189. let total = len(accepted)
  190. if ix == -1
  191. " not in index, go back to most recent or back to first
  192. if s:most_recent == -1 || s:most_recent >= total
  193. let s:most_recent = 0
  194. endif
  195. elseif target < 0
  196. " before first buffer
  197. while target < 0 | let target += total | endwhile
  198. let s:most_recent = target
  199. else
  200. let s:most_recent = target
  201. endif
  202. return ":buffer " . accepted[s:most_recent] . "\<cr>"
  203. endfunction
  204. """"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
  205. function! airline#extensions#tabline#xtabline#select_buffer(nr)
  206. """Switch to visible buffer in the tabline with [count]."""
  207. if ( a:nr == 0 || !s:xtabline_filtering ) | execute g:xtabline_alt_action | return | endif
  208. let accepted = t:xtl_accepted
  209. if (a:nr > len(accepted)) || s:NotEnoughBuffers() || accepted[a:nr - 1] == bufnr("%")
  210. return
  211. else
  212. let g:xtabline_changing_buffer = 1
  213. execute "buffer ".accepted[a:nr - 1]
  214. endif
  215. endfunction
  216. """"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
  217. function! s:TabBuffers()
  218. """Return a list of buffers names for this tab."""
  219. return map(copy(t:xtl_accepted), 'bufname(v:val)')
  220. endfunction
  221. """"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
  222. " Helper functions
  223. """"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
  224. function! s:NotEnoughBuffers()
  225. """Just return if there aren't enough buffers."""
  226. if len(t:xtl_accepted) < 2
  227. if index(t:xtl_accepted, bufnr("%")) == -1
  228. return
  229. elseif !len(t:xtl_accepted)
  230. call airline#util#warning("No available buffers for this tab.")
  231. else
  232. call airline#util#warning("No other available buffers for this tab.")
  233. endif
  234. return 1
  235. endif
  236. endfunction
  237. function! s:RefreshTabline()
  238. call airline#extensions#tabline#buflist#invalidate()
  239. endfunction
  240. """"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
  241. " TabPageCd
  242. """"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
  243. " tabpagecd - Turn :cd into :tabpagecd, to use one tab page per project
  244. """"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
  245. function! s:InitCwds()
  246. if !exists('g:xtab_cwds') | let g:xtab_cwds = [] | endif
  247. while len(g:xtab_cwds) < tabpagenr("$")
  248. call add(g:xtab_cwds, getcwd())
  249. endwhile
  250. let s:state = 1
  251. let t:cwd = getcwd()
  252. let s:last_tab = 0
  253. call airline#extensions#tabline#xtabline#filter_buffers()
  254. endfunction
  255. """"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
  256. function! airline#extensions#tabline#xtabline#update_obsession()
  257. let string = 'let g:xtab_cwds = '.string(g:xtab_cwds).' | call airline#extensions#tabline#xtabline#update_obsession()'
  258. if !exists('g:obsession_append')
  259. let g:obsession_append = [string]
  260. else
  261. call filter(g:obsession_append, 'v:val !~# "^let g:xtab_cwds"')
  262. call add(g:obsession_append, string)
  263. endif
  264. endfunction
  265. """"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
  266. function! s:Do(action)
  267. if !exists('#airline')
  268. " airline disabled
  269. return
  270. endif
  271. let arg = a:action
  272. if !s:state | call s:InitCwds() | return | endif
  273. """"""""""""""""""""""""""""""""""""""""""""""""""""""""""""
  274. if arg == 'new'
  275. call insert(g:xtab_cwds, getcwd(), tabpagenr()-1)
  276. """"""""""""""""""""""""""""""""""""""""""""""""""""""""""""
  277. elseif arg == 'enter'
  278. let t:cwd =g:xtab_cwds[tabpagenr()-1]
  279. cd `=t:cwd`
  280. call airline#extensions#tabline#xtabline#filter_buffers()
  281. """"""""""""""""""""""""""""""""""""""""""""""""""""""""""""
  282. elseif arg == 'leave'
  283. let t:cwd = getcwd()
  284. let g:xtab_cwds[tabpagenr()-1] = t:cwd
  285. let s:last_tab = tabpagenr() - 1
  286. if !exists('t:name') | let t:name = t:cwd | endif
  287. let s:most_recent_tab = {'cwd': t:cwd, 'name': t:name, 'buffers': s:TabBuffers()}
  288. """"""""""""""""""""""""""""""""""""""""""""""""""""""""""""
  289. elseif arg == 'close'
  290. let s:most_recently_closed_tab = copy(s:most_recent_tab)
  291. call remove(g:xtab_cwds, s:last_tab)
  292. endif
  293. """"""""""""""""""""""""""""""""""""""""""""""""""""""""""""
  294. call airline#extensions#tabline#xtabline#update_obsession()
  295. endfunction
  296. """"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""