From b2c93bee2c50887d4c80ecf80982c73388132fe1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Dammsh=C3=A4user?= Date: Sat, 1 Feb 2020 22:26:35 +0100 Subject: [PATCH 1/5] Enable autoloading --- autoload/buftabline.vim | 129 ++++++++++++++++++++++++++++++++++++++++ plugin/buftabline.vim | 125 -------------------------------------- 2 files changed, 129 insertions(+), 125 deletions(-) create mode 100644 autoload/buftabline.vim diff --git a/autoload/buftabline.vim b/autoload/buftabline.vim new file mode 100644 index 0000000..b879a41 --- /dev/null +++ b/autoload/buftabline.vim @@ -0,0 +1,129 @@ +if exists('g:autoloadedBuftabline') + finish +endif +let g:autoloadedBuftabline = 1 + +function! buftabline#user_buffers() " help buffers are always unlisted, but quickfix buffers are not + 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() + 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) : ' ' + + let bufnums = buftabline#user_buffers() + 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' + 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 + + " disambiguate same-basename files by adding trailing path segments + while len(filter(tabs_per_tail, 'v:val > 1')) + let [ambiguous, tabs_per_tail] = [tabs_per_tail, {}] + for tab in path_tabs + if -1 < tab.sep && has_key(ambiguous, tab.label) + let tab.sep = strridx(tab.path, s:dirsep, tab.sep - 1) + let tab.label = tab.path[tab.sep + 1:] + endif + let tabs_per_tail[tab.label] = get(tabs_per_tail, tab.label, 0) + 1 + endfor + endwhile + + " now keep the current buffer center-screen as much as possible: + + " 1. setup + let lft = { 'lasttab': 0, 'cut': '.', 'indicator': '<', 'width': 0, 'half': &columns / 2 } + let rgt = { 'lasttab': -1, 'cut': '.$', 'indicator': '>', 'width': 0, 'half': &columns - lft.half } + + " 2. sum the string lengths for the left and right halves + let currentside = lft + for tab in tabs + let tab.label = lpad . get(tab, 'pre', '') . tab.label . ' ' + let tab.width = strwidth(strtrans(tab.label)) + if centerbuf == tab.num + let halfwidth = tab.width / 2 + let lft.width += halfwidth + let rgt.width += tab.width - halfwidth + let currentside = rgt + continue + endif + let currentside.width += tab.width + endfor + if currentside is lft " centered buffer not seen? + " then blame any overflow on the right side, to protect the left + let [lft.width, rgt.width] = [0, lft.width] + endif + + " 3. toss away tabs and pieces until all fits: + if ( lft.width + rgt.width ) > &columns + let oversized + \ = lft.width < lft.half ? [ [ rgt, &columns - lft.width ] ] + \ : rgt.width < rgt.half ? [ [ lft, &columns - rgt.width ] ] + \ : [ [ lft, lft.half ], [ rgt, rgt.half ] ] + for [side, budget] in oversized + let delta = side.width - budget + " toss entire tabs to close the distance + while delta >= tabs[side.lasttab].width + let delta -= remove(tabs, side.lasttab).width + endwhile + " then snip at the last one to make it fit + let endtab = tabs[side.lasttab] + while delta > ( endtab.width - strwidth(strtrans(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#' +endfunction + +function! buftabline#update(zombie) + set tabline= + if tabpagenr('$') > 1 | set guioptions+=e showtabline=2 | return | endif + set guioptions-=e + if 0 == g:buftabline_show + set showtabline=1 + return + elseif 1 == g:buftabline_show + " account for BufDelete triggering before buffer is actually deleted + let bufnums = filter(buftabline#user_buffers(), 'v:val != a:zombie') + let &g:showtabline = 1 + ( len(bufnums) > 1 ) + elseif 2 == g:buftabline_show + set showtabline=2 + endif + set tabline=%!buftabline#render() +endfunction diff --git a/plugin/buftabline.vim b/plugin/buftabline.vim index 091a5f7..6a9c137 100644 --- a/plugin/buftabline.vim +++ b/plugin/buftabline.vim @@ -40,131 +40,6 @@ let g:buftabline_separators = get(g:, 'buftabline_separators', 0) let g:buftabline_show = get(g:, 'buftabline_show', 2) let g:buftabline_plug_max = get(g:, 'buftabline_plug_max', 10) -function! buftabline#user_buffers() " help buffers are always unlisted, but quickfix buffers are not - 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() - 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) : ' ' - - let bufnums = buftabline#user_buffers() - 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' - 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 - - " disambiguate same-basename files by adding trailing path segments - while len(filter(tabs_per_tail, 'v:val > 1')) - let [ambiguous, tabs_per_tail] = [tabs_per_tail, {}] - for tab in path_tabs - if -1 < tab.sep && has_key(ambiguous, tab.label) - let tab.sep = strridx(tab.path, s:dirsep, tab.sep - 1) - let tab.label = tab.path[tab.sep + 1:] - endif - let tabs_per_tail[tab.label] = get(tabs_per_tail, tab.label, 0) + 1 - endfor - endwhile - - " now keep the current buffer center-screen as much as possible: - - " 1. setup - let lft = { 'lasttab': 0, 'cut': '.', 'indicator': '<', 'width': 0, 'half': &columns / 2 } - let rgt = { 'lasttab': -1, 'cut': '.$', 'indicator': '>', 'width': 0, 'half': &columns - lft.half } - - " 2. sum the string lengths for the left and right halves - let currentside = lft - for tab in tabs - let tab.label = lpad . get(tab, 'pre', '') . tab.label . ' ' - let tab.width = strwidth(strtrans(tab.label)) - if centerbuf == tab.num - let halfwidth = tab.width / 2 - let lft.width += halfwidth - let rgt.width += tab.width - halfwidth - let currentside = rgt - continue - endif - let currentside.width += tab.width - endfor - if currentside is lft " centered buffer not seen? - " then blame any overflow on the right side, to protect the left - let [lft.width, rgt.width] = [0, lft.width] - endif - - " 3. toss away tabs and pieces until all fits: - if ( lft.width + rgt.width ) > &columns - let oversized - \ = lft.width < lft.half ? [ [ rgt, &columns - lft.width ] ] - \ : rgt.width < rgt.half ? [ [ lft, &columns - rgt.width ] ] - \ : [ [ lft, lft.half ], [ rgt, rgt.half ] ] - for [side, budget] in oversized - let delta = side.width - budget - " toss entire tabs to close the distance - while delta >= tabs[side.lasttab].width - let delta -= remove(tabs, side.lasttab).width - endwhile - " then snip at the last one to make it fit - let endtab = tabs[side.lasttab] - while delta > ( endtab.width - strwidth(strtrans(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#' -endfunction - -function! buftabline#update(zombie) - set tabline= - if tabpagenr('$') > 1 | set guioptions+=e showtabline=2 | return | endif - set guioptions-=e - if 0 == g:buftabline_show - set showtabline=1 - return - elseif 1 == g:buftabline_show - " account for BufDelete triggering before buffer is actually deleted - let bufnums = filter(buftabline#user_buffers(), 'v:val != a:zombie') - let &g:showtabline = 1 + ( len(bufnums) > 1 ) - elseif 2 == g:buftabline_show - set showtabline=2 - endif - set tabline=%!buftabline#render() -endfunction - augroup BufTabLine autocmd! autocmd VimEnter * call buftabline#update(0) From 2927fd50de2726d9555f5ac4275c7b631af37da1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Dammsh=C3=A4user?= Date: Sat, 1 Feb 2020 22:51:40 +0100 Subject: [PATCH 2/5] Add way to disable the plugin completely --- plugin/buftabline.vim | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/plugin/buftabline.vim b/plugin/buftabline.vim index 6a9c137..2e67d4d 100644 --- a/plugin/buftabline.vim +++ b/plugin/buftabline.vim @@ -27,6 +27,11 @@ if v:version < 700 finish endif +if exists('g:loadedBuftabline') + finish +endif +let g:loadedBuftabline = 1 + scriptencoding utf-8 hi default link BufTabLineCurrent TabLineSel From 1f63152cda35cf83d48471723ccf8d26fc981713 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Dammsh=C3=A4user?= Date: Sat, 1 Feb 2020 22:53:35 +0100 Subject: [PATCH 3/5] Add way to disable Buftabline In contrast to the full disable toggle, this links highlight groups and defines default values but does not enable autocmds of Buftabline. --- plugin/buftabline.vim | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/plugin/buftabline.vim b/plugin/buftabline.vim index 2e67d4d..6639ba5 100644 --- a/plugin/buftabline.vim +++ b/plugin/buftabline.vim @@ -44,6 +44,12 @@ let g:buftabline_indicators = get(g:, 'buftabline_indicators', 0) let g:buftabline_separators = get(g:, 'buftabline_separators', 0) let g:buftabline_show = get(g:, 'buftabline_show', 2) let g:buftabline_plug_max = get(g:, 'buftabline_plug_max', 10) +let g:buftabline_enabled = get(g:, 'buftabline_enabled', 1) + +" This disables the plugin but loads configuration +if !g:buftabline_enabled + finish +endif augroup BufTabLine autocmd! From 76954b6d5bc34e3311c214bbeb4b7aae71d8a8a2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Dammsh=C3=A4user?= Date: Wed, 26 Feb 2020 22:14:38 +0100 Subject: [PATCH 4/5] Revert autoloading --- autoload/buftabline.vim | 129 ---------------------------------------- plugin/buftabline.vim | 125 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 125 insertions(+), 129 deletions(-) delete mode 100644 autoload/buftabline.vim diff --git a/autoload/buftabline.vim b/autoload/buftabline.vim deleted file mode 100644 index b879a41..0000000 --- a/autoload/buftabline.vim +++ /dev/null @@ -1,129 +0,0 @@ -if exists('g:autoloadedBuftabline') - finish -endif -let g:autoloadedBuftabline = 1 - -function! buftabline#user_buffers() " help buffers are always unlisted, but quickfix buffers are not - 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() - 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) : ' ' - - let bufnums = buftabline#user_buffers() - 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' - 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 - - " disambiguate same-basename files by adding trailing path segments - while len(filter(tabs_per_tail, 'v:val > 1')) - let [ambiguous, tabs_per_tail] = [tabs_per_tail, {}] - for tab in path_tabs - if -1 < tab.sep && has_key(ambiguous, tab.label) - let tab.sep = strridx(tab.path, s:dirsep, tab.sep - 1) - let tab.label = tab.path[tab.sep + 1:] - endif - let tabs_per_tail[tab.label] = get(tabs_per_tail, tab.label, 0) + 1 - endfor - endwhile - - " now keep the current buffer center-screen as much as possible: - - " 1. setup - let lft = { 'lasttab': 0, 'cut': '.', 'indicator': '<', 'width': 0, 'half': &columns / 2 } - let rgt = { 'lasttab': -1, 'cut': '.$', 'indicator': '>', 'width': 0, 'half': &columns - lft.half } - - " 2. sum the string lengths for the left and right halves - let currentside = lft - for tab in tabs - let tab.label = lpad . get(tab, 'pre', '') . tab.label . ' ' - let tab.width = strwidth(strtrans(tab.label)) - if centerbuf == tab.num - let halfwidth = tab.width / 2 - let lft.width += halfwidth - let rgt.width += tab.width - halfwidth - let currentside = rgt - continue - endif - let currentside.width += tab.width - endfor - if currentside is lft " centered buffer not seen? - " then blame any overflow on the right side, to protect the left - let [lft.width, rgt.width] = [0, lft.width] - endif - - " 3. toss away tabs and pieces until all fits: - if ( lft.width + rgt.width ) > &columns - let oversized - \ = lft.width < lft.half ? [ [ rgt, &columns - lft.width ] ] - \ : rgt.width < rgt.half ? [ [ lft, &columns - rgt.width ] ] - \ : [ [ lft, lft.half ], [ rgt, rgt.half ] ] - for [side, budget] in oversized - let delta = side.width - budget - " toss entire tabs to close the distance - while delta >= tabs[side.lasttab].width - let delta -= remove(tabs, side.lasttab).width - endwhile - " then snip at the last one to make it fit - let endtab = tabs[side.lasttab] - while delta > ( endtab.width - strwidth(strtrans(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#' -endfunction - -function! buftabline#update(zombie) - set tabline= - if tabpagenr('$') > 1 | set guioptions+=e showtabline=2 | return | endif - set guioptions-=e - if 0 == g:buftabline_show - set showtabline=1 - return - elseif 1 == g:buftabline_show - " account for BufDelete triggering before buffer is actually deleted - let bufnums = filter(buftabline#user_buffers(), 'v:val != a:zombie') - let &g:showtabline = 1 + ( len(bufnums) > 1 ) - elseif 2 == g:buftabline_show - set showtabline=2 - endif - set tabline=%!buftabline#render() -endfunction diff --git a/plugin/buftabline.vim b/plugin/buftabline.vim index 6639ba5..a752a5c 100644 --- a/plugin/buftabline.vim +++ b/plugin/buftabline.vim @@ -46,6 +46,131 @@ let g:buftabline_show = get(g:, 'buftabline_show', 2) let g:buftabline_plug_max = get(g:, 'buftabline_plug_max', 10) let g:buftabline_enabled = get(g:, 'buftabline_enabled', 1) +function! buftabline#user_buffers() " help buffers are always unlisted, but quickfix buffers are not + 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() + 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) : ' ' + + let bufnums = buftabline#user_buffers() + 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' + 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 + + " disambiguate same-basename files by adding trailing path segments + while len(filter(tabs_per_tail, 'v:val > 1')) + let [ambiguous, tabs_per_tail] = [tabs_per_tail, {}] + for tab in path_tabs + if -1 < tab.sep && has_key(ambiguous, tab.label) + let tab.sep = strridx(tab.path, s:dirsep, tab.sep - 1) + let tab.label = tab.path[tab.sep + 1:] + endif + let tabs_per_tail[tab.label] = get(tabs_per_tail, tab.label, 0) + 1 + endfor + endwhile + + " now keep the current buffer center-screen as much as possible: + + " 1. setup + let lft = { 'lasttab': 0, 'cut': '.', 'indicator': '<', 'width': 0, 'half': &columns / 2 } + let rgt = { 'lasttab': -1, 'cut': '.$', 'indicator': '>', 'width': 0, 'half': &columns - lft.half } + + " 2. sum the string lengths for the left and right halves + let currentside = lft + for tab in tabs + let tab.label = lpad . get(tab, 'pre', '') . tab.label . ' ' + let tab.width = strwidth(strtrans(tab.label)) + if centerbuf == tab.num + let halfwidth = tab.width / 2 + let lft.width += halfwidth + let rgt.width += tab.width - halfwidth + let currentside = rgt + continue + endif + let currentside.width += tab.width + endfor + if currentside is lft " centered buffer not seen? + " then blame any overflow on the right side, to protect the left + let [lft.width, rgt.width] = [0, lft.width] + endif + + " 3. toss away tabs and pieces until all fits: + if ( lft.width + rgt.width ) > &columns + let oversized + \ = lft.width < lft.half ? [ [ rgt, &columns - lft.width ] ] + \ : rgt.width < rgt.half ? [ [ lft, &columns - rgt.width ] ] + \ : [ [ lft, lft.half ], [ rgt, rgt.half ] ] + for [side, budget] in oversized + let delta = side.width - budget + " toss entire tabs to close the distance + while delta >= tabs[side.lasttab].width + let delta -= remove(tabs, side.lasttab).width + endwhile + " then snip at the last one to make it fit + let endtab = tabs[side.lasttab] + while delta > ( endtab.width - strwidth(strtrans(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#' +endfunction + +function! buftabline#update(zombie) + set tabline= + if tabpagenr('$') > 1 | set guioptions+=e showtabline=2 | return | endif + set guioptions-=e + if 0 == g:buftabline_show + set showtabline=1 + return + elseif 1 == g:buftabline_show + " account for BufDelete triggering before buffer is actually deleted + let bufnums = filter(buftabline#user_buffers(), 'v:val != a:zombie') + let &g:showtabline = 1 + ( len(bufnums) > 1 ) + elseif 2 == g:buftabline_show + set showtabline=2 + endif + set tabline=%!buftabline#render() +endfunction + " This disables the plugin but loads configuration if !g:buftabline_enabled finish From 054f43d0dd16bcbd7f052878fc6aea603f977832 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Dammsh=C3=A4user?= Date: Wed, 26 Feb 2020 22:15:00 +0100 Subject: [PATCH 5/5] Add width as configuration to render function --- plugin/buftabline.vim | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/plugin/buftabline.vim b/plugin/buftabline.vim index a752a5c..d484a9d 100644 --- a/plugin/buftabline.vim +++ b/plugin/buftabline.vim @@ -53,10 +53,15 @@ endfunction let s:dirsep = fnamemodify(getcwd(),':p')[-1:] let s:centerbuf = winbufnr(0) function! buftabline#render() + return buftabline#renderWithWidth(&columns) +endfunction + +function! buftabline#renderWithWidth(width) 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) : ' ' + let columns = a:width let bufnums = buftabline#user_buffers() let centerbuf = s:centerbuf " prevent tabline jumping around when non-user buffer current (e.g. help) @@ -105,8 +110,8 @@ function! buftabline#render() " now keep the current buffer center-screen as much as possible: " 1. setup - let lft = { 'lasttab': 0, 'cut': '.', 'indicator': '<', 'width': 0, 'half': &columns / 2 } - let rgt = { 'lasttab': -1, 'cut': '.$', 'indicator': '>', 'width': 0, 'half': &columns - lft.half } + let lft = { 'lasttab': 0, 'cut': '.', 'indicator': '<', 'width': 0, 'half': columns / 2 } + let rgt = { 'lasttab': -1, 'cut': '.$', 'indicator': '>', 'width': 0, 'half': columns - lft.half } " 2. sum the string lengths for the left and right halves let currentside = lft @@ -128,10 +133,10 @@ function! buftabline#render() endif " 3. toss away tabs and pieces until all fits: - if ( lft.width + rgt.width ) > &columns + if ( lft.width + rgt.width ) > columns let oversized - \ = lft.width < lft.half ? [ [ rgt, &columns - lft.width ] ] - \ : rgt.width < rgt.half ? [ [ lft, &columns - rgt.width ] ] + \ = lft.width < lft.half ? [ [ rgt, columns - lft.width ] ] + \ : rgt.width < rgt.half ? [ [ lft, columns - rgt.width ] ] \ : [ [ lft, lft.half ], [ rgt, rgt.half ] ] for [side, budget] in oversized let delta = side.width - budget