fix(api): merge split window config only on success

Problem: nvim_win_set_config may merge configs despite failing to configure a
split, and without applying necessary side-effects (like setting style=minimal
options). Plus, autocommands may apply a different config after the merge,
causing side-effects to apply for an outdated config.

Solution: merge configs last, only on success. Include fields only relevant to
splits. Properly set _cmdline_offset for splits.

Maybe better to disallow _cmdline_offset for splits instead, as the pum is
relative to cmdline_row anyway? (I didn't want to change behaviour too much)

Also use expect_unchanged in an unrelated test to quash a warning.
This commit is contained in:
Sean Dewar
2026-03-07 12:12:02 +00:00
parent 65a1709112
commit 137d5ab01d
5 changed files with 71 additions and 21 deletions

View File

@@ -431,7 +431,6 @@ static bool win_config_split(win_T *win, Dict(win_config) *config, WinConfig *fc
fconfig->split = (old_split == kWinSplitBelow || p_sb) ? kWinSplitBelow : kWinSplitAbove;
}
}
merge_win_config(&win->w_config, *fconfig);
// If there's no "vertical" or "split" set, or if "split" is unchanged, then we can just change
// the size of the window.
@@ -605,6 +604,14 @@ resize:
if (HAS_KEY_X(config, height)) {
win_setheight_win(fconfig->height, win);
}
// Merge configs now. If previously a float, clear fields irrelevant to splits that `fconfig` may
// have shallowly copied; don't free them as win_split_ins handled that. If already a split,
// clearing isn't needed, as parse_win_config shouldn't allow setting irrelevant fields.
if (!was_split) {
clear_float_config(fconfig, false);
}
merge_win_config(&win->w_config, *fconfig);
return true;
#undef HAS_KEY_X
}
@@ -662,11 +669,9 @@ void nvim_win_set_config(Window window, Dict(win_config) *config, Error *err)
win_config_float(win, fconfig);
}
if (HAS_KEY_X(config, style)) {
if (fconfig.style == kWinStyleMinimal) {
win_set_minimal_style(win);
didset_window_options(win, true);
}
if (HAS_KEY_X(config, style) && fconfig.style == kWinStyleMinimal) {
win_set_minimal_style(win);
didset_window_options(win, true);
}
if (fconfig._cmdline_offset < INT_MAX) {
cmdline_win = win;