Patch 8.2.2854
Problem: Custom statusline cannot contain % items.
Solution: Add "%{% expr %}". (closes #8190)
Files: runtime/doc/options.txt, src/buffer.c, src/optionstr.c,
src/testdir/test_statusline.vim
*** ../vim-8.2.2853/runtime/doc/options.txt 2021-05-06 18:46:31.039085745
+0200
--- runtime/doc/options.txt 2021-05-15 16:54:06.138186893 +0200
***************
*** 7334,7339 ****
--- 7339,7356 ----
Note that there is no '%' before the closing '}'. The
expression cannot contain a '}' character, call a function to
work around that. See |stl-%{| below.
+ {% - This is almost same as { except the result of the expression is
+ re-evaluated as a statusline format string. Thus if the
+ return value of expr contains % items they will get expanded.
+ The expression can contain the } character, the end of
+ expression is denoted by %}.
+ The For example: >
+ func! Stl_filename() abort
+ return "%t"
+ endfunc
+ < `stl=%{Stl_filename()}` results in `"%t"`
+ `stl=%{%Stl_filename()%}` results in `"Name of current file"`
+ } - End of `{%` expression
( - Start of item group. Can be used for setting the width and
alignment of a section. Must be followed by %) somewhere.
) - End of item group. No width fields allowed.
*** ../vim-8.2.2853/src/buffer.c 2021-03-04 21:55:54.601235264 +0100
--- src/buffer.c 2021-05-15 16:59:14.820874600 +0200
***************
*** 27,32 ****
--- 27,38 ----
#include "vim.h"
+
+ #ifdef FEAT_EVAL
+ // Determines how deeply nested %{} blocks will be evaluated in statusline.
+ # define MAX_STL_EVAL_DEPTH 100
+ #endif
+
static void enter_buffer(buf_T *buf);
static void buflist_getfpos(void);
static char_u *buflist_match(regmatch_T *rmp, buf_T *buf, int ignore_case);
***************
*** 4113,4118 ****
--- 4119,4127 ----
int group_end_userhl;
int group_start_userhl;
int groupdepth;
+ #ifdef FEAT_EVAL
+ int evaldepth;
+ #endif
int minwid;
int maxwid;
int zeropad;
***************
*** 4187,4192 ****
--- 4196,4204 ----
byteval = (*mb_ptr2char)(p + wp->w_cursor.col);
groupdepth = 0;
+ #ifdef FEAT_EVAL
+ evaldepth = 0;
+ #endif
p = out;
curitem = 0;
prevchar_isflag = TRUE;
***************
*** 4447,4452 ****
--- 4459,4473 ----
curitem++;
continue;
}
+ #ifdef FEAT_EVAL
+ // Denotes end of expanded %{} block
+ if (*s == '}' && evaldepth > 0)
+ {
+ s++;
+ evaldepth--;
+ continue;
+ }
+ #endif
if (vim_strchr(STL_ALL, *s) == NULL)
{
s++;
***************
*** 4482,4497 ****
break;
case STL_VIM_EXPR: // '{'
itemisflag = TRUE;
t = p;
! while (*s != '}' && *s != NUL && p + 1 < out + outlen)
*p++ = *s++;
if (*s != '}') // missing '}' or out of space
break;
s++;
! *p = 0;
p = t;
-
#ifdef FEAT_EVAL
vim_snprintf((char *)buf_tmp, sizeof(buf_tmp),
"%d", curbuf->b_fnum);
--- 4503,4529 ----
break;
case STL_VIM_EXPR: // '{'
+ {
+ #ifdef FEAT_EVAL
+ char_u *block_start = s - 1;
+ #endif
+ int reevaluate = (*s == '%');
+
+ if (reevaluate)
+ s++;
itemisflag = TRUE;
t = p;
! while ((*s != '}' || (reevaluate && s[-1] != '%'))
! && *s != NUL && p + 1 < out + outlen)
*p++ = *s++;
if (*s != '}') // missing '}' or out of space
break;
s++;
! if (reevaluate)
! p[-1] = 0; // remove the % at the end of %{% expr %}
! else
! *p = 0;
p = t;
#ifdef FEAT_EVAL
vim_snprintf((char *)buf_tmp, sizeof(buf_tmp),
"%d", curbuf->b_fnum);
***************
*** 4525,4533 ****
itemisflag = FALSE;
}
}
#endif
break;
!
case STL_LINE:
num = (wp->w_buffer->b_ml.ml_flags & ML_EMPTY)
? 0L : (long)(wp->w_cursor.lnum);
--- 4557,4598 ----
itemisflag = FALSE;
}
}
+
+ // If the output of the expression needs to be evaluated
+ // replace the %{} block with the result of evaluation
+ if (reevaluate && str != NULL && *str != 0
+ && strchr((const char *)str, '%') != NULL
+ && evaldepth < MAX_STL_EVAL_DEPTH)
+ {
+ size_t parsed_usefmt = (size_t)(block_start - usefmt);
+ size_t str_length = strlen((const char *)str);
+ size_t fmt_length = strlen((const char *)s);
+ size_t new_fmt_len = parsed_usefmt
+ + str_length + fmt_length + 3;
+ char_u *new_fmt = (char_u *)alloc(new_fmt_len * sizeof(char_u));
+ char_u *new_fmt_p = new_fmt;
+
+ new_fmt_p = (char_u *)memcpy(new_fmt_p, usefmt, parsed_usefmt)
+ + parsed_usefmt;
+ new_fmt_p = (char_u *)memcpy(new_fmt_p , str, str_length)
+ + str_length;
+ new_fmt_p = (char_u *)memcpy(new_fmt_p, "%}", 2) + 2;
+ new_fmt_p = (char_u *)memcpy(new_fmt_p , s, fmt_length)
+ + fmt_length;
+ *new_fmt_p = 0;
+ new_fmt_p = NULL;
+
+ if (usefmt != fmt)
+ vim_free(usefmt);
+ VIM_CLEAR(str);
+ usefmt = new_fmt;
+ s = usefmt + parsed_usefmt;
+ evaldepth++;
+ continue;
+ }
#endif
break;
! }
case STL_LINE:
num = (wp->w_buffer->b_ml.ml_flags & ML_EMPTY)
? 0L : (long)(wp->w_cursor.lnum);
*** ../vim-8.2.2853/src/optionstr.c 2021-05-03 20:40:35.263818664 +0200
--- src/optionstr.c 2021-05-15 17:00:55.640446428 +0200
***************
*** 618,625 ****
}
if (*s == '{')
{
s++;
! while (*s != '}' && *s)
s++;
if (*s != '}')
return N_("E540: Unclosed expression sequence");
--- 618,627 ----
}
if (*s == '{')
{
+ int reevaluate = (*s == '%');
+
s++;
! while ((*s != '}' || (reevaluate && s[-1] != '%')) && *s)
s++;
if (*s != '}')
return N_("E540: Unclosed expression sequence");
*** ../vim-8.2.2853/src/testdir/test_statusline.vim 2021-04-08
18:27:49.525472168 +0200
--- src/testdir/test_statusline.vim 2021-05-15 17:20:46.167510458 +0200
***************
*** 251,256 ****
--- 251,276 ----
call assert_match('^vimLineComment\s*$', s:get_statusline())
syntax off
+ "%{%expr%}: evaluates enxpressions present in result of expr
+ func! Inner_eval()
+ return '%n some other text'
+ endfunc
+ func! Outer_eval()
+ return 'some text %{%Inner_eval()%}'
+ endfunc
+ set statusline=%{%Outer_eval()%}
+ call assert_match('^some text ' . bufnr() . ' some other text\s*$',
s:get_statusline())
+ delfunc Inner_eval
+ delfunc Outer_eval
+
+ "%{%expr%}: Doesn't get stuck in recursion
+ func! Recurse_eval()
+ return '%{%Recurse_eval()%}'
+ endfunc
+ set statusline=%{%Recurse_eval()%}
+ call assert_match('^%{%Recurse_eval()%}\s*$', s:get_statusline())
+ delfunc Recurse_eval
+
"%(: Start of item group.
set statusline=ab%(cd%q%)de
call assert_match('^abde\s*$', s:get_statusline())
*** ../vim-8.2.2853/src/version.c 2021-05-15 15:09:02.144699051 +0200
--- src/version.c 2021-05-15 17:21:18.095377858 +0200
***************
*** 752,753 ****
--- 752,755 ----
{ /* Add new patch number below this line */
+ /**/
+ 2854,
/**/
--
This is an airconditioned room, do not open Windows.
/// Bram Moolenaar -- [email protected] -- http://www.Moolenaar.net \\\
/// \\\
\\\ sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ ///
\\\ help me help AIDS victims -- http://ICCF-Holland.org ///
--
--
You received this message from the "vim_dev" 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_dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
To view this discussion on the web visit
https://groups.google.com/d/msgid/vim_dev/202105151524.14FFOA3t3347989%40masaka.moolenaar.net.