mirror of
https://github.com/neovim/neovim.git
synced 2025-10-07 02:16:31 +00:00
vim-patch:9.1.1831: stray vseps in right-most 'winfixwidth' window
Problem: vertical separator of 'winfixwidth' windows may remain if they
become right-most windows from closing windows to the right.
Solution: Don't implicitly rely on frame_new_width to fix vseps, as the
call may be skipped for 'winfixwidth' windows to preserve
their width; do it explicitly in winframe_remove (Sean Dewar).
Note that I prefer win_new_width here over setting w_width directly, which
would've previously been done by win_split_ins after frame_add_vsep, as this
wasn't true for winframe_remove.
Though the equivalent issue of bottom 'winfixheight' windows leaving stray
statuslines with &ls=0 doesn't seem to exist, test it anyway.
closes: vim/vim#18481
620c655677
Nvim: calling win_new_width over setting w_width directly is especially
important in making sure stuff like w_view_width is correct here.
Co-authored-by: Sean Dewar <6256228+seandewar@users.noreply.github.com>
This commit is contained in:
@@ -1440,7 +1440,7 @@ win_T *win_split_ins(int size, int flags, win_T *new_wp, int dir, frame_T *to_fl
|
|||||||
}
|
}
|
||||||
if (toplevel) {
|
if (toplevel) {
|
||||||
if (flags & WSP_BOT) {
|
if (flags & WSP_BOT) {
|
||||||
frame_add_vsep(curfrp);
|
frame_set_vsep(curfrp, true);
|
||||||
}
|
}
|
||||||
// Set width of neighbor frame
|
// Set width of neighbor frame
|
||||||
frame_new_width(curfrp, curfrp->fr_width
|
frame_new_width(curfrp, curfrp->fr_width
|
||||||
@@ -3230,6 +3230,12 @@ win_T *winframe_remove(win_T *win, int *dirp, tabpage_T *tp, frame_T **unflat_al
|
|||||||
int row = topleft->w_winrow;
|
int row = topleft->w_winrow;
|
||||||
int col = topleft->w_wincol;
|
int col = topleft->w_wincol;
|
||||||
|
|
||||||
|
// If this is a rightmost window, remove vertical separators to the left.
|
||||||
|
if (win->w_vsep_width == 0 && frp_close->fr_parent->fr_layout == FR_ROW
|
||||||
|
&& frp_close->fr_prev != NULL) {
|
||||||
|
frame_set_vsep(frp_close->fr_prev, false);
|
||||||
|
}
|
||||||
|
|
||||||
// Remove this frame from the list of frames.
|
// Remove this frame from the list of frames.
|
||||||
frame_remove(frp_close);
|
frame_remove(frp_close);
|
||||||
|
|
||||||
@@ -3422,7 +3428,7 @@ void winframe_restore(win_T *wp, int dir, frame_T *unflat_altfr)
|
|||||||
|
|
||||||
// Vertical separators to the left may have been lost. Restore them.
|
// Vertical separators to the left may have been lost. Restore them.
|
||||||
if (wp->w_vsep_width == 0 && frp->fr_parent->fr_layout == FR_ROW && frp->fr_prev != NULL) {
|
if (wp->w_vsep_width == 0 && frp->fr_parent->fr_layout == FR_ROW && frp->fr_prev != NULL) {
|
||||||
frame_add_vsep(frp->fr_prev);
|
frame_set_vsep(frp->fr_prev, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Statuslines or horizontal separators above may have been lost. Restore them.
|
// Statuslines or horizontal separators above may have been lost. Restore them.
|
||||||
@@ -3868,23 +3874,26 @@ static void frame_new_width(frame_T *topfrp, int width, bool leftfirst, bool wfw
|
|||||||
topfrp->fr_width = width;
|
topfrp->fr_width = width;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Add the vertical separator to windows at the right side of "frp".
|
/// Add or remove the vertical separator of windows to the right side of "frp".
|
||||||
/// Note: Does not check if there is room!
|
/// Note: Does not check if there is room!
|
||||||
static void frame_add_vsep(const frame_T *frp)
|
static void frame_set_vsep(const frame_T *frp, bool add)
|
||||||
FUNC_ATTR_NONNULL_ARG(1)
|
FUNC_ATTR_NONNULL_ARG(1)
|
||||||
{
|
{
|
||||||
if (frp->fr_layout == FR_LEAF) {
|
if (frp->fr_layout == FR_LEAF) {
|
||||||
win_T *wp = frp->fr_win;
|
win_T *wp = frp->fr_win;
|
||||||
if (wp->w_vsep_width == 0) {
|
if (add && wp->w_vsep_width == 0) {
|
||||||
if (wp->w_width > 0) { // don't make it negative
|
if (wp->w_width > 0) { // don't make it negative
|
||||||
wp->w_width--;
|
win_new_width(wp, wp->w_width - 1);
|
||||||
}
|
}
|
||||||
wp->w_vsep_width = 1;
|
wp->w_vsep_width = 1;
|
||||||
|
} else if (!add && wp->w_vsep_width == 1) {
|
||||||
|
win_new_width(wp, wp->w_width + 1);
|
||||||
|
wp->w_vsep_width = 0;
|
||||||
}
|
}
|
||||||
} else if (frp->fr_layout == FR_COL) {
|
} else if (frp->fr_layout == FR_COL) {
|
||||||
// Handle all the frames in the column.
|
// Handle all the frames in the column.
|
||||||
FOR_ALL_FRAMES(frp, frp->fr_child) {
|
FOR_ALL_FRAMES(frp, frp->fr_child) {
|
||||||
frame_add_vsep(frp);
|
frame_set_vsep(frp, add);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
assert(frp->fr_layout == FR_ROW);
|
assert(frp->fr_layout == FR_ROW);
|
||||||
@@ -3893,7 +3902,7 @@ static void frame_add_vsep(const frame_T *frp)
|
|||||||
while (frp->fr_next != NULL) {
|
while (frp->fr_next != NULL) {
|
||||||
frp = frp->fr_next;
|
frp = frp->fr_next;
|
||||||
}
|
}
|
||||||
frame_add_vsep(frp);
|
frame_set_vsep(frp, add);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -1,11 +1,14 @@
|
|||||||
|
local t = require('test.testutil')
|
||||||
local n = require('test.functional.testnvim')()
|
local n = require('test.functional.testnvim')()
|
||||||
local Screen = require('test.functional.ui.screen')
|
local Screen = require('test.functional.ui.screen')
|
||||||
|
|
||||||
local clear = n.clear
|
local clear = n.clear
|
||||||
|
local eq = t.eq
|
||||||
local exec = n.exec
|
local exec = n.exec
|
||||||
local exec_lua = n.exec_lua
|
local exec_lua = n.exec_lua
|
||||||
local command = n.command
|
local command = n.command
|
||||||
local feed = n.feed
|
local feed = n.feed
|
||||||
|
local fn = n.fn
|
||||||
|
|
||||||
-- oldtest: Test_window_cmd_ls0_split_scrolling()
|
-- oldtest: Test_window_cmd_ls0_split_scrolling()
|
||||||
it('scrolling with laststatus=0 and :botright split', function()
|
it('scrolling with laststatus=0 and :botright split', function()
|
||||||
@@ -354,3 +357,53 @@ describe('splitkeep', function()
|
|||||||
]])
|
]])
|
||||||
end)
|
end)
|
||||||
end)
|
end)
|
||||||
|
|
||||||
|
-- oldtest: Test_winfixsize_vsep_statusline()
|
||||||
|
it("'winfixwidth/height' does not leave stray vseps/statuslines", function()
|
||||||
|
clear()
|
||||||
|
local screen = Screen.new(75, 8)
|
||||||
|
exec([[
|
||||||
|
set noequalalways splitbelow splitright
|
||||||
|
vsplit
|
||||||
|
setlocal winfixwidth
|
||||||
|
vsplit
|
||||||
|
]])
|
||||||
|
eq(16, fn.winwidth(1))
|
||||||
|
eq(37, fn.winwidth(2))
|
||||||
|
eq(20, fn.winwidth(3))
|
||||||
|
|
||||||
|
command('quit')
|
||||||
|
screen:expect([[
|
||||||
|
^ │ |
|
||||||
|
{1:~ }│{1:~ }|*5
|
||||||
|
{3:[No Name] }{2:[No Name] }|
|
||||||
|
|
|
||||||
|
]])
|
||||||
|
-- Checks w_view_width in Nvim; especially important as the screen test may still pass if only
|
||||||
|
-- w_width changed to make room for the vsep.
|
||||||
|
eq(36, fn.winwidth(1))
|
||||||
|
eq(38, fn.winwidth(2))
|
||||||
|
|
||||||
|
exec([[
|
||||||
|
set laststatus=0
|
||||||
|
only
|
||||||
|
split
|
||||||
|
set winfixheight
|
||||||
|
split
|
||||||
|
]])
|
||||||
|
eq(1, fn.winheight(1))
|
||||||
|
eq(3, fn.winheight(2))
|
||||||
|
eq(1, fn.winheight(3))
|
||||||
|
|
||||||
|
command('quit')
|
||||||
|
screen:expect([[
|
||||||
|
^ |
|
||||||
|
{1:~ }|
|
||||||
|
{3:[No Name] }|
|
||||||
|
|
|
||||||
|
{1:~ }|*3
|
||||||
|
|
|
||||||
|
]])
|
||||||
|
eq(2, fn.winheight(1))
|
||||||
|
eq(4, fn.winheight(2))
|
||||||
|
end)
|
||||||
|
@@ -2261,4 +2261,50 @@ func Test_winfixsize_positions()
|
|||||||
%bwipe
|
%bwipe
|
||||||
endfunc
|
endfunc
|
||||||
|
|
||||||
|
func Test_winfixsize_vsep_statusline()
|
||||||
|
CheckScreendump
|
||||||
|
let lines =<< trim END
|
||||||
|
set noequalalways splitbelow splitright
|
||||||
|
vsplit
|
||||||
|
setlocal winfixwidth
|
||||||
|
vsplit
|
||||||
|
func SetupWfh()
|
||||||
|
set laststatus=0
|
||||||
|
only
|
||||||
|
split
|
||||||
|
set winfixheight
|
||||||
|
split
|
||||||
|
endfunc
|
||||||
|
END
|
||||||
|
call writefile(lines, 'XTestWinfixsizeVsepStatusline', 'D')
|
||||||
|
let buf = RunVimInTerminal('-S XTestWinfixsizeVsepStatusline', #{rows: 8})
|
||||||
|
|
||||||
|
call term_sendkeys(buf, ":echo winwidth(1) winwidth(2) winwidth(3)\n")
|
||||||
|
call WaitForAssert({-> assert_match('^16 37 20\>', term_getline(buf, 8))})
|
||||||
|
|
||||||
|
call term_sendkeys(buf, ":quit\n")
|
||||||
|
call VerifyScreenDump(buf, 'Test_winfixsize_vsep_statusline_1', {})
|
||||||
|
|
||||||
|
" Reported widths should be consistent with the screen dump.
|
||||||
|
call term_sendkeys(buf, ":echo winwidth(1) winwidth(2)\n")
|
||||||
|
" (May be better if 'wfw' window remains at 37 columns, but the resize is
|
||||||
|
" consistent with how things currently work for 'winfix*' windows)
|
||||||
|
call WaitForAssert({-> assert_match('^36 38\>', term_getline(buf, 8))})
|
||||||
|
|
||||||
|
" For good measure, also check bottom-most 'winfixheight' windows don't leave
|
||||||
|
" stray statuslines with &laststatus=0.
|
||||||
|
call term_sendkeys(buf,
|
||||||
|
\ ":call SetupWfh() | echo winheight(1) winheight(2) winheight(3)\n")
|
||||||
|
call WaitForAssert({-> assert_match('^1 3 1\>', term_getline(buf, 8))})
|
||||||
|
|
||||||
|
call term_sendkeys(buf, ":quit\n")
|
||||||
|
call VerifyScreenDump(buf, 'Test_winfixsize_vsep_statusline_2', {})
|
||||||
|
|
||||||
|
call term_sendkeys(buf, ":echo winheight(1) winheight(2)\n")
|
||||||
|
" (Likewise, may be better if 'wfh' window remains at 3 rows)
|
||||||
|
call WaitForAssert({-> assert_match('^2 4\>', term_getline(buf, 8))})
|
||||||
|
|
||||||
|
call StopVimInTerminal(buf)
|
||||||
|
endfunc
|
||||||
|
|
||||||
" vim: shiftwidth=2 sts=2 expandtab
|
" vim: shiftwidth=2 sts=2 expandtab
|
||||||
|
Reference in New Issue
Block a user