Skip to content

Commit

Permalink
first pass on making rendering user-configurable
Browse files Browse the repository at this point in the history
  • Loading branch information
deathlyfrantic committed Feb 20, 2018
1 parent 14d208b commit 46bdf70
Showing 1 changed file with 52 additions and 25 deletions.
77 changes: 52 additions & 25 deletions plugin/buftabline.vim
Original file line number Diff line number Diff line change
Expand Up @@ -44,42 +44,56 @@ function! buftabline#user_buffers() " help buffers are always unlisted, but quic
return filter(range(1,bufnr('$')),'buflisted(v:val) && "quickfix" !=? getbufvar(v:val, "&buftype")')
endfunction

let s:dirsep = fnamemodify(getcwd(),':p')[-1:]
let s:centerbuf = winbufnr(0)
function! buftabline#render()
function! s:visible_width(s)
" remove '%#highlight#' groups, '%1*' hl-user groups, '%*' endings
let pattern = '\V\(%#\w\+#\)\|\(%\d\{-0,1}*\)'
return strwidth(strtrans(substitute(a:s, pattern, '', 'g')))
endfunction

function! buftabline#default_format(opts)
let opts = a:opts
let show_num = g:buftabline_numbers == 1
let show_ord = g:buftabline_numbers == 2
let show_mod = g:buftabline_indicators
let lpad = g:buftabline_separators ? nr2char(0x23B8) : ' '
if strlen(opts.name)
let mod = show_mod && opts.modified ? '+' : ''
let num = show_num ? opts.bufnum : show_ord ? opts.ordnum : ''
let pre = mod . num
if strlen(pre)
let pre .= ' '
endif
let rv = pre . opts.name
elseif -1 < index(['nofile', 'acwrite'], opts.buftype)
let rv = show_mod ? '!' . opts.ordnum : opts.ordnum ? opts.ordnum . '!' : '!'
else
let mod = show_mod && opts.modified ? '+' : ''
let num = show_num ? opts.bufnum : show_ord ? opts.ordnum : '*'
let rv = mod . num
endif
let hl = opts.current ? 'Current' : opts.active ? 'Active' : 'Hidden'
let lpad = opts.ordnum > 1 && g:buftabline_separators ? nr2char(0x23B8) : ' '
return '%#BufTabLine' . hl . '#' . lpad . rv . ' %#BufTabLineFill#'
endfunction

let bufnums = buftabline#user_buffers()
let s:dirsep = fnamemodify(getcwd(),':p')[-1:]
let s:centerbuf = winbufnr(0)
function! buftabline#render()
let centerbuf = s:centerbuf " prevent tabline jumping around when non-user buffer current (e.g. help)

" pick up data on all the buffers
let tabs = []
let path_tabs = []
let tabs_per_tail = {}
let currentbuf = winbufnr(0)
let screen_num = 0
for bufnum in bufnums
let screen_num = show_num ? bufnum : show_ord ? screen_num + 1 : ''
let tab = { 'num': bufnum }
let tab.hilite = currentbuf == bufnum ? 'Current' : bufwinnr(bufnum) > 0 ? 'Active' : 'Hidden'

for bufnum in buftabline#user_buffers()
let tab = { 'num': bufnum, 'label': '' }
if currentbuf == bufnum | let [centerbuf, s:centerbuf] = [bufnum, bufnum] | endif
let bufpath = bufname(bufnum)
if strlen(bufpath)
let tab.path = fnamemodify(bufpath, ':p:~:.')
let tab.sep = strridx(tab.path, s:dirsep, strlen(tab.path) - 2) " keep trailing dirsep
let tab.label = tab.path[tab.sep + 1:]
let pre = ( show_mod && getbufvar(bufnum, '&mod') ? '+' : '' ) . screen_num
let tab.pre = strlen(pre) ? pre . ' ' : ''
let tabs_per_tail[tab.label] = get(tabs_per_tail, tab.label, 0) + 1
let path_tabs += [tab]
elseif -1 < index(['nofile','acwrite'], getbufvar(bufnum, '&buftype')) " scratch buffer
let tab.label = ( show_mod ? '!' . screen_num : screen_num ? screen_num . ' !' : '!' )
else " unnamed file
let tab.label = ( show_mod && getbufvar(bufnum, '&mod') ? '+' : '' )
\ . ( screen_num ? screen_num : '*' )
endif
let tabs += [tab]
endfor
Expand All @@ -96,6 +110,20 @@ function! buftabline#render()
endfor
endwhile

let ordnum = 0
for tab in tabs
let ordnum += 1
let tab.opts = {
\ 'name': tab.label,
\ 'bufnum': tab.num,
\ 'ordnum': ordnum,
\ 'modified': getbufvar(bufnum, '&modified'),
\ 'buftype': getbufvar(bufnum, '&buftype'),
\ 'current': currentbuf == tab.num,
\ 'active': bufwinnr(bufnum) > 0,
\ }
endfor

" now keep the current buffer center-screen as much as possible:

" 1. setup
Expand All @@ -104,9 +132,10 @@ function! buftabline#render()

" 2. sum the string lengths for the left and right halves
let currentside = lft
let formatter = get(g:, 'buftabline_format', 'buftabline#default_format')
for tab in tabs
let tab.label = lpad . get(tab, 'pre', '') . tab.label . ' '
let tab.width = strwidth(strtrans(tab.label))
execute printf('let tab.label = %s(tab.opts)', formatter)
let tab.width = s:visible_width(tab.label)
if centerbuf == tab.num
let halfwidth = tab.width / 2
let lft.width += halfwidth
Expand Down Expand Up @@ -135,17 +164,15 @@ function! buftabline#render()
endwhile
" then snip at the last one to make it fit
let endtab = tabs[side.lasttab]
while delta > ( endtab.width - strwidth(strtrans(endtab.label)) )
while delta > ( endtab.width - s:visible_width(endtab.label) )
let endtab.label = substitute(endtab.label, side.cut, '', '')
endwhile
let endtab.label = substitute(endtab.label, side.cut, side.indicator, '')
endfor
endif

if len(tabs) | let tabs[0].label = substitute(tabs[0].label, lpad, ' ', '') | endif

let swallowclicks = '%'.(1 + tabpagenr('$')).'X'
return swallowclicks . join(map(tabs,'printf("%%#BufTabLine%s#%s",v:val.hilite,strtrans(v:val.label))'),'') . '%#BufTabLineFill#'
return swallowclicks . join(map(tabs,'strtrans(v:val.label)'),'')
endfunction

function! buftabline#update(zombie)
Expand Down

0 comments on commit 46bdf70

Please sign in to comment.