mirror of
https://github.com/vim-airline/vim-airline.git
synced 2025-12-25 05:11:06 +08:00
Some checks failed
CI / Test (v7.4) (push) Has been cancelled
CI / Test (v8.0.0000) (push) Has been cancelled
CI / Test (v8.1.0000) (push) Has been cancelled
CI / Test (v8.2.0000) (push) Has been cancelled
CI / Test (v8.2.1000) (push) Has been cancelled
CI / Test (v9.0.0000) (push) Has been cancelled
CI / Test (v9.1.0000) (push) Has been cancelled
reviewdog / runner / vint (push) Has been cancelled
Previously, when using the rendering in buffers.vim, the tabline only considered the current buffer and column width when checking for updates, despite optionally using the tab number in rendering. This would cause incorrect tabline rendering when switching between tab pages if the buffer and column width didn't change. This change mimics the already existent behavior in `tabline/tabs.vim` which caches the current tab number for comparison when updating. Some other formatting is changed to align `buffers.vim` to `tabs.vim`. Fixes: vim-airline/vim-airline#2733
270 lines
8.8 KiB
VimL
270 lines
8.8 KiB
VimL
" MIT License. Copyright (c) 2013-2021 Bailey Ling et al.
|
|
" vim: et ts=2 sts=2 sw=2
|
|
|
|
scriptencoding utf-8
|
|
|
|
let s:spc = g:airline_symbols.space
|
|
let s:current_bufnr = -1
|
|
let s:current_tabnr = -1
|
|
let s:current_modified = 0
|
|
let s:current_tabline = ''
|
|
let s:current_visible_buffers = []
|
|
|
|
let s:number_map = {
|
|
\ '0': '⁰',
|
|
\ '1': '¹',
|
|
\ '2': '²',
|
|
\ '3': '³',
|
|
\ '4': '⁴',
|
|
\ '5': '⁵',
|
|
\ '6': '⁶',
|
|
\ '7': '⁷',
|
|
\ '8': '⁸',
|
|
\ '9': '⁹'
|
|
\ }
|
|
let s:number_map = &encoding == 'utf-8'
|
|
\ ? get(g:, 'airline#extensions#tabline#buffer_idx_format', s:number_map)
|
|
\ : {}
|
|
|
|
function! airline#extensions#tabline#buffers#off()
|
|
augroup airline_tabline_buffers
|
|
autocmd!
|
|
augroup END
|
|
endfunction
|
|
|
|
function! airline#extensions#tabline#buffers#on()
|
|
let terminal_event = has("nvim") ? 'TermOpen' : 'TerminalOpen'
|
|
augroup airline_tabline_buffers
|
|
autocmd!
|
|
autocmd BufDelete * call airline#extensions#tabline#buflist#clean()
|
|
if exists("##".terminal_event)
|
|
exe 'autocmd '. terminal_event. ' * call airline#extensions#tabline#buflist#clean()'
|
|
endif
|
|
autocmd User BufMRUChange call airline#extensions#tabline#buflist#clean()
|
|
augroup END
|
|
endfunction
|
|
|
|
function! airline#extensions#tabline#buffers#invalidate()
|
|
let s:current_bufnr = -1
|
|
endfunction
|
|
|
|
function! airline#extensions#tabline#buffers#get()
|
|
let curbuf = bufnr('%')
|
|
let curtab = tabpagenr()
|
|
try
|
|
call <sid>map_keys()
|
|
catch
|
|
" no-op
|
|
endtry
|
|
if curbuf == s:current_bufnr && curtab == s:current_tabnr && &columns == s:column_width
|
|
if !g:airline_detect_modified || getbufvar(curbuf, '&modified') == s:current_modified
|
|
return s:current_tabline
|
|
endif
|
|
endif
|
|
|
|
let b = airline#extensions#tabline#new_builder()
|
|
let tab_bufs = tabpagebuflist(tabpagenr())
|
|
let show_buf_label_first = 0
|
|
|
|
if get(g:, 'airline#extensions#tabline#buf_label_first', 0)
|
|
let show_buf_label_first = 1
|
|
endif
|
|
if show_buf_label_first
|
|
call airline#extensions#tabline#add_label(b, 'buffers', 0)
|
|
endif
|
|
|
|
let b.tab_bufs = tabpagebuflist(tabpagenr())
|
|
|
|
let b.overflow_group = 'airline_tabhid'
|
|
let b.buffers = airline#extensions#tabline#buflist#list()
|
|
if get(g:, 'airline#extensions#tabline#current_first', 0)
|
|
if index(b.buffers, curbuf) > -1
|
|
call remove(b.buffers, index(b.buffers, curbuf))
|
|
endif
|
|
let b.buffers = [curbuf] + b.buffers
|
|
endif
|
|
|
|
function! b.get_group(i) dict
|
|
let bufnum = get(self.buffers, a:i, -1)
|
|
if bufnum == -1
|
|
return ''
|
|
endif
|
|
let group = airline#extensions#tabline#group_of_bufnr(self.tab_bufs, bufnum)
|
|
if bufnum == bufnr('%')
|
|
let s:current_modified = (group == 'airline_tabmod') ? 1 : 0
|
|
endif
|
|
return group
|
|
endfunction
|
|
|
|
if has("tablineat")
|
|
function! b.get_pretitle(i) dict
|
|
let bufnum = get(self.buffers, a:i, -1)
|
|
return '%'.bufnum.'@airline#extensions#tabline#buffers#clickbuf@'
|
|
endfunction
|
|
|
|
function! b.get_posttitle(i) dict
|
|
return '%X'
|
|
endfunction
|
|
endif
|
|
|
|
function! b.get_title(i) dict
|
|
let bufnum = get(self.buffers, a:i, -1)
|
|
let group = self.get_group(a:i)
|
|
let pgroup = self.get_group(a:i - 1)
|
|
" always add a space when powerline_fonts are used
|
|
" or for the very first item
|
|
if get(g:, 'airline_powerline_fonts', 0) || a:i == 0
|
|
let space = s:spc
|
|
else
|
|
let space= (pgroup == group ? s:spc : '')
|
|
endif
|
|
|
|
if get(g:, 'airline#extensions#tabline#buffer_idx_mode', 0)
|
|
if len(s:number_map) > 0
|
|
return space. s:get_number(a:i) . '%(%{airline#extensions#tabline#get_buffer_name('.bufnum.')}%)' . s:spc
|
|
else
|
|
return '['.(a:i+1).s:spc.'%(%{airline#extensions#tabline#get_buffer_name('.bufnum.')}%)'.']'
|
|
endif
|
|
else
|
|
return space.'%(%{airline#extensions#tabline#get_buffer_name('.bufnum.')}%)'.s:spc
|
|
endif
|
|
endfunction
|
|
|
|
let current_buffer = max([index(b.buffers, curbuf), 0])
|
|
let last_buffer = len(b.buffers) - 1
|
|
call b.insert_titles(current_buffer, 0, last_buffer)
|
|
|
|
call b.add_section('airline_tabfill', '')
|
|
call b.split()
|
|
call b.add_section('airline_tabfill', '')
|
|
if !show_buf_label_first
|
|
call airline#extensions#tabline#add_label(b, 'buffers', 1)
|
|
endif
|
|
|
|
call airline#extensions#tabline#add_tab_label(b)
|
|
|
|
let s:current_bufnr = curbuf
|
|
let s:current_tabnr = curtab
|
|
let s:column_width = &columns
|
|
let s:current_tabline = b.build()
|
|
let s:current_visible_buffers = copy(b.buffers)
|
|
" Do not remove from s:current_visible_buffers, this breaks s:select_tab()
|
|
"if b._right_title <= last_buffer
|
|
" call remove(s:current_visible_buffers, b._right_title, last_buffer)
|
|
"endif
|
|
"if b._left_title > 0
|
|
" call remove(s:current_visible_buffers, 0, b._left_title)
|
|
"endif
|
|
return s:current_tabline
|
|
endfunction
|
|
|
|
function! s:get_number(index)
|
|
if len(s:number_map) == 0
|
|
return a:index
|
|
endif
|
|
let bidx_mode = get(g:, 'airline#extensions#tabline#buffer_idx_mode', 0)
|
|
let number_format = bidx_mode > 1 ? '%02d' : '%d'
|
|
let l:count = bidx_mode == 2 ? a:index+11 : a:index+1
|
|
return join(map(split(printf(number_format, l:count), '\zs'),
|
|
\ 'get(s:number_map, v:val, "")'), '')
|
|
endfunction
|
|
|
|
function! s:select_tab(buf_index)
|
|
" no-op when called in 'keymap_ignored_filetypes'
|
|
if count(get(g:, 'airline#extensions#tabline#keymap_ignored_filetypes',
|
|
\ ['vimfiler', 'nerdtree']), &ft)
|
|
return
|
|
endif
|
|
let idx = a:buf_index
|
|
if s:current_visible_buffers[0] == -1
|
|
let idx = idx + 1
|
|
endif
|
|
|
|
let buf = get(s:current_visible_buffers, idx, 0)
|
|
if buf != 0
|
|
exec 'b!' . buf
|
|
endif
|
|
endfunction
|
|
|
|
function! s:jump_to_tab(offset)
|
|
let l = airline#extensions#tabline#buflist#list()
|
|
let i = index(l, bufnr('%'))
|
|
if i > -1
|
|
exec 'b!' . l[(i + a:offset) % len(l)]
|
|
endif
|
|
endfunction
|
|
|
|
function! s:map_keys()
|
|
let bidx_mode = get(g:, 'airline#extensions#tabline#buffer_idx_mode', 1)
|
|
if bidx_mode > 0
|
|
if bidx_mode == 1
|
|
for i in range(1, 10)
|
|
exe printf('noremap <silent> <Plug>AirlineSelectTab%d :call <SID>select_tab(%d)<CR>', i%10, i-1)
|
|
endfor
|
|
else
|
|
let start_idx = bidx_mode == 2 ? 11 : 1
|
|
for i in range(start_idx, 99)
|
|
exe printf('noremap <silent> <Plug>AirlineSelectTab%02d :call <SID>select_tab(%d)<CR>', i, i-start_idx)
|
|
endfor
|
|
endif
|
|
noremap <silent> <Plug>AirlineSelectPrevTab :<C-u>call <SID>jump_to_tab(-v:count1)<CR>
|
|
noremap <silent> <Plug>AirlineSelectNextTab :<C-u>call <SID>jump_to_tab(v:count1)<CR>
|
|
" Enable this for debugging
|
|
" com! AirlineBufferList :echo map(copy(s:current_visible_buffers), {i,k -> k.": ".bufname(k)})
|
|
endif
|
|
endfunction
|
|
|
|
function! airline#extensions#tabline#buffers#clickbuf(minwid, clicks, button, modifiers) abort
|
|
" Clickable buffers
|
|
" works only in recent NeoVim with has('tablineat')
|
|
|
|
" single mouse button click without modifiers pressed
|
|
if a:clicks == 1 && a:modifiers !~# '[^ ]'
|
|
if a:button is# 'l'
|
|
" left button - switch to buffer
|
|
try
|
|
silent execute 'buffer' a:minwid
|
|
catch
|
|
call airline#util#warning("Cannot switch buffer, current buffer is modified! See :h 'hidden'")
|
|
endtry
|
|
elseif a:button is# 'm'
|
|
" middle button - delete buffer
|
|
|
|
if get(g:, 'airline#extensions#tabline#middle_click_preserves_windows', 0) == 0 || winnr('$') == 1
|
|
" just simply delete the clicked buffer. This will cause windows
|
|
" associated with the clicked buffer to be closed.
|
|
silent execute 'bdelete' a:minwid
|
|
else
|
|
" find windows displaying the clicked buffer and open an new
|
|
" buffer in them.
|
|
let current_window = bufwinnr("%")
|
|
let window_number = bufwinnr(a:minwid)
|
|
let last_window_visited = -1
|
|
|
|
" Set to 1 if the clicked buffer was open in any windows.
|
|
let buffer_in_window = 0
|
|
|
|
" Find the next window with the clicked buffer open. If bufwinnr()
|
|
" returns the same window number, this is because we clicked a new
|
|
" buffer, and then tried editing a new buffer. Vim won't create a
|
|
" new empty buffer for the same window, so we get the same window
|
|
" number from bufwinnr(). In this case we just give up and don't
|
|
" delete the buffer.
|
|
" This could be made cleaner if we could check if the clicked buffer
|
|
" is a new buffer, but I don't know if there is a way to do that.
|
|
while window_number != -1 && window_number != last_window_visited
|
|
let buffer_in_window = 1
|
|
silent execute window_number . 'wincmd w'
|
|
silent execute 'enew'
|
|
let last_window_visited = window_number
|
|
let window_number = bufwinnr(a:minwid)
|
|
endwhile
|
|
silent execute current_window . 'wincmd w'
|
|
if window_number != last_window_visited || buffer_in_window == 0
|
|
silent execute 'bdelete' a:minwid
|
|
endif
|
|
endif
|
|
endif
|
|
endif
|
|
endfunction
|