0
0
mirror of https://github.com/vim/vim.git synced 2025-07-26 11:04:33 -04:00

patch 8.1.1372: when evaluating 'statusline' the current window is unknown

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)
This commit is contained in:
Bram Moolenaar 2019-05-23 22:11:59 +02:00
parent 99499b1c05
commit 1c6fd1e100
4 changed files with 65 additions and 23 deletions

View File

@ -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 When on allow some options that are an expression to be set in the
modeline. Check the option for whether it is affected by modeline. Check the option for whether it is affected by
'modelineexpr'. Also see |modeline|. 'modelineexpr'. Also see |modeline|.
This option cannot be set from a |modeline| or in the |sandbox|, for
security reasons.
*'modelines'* *'mls'* *'modelines'* *'mls'*
'modelines' 'mls' number (default 5) '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, When the option starts with "%!" then it is used as an expression,
evaluated and the result is used as the option value. Example: > evaluated and the result is used as the option value. Example: >
:set statusline=%!MyStatusLine() :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 Note that the "%!" expression is evaluated in the context of the
current window and buffer, while %{} items are evaluated in the current window and buffer, while %{} items are evaluated in the
context of the window that the statusline belongs to. 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 become empty. This will make a group like the following disappear
completely from the statusline when none of the flags are set. > completely from the statusline when none of the flags are set. >
:set statusline=...%(\ [%M%R%H]%)... :set statusline=...%(\ [%M%R%H]%)...
< *g:actual_curbuf* < Beware that an expression is evaluated each and every time the status
Beware that an expression is evaluated each and every time the status line is displayed.
line is displayed. The current buffer and current window will be set *g:actual_curbuf* *g:actual_curwin*
temporarily to that of the window (and buffer) whose statusline is The current buffer and current window will be set temporarily to that
currently being drawn. The expression will evaluate in this context. of the window (and buffer) whose statusline is currently being drawn.
The variable "g:actual_curbuf" is set to the `bufnr()` number of the The expression will evaluate in this context. The variable
real current buffer. "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 The 'statusline' option will be evaluated in the |sandbox| if set from
a modeline, see |sandbox-option|. a modeline, see |sandbox-option|.

View File

