aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFamiu Haque <famiuhaque@protonmail.com>2022-05-28 12:58:09 +0600
committerFamiu Haque <famiuhaque@protonmail.com>2022-05-28 15:29:56 +0600
commit9cf1ac037749bf3e32455627071cad4f83e5f6b7 (patch)
tree7a6dcd8ac935d06ae0d50284f4f162a3dd6c4f87
parent77d9c672f82d260dc5421519a2f78ed1acc95d6a (diff)
downloadrneovim-9cf1ac037749bf3e32455627071cad4f83e5f6b7.tar.gz
rneovim-9cf1ac037749bf3e32455627071cad4f83e5f6b7.tar.bz2
rneovim-9cf1ac037749bf3e32455627071cad4f83e5f6b7.zip
fix(winbar): only allow adding winbar when there is space
-rw-r--r--src/nvim/window.c60
-rw-r--r--test/functional/ui/winbar_spec.lua63
2 files changed, 115 insertions, 8 deletions
diff --git a/src/nvim/window.c b/src/nvim/window.c
index 58722b1756..060f498f07 100644
--- a/src/nvim/window.c
+++ b/src/nvim/window.c
@@ -6620,17 +6620,15 @@ static void win_remove_status_line(win_T *wp, bool add_hsep)
wp->w_status_click_defs = NULL;
}
-// Look for resizable frames and take lines from them to make room for the statusline
-static void resize_frame_for_status(frame_T *fr)
+// Look for a horizontally resizable frame, starting with frame "fr".
+// Returns NULL if there are no resizable frames.
+static frame_T *find_horizontally_resizable_frame(frame_T *fr)
{
- // Find a frame to take a line from.
frame_T *fp = fr;
- win_T *wp = fr->fr_win;
while (fp->fr_height <= frame_minheight(fp, NULL)) {
if (fp == topframe) {
- emsg(_(e_noroom));
- return;
+ return NULL;
}
// In a column of frames: go to frame above. If already at
// the top or in a row of frames: go to parent.
@@ -6640,13 +6638,49 @@ static void resize_frame_for_status(frame_T *fr)
fp = fp->fr_parent;
}
}
- if (fp != fr) {
+
+ return fp;
+}
+
+// Look for resizable frames and take lines from them to make room for the statusline.
+// @return Success or failure.
+static bool resize_frame_for_status(frame_T *fr)
+{
+ win_T *wp = fr->fr_win;
+ frame_T *fp = find_horizontally_resizable_frame(fr);
+
+ if (fp == NULL) {
+ emsg(_(e_noroom));
+ return false;
+ } else if (fp != fr) {
frame_new_height(fp, fp->fr_height - 1, false, false);
frame_fix_height(wp);
(void)win_comp_pos();
} else {
win_new_height(wp, wp->w_height - 1);
}
+
+ return true;
+}
+
+// Look for resizable frames and take lines from them to make room for the winbar.
+// @return Success or failure.
+static bool resize_frame_for_winbar(frame_T *fr)
+{
+ win_T *wp = fr->fr_win;
+ frame_T *fp = find_horizontally_resizable_frame(fr);
+
+ if (fp == NULL || fp == fr) {
+ emsg(_(e_noroom));
+ return false;
+ } else {
+ frame_new_height(fp, fp->fr_height - 1, false, false);
+ win_new_height(wp, wp->w_height + 1);
+ frame_fix_height(wp);
+ win_comp_pos();
+ }
+
+ return true;
}
static void last_status_rec(frame_T *fr, bool statusline, bool is_stl_global)
@@ -6664,7 +6698,9 @@ static void last_status_rec(frame_T *fr, bool statusline, bool is_stl_global)
} else if (wp->w_status_height == 0 && !is_stl_global && statusline) {
// Add statusline to window if needed
wp->w_status_height = STATUS_HEIGHT;
- resize_frame_for_status(fr);
+ if (!resize_frame_for_status(fr)) {
+ return;
+ }
comp_col();
}
} else if (wp->w_status_height != 0 && is_stl_global) {
@@ -6695,6 +6731,14 @@ void set_winbar(void)
: ((*p_wbr != NUL || *wp->w_p_wbr != NUL) ? 1 : 0);
if (wp->w_winbar_height != winbar_height) {
+ if (winbar_height == 1 && wp->w_height_inner <= 1) {
+ if (wp->w_floating) {
+ emsg(_(e_noroom));
+ continue;
+ } else if (!resize_frame_for_winbar(wp->w_frame)) {
+ return;
+ }
+ }
wp->w_winbar_height = winbar_height;
win_set_inner_size(wp);
wp->w_redr_status = wp->w_redr_status || winbar_height;
diff --git a/test/functional/ui/winbar_spec.lua b/test/functional/ui/winbar_spec.lua
index 476da0d19f..982d2d67fd 100644
--- a/test/functional/ui/winbar_spec.lua
+++ b/test/functional/ui/winbar_spec.lua
@@ -7,6 +7,7 @@ local meths = helpers.meths
local eq = helpers.eq
local poke_eventloop = helpers.poke_eventloop
local feed = helpers.feed
+local pcall_err = helpers.pcall_err
describe('winbar', function()
local screen
@@ -28,6 +29,7 @@ describe('winbar', function()
})
meths.set_option('winbar', 'Set Up The Bars')
end)
+
it('works', function()
screen:expect([[
{1:Set Up The Bars }|
@@ -45,6 +47,7 @@ describe('winbar', function()
|
]])
end)
+
it('works with custom \'fillchars\' value', function()
command('set fillchars=wbr:+')
screen:expect([[
@@ -63,6 +66,7 @@ describe('winbar', function()
|
]])
end)
+
it('works with custom highlight', function()
command('hi WinBar guifg=red')
screen:expect([[
@@ -81,6 +85,7 @@ describe('winbar', function()
|
]])
end)
+
it('works with splits', function()
command('hi WinBar guifg=red')
command('hi WinBarNC guifg=blue')
@@ -101,6 +106,7 @@ describe('winbar', function()
|
]])
end)
+
it('works when switching value of \'winbar\'', function()
command('belowright vsplit | split | split | set winbar=')
screen:expect([[
@@ -151,6 +157,7 @@ describe('winbar', function()
|
]])
end)
+
it('can be ruler', function()
insert [[
just some
@@ -204,6 +211,7 @@ describe('winbar', function()
|
]]}
end)
+
it('works with laststatus=3', function()
command('set laststatus=3')
screen:expect([[
@@ -495,4 +503,59 @@ describe('winbar', function()
|
]])
end)
+
+ it('properly resizes window when there is no space in it', function()
+ command('set winbar= | 1split')
+ screen:expect([[
+ ^ |
+ {4:[No Name] }|
+ |
+ {3:~ }|
+ {3:~ }|
+ {3:~ }|
+ {3:~ }|
+ {3:~ }|
+ {3:~ }|
+ {3:~ }|
+ {3:~ }|
+ {2:[No Name] }|
+ |
+ ]])
+ command('set winbar=a')
+ screen:expect([[
+ {1:a }|
+ ^ |
+ {4:[No Name] }|
+ {1:a }|
+ |
+ {3:~ }|
+ {3:~ }|
+ {3:~ }|
+ {3:~ }|
+ {3:~ }|
+ {3:~ }|
+ {2:[No Name] }|
+ |
+ ]])
+ end)
+
+ it('cannot be added unless there is room', function()
+ command('set winbar= | split | split | split | split | split')
+ screen:expect([[
+ ^ |
+ {4:[No Name] }|
+ |
+ {2:[No Name] }|
+ |
+ {2:[No Name] }|
+ |
+ {2:[No Name] }|
+ |
+ {2:[No Name] }|
+ |
+ {2:[No Name] }|
+ |
+ ]])
+ eq('Vim(set):E36: Not enough room', pcall_err(command, 'set winbar=test'))
+ end)
end)