Skip to content
Permalink
Browse files

patch 8.1.1372: when evaluating 'statusline' the current window is un…

…known

Problem:    When evaluating 'statusline' the current window is unknown.
            (Daniel Hahler)
Solution:   Set "g:actual_curwin" for %{} items.  Set "g:statusline_winid"
            when evaluationg %!. (closes #4406, closes #3299)
  • Loading branch information...
brammool committed May 23, 2019
1 parent 99499b1 commit 1c6fd1e100fd0457375642ec50d483bcc0f61bb2
Showing with 65 additions and 23 deletions.
  1. +14 −8 runtime/doc/options.txt
  2. +27 −14 src/buffer.c
  3. +22 −1 src/testdir/test_statusline.vim
  4. +2 −0 src/version.c
@@ -5082,6 +5082,8 @@ A jump table for the options with a short description can be found at |Q_op|.
When on allow some options that are an expression to be set in the
modeline. Check the option for whether it is affected by
'modelineexpr'. Also see |modeline|.
This option cannot be set from a |modeline| or in the |sandbox|, for
security reasons.

*'modelines'* *'mls'*
'modelines' 'mls' number (default 5)
@@ -7089,7 +7091,9 @@ A jump table for the options with a short description can be found at |Q_op|.
When the option starts with "%!" then it is used as an expression,
evaluated and the result is used as the option value. Example: >
:set statusline=%!MyStatusLine()
< The result can contain %{} items that will be evaluated too.
< The *g:statusline_winid* variable will be set to the |window-ID| of the
window that the status line belongs to.
The result can contain %{} items that will be evaluated too.
Note that the "%!" expression is evaluated in the context of the
current window and buffer, while %{} items are evaluated in the
context of the window that the statusline belongs to.
@@ -7192,13 +7196,15 @@ A jump table for the options with a short description can be found at |Q_op|.
become empty. This will make a group like the following disappear
completely from the statusline when none of the flags are set. >
:set statusline=...%(\ [%M%R%H]%)...
< *g:actual_curbuf*
Beware that an expression is evaluated each and every time the status
line is displayed. The current buffer and current window will be set
temporarily to that of the window (and buffer) whose statusline is
currently being drawn. The expression will evaluate in this context.
The variable "g:actual_curbuf" is set to the `bufnr()` number of the
real current buffer.
< Beware that an expression is evaluated each and every time the status
line is displayed.
*g:actual_curbuf* *g:actual_curwin*
The current buffer and current window will be set temporarily to that
of the window (and buffer) whose statusline is currently being drawn.
The expression will evaluate in this context. The variable
"g:actual_curbuf" is set to the `bufnr()` number of the real current
buffer and "g:actual_curwin" to the |window-ID| of the real current
window. These values are strings.

The 'statusline' option will be evaluated in the |sandbox| if set from
a modeline, see |sandbox-option|.
@@ -3893,7 +3893,8 @@ build_stl_str_hl(
char_u base;
char_u opt;
#define TMPLEN 70
char_u tmp[TMPLEN];
char_u buf_tmp[TMPLEN];
char_u win_tmp[TMPLEN];
char_u *usefmt = fmt;
struct stl_hlrec *sp;
int save_must_redraw = must_redraw;
@@ -3906,9 +3907,17 @@ build_stl_str_hl(
*/
if (fmt[0] == '%' && fmt[1] == '!')
{
typval_T tv;

tv.v_type = VAR_NUMBER;
tv.vval.v_number = wp->w_id;
set_var((char_u *)"g:statusline_winid", &tv, FALSE);

usefmt = eval_to_string_safe(fmt + 2, NULL, use_sandbox);
if (usefmt == NULL)
usefmt = fmt;

do_unlet((char_u *)"g:statusline_winid", TRUE);
}
#endif

@@ -4225,8 +4234,11 @@ build_stl_str_hl(
p = t;

#ifdef FEAT_EVAL
vim_snprintf((char *)tmp, sizeof(tmp), "%d", curbuf->b_fnum);
set_internal_string_var((char_u *)"g:actual_curbuf", tmp);
vim_snprintf((char *)buf_tmp, sizeof(buf_tmp),
"%d", curbuf->b_fnum);
set_internal_string_var((char_u *)"g:actual_curbuf", buf_tmp);
vim_snprintf((char *)win_tmp, sizeof(win_tmp), "%d", curwin->w_id);
set_internal_string_var((char_u *)"g:actual_curwin", win_tmp);

save_curbuf = curbuf;
save_curwin = curwin;
@@ -4238,6 +4250,7 @@ build_stl_str_hl(
curwin = save_curwin;
curbuf = save_curbuf;
do_unlet((char_u *)"g:actual_curbuf", TRUE);
do_unlet((char_u *)"g:actual_curwin", TRUE);

if (str != NULL && *str != 0)
{
@@ -4290,21 +4303,21 @@ build_stl_str_hl(
break;

case STL_ALTPERCENT:
str = tmp;
str = buf_tmp;
get_rel_pos(wp, str, TMPLEN);
break;

case STL_ARGLISTSTAT:
fillable = FALSE;
tmp[0] = 0;
if (append_arg_number(wp, tmp, (int)sizeof(tmp), FALSE))
str = tmp;
buf_tmp[0] = 0;
if (append_arg_number(wp, buf_tmp, (int)sizeof(buf_tmp), FALSE))
str = buf_tmp;
break;

case STL_KEYMAP:
fillable = FALSE;
if (get_keymap_str(wp, (char_u *)"<%s>", tmp, TMPLEN))
str = tmp;
if (get_keymap_str(wp, (char_u *)"<%s>", buf_tmp, TMPLEN))
str = buf_tmp;
break;
case STL_PAGENUM:
#if defined(FEAT_PRINTER) || defined(FEAT_GUI_TABLINE)
@@ -4360,9 +4373,9 @@ build_stl_str_hl(
if (*wp->w_buffer->b_p_ft != NUL
&& STRLEN(wp->w_buffer->b_p_ft) < TMPLEN - 3)
{
vim_snprintf((char *)tmp, sizeof(tmp), "[%s]",
vim_snprintf((char *)buf_tmp, sizeof(buf_tmp), "[%s]",
wp->w_buffer->b_p_ft);
str = tmp;
str = buf_tmp;
}
break;

@@ -4371,11 +4384,11 @@ build_stl_str_hl(
if (*wp->w_buffer->b_p_ft != NUL
&& STRLEN(wp->w_buffer->b_p_ft) < TMPLEN - 2)
{
vim_snprintf((char *)tmp, sizeof(tmp), ",%s",
vim_snprintf((char *)buf_tmp, sizeof(buf_tmp), ",%s",
wp->w_buffer->b_p_ft);
for (t = tmp; *t != 0; t++)
for (t = buf_tmp; *t != 0; t++)
*t = TOUPPER_LOC(*t);
str = tmp;
str = buf_tmp;
}
break;

@@ -29,7 +29,9 @@ endfunc

" Function used to display syntax group.
func SyntaxItem()
return synIDattr(synID(line("."),col("."),1),"name")
call assert_equal(s:expected_curbuf, g:actual_curbuf)
call assert_equal(s:expected_curwin, g:actual_curwin)
return synIDattr(synID(line("."), col("."),1), "name")
endfunc

func Test_caught_error_in_statusline()
@@ -218,6 +220,8 @@ func Test_statusline()

"%{: Evaluate expression between '%{' and '}' and substitute result.
syntax on
let s:expected_curbuf = string(bufnr(''))
let s:expected_curwin = string(win_getid())
set statusline=%{SyntaxItem()}
call assert_match('^vimNumber\s*$', s:get_statusline())
s/^/"/
@@ -332,6 +336,23 @@ func Test_statusline()
set statusline=%!2*3+1
call assert_match('7\s*$', s:get_statusline())

func GetNested()
call assert_equal(string(win_getid()), g:actual_curwin)
call assert_equal(string(bufnr('')), g:actual_curbuf)
return 'nested'
endfunc
func GetStatusLine()
call assert_equal(win_getid(), g:statusline_winid)
return 'the %{GetNested()} line'
endfunc
set statusline=%!GetStatusLine()
call assert_match('the nested line', s:get_statusline())
call assert_false(exists('g:actual_curwin'))
call assert_false(exists('g:actual_curbuf'))
call assert_false(exists('g:statusline_winid'))
delfunc GetNested
delfunc GetStatusLine

" Check statusline in current and non-current window
" with the 'fillchars' option.
set fillchars=stl:^,stlnc:=,vert:\|,fold:-,diff:-
@@ -767,6 +767,8 @@ static char *(features[]) =

static int included_patches[] =
{ /* Add new patch number below this line */
/**/
1372,
/**/
1371,
/**/

0 comments on commit 1c6fd1e

Please sign in to comment.
You can’t perform that action at this time.