summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--runtime/doc/options.txt22
-rw-r--r--src/buffer.c41
-rw-r--r--src/testdir/test_statusline.vim23
-rw-r--r--src/version.c2
4 files changed, 65 insertions, 23 deletions
diff --git a/runtime/doc/options.txt b/runtime/doc/options.txt
index 53d72b38c1..2c2afa17c2 100644
--- a/runtime/doc/options.txt
+++ b/runtime/doc/options.txt
@@ -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|.
diff --git a/src/buffer.c b/src/buffer.c
index 0e45f0e66c..425c9143a1 100644
--- a/src/buffer.c
+++ b/src/buffer.c
@@ -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;
diff --git a/src/testdir/test_statusline.vim b/src/testdir/test_statusline.vim
index b86340a23a..e1830d08ba 100644
--- a/src/testdir/test_statusline.vim
+++ b/src/testdir/test_statusline.vim
@@ -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:-
diff --git a/src/version.c b/src/version.c
index c2ee827a8c..7bac657e59 100644
--- a/src/version.c
+++ b/src/version.c
@@ -768,6 +768,8 @@ static char *(features[]) =
static int included_patches[] =
{ /* Add new patch number below this line */
/**/
+ 1372,
+/**/
1371,
/**/
1370,