diff options
author | Famiu Haque <famiuhaque@protonmail.com> | 2022-05-28 12:58:09 +0600 |
---|---|---|
committer | Famiu Haque <famiuhaque@protonmail.com> | 2022-05-28 15:29:56 +0600 |
commit | 9cf1ac037749bf3e32455627071cad4f83e5f6b7 (patch) | |
tree | 7a6dcd8ac935d06ae0d50284f4f162a3dd6c4f87 | |
parent | 77d9c672f82d260dc5421519a2f78ed1acc95d6a (diff) | |
download | rneovim-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.c | 60 | ||||
-rw-r--r-- | test/functional/ui/winbar_spec.lua | 63 |
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) |