On Saturday, May 30, 2015 at 3:45:07 PM UTC-5, Nicola wrote: > Hi, > I have recently re-implemented my status line from scratch. Since getting > to my (hopefully final) solution took a while (and help from this group) I'm > giving back my approach, in the hope that it may be useful to other > non-expert Vim users, and maybe to get feedback to improve it even further. > If you don't feel like reading this somewhat lengthy post, my code is here: > > https://github.com/lifepillar/lifepillar-vim-config/blob/master/vimrc#L480 > > My requirements for a status line are as follows: > > 1. show slightly different information for active and inactive status lines; > 2. display the current mode in the active status line; > 3. color some parts of the active status line with a second color (besides > the background) that depends on the current mode; > 4. do not render everything slow as hell :) > > After trying at least three different ways to reach such goals, with varying > amounts of bugs, and following some advice from the group, I have > decided to keep it simple, which means: > > 1. set g:statusline once, and never redefine it; > 2. do not use l:statusline, so that plugins (e.g., CtrlP) can override my > status line without the need for me to add custom logic depending on > the plugin; > 3. try to avoid Ex-mode for performance; > 4. do not maintain buffer or window variables; > 5. do not use autocommands. > > Avoiding 4 and 5 almost surely means avoiding subtle bugs that are hard > to fix (at least for me). > > The main problem is: how does a function that builds a status line know > whether it is building the status line for the active window? This is > not trivial > because (see :h statusline), winnr() is evaluated differently depending on the > context. Instead of fighting against Vim, I have decided to follow its logic, > which inevitably leads to define: > > set statusline=%!BuildStatusLine(winnr()) > > Here, winnr() is always the number of the currently *active* window. > As far as I know, there is no way for BuildStatusLine() to know which window > it is building a status line for, but it can put the information it knows > (the number of the active window) into the status line's string. So, > the minimal > BuildStatusLine() is: > > func! BuildStatusLine(nr) > return '%{ReallyBuildStatusLine(' . a:nr . ')}' > endfunc > > Since ReallyBuildStatusLine() is evaluated in %{} context, winnr() returns the > number of the window *that the status line belongs to*. So, a minimal > implementation is: > > func! ReallyBuildStatusLine(nr) > if (winnr() == a:nr) > " return active status line > else > " return inactive status line > endif > endfunc > > Discovering that things were this simple was a "a-ha" moment for me. Of > course, > things are not that simple :) If all you want is putting different > strings in different > status lines, this is all you need, as far as I can see. But if you want to > use > '%' items, say highlight groups, you'll soon discover that you cannot use them > in the latter function, because they will be taken as literal strings and not > interpolated. > > To solve this problem, at first I have used a trick like this: > > func! SomeText(nr, flag) > return (winnr() == a:nr) ? (flag ? 'text' : '') : (flag ? '' : 'text') > endfunc > > func! BuildStatusLine(nr) > return '%#MyHighlight#%{SomeText(' . a:nr . ',1)}%*%{SomeText(' . > a:nr . ',0)}...' > endfunc > > It works, but it's ugly. Eventually, I decided to redefine a highlight > group on-the-fly: > > func! SetHighlight(nr) > if (winnr() == a:nr) > hi! link StlHighlight MyHighlight > else > hi! link StlHighlight StatusLineNC > endif > return '' > endfunc > > func! BuildStatusLine(nr) > return '%{SetHighlight(' . a:nr . ')}%#StlHighlight#%{SomeText()}%*...' > endfunc > > I thought this would be slow, but in my (limited) benchmarks this seems > to perform > quite well. > > So, in the end, I have a bi-colored collapsible status line highlighting the > current mode (and showing other information), which can be drawn in 1.5x-2x > time compared to a basic status line. My approach may not be general enough > to cover all use cases, but I'm pretty satisfied with it! If you know > how I can do > better than this, please let me know! > > Nicola
Have you ever tried vim-airline? https://github.com/bling/vim-airline -- -- You received this message from the "vim_use" maillist. Do not top-post! Type your reply below the text you are replying to. For more information, visit http://www.vim.org/maillist.php --- You received this message because you are subscribed to the Google Groups "vim_use" group. To unsubscribe from this group and stop receiving emails from it, send an email to [email protected]. For more options, visit https://groups.google.com/d/optout.