@ -3893,7 +3893,8 @@ build_stl_str_hl(
char_u base; char_u base;
char_u opt; char_u opt;
#define TMPLEN 70 #define TMPLEN 70
char_u tmp[TMPLEN]; char_u buf_tmp[TMPLEN];
char_u win_tmp[TMPLEN];
char_u *usefmt = fmt; char_u *usefmt = fmt;
struct stl_hlrec *sp; struct stl_hlrec *sp;
int save_must_redraw = must_redraw; int save_must_redraw = must_redraw;
@ -3906,9 +3907,17 @@ build_stl_str_hl(
*/ */
if (fmt[0] == '%' && fmt[1] == '!') 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); usefmt = eval_to_string_safe(fmt + 2, NULL, use_sandbox);
if (usefmt == NULL) if (usefmt == NULL)
usefmt = fmt; usefmt = fmt;
do_unlet((char_u *)"g:statusline_winid", TRUE);
} }
#endif #endif
@ -4225,8 +4234,11 @@ build_stl_str_hl(
p = t; p = t;
#ifdef FEAT_EVAL #ifdef FEAT_EVAL
vim_snprintf((char *)tmp, sizeof(tmp), "%d", curbuf->b_fnum); vim_snprintf((char *)buf_tmp, sizeof(buf_tmp),
set_internal_string_var((char_u *)"g:actual_curbuf", 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_curbuf = curbuf;
save_curwin = curwin; save_curwin = curwin;
@ -4238,6 +4250,7 @@ build_stl_str_hl(
curwin = save_curwin; curwin = save_curwin;
curbuf = save_curbuf; curbuf = save_curbuf;
do_unlet((char_u *)"g:actual_curbuf", TRUE); do_unlet((char_u *)"g:actual_curbuf", TRUE);
do_unlet((char_u *)"g:actual_curwin", TRUE);
if (str != NULL && *str != 0) if (str != NULL && *str != 0)
{ {
@ -4290,21 +4303,21 @@ build_stl_str_hl(
break; break;
case STL_ALTPERCENT: case STL_ALTPERCENT:
str = tmp; str = buf_tmp;
get_rel_pos(wp, str, TMPLEN); get_rel_pos(wp, str, TMPLEN);
break; break;
case STL_ARGLISTSTAT: case STL_ARGLISTSTAT:
fillable = FALSE; fillable = FALSE;
tmp[0] = 0; buf_tmp[0] = 0;
if (append_arg_number(wp, tmp, (int)sizeof(tmp), FALSE)) if (append_arg_number(wp, buf_tmp, (int)sizeof(buf_tmp), FALSE))
str = tmp; str = buf_tmp;
break; break;
case STL_KEYMAP: case STL_KEYMAP:
fillable = FALSE; fillable = FALSE;
if (get_keymap_str(wp, (char_u *)"<%s>", tmp, TMPLEN)) if (get_keymap_str(wp, (char_u *)"<%s>", buf_tmp, TMPLEN))
str = tmp; str = buf_tmp;
break; break;
case STL_PAGENUM: case STL_PAGENUM:
#if defined(FEAT_PRINTER) || defined(FEAT_GUI_TABLINE) #if defined(FEAT_PRINTER) || defined(FEAT_GUI_TABLINE)
@ -4360,9 +4373,9 @@ build_stl_str_hl(
if (*wp->w_buffer->b_p_ft != NUL if (*wp->w_buffer->b_p_ft != NUL
&& STRLEN(wp->w_buffer->b_p_ft) < TMPLEN - 3) && 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); wp->w_buffer->b_p_ft);
str = tmp; str = buf_tmp;
} }
break; break;
@ -4371,11 +4384,11 @@ build_stl_str_hl(
if (*wp->w_buffer->b_p_ft != NUL if (*wp->w_buffer->b_p_ft != NUL
&& STRLEN(wp->w_buffer->b_p_ft) < TMPLEN - 2) && 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); wp->w_buffer->b_p_ft);
for (t = tmp; *t != 0; t++) for (t = buf_tmp; *t != 0; t++)
*t = TOUPPER_LOC(*t); *t = TOUPPER_LOC(*t);
str = tmp; str = buf_tmp;
} }
break; break;

View File

@ -29,7 +29,9 @@ endfunc
" Function used to display syntax group. " Function used to display syntax group.
func SyntaxItem() 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 endfunc
func Test_caught_error_in_statusline() func Test_caught_error_in_statusline()
@ -218,6 +220,8 @@ func Test_statusline()
"%{: Evaluate expression between '%{' and '}' and substitute result. "%{: Evaluate expression between '%{' and '}' and substitute result.
syntax on syntax on
let s:expected_curbuf = string(bufnr(''))
let s:expected_curwin = string(win_getid())
set statusline=%{SyntaxItem()} set statusline=%{SyntaxItem()}
call assert_match('^vimNumber\s*$', s:get_statusline()) call assert_match('^vimNumber\s*$', s:get_statusline())
s/^/"/ s/^/"/
@ -332,6 +336,23 @@ func Test_statusline()
set statusline=%!2*3+1 set statusline=%!2*3+1
call assert_match('7\s*$', s:get_statusline()) 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 " Check statusline in current and non-current window
" with the 'fillchars' option. " with the 'fillchars' option.
set fillchars=stl:^,stlnc:=,vert:\|,fold:-,diff:- set fillchars=stl:^,stlnc:=,vert:\|,fold:-,diff:-

View File

@ -767,6 +767,8 @@ static char *(features[]) =
static int included_patches[] = static int included_patches[] =
{ /* Add new patch number below this line */ { /* Add new patch number below this line */
/**/
1372,
/**/ /**/
1371, 1371,
/**/ /**/