mirror of
https://github.com/neovim/neovim.git
synced 2026-08-27 01:21:48 +00:00
feat(options): add 'winpinned' to pin a window #39157
Problem: - Unable to "pin" a window to prevent closing without specifically being targeted. - :fclose closes hidden windows (even before visible windows). Solution: - Add 'winpinned' window-local option. When set, window is skipped by :fclose and :only. Pin the ui2 cmdline window (which should always be visible), so that it is not closed by :only/fclose. - Skip over hidden (and pinned) windows with :fclose. Co-authored-by: glepnir <glephunter@gmail.com>
This commit is contained in:
@@ -667,6 +667,7 @@ local function option_scope_doc(o)
|
||||
'syntax',
|
||||
'winfixheight',
|
||||
'winfixwidth',
|
||||
'winpinned',
|
||||
}, o.full_name)
|
||||
then
|
||||
r = r .. ' |local-noglobal|'
|
||||
|
||||
@@ -148,6 +148,8 @@ typedef struct {
|
||||
#define w_p_wfh w_onebuf_opt.wo_wfh // 'winfixheight'
|
||||
int wo_wfw;
|
||||
#define w_p_wfw w_onebuf_opt.wo_wfw // 'winfixwidth'
|
||||
int wo_wp;
|
||||
#define w_p_wp w_onebuf_opt.wo_wp // 'winpinned'
|
||||
int wo_pvw;
|
||||
#define w_p_pvw w_onebuf_opt.wo_pvw // 'previewwindow'
|
||||
OptInt wo_lhi;
|
||||
|
||||
@@ -5329,7 +5329,7 @@ void tabpage_close(int forceit)
|
||||
ex_win_close(forceit, curwin, NULL);
|
||||
}
|
||||
if (!ONE_WINDOW) {
|
||||
close_others(true, forceit);
|
||||
close_others(true, forceit, true);
|
||||
}
|
||||
if (ONE_WINDOW) {
|
||||
ex_win_close(forceit, curwin, NULL);
|
||||
@@ -5402,7 +5402,7 @@ static void ex_only(exarg_T *eap)
|
||||
win_goto(wp);
|
||||
}
|
||||
}
|
||||
close_others(true, eap->forceit);
|
||||
close_others(true, eap->forceit, false);
|
||||
}
|
||||
|
||||
static void ex_hide(exarg_T *eap)
|
||||
|
||||
@@ -4859,6 +4859,8 @@ void *get_varp_from(vimoption_T *p, buf_T *buf, win_T *win)
|
||||
return &(win->w_p_wfh);
|
||||
case kOptWinfixwidth:
|
||||
return &(win->w_p_wfw);
|
||||
case kOptWinpinned:
|
||||
return &(win->w_p_wp);
|
||||
case kOptPreviewwindow:
|
||||
return &(win->w_p_pvw);
|
||||
case kOptLhistory:
|
||||
|
||||
@@ -10713,6 +10713,19 @@ local options = {
|
||||
type = 'number',
|
||||
varname = 'p_wmw',
|
||||
},
|
||||
{
|
||||
abbreviation = 'wp',
|
||||
defaults = false,
|
||||
desc = [=[
|
||||
If enabled, the window is pinned and will not be closed by |:only|
|
||||
and |:fclose|. Only commands specifically targeting the window can
|
||||
close it.
|
||||
]=],
|
||||
full_name = 'winpinned',
|
||||
scope = { 'win' },
|
||||
short_desc = N_('prevent closing window with :only and :fclose'),
|
||||
type = 'boolean',
|
||||
},
|
||||
{
|
||||
abbreviation = 'wiw',
|
||||
cb = 'did_set_winwidth',
|
||||
|
||||
@@ -4248,10 +4248,12 @@ static int frame_minwidth(frame_T *topfrp, win_T *next_curwin)
|
||||
/// Buffers in the other windows become hidden if 'hidden' is set, or '!' is
|
||||
/// used and the buffer was modified.
|
||||
///
|
||||
/// Used by ":bdel" and ":only".
|
||||
/// Used by ":tabclose" and ":only".
|
||||
///
|
||||
/// @param forceit always hide all other windows
|
||||
void close_others(int message, int forceit)
|
||||
/// @param message if true, display error messages
|
||||
/// @param forceit always hide all other windows
|
||||
/// @param ignore_pinned if true, also close pinned windows (for :tabclose)
|
||||
void close_others(int message, int forceit, bool ignore_pinned)
|
||||
{
|
||||
win_T *const old_curwin = curwin;
|
||||
|
||||
@@ -4280,7 +4282,8 @@ void close_others(int message, int forceit)
|
||||
curbuf = curwin->w_buffer;
|
||||
}
|
||||
|
||||
if (wp == curwin) { // don't close current window
|
||||
// don't close current window or pinned windows
|
||||
if (wp == curwin || (wp->w_p_wp && !ignore_pinned)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -4312,7 +4315,17 @@ void close_others(int message, int forceit)
|
||||
}
|
||||
|
||||
if (message && !ONE_WINDOW) {
|
||||
emsg(_("E445: Other window contains changes"));
|
||||
// Check if remaining windows are non-pinned
|
||||
bool has_non_pinned = false;
|
||||
for (win_T *wp = firstwin; wp != NULL; wp = wp->w_next) {
|
||||
if (wp != curwin && !wp->w_p_wp) {
|
||||
has_non_pinned = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (has_non_pinned) {
|
||||
emsg(_("E445: Other window contains changes"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -298,6 +298,9 @@ void win_float_remove(bool bang, int count)
|
||||
{
|
||||
kvec_t(win_T *) float_win_arr = KV_INITIAL_VALUE;
|
||||
for (win_T *wp = lastwin; wp && wp->w_floating; wp = wp->w_prev) {
|
||||
if (wp->w_config.hide || wp->w_p_wp) {
|
||||
continue;
|
||||
}
|
||||
kv_push(float_win_arr, wp);
|
||||
}
|
||||
if (float_win_arr.size > 0) {
|
||||
|
||||
Reference in New Issue
Block a user