mirror of
https://github.com/neovim/neovim.git
synced 2025-09-05 19:08:15 +00:00
vim-patch:9.0.0844: handling 'statusline' errors is spread out (#20992)
Problem: Handling 'statusline' errors is spread out.
Solution: Pass the option name to the lower levels so the option can be
reset there when an error is encountered. (Luuk van Baal,
closes vim/vim#11467)
7b224fdf4a
This commit is contained in:
@@ -2223,7 +2223,8 @@ Dictionary nvim_eval_statusline(String str, Dict(eval_statusline) *opts, Error *
|
||||
buf,
|
||||
sizeof(buf),
|
||||
str.data,
|
||||
false,
|
||||
NULL,
|
||||
0,
|
||||
fillchar,
|
||||
maxwidth,
|
||||
hltab_ptr,
|
||||
|
@@ -3203,17 +3203,9 @@ void maketitle(void)
|
||||
|
||||
if (*p_titlestring != NUL) {
|
||||
if (stl_syntax & STL_IN_TITLE) {
|
||||
int use_sandbox = false;
|
||||
const int called_emsg_before = called_emsg;
|
||||
|
||||
use_sandbox = was_set_insecurely(curwin, "titlestring", 0);
|
||||
build_stl_str_hl(curwin, buf, sizeof(buf),
|
||||
p_titlestring, use_sandbox,
|
||||
0, maxlen, NULL, NULL);
|
||||
build_stl_str_hl(curwin, buf, sizeof(buf), p_titlestring,
|
||||
"titlestring", 0, 0, maxlen, NULL, NULL);
|
||||
title_str = buf;
|
||||
if (called_emsg > called_emsg_before) {
|
||||
set_string_option_direct("titlestring", -1, "", OPT_FREE, SID_ERROR);
|
||||
}
|
||||
} else {
|
||||
title_str = p_titlestring;
|
||||
}
|
||||
@@ -3317,16 +3309,8 @@ void maketitle(void)
|
||||
icon_str = buf;
|
||||
if (*p_iconstring != NUL) {
|
||||
if (stl_syntax & STL_IN_ICON) {
|
||||
int use_sandbox = false;
|
||||
const int called_emsg_before = called_emsg;
|
||||
|
||||
use_sandbox = was_set_insecurely(curwin, "iconstring", 0);
|
||||
build_stl_str_hl(curwin, icon_str, sizeof(buf),
|
||||
p_iconstring, use_sandbox,
|
||||
0, 0, NULL, NULL);
|
||||
if (called_emsg > called_emsg_before) {
|
||||
set_string_option_direct("iconstring", -1, "", OPT_FREE, SID_ERROR);
|
||||
}
|
||||
build_stl_str_hl(curwin, icon_str, sizeof(buf), p_iconstring,
|
||||
"iconstring", 0, 0, 0, NULL, NULL);
|
||||
} else {
|
||||
icon_str = p_iconstring;
|
||||
}
|
||||
|
@@ -522,7 +522,6 @@ static void prt_header(prt_settings_T *const psettings, const int pagenum, const
|
||||
|
||||
if (*p_header != NUL) {
|
||||
linenr_T tmp_lnum, tmp_topline, tmp_botline;
|
||||
int use_sandbox = false;
|
||||
|
||||
// Need to (temporarily) set current line number and first/last line
|
||||
// number on the 'window'. Since we don't know how long the page is,
|
||||
@@ -536,9 +535,8 @@ static void prt_header(prt_settings_T *const psettings, const int pagenum, const
|
||||
curwin->w_botline = lnum + 63;
|
||||
printer_page_num = pagenum;
|
||||
|
||||
use_sandbox = was_set_insecurely(curwin, "printheader", 0);
|
||||
build_stl_str_hl(curwin, (char *)tbuf, (size_t)width + IOSIZE,
|
||||
(char *)p_header, use_sandbox,
|
||||
(char *)p_header, "printheader", 0,
|
||||
' ', width, NULL, NULL);
|
||||
|
||||
// Reset line numbers
|
||||
|
@@ -999,16 +999,7 @@ void draw_tabline(void)
|
||||
|
||||
// Use the 'tabline' option if it's set.
|
||||
if (*p_tal != NUL) {
|
||||
int saved_did_emsg = did_emsg;
|
||||
|
||||
// Check for an error. If there is one we would loop in redrawing the
|
||||
// screen. Avoid that by making 'tabline' empty.
|
||||
did_emsg = false;
|
||||
win_redr_custom(NULL, false, false);
|
||||
if (did_emsg) {
|
||||
set_string_option_direct("tabline", -1, "", OPT_FREE, SID_ERROR);
|
||||
}
|
||||
did_emsg |= saved_did_emsg;
|
||||
} else {
|
||||
FOR_ALL_TABS(tp) {
|
||||
tabcount++;
|
||||
|
@@ -214,11 +214,7 @@ void win_redr_ruler(win_T *wp, bool always)
|
||||
}
|
||||
|
||||
if (*p_ruf && p_ch > 0 && !ui_has(kUIMessages)) {
|
||||
const int called_emsg_before = called_emsg;
|
||||
win_redr_custom(wp, false, true);
|
||||
if (called_emsg > called_emsg_before) {
|
||||
set_string_option_direct("rulerformat", -1, "", OPT_FREE, SID_ERROR);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -389,7 +385,6 @@ int fillchar_status(int *attr, win_T *wp)
|
||||
void redraw_custom_statusline(win_T *wp)
|
||||
{
|
||||
static bool entered = false;
|
||||
int saved_did_emsg = did_emsg;
|
||||
|
||||
// When called recursively return. This can happen when the statusline
|
||||
// contains an expression that triggers a redraw.
|
||||
@@ -398,17 +393,7 @@ void redraw_custom_statusline(win_T *wp)
|
||||
}
|
||||
entered = true;
|
||||
|
||||
did_emsg = false;
|
||||
win_redr_custom(wp, false, false);
|
||||
if (did_emsg) {
|
||||
// When there is an error disable the statusline, otherwise the
|
||||
// display is messed up with errors and a redraw triggers the problem
|
||||
// again and again.
|
||||
set_string_option_direct("statusline", -1, "",
|
||||
OPT_FREE | (*wp->w_p_stl != NUL
|
||||
? OPT_LOCAL : OPT_GLOBAL), SID_ERROR);
|
||||
}
|
||||
did_emsg |= saved_did_emsg;
|
||||
entered = false;
|
||||
}
|
||||
|
||||
@@ -429,9 +414,10 @@ void win_redr_custom(win_T *wp, bool draw_winbar, bool draw_ruler)
|
||||
char buf[MAXPATHL];
|
||||
char *stl;
|
||||
char *p;
|
||||
char *opt_name;
|
||||
int opt_scope = 0;
|
||||
stl_hlrec_t *hltab;
|
||||
StlClickRecord *tabtab;
|
||||
int use_sandbox = false;
|
||||
win_T *ewp;
|
||||
int p_crb_save;
|
||||
bool is_stl_global = global_stl_height() > 0;
|
||||
@@ -454,9 +440,11 @@ void win_redr_custom(win_T *wp, bool draw_winbar, bool draw_ruler)
|
||||
fillchar = ' ';
|
||||
attr = HL_ATTR(HLF_TPF);
|
||||
maxwidth = Columns;
|
||||
use_sandbox = was_set_insecurely(wp, "tabline", 0);
|
||||
opt_name = "tabline";
|
||||
} else if (draw_winbar) {
|
||||
opt_name = "winbar";
|
||||
stl = ((*wp->w_p_wbr != NUL) ? wp->w_p_wbr : p_wbr);
|
||||
opt_scope = ((*wp->w_p_wbr != NUL) ? OPT_LOCAL : 0);
|
||||
row = -1; // row zero is first row of text
|
||||
col = 0;
|
||||
grid = &wp->w_grid;
|
||||
@@ -469,7 +457,6 @@ void win_redr_custom(win_T *wp, bool draw_winbar, bool draw_ruler)
|
||||
fillchar = wp->w_p_fcs_chars.wbr;
|
||||
attr = (wp == curwin) ? win_hl_attr(wp, HLF_WBR) : win_hl_attr(wp, HLF_WBRNC);
|
||||
maxwidth = wp->w_width_inner;
|
||||
use_sandbox = was_set_insecurely(wp, "winbar", 0);
|
||||
stl_clear_click_defs(wp->w_winbar_click_defs, (long)wp->w_winbar_click_defs_size);
|
||||
wp->w_winbar_click_defs = stl_alloc_click_defs(wp->w_winbar_click_defs, maxwidth,
|
||||
&wp->w_winbar_click_defs_size);
|
||||
@@ -483,6 +470,7 @@ void win_redr_custom(win_T *wp, bool draw_winbar, bool draw_ruler)
|
||||
|
||||
if (draw_ruler) {
|
||||
stl = p_ruf;
|
||||
opt_name = "rulerformat";
|
||||
// advance past any leading group spec - implicit in ru_col
|
||||
if (*stl == '%') {
|
||||
if (*++stl == '-') {
|
||||
@@ -509,15 +497,10 @@ void win_redr_custom(win_T *wp, bool draw_winbar, bool draw_ruler)
|
||||
fillchar = ' ';
|
||||
attr = HL_ATTR(HLF_MSG);
|
||||
}
|
||||
|
||||
use_sandbox = was_set_insecurely(wp, "rulerformat", 0);
|
||||
} else {
|
||||
if (*wp->w_p_stl != NUL) {
|
||||
stl = wp->w_p_stl;
|
||||
} else {
|
||||
stl = p_stl;
|
||||
}
|
||||
use_sandbox = was_set_insecurely(wp, "statusline", *wp->w_p_stl == NUL ? 0 : OPT_LOCAL);
|
||||
opt_name = "statusline";
|
||||
stl = ((*wp->w_p_stl != NUL) ? wp->w_p_stl : p_stl);
|
||||
opt_scope = ((*wp->w_p_stl != NUL) ? OPT_LOCAL : 0);
|
||||
}
|
||||
|
||||
col += is_stl_global ? 0 : wp->w_wincol;
|
||||
@@ -536,9 +519,8 @@ void win_redr_custom(win_T *wp, bool draw_winbar, bool draw_ruler)
|
||||
// Make a copy, because the statusline may include a function call that
|
||||
// might change the option value and free the memory.
|
||||
stl = xstrdup(stl);
|
||||
width =
|
||||
build_stl_str_hl(ewp, buf, sizeof(buf), stl, use_sandbox,
|
||||
fillchar, maxwidth, &hltab, &tabtab);
|
||||
width = build_stl_str_hl(ewp, buf, sizeof(buf), stl, opt_name,
|
||||
opt_scope, fillchar, maxwidth, &hltab, &tabtab);
|
||||
xfree(stl);
|
||||
ewp->w_p_crb = p_crb_save;
|
||||
|
||||
@@ -611,15 +593,16 @@ theend:
|
||||
/// Note: This should not be NameBuff
|
||||
/// @param outlen The length of the output buffer
|
||||
/// @param fmt The statusline format string
|
||||
/// @param use_sandbox Use a sandboxed environment when evaluating fmt
|
||||
/// @param opt_name The option name corresponding to "fmt"
|
||||
/// @param opt_scope The scope corresponding to "opt_name"
|
||||
/// @param fillchar Character to use when filling empty space in the statusline
|
||||
/// @param maxwidth The maximum width to make the statusline
|
||||
/// @param hltab HL attributes (can be NULL)
|
||||
/// @param tabtab Tab clicks definition (can be NULL).
|
||||
///
|
||||
/// @return The final width of the statusline
|
||||
int build_stl_str_hl(win_T *wp, char *out, size_t outlen, char *fmt, int use_sandbox, int fillchar,
|
||||
int maxwidth, stl_hlrec_t **hltab, StlClickRecord **tabtab)
|
||||
int build_stl_str_hl(win_T *wp, char *out, size_t outlen, char *fmt, char *opt_name, int opt_scope,
|
||||
int fillchar, int maxwidth, stl_hlrec_t **hltab, StlClickRecord **tabtab)
|
||||
{
|
||||
static size_t stl_items_len = 20; // Initial value, grows as needed.
|
||||
static stl_item_t *stl_items = NULL;
|
||||
@@ -634,6 +617,10 @@ int build_stl_str_hl(win_T *wp, char *out, size_t outlen, char *fmt, int use_san
|
||||
char *usefmt = fmt;
|
||||
const int save_must_redraw = must_redraw;
|
||||
const int save_redr_type = curwin->w_redr_type;
|
||||
// TODO(Bram): find out why using called_emsg_before makes tests fail, does it
|
||||
// matter?
|
||||
// const int called_emsg_before = called_emsg;
|
||||
const int did_emsg_before = did_emsg;
|
||||
|
||||
if (stl_items == NULL) {
|
||||
stl_items = xmalloc(sizeof(stl_item_t) * stl_items_len);
|
||||
@@ -647,6 +634,11 @@ int build_stl_str_hl(win_T *wp, char *out, size_t outlen, char *fmt, int use_san
|
||||
stl_separator_locations = xmalloc(sizeof(int) * stl_items_len);
|
||||
}
|
||||
|
||||
// if "fmt" was set insecurely it needs to be evaluated in the sandbox
|
||||
// "opt_name" will be NULL when caller is nvim_eval_statusline()
|
||||
const int use_sandbox = opt_name ? was_set_insecurely(wp, opt_name, opt_scope)
|
||||
: false;
|
||||
|
||||
// When the format starts with "%!" then evaluate it as an expression and
|
||||
// use the result as the actual format string.
|
||||
if (fmt[0] == '%' && fmt[1] == '!') {
|
||||
@@ -1769,5 +1761,15 @@ int build_stl_str_hl(win_T *wp, char *out, size_t outlen, char *fmt, int use_san
|
||||
curwin->w_redr_type = save_redr_type;
|
||||
}
|
||||
|
||||
// Check for an error. If there is one the display will be messed up and
|
||||
// might loop redrawing. Avoid that by making the corresponding option
|
||||
// empty.
|
||||
// TODO(Bram): find out why using called_emsg_before makes tests fail, does it
|
||||
// matter?
|
||||
// if (called_emsg > called_emsg_before)
|
||||
if (opt_name && did_emsg > did_emsg_before) {
|
||||
set_string_option_direct(opt_name, -1, "", OPT_FREE | opt_scope, SID_ERROR);
|
||||
}
|
||||
|
||||
return width;
|
||||
}
|
||||
|
@@ -35,11 +35,12 @@ describe('ffi.cdef', function()
|
||||
|
||||
int build_stl_str_hl(
|
||||
win_T *wp,
|
||||
char_u *out,
|
||||
char *out,
|
||||
size_t outlen,
|
||||
char_u *fmt,
|
||||
int use_sandbox,
|
||||
char_u fillchar,
|
||||
char *fmt,
|
||||
char *opt_name,
|
||||
int opt_scope,
|
||||
int fillchar,
|
||||
int maxwidth,
|
||||
stl_hlrec_t **hltab,
|
||||
StlClickRecord **tabtab
|
||||
@@ -48,9 +49,10 @@ describe('ffi.cdef', function()
|
||||
|
||||
return ffi.C.build_stl_str_hl(
|
||||
ffi.C.find_window_by_handle(0, ffi.new('Error')),
|
||||
ffi.new('char_u[1024]'),
|
||||
ffi.new('char[1024]'),
|
||||
1024,
|
||||
ffi.cast('char_u*', 'StatusLineOfLength20'),
|
||||
ffi.cast('char*', 'StatusLineOfLength20'),
|
||||
nil,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
|
@@ -233,7 +233,8 @@ describe('buffer functions', function()
|
||||
output_buffer,
|
||||
buffer_byte_size,
|
||||
to_cstr(pat),
|
||||
false,
|
||||
NULL,
|
||||
0,
|
||||
fillchar,
|
||||
maximum_cell_count,
|
||||
NULL,
|
||||
|
Reference in New Issue
Block a user