Tuesday, May 26, 2015

Re: Does trigger any event?

2015-05-26 20:32 GMT+03:00 Nicola <nvitacolonna@gmail.com>:
> On 2015-05-26 09:04:39 +0000, Nicola said:
>
>> On 2015-05-26 04:59:00 +0000, Nikolay Pavlov said:
>>
>>> Default value from &l:statusline is &g:statusline (actually,
>>> pseudo-value "no value set, fall back to &g:statusline"). If you set
>>> &g:statusline to `%!BuildNewStatusLine()` and run
>>> `RefreshStatusLines()` inside then this function will be run only when
>>> new window appears because `RefreshStatusLines()` will set
>>> &l:statusline which will be used then and which will only call
>>> BuildStatusLine, but not BuildNewStatusLine.
>>
>>
>> Ok, I'm having some difficulty with this. Currently I have something like
>> this in my .vimrc:
>>
>> func! WinNrFromID(window_id)
>> return filter(range(1, winnr('$')), 'getwinvar(v:val,
>> "custom_window_id") == ' . a:window_id)[0]
>> endf
>>
>> func! BuildStatusLine(window_id)
>> let nr = WinNrFromID(window_id)
>> " Build the status line
>> endf
>>
>> let g:window_id = 0 " Global unique id
>>
>> func! SetupLocalStatusLine()
>> let g:window_id +=1
>> let w:custom_window_id = g:window_id
>> exec 'setlocal statusline=%!BuildStatusLine(' . w:custom_window_id . ')'
>> endf
>>
>> set statusline=%!SetupLocalStatusLine()
>>
>> Problems:
>>
>> 1) How do I detect whether a window is the active one (I want different
>> status lines
>> for active and inactive windows)? I cannot use winnr() inside
>> BuildStatusLine()
>> or in the context of %!.
>
>
> On a second thought, that's not true: I can use winnr() to get the current
> window.
> So, the real problem is:
>
>> 2) When I open several windows and then I close them with <c-w>o, I get an
>> out of bounds
>> error in WinNrFromID(). Why? Is the function being called for
>> closing/closed windows?
>
>
> All works as expected (including <C-w><C-o>!) if I open windows with :new,
> :vnew, etc...
> But when I split a window, say with <C-w><C-s>, SetupLocalStatusLine()
> is not called, which means that somehow the current &l:statusline is
> re-used. The rest
> is just a consequence of that. I have no idea how to fix this.
>
> I have also noticed that when I split a window, BuildStatusLine() is called
> three times, while
> I'd expect it to be called twice (once per split window). Is that expected
> behaviour?

Ah, now I remember that bug that appeared years ago in powerline.

Fix that powerline uses is simple: SetupLocalStatusLine is called each
time. Specifically this is why I had an advice not to set &statusline
value if it is correct:

function WinNrFromID(window_id)
call filter(map(range(1, winnr('$')), 'getwinvar(v:val,
"&statusline") is# "%!BuildStatusLine(".getwinvar(v:val,
"custom_window_id").")" ? [v:val, getwinvar(v:val,
"custom_window_id")] : (getwinvar(v:val, "custom_window_id") is# "" ?
[setwinvar(v:val, "custom_window_id", extend(s:, {"last_window_id":
get(s:, "last_window_id", 0) + 1}).last_window_id), setwinvar(v:val,
"&statusline", "%!BuildStatusLine(" . s:last_window_id . ")"), v:val,
s:last_window_id][-2:] : [setwinvar(v:val, "&statusline",
"%!BuildStatusLine(" . getwinvar(v:val, "custom_window_id") . ")"),
v:val, getwinvar(v:val, "custom_window_id")][-2:])'), 'v:val[1] ==
a:window_id')[0][0]
endfunction

: this one will update get window number and update &stl value if
necessary. To be called always. Highly optimized (main VimL
optimization principle: the less Ex commands the better: additional
getwinvar() calls are nothing compared to additional :let, not to
mention cycle which is at least two (:for and :endfor) commands
multiplied by a number of windows).

Most likely I have missed some parenthesis above, but you should get
the principle:

0. Initial list: 1 ... {last window number}.
1. map() body: returns a list of pairs [winnr, window_id]. During the
processing of the initial list three variants are being checked:

1. Status line is not %!BuildStatusLine({w:custom_window_id}).
1. Window does not have w:custom_window_id: assign both
w:custom_window_id and &l:statusline. This part should catch your
problem.
2. Window does have w:custom_window_id, but &statusline value
does not match: assign &l:statusline.
2. Status line is correct.

2. filter() body: checks which of the pairs is the needed one.

I am not sure whether you do need the optimization. Just taken an
opportunity to show it: &statusline functions usually need to be very
fast.

>
>
> Nicola
>
>
> --
> --
> 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 vim_use+unsubscribe@googlegroups.com.
> For more options, visit https://groups.google.com/d/optout.

--
--
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 vim_use+unsubscribe@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

No comments: