It's a hack, but you could try this:
augroup filetype_nerdtree
au!
au FileType nerdtree call s:disable_lightline_on_nerdtree()
au WinEnter,BufWinEnter,TabEnter * call s:disable_lightline_on_nerdtree()
augroup END
fu s:disable_lightline_on_nerdtree() abort
let nerdtree_winnr = index(map(range(1, winnr('$')), {_,v -> getbufvar(winbufnr(v), '&ft')}), 'nerdtree') + 1
call timer_start(0, {-> nerdtree_winnr && setwinvar(nerdtree_winnr, '&stl', '%#Normal#')})
endfu
I'm still trying to understand what your snippet do because I am new to vim scripting. But I guess it basically sets window's statusline to%#Normal# whenever the corresponding buffer is equal to 'nerdtree', on WinLeave and TabEnter events, does it ?
Yes, that's what it does. Although, now I think that WinEnter
, BufWinEnter
and TabEnter
is a better set of events.
This displays the number of the last window in the current tab page:
:echo winnr('$')
This displays the numbers of all the windows in the current tab page, as a list:
:echo range(1, winnr('$'))
This displays the filetypes of the buffers displayed in all the windows of the current tab page:
┌ iterates over the numbers of the windows
│ ┌ evaluates to the number of the buffer displayed in the window whose number is v
│ ├─────────┐
:echo map(range(1, winnr('$')), {_,v -> getbufvar(winbufnr(v), '&ft')})
├───────────────────────────┘
└ evaluates to the filetype of the buffer whose number is winbufnr(v)
This displays the number of the window displaying a nerdtree buffer (or 0
if there is none):
:echo index(map(range(1, winnr('$')), {_,v -> getbufvar(winbufnr(v), '&ft')}), 'nerdtree') + 1
Finally, this sets the local value of the 'statusline'
option bound to the window displaying the nerdtree buffer to %#Normal#
:
:call setwinvar(index(map(range(1, winnr('$')), {_,v -> getbufvar(winbufnr(v), '&ft')}), 'nerdtree') + 1, '&stl', '%#Normal#')
Now you could execute this last function call directly from an autocmd, but there would still be 2 issues:
- the function would be called even when there is no nerdtree buffer displayed in the tab page, which would disable the status line in the current window
- Lightline would still update the status line contents of the nerdtree window after your function call, undoing your reset
To fix 1.
, you need a guard which makes sure that a window is currently displaying a nerdtree buffer:
let nerdtree_winnr = index(map(range(1, winnr('$')), {_,v -> getbufvar(winbufnr(v), '&ft')}), 'nerdtree') + 1
if nerdtree_winnr
call setwinvar(nerdtree_winnr, '&stl', '%#Normal#')
endif
To fix 2.
, you need to delay the function call until Lightline has finished updating all the status lines.
You can do so with a timer:
call timer_start(0, {-> nerdtree_winnr && setwinvar(nerdtree_winnr, '&stl', '%#Normal#')})
^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^
timer guard
You can make the nesting of function calls inside index()
a little more readable, using the method call operator ->
(introduced in 8.1.1803
):
let nerdtree_winnr = winnr('$')->range()->map({_,v -> winbufnr(v+1)->getbufvar('&ft')})->index('nerdtree') + 1
It works very well, I don't see any flickering.
I can definitely see some flickering. If – in the future – you do too, try to replace the timer with a one-shot autocmd listening to the SafeState
event (introduced in 8.1.2044
):
let nerdtree_winnr = index(map(range(1, winnr('$')), {_,v -> getbufvar(winbufnr(v), '&ft')}), 'nerdtree') + 1
if nerdtree_winnr
exe 'au SafeState * ++once call setwinvar('..nerdtree_winnr..', "&stl", "%#Normal#")'
" ^^^^^^
" fire only once
endif
During my limited tests, it seemed to fix the issue.
If one day you decide to use your own status line, you could use this template to achieve a similar effect:
filetype on
set ls=2
fu s:snr() abort
return matchstr(expand('<sfile>'), '.*\zs<SNR>\d\+_')
endfu
let s:snr = get(s:, 'snr', s:snr())
let &stl = '%!'..s:snr..'stl()'
fu s:stl() abort
return getbufvar(winbufnr(g:statusline_winid), '&ft', '') is# 'nerdtree'
\ ? '%#Normal#'
\ : '...'
" ^^^
" here, write the contents of your status line for filetypes other than nerdtree
endfu
It requires the patch 8.1.1372
to be able to inspect g:statusline_winid
.
The latter is a temporary global variable which contains the ID of the window to which the status line currently being drawn belongs.
Note that neither the method call operator ->
, nor the SafeState
event, nor the g:statusline_winid
variable are available in Nvim.
If you know C, you could try to port the relevant Vim patches.
For more info, see:
:h index()
:h map()
:h range()
:h winnr()
:h getbufvar()
:h winbufnr()
:h setwinvar()
:h timer_start()
:h lambda
:h SafeState
:h autocmd-once
:h g:statusline_winid
%#Normal#
whenever the corresponding buffer is equal to 'nerdtree', on WinLeave and TabEnter events, does it ? Would you mind posting your code in a individual response so I can accept your answer? Anyway, thanks again.BufEnter
event to the `timer_start' call, and now it works in that scenario as well.