1

I tried to write a small script to give the statusline distinguishable appearance on current and non-current window.

The local active and inactive statuslines are defined by the following code:

  • Active statusline:
function! SttLine_Active(usesimple)
    setl statusline=
if (!a:usesimple)
    setl statusline+=\%#StatusBlockColour#
    setl statusline+=\ %{g:currentmode[mode()]}\ %0*

    setl statusline+=\%#StatusLineColour#
    setl statusline+=\ %p%%\(%L)\ ≡\ L%l\:%c\ \|%0*

    setl statusline+=\%#StatusFileColour#
    setl statusline+=\ [%{winnr()}]\ %f\ %m%=%0*

    setl statusline+=\%#StatusBlockColour#
    setl statusline+=\ ⌨\ %{&fileformat}:\ %y
    setl statusline+=\ %{&fileencoding?&fileencoding:&encoding}\ %0*
else
    setl statusline+=\%#StatusFileColour#
    setl statusline+=\ %f\ %m\ %=%0*
endif

endfunction

  • Inactive statusline
function! SttLine_Inactive(usesimple)
    setl statusline=
if (!a:usesimple)
    setl statusline+=\%#StatusBlockGrey#
    setl statusline+=\ %{g:currentmode[mode()]}\ %0*

    setl statusline+=\%#StatusLineGrey#
    setl statusline+=\ %p%%\(%L)\ ≡\ L%l\:%c\ \|%0*

    setl statusline+=\%#StatusFileGrey#
    setl statusline+=\ [%{winnr()}]\ %f\ %m%=%0*

    setl statusline+=\%#StatusBlockGrey#
    setl statusline+=\ ⌨\ %{&fileformat}:\ %y
    setl statusline+=\ %{&fileencoding?&fileencoding:&encoding}\ %0*
else
    setl statusline+=\%#StatusFileGrey#
    setl statusline+=\ %f\ %m\ %=%0*
endif

endfunction


I then define some functions for different actions in vim, including VimEnter, WinNew, WinEnter and WinLeave as I want a different style for netrw window

  • Function execute when vim start
function! SttLine_VimStart()
    let usesimple = (&filetype=="netrw") || (&filetype=="help")
    call SttLine_Active(usesimple)
endfunction
  • Function that executes when a new window is opened:
function! SttLine_NewWin()
    let nWin  = bufnr("$")
let iwin     = 0
let hasnetrw = 0
while (iwin < nWin)
    if (getbufvar(iwin, "&filetype") == "netrw")
        let hasnetrw = 1
    endif

    let iwin += 1
endwhile

if (hasnetrw>0)
    vert res
    vert res -25
endif

endfunction

  • Function executes on enter a window
function! SttLine_Enter()
    let usesimple = (&filetype=="netrw") || (&filetype=="help")
    call SttLine_Active(usesimple)
endfunction
  • Function executes on leaving a window
function! SttLine_Leave()
    let usesimple = (&filetype=="netrw") || (&filetype=="help")
    call SttLine_Inactive(usesimple)
endfunction

Finally the augroup for those functions above

  • augroup to call the correct statusline:
augroup Auto_Change_SttLine
    autocmd!
    autocmd VimEnter * call SttLine_VimStart()
    autocmd WinNew   * call SttLine_NewWin()
    autocmd WinEnter * call SttLine_Enter()
    autocmd WinLeave * call SttLine_Leave()
augroup END

  • To test the script:
  1. I open a file, let's call it file_01.txt from the terminal: $ vim file01.txt
  2. then in vim, I open another file, file_02.txt: :new file_02.txt
  • My problem

The first time, it worked as I expected. But for the next times I opened vim, it failed sometimes.

I realize that if I close file_02.txt before closing file_01.txt, the next time I start vim, my script fails.

In order to fix it, I need to close file_01.txt before closing file_02.txt.

  • My question

What is causing this problem and how to make my script work regardless of the previous closing order?

Here is my youtube video demonstrating the steps I did to produce the error.


  • Additional information

Below are the highlight I used for my statusline

hi StatusBlockColour    cterm=bold ctermfg=235 ctermbg=190
hi StatusBlockGrey      cterm=bold ctermfg=235 ctermbg=247
hi StatusLineColour     cterm=bold ctermfg=190 ctermbg=240
hi StatusLineGrey       cterm=bold ctermfg=245 ctermbg=240
hi StatusFileColour     cterm=bold ctermfg=208 ctermbg=240
hi StatusFileGrey       cterm=bold ctermfg=245 ctermbg=240

  • Update 1 I just found some other issues in my .vimrc. I used
au BufWinLeave * mkview
au BufWinEnter * silent loadview

to restore the last view. It accidentally enabled me to run SttLine_Enter() and the result is bad.

Recently I added to my augroup a new au for BufWinEnter, so it became:

  • (Updated) augroup to call the statusline:
augroup Auto_Change_SttLine
    autocmd!
    autocmd VimEnter    * call SttLine_VimStart()
    autocmd WinNew      * call SttLine_NewWin()
    autocmd BufWinEnter * call SttLine_Enter()
    autocmd WinEnter    * call SttLine_Enter()
    autocmd WinLeave    * call SttLine_Leave()
augroup END
Rekkhan
  • 43
  • 6
  • 1
    Do you use views? – D. Ben Knoble Feb 13 '22 at 15:32
  • what is views. I'm quite new to vim. – Rekkhan Feb 13 '22 at 18:09
  • 1
    :help View, and also check :set viminfo? maybe. I'm just trying to think of things that could be automatically restoring state; normally, very few thing can affect vim between instances. See also How to debug my vimrc – D. Ben Knoble Feb 14 '22 at 19:20
  • @D.BenKnoble I just found out that it has something to do with mkview and loadview. My autocmd for setting up a sttline for newly opened window works because of those commands, but unfortunately they also cause the unexpected behaviour I post. I'll take a look to View and viminfo as you suggest to see if there is a work around to prevent the "negative" effect of mkview and loadview. I updated my post too. – Rekkhan Feb 15 '22 at 02:07

0 Answers0