tabline.vim 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483
  1. " MIT License. Copyright (c) 2013-2021 Bailey Ling et al.
  2. " vim: et ts=2 sts=2 sw=2 et
  3. scriptencoding utf-8
  4. let s:taboo = get(g:, 'airline#extensions#taboo#enabled', 1) && get(g:, 'loaded_taboo', 0)
  5. if s:taboo
  6. let g:taboo_tabline = 0
  7. endif
  8. let s:ctrlspace = get(g:, 'CtrlSpaceLoaded', 0)
  9. let s:tabws = get(g:, 'tabws_loaded', 0)
  10. let s:current_tabcnt = -1
  11. " Dictionary functions are not possible in Vim9 Script,
  12. " so use the legacy Vim Script implementation
  13. function! airline#extensions#tabline#init(ext)
  14. if has('gui_running') && match(&guioptions, 'e') > -1
  15. set guioptions-=e
  16. endif
  17. autocmd User AirlineToggledOn call s:toggle_on()
  18. autocmd User AirlineToggledOff call s:toggle_off()
  19. call s:toggle_on()
  20. call a:ext.add_theme_func('airline#extensions#tabline#load_theme')
  21. endfunction
  22. function! airline#extensions#tabline#add_label(dict, type, right)
  23. if get(g:, 'airline#extensions#tabline#show_tab_type', 1)
  24. call a:dict.add_section_spaced('airline_tablabel'. (a:right ? '_right' : ''),
  25. \ get(g:, 'airline#extensions#tabline#'.a:type.'_label', a:type))
  26. endif
  27. endfunction
  28. function! airline#extensions#tabline#add_tab_label(dict)
  29. let show_tab_count = get(g:, 'airline#extensions#tabline#show_tab_count', 1)
  30. if show_tab_count == 2
  31. call a:dict.add_section_spaced('airline_tabmod', printf('%s %d/%d', "tab", tabpagenr(), tabpagenr('$')))
  32. elseif show_tab_count == 1 && tabpagenr('$') > 1
  33. call a:dict.add_section_spaced('airline_tabmod', printf('%s %d/%d', "tab", tabpagenr(), tabpagenr('$')))
  34. endif
  35. endfunction
  36. if !exists(":def") || !airline#util#has_vim9_script()
  37. " Legacy Vim Script Implementation
  38. function! s:toggle_off()
  39. call airline#extensions#tabline#autoshow#off()
  40. call airline#extensions#tabline#tabs#off()
  41. call airline#extensions#tabline#buffers#off()
  42. if s:ctrlspace
  43. call airline#extensions#tabline#ctrlspace#off()
  44. endif
  45. if s:tabws
  46. call airline#extensions#tabline#tabws#off()
  47. endif
  48. endfunction
  49. function! s:toggle_on()
  50. if get(g:, 'airline_statusline_ontop', 0)
  51. call airline#extensions#tabline#enable()
  52. let &tabline='%!airline#statusline('.winnr().')'
  53. return
  54. endif
  55. call airline#extensions#tabline#autoshow#on()
  56. call airline#extensions#tabline#tabs#on()
  57. call airline#extensions#tabline#buffers#on()
  58. if s:ctrlspace
  59. call airline#extensions#tabline#ctrlspace#on()
  60. endif
  61. if s:tabws
  62. call airline#extensions#tabline#tabws#on()
  63. endif
  64. set tabline=%!airline#extensions#tabline#get()
  65. endfunction
  66. function! airline#extensions#tabline#load_theme(palette)
  67. if pumvisible()
  68. return
  69. endif
  70. let colors = get(a:palette, 'tabline', {})
  71. let tablabel = get(colors, 'airline_tablabel', a:palette.normal.airline_b)
  72. " Theme for tabs on the left
  73. let tab = get(colors, 'airline_tab', a:palette.inactive.airline_c)
  74. let tabsel = get(colors, 'airline_tabsel', a:palette.normal.airline_a)
  75. let tabtype = get(colors, 'airline_tabtype', a:palette.visual.airline_a)
  76. let tabfill = get(colors, 'airline_tabfill', a:palette.normal.airline_c)
  77. let tabmod = get(colors, 'airline_tabmod', a:palette.insert.airline_a)
  78. let tabhid = get(colors, 'airline_tabhid', a:palette.normal.airline_c)
  79. if has_key(a:palette, 'normal_modified') && has_key(a:palette.normal_modified, 'airline_c')
  80. let tabmodu = get(colors, 'airline_tabmod_unsel', a:palette.normal_modified.airline_c)
  81. let tabmodu_right = get(colors, 'airline_tabmod_unsel_right', a:palette.normal_modified.airline_c)
  82. else
  83. "Fall back to normal airline_c if modified airline_c isn't present
  84. let tabmodu = get(colors, 'airline_tabmod_unsel', a:palette.normal.airline_c)
  85. let tabmodu_right = get(colors, 'airline_tabmod_unsel_right', a:palette.normal.airline_c)
  86. endif
  87. call airline#highlighter#exec('airline_tablabel', tablabel)
  88. call airline#highlighter#exec('airline_tab', tab)
  89. call airline#highlighter#exec('airline_tabsel', tabsel)
  90. call airline#highlighter#exec('airline_tabtype', tabtype)
  91. call airline#highlighter#exec('airline_tabfill', tabfill)
  92. call airline#highlighter#exec('airline_tabmod', tabmod)
  93. call airline#highlighter#exec('airline_tabmod_unsel', tabmodu)
  94. call airline#highlighter#exec('airline_tabhid', tabhid)
  95. " Theme for tabs on the right
  96. " label on the right
  97. let tablabel_r = get(colors, 'airline_tablabel', a:palette.normal.airline_b)
  98. let tabsel_right = get(colors, 'airline_tabsel_right', a:palette.normal.airline_a)
  99. let tab_right = get(colors, 'airline_tab_right', a:palette.inactive.airline_c)
  100. let tabmod_right = get(colors, 'airline_tabmod_right', a:palette.insert.airline_a)
  101. let tabhid_right = get(colors, 'airline_tabhid_right', a:palette.normal.airline_c)
  102. call airline#highlighter#exec('airline_tablabel_right', tablabel_r)
  103. call airline#highlighter#exec('airline_tab_right', tab_right)
  104. call airline#highlighter#exec('airline_tabsel_right', tabsel_right)
  105. call airline#highlighter#exec('airline_tabmod_right', tabmod_right)
  106. call airline#highlighter#exec('airline_tabhid_right', tabhid_right)
  107. call airline#highlighter#exec('airline_tabmod_unsel_right', tabmodu_right)
  108. endfunction
  109. function! s:update_tabline(forceit)
  110. if get(g:, 'airline#extensions#tabline#disable_refresh', 0)
  111. return
  112. endif
  113. " loading a session file
  114. " On SessionLoadPost, g:SessionLoad variable is still set :/
  115. if !a:forceit && get(g:, 'SessionLoad', 0)
  116. return
  117. endif
  118. let match = expand('<afile>')
  119. if pumvisible()
  120. return
  121. elseif !get(g:, 'airline#extensions#tabline#enabled', 0)
  122. return
  123. " return, if buffer matches ignore pattern or is directory (netrw)
  124. elseif empty(match) || airline#util#ignore_buf(match) || isdirectory(match)
  125. return
  126. endif
  127. call airline#util#doautocmd('BufMRUChange')
  128. call airline#extensions#tabline#redraw()
  129. endfunction
  130. function! airline#extensions#tabline#redraw()
  131. " sometimes, the tabline is not correctly updated see #1580
  132. " so force redraw here
  133. if exists(":redrawtabline") == 2
  134. redrawtabline
  135. else
  136. " Have to set a property equal to itself to get airline to re-eval.
  137. " Setting `let &tabline=&tabline` destroys the cursor position so we
  138. " need something less invasive.
  139. let &ro = &ro
  140. endif
  141. endfunction
  142. function! airline#extensions#tabline#enable()
  143. if &lines > 3
  144. set showtabline=2
  145. endif
  146. endfunction
  147. function! airline#extensions#tabline#get()
  148. let show_buffers = get(g:, 'airline#extensions#tabline#show_buffers', 1)
  149. let show_tabs = get(g:, 'airline#extensions#tabline#show_tabs', 1)
  150. let curtabcnt = tabpagenr('$')
  151. if curtabcnt != s:current_tabcnt
  152. let s:current_tabcnt = curtabcnt
  153. call airline#extensions#tabline#tabs#invalidate()
  154. call airline#extensions#tabline#buffers#invalidate()
  155. call airline#extensions#tabline#ctrlspace#invalidate()
  156. call airline#extensions#tabline#tabws#invalidate()
  157. endif
  158. if !exists('#airline#BufAdd#*')
  159. autocmd airline BufAdd * call <sid>update_tabline(0)
  160. endif
  161. if !exists('#airline#SessionLoadPost')
  162. autocmd airline SessionLoadPost * call <sid>update_tabline(1)
  163. endif
  164. if s:ctrlspace
  165. return airline#extensions#tabline#ctrlspace#get()
  166. elseif s:tabws
  167. return airline#extensions#tabline#tabws#get()
  168. elseif show_buffers && curtabcnt == 1 || !show_tabs
  169. return airline#extensions#tabline#buffers#get()
  170. else
  171. return airline#extensions#tabline#tabs#get()
  172. endif
  173. endfunction
  174. function! airline#extensions#tabline#title(n)
  175. let title = ''
  176. if s:taboo
  177. let title = TabooTabTitle(a:n)
  178. endif
  179. if empty(title) && exists('*gettabvar')
  180. let title = gettabvar(a:n, 'title')
  181. endif
  182. let formatter = get(g:, 'airline#extensions#tabline#tabtitle_formatter')
  183. if empty(title) && formatter !=# '' && exists("*".formatter)
  184. let title = call(formatter, [a:n])
  185. endif
  186. if empty(title)
  187. let buflist = tabpagebuflist(a:n)
  188. let winnr = tabpagewinnr(a:n)
  189. let all_buffers = airline#extensions#tabline#buflist#list()
  190. let curbuf = filter(buflist, 'index(all_buffers, v:val) != -1')
  191. if len(curbuf) == 0
  192. call add(curbuf, tabpagebuflist(a:n)[0])
  193. endif
  194. " a:n: -> buffer number
  195. " curbuf: list of buffers in current tabpage
  196. " we need the buffername in current tab page.
  197. return airline#extensions#tabline#get_buffer_name(curbuf[0], curbuf)
  198. endif
  199. return title
  200. endfunction
  201. function! airline#extensions#tabline#get_buffer_name(nr, ...)
  202. let buffers = a:0 ? a:1 : airline#extensions#tabline#buflist#list()
  203. let formatter = get(g:, 'airline#extensions#tabline#formatter', 'default')
  204. return airline#extensions#tabline#formatters#{formatter}#format(a:nr, buffers)
  205. endfunction
  206. function! airline#extensions#tabline#new_builder()
  207. let builder_context = {
  208. \ 'active' : 1,
  209. \ 'tabline' : 1,
  210. \ 'right_sep' : get(g:, 'airline#extensions#tabline#right_sep' , g:airline_right_sep),
  211. \ 'right_alt_sep' : get(g:, 'airline#extensions#tabline#right_alt_sep', g:airline_right_alt_sep),
  212. \ }
  213. if get(g:, 'airline_powerline_fonts', 0)
  214. let builder_context.left_sep = get(g:, 'airline#extensions#tabline#left_sep' , g:airline_left_sep)
  215. let builder_context.left_alt_sep = get(g:, 'airline#extensions#tabline#left_alt_sep' , g:airline_left_alt_sep)
  216. else
  217. let builder_context.left_sep = get(g:, 'airline#extensions#tabline#left_sep' , ' ')
  218. let builder_context.left_alt_sep = get(g:, 'airline#extensions#tabline#left_alt_sep' , '|')
  219. endif
  220. return airline#extensions#tabline#builder#new(builder_context)
  221. endfunction
  222. function! airline#extensions#tabline#group_of_bufnr(tab_bufs, bufnr)
  223. let cur = bufnr('%')
  224. if cur == a:bufnr
  225. if g:airline_detect_modified && getbufvar(a:bufnr, '&modified')
  226. let group = 'airline_tabmod'
  227. else
  228. let group = 'airline_tabsel'
  229. endif
  230. else
  231. if g:airline_detect_modified && getbufvar(a:bufnr, '&modified')
  232. let group = 'airline_tabmod_unsel'
  233. elseif index(a:tab_bufs, a:bufnr) > -1
  234. let group = 'airline_tab'
  235. else
  236. let group = 'airline_tabhid'
  237. endif
  238. endif
  239. return group
  240. endfunction
  241. finish
  242. else
  243. def s:toggle_off(): void
  244. airline#extensions#tabline#autoshow#off()
  245. airline#extensions#tabline#tabs#off()
  246. airline#extensions#tabline#buffers#off()
  247. if s:ctrlspace
  248. airline#extensions#tabline#ctrlspace#off()
  249. endif
  250. if s:tabws
  251. airline#extensions#tabline#tabws#off()
  252. endif
  253. enddef
  254. def s:toggle_on(): void
  255. if get(g:, 'airline_statusline_ontop', 0)
  256. airline#extensions#tabline#enable()
  257. &tabline = '%!airline#statusline(' .. winnr() .. ')'
  258. return
  259. endif
  260. airline#extensions#tabline#autoshow#on()
  261. airline#extensions#tabline#tabs#on()
  262. airline#extensions#tabline#buffers#on()
  263. if s:ctrlspace
  264. airline#extensions#tabline#ctrlspace#on()
  265. endif
  266. if s:tabws
  267. airline#extensions#tabline#tabws#on()
  268. endif
  269. &tabline = '%!airline#extensions#tabline#get()'
  270. enddef
  271. def airline#extensions#tabline#load_theme(palette: dict<any>): number
  272. # Needs to return a number, because it is implicitly used as extern_funcref
  273. # And funcrefs should return a value (see airline#util#exec_funcrefs())
  274. if pumvisible()
  275. return 0
  276. endif
  277. var colors = get(palette, 'tabline', {})
  278. var tablabel = get(colors, 'airline_tablabel', palette.normal.airline_b)
  279. # Theme for tabs on the left
  280. var tab = get(colors, 'airline_tab', palette.inactive.airline_c)
  281. var tabsel = get(colors, 'airline_tabsel', palette.normal.airline_a)
  282. var tabtype = get(colors, 'airline_tabtype', palette.visual.airline_a)
  283. var tabfill = get(colors, 'airline_tabfill', palette.normal.airline_c)
  284. var tabmod = get(colors, 'airline_tabmod', palette.insert.airline_a)
  285. var tabhid = get(colors, 'airline_tabhid', palette.normal.airline_c)
  286. var tabmodu = tabhid
  287. var tabmodu_right = tabhid
  288. if has_key(palette, 'normal_modified') && has_key(palette.normal_modified, 'airline_c')
  289. tabmodu = get(colors, 'airline_tabmod_unsel', palette.normal_modified.airline_c)
  290. tabmodu_right = get(colors, 'airline_tabmod_unsel_right', palette.normal_modified.airline_c)
  291. else
  292. # Fall back to normal airline_c if modified airline_c isn't present
  293. tabmodu = get(colors, 'airline_tabmod_unsel', palette.normal.airline_c)
  294. tabmodu_right = get(colors, 'airline_tabmod_unsel_right', palette.normal.airline_c)
  295. endif
  296. airline#highlighter#exec('airline_tablabel', tablabel)
  297. airline#highlighter#exec('airline_tab', tab)
  298. airline#highlighter#exec('airline_tabsel', tabsel)
  299. airline#highlighter#exec('airline_tabtype', tabtype)
  300. airline#highlighter#exec('airline_tabfill', tabfill)
  301. airline#highlighter#exec('airline_tabmod', tabmod)
  302. airline#highlighter#exec('airline_tabmod_unsel', tabmodu)
  303. airline#highlighter#exec('airline_tabmod_unsel_right', tabmodu_right)
  304. airline#highlighter#exec('airline_tabhid', tabhid)
  305. # Theme for tabs on the right
  306. var tablabel_r = get(colors, 'airline_tablabel', palette.normal.airline_b)
  307. var tabsel_right = get(colors, 'airline_tabsel_right', palette.normal.airline_a)
  308. var tab_right = get(colors, 'airline_tab_right', palette.inactive.airline_c)
  309. var tabmod_right = get(colors, 'airline_tabmod_right', palette.insert.airline_a)
  310. var tabhid_right = get(colors, 'airline_tabhid_right', palette.normal.airline_c)
  311. airline#highlighter#exec('airline_tablabel_right', tablabel_r)
  312. airline#highlighter#exec('airline_tab_right', tab_right)
  313. airline#highlighter#exec('airline_tabsel_right', tabsel_right)
  314. airline#highlighter#exec('airline_tabmod_right', tabmod_right)
  315. airline#highlighter#exec('airline_tabhid_right', tabhid_right)
  316. return 0
  317. enddef
  318. def s:update_tabline(forceit: number): void
  319. if get(g:, 'airline#extensions#tabline#disable_refresh', 0)
  320. return
  321. endif
  322. # loading a session file
  323. # On SessionLoadPost, g:SessionLoad variable is still set :/
  324. if !forceit && get(g:, 'SessionLoad', 0)
  325. return
  326. endif
  327. var match = expand('<afile>')
  328. if pumvisible()
  329. return
  330. elseif !get(g:, 'airline#extensions#tabline#enabled', 0)
  331. return
  332. # return, if buffer matches ignore pattern or is directory (netrw)
  333. elseif empty(match) || airline#util#ignore_buf(match) || isdirectory(match)
  334. return
  335. endif
  336. airline#util#doautocmd('BufMRUChange')
  337. airline#extensions#tabline#redraw()
  338. enddef
  339. def airline#extensions#tabline#redraw(): void
  340. # redrawtabline should always be available
  341. :redrawtabline
  342. enddef
  343. def airline#extensions#tabline#enable(): void
  344. if &lines > 3
  345. &showtabline = 2
  346. endif
  347. enddef
  348. def airline#extensions#tabline#get(): string
  349. var show_buffers = get(g:, 'airline#extensions#tabline#show_buffers', 1)
  350. var show_tabs = get(g:, 'airline#extensions#tabline#show_tabs', 1)
  351. var curtabcnt = tabpagenr('$')
  352. if curtabcnt != s:current_tabcnt
  353. s:current_tabcnt = curtabcnt
  354. airline#extensions#tabline#tabs#invalidate()
  355. airline#extensions#tabline#buffers#invalidate()
  356. airline#extensions#tabline#ctrlspace#invalidate()
  357. airline#extensions#tabline#tabws#invalidate()
  358. endif
  359. if !exists('#airline#BufAdd#*')
  360. autocmd airline BufAdd * call <sid>update_tabline(0)
  361. endif
  362. if !exists('#airline#SessionLoadPost')
  363. autocmd airline SessionLoadPost * call <sid>update_tabline(1)
  364. endif
  365. if s:ctrlspace
  366. return airline#extensions#tabline#ctrlspace#get()
  367. elseif s:tabws
  368. return airline#extensions#tabline#tabws#get()
  369. elseif show_buffers && curtabcnt == 1 || !show_tabs
  370. return airline#extensions#tabline#buffers#get()
  371. else
  372. return airline#extensions#tabline#tabs#get()
  373. endif
  374. enddef
  375. def airline#extensions#tabline#title(n: number): string
  376. var title = ''
  377. if get(g:, 'airline#extensions#taboo#enabled', 1) &&
  378. get(g:, 'loaded_taboo', 0) && exists("*TabooTabTitle")
  379. title = call("TabooTabTitle", [n])
  380. endif
  381. if empty(title)
  382. title = gettabvar(n, 'title')
  383. endif
  384. var formatter = get(g:, 'airline#extensions#tabline#tabtitle_formatter', '')
  385. if empty(title) && !empty(formatter) && exists("*" .. formatter)
  386. title = call(formatter, [n])
  387. endif
  388. if empty(title)
  389. var buflist = tabpagebuflist(n)
  390. var winnr = tabpagewinnr(n)
  391. var all_buffers = airline#extensions#tabline#buflist#list()
  392. var curbuf = filter(buflist, (_, v) => index(all_buffers, v) != -1)
  393. if len(curbuf) == 0
  394. add(curbuf, tabpagebuflist(n)[0])
  395. endif
  396. return airline#extensions#tabline#get_buffer_name(curbuf[0], curbuf)
  397. endif
  398. return title
  399. enddef
  400. def airline#extensions#tabline#get_buffer_name(nr: number, buffers = airline#extensions#tabline#buflist#list()): string
  401. var Formatter = 'airline#extensions#tabline#formatters#' .. get(g:, 'airline#extensions#tabline#formatter', 'default') .. '#format'
  402. return call(Formatter, [ nr, buffers] )
  403. enddef
  404. def airline#extensions#tabline#new_builder(): dict<any>
  405. var builder_context = {
  406. 'active': 1,
  407. 'tabline': 1,
  408. 'right_sep': get(g:, 'airline#extensions#tabline#right_sep', g:airline_right_sep),
  409. 'right_alt_sep': get(g:, 'airline#extensions#tabline#right_alt_sep', g:airline_right_alt_sep),
  410. 'left_sep': get(g:, 'airline#extensions#tabline#left_sep', g:airline_left_sep),
  411. 'left_alt_sep': get(g:, 'airline#extensions#tabline#left_alt_sep', g:airline_left_alt_sep),
  412. }
  413. return airline#extensions#tabline#builder#new(builder_context)
  414. enddef
  415. def airline#extensions#tabline#group_of_bufnr(tab_bufs: list<number>, bufnr: number): string
  416. var cur = bufnr('%')
  417. var group = ''
  418. if cur == bufnr
  419. if g:airline_detect_modified && getbufvar(bufnr, '&modified')
  420. group = 'airline_tabmod'
  421. else
  422. group = 'airline_tabsel'
  423. endif
  424. else
  425. if g:airline_detect_modified && getbufvar(bufnr, '&modified')
  426. group = 'airline_tabmod_unsel'
  427. elseif index(tab_bufs, bufnr) > -1
  428. group = 'airline_tab'
  429. else
  430. group = 'airline_tabhid'
  431. endif
  432. endif
  433. return group
  434. enddef
  435. endif