mirror of
https://github.com/neovim/neovim.git
synced 2025-09-16 00:08:19 +00:00
vim-patch:8.2.2854: custom statusline cannot contain % items (#14558)
Problem: Custom statusline cannot contain % items.
Solution: Add "%{% expr %}". (closes vim/vim#8190)
30e3de21fc
This commit is contained in:
@@ -85,6 +85,9 @@
|
||||
# include "buffer.c.generated.h"
|
||||
#endif
|
||||
|
||||
// Determines how deeply nested %{} blocks will be evaluated in statusline.
|
||||
#define MAX_STL_EVAL_DEPTH 100
|
||||
|
||||
static char *msg_loclist = N_("[Location List]");
|
||||
static char *msg_qflist = N_("[Quickfix List]");
|
||||
static char *e_auabort = N_("E855: Autocommands caused command to abort");
|
||||
@@ -3572,6 +3575,7 @@ int build_stl_str_hl(
|
||||
}
|
||||
|
||||
int groupdepth = 0;
|
||||
int evaldepth = 0;
|
||||
|
||||
int curitem = 0;
|
||||
bool prevchar_isflag = true;
|
||||
@@ -3909,6 +3913,13 @@ int build_stl_str_hl(
|
||||
continue;
|
||||
}
|
||||
|
||||
// Denotes end of expanded %{} block
|
||||
if (*fmt_p == '}' && evaldepth > 0) {
|
||||
fmt_p++;
|
||||
evaldepth--;
|
||||
continue;
|
||||
}
|
||||
|
||||
// An invalid item was specified.
|
||||
// Continue processing on the next character of the format string.
|
||||
if (vim_strchr(STL_ALL, *fmt_p) == NULL) {
|
||||
@@ -3950,18 +3961,30 @@ int build_stl_str_hl(
|
||||
}
|
||||
case STL_VIM_EXPR: // '{'
|
||||
{
|
||||
char_u *block_start = fmt_p - 1;
|
||||
int reevaluate = (*fmt_p == '%');
|
||||
itemisflag = true;
|
||||
|
||||
if (reevaluate) {
|
||||
fmt_p++;
|
||||
}
|
||||
|
||||
// Attempt to copy the expression to evaluate into
|
||||
// the output buffer as a null-terminated string.
|
||||
char_u *t = out_p;
|
||||
while (*fmt_p != '}' && *fmt_p != NUL && out_p < out_end_p)
|
||||
while ((*fmt_p != '}' || (reevaluate && fmt_p[-1] != '%'))
|
||||
&& *fmt_p != NUL && out_p < out_end_p) {
|
||||
*out_p++ = *fmt_p++;
|
||||
}
|
||||
if (*fmt_p != '}') { // missing '}' or out of space
|
||||
break;
|
||||
}
|
||||
fmt_p++;
|
||||
*out_p = 0;
|
||||
if (reevaluate) {
|
||||
out_p[-1] = 0; // remove the % at the end of %{% expr %}
|
||||
} else {
|
||||
*out_p = 0;
|
||||
}
|
||||
|
||||
// Move our position in the output buffer
|
||||
// to the beginning of the expression
|
||||
@@ -4007,6 +4030,40 @@ int build_stl_str_hl(
|
||||
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 *)fmt_p);
|
||||
size_t new_fmt_len = parsed_usefmt
|
||||
+ str_length + fmt_length + 3;
|
||||
char_u *new_fmt = (char_u *)xmalloc(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 , fmt_p, fmt_length)
|
||||
+ fmt_length;
|
||||
*new_fmt_p = 0;
|
||||
new_fmt_p = NULL;
|
||||
|
||||
if (usefmt != fmt) {
|
||||
xfree(usefmt);
|
||||
}
|
||||
XFREE_CLEAR(str);
|
||||
usefmt = new_fmt;
|
||||
fmt_p = usefmt + parsed_usefmt;
|
||||
evaldepth++;
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user