From 11b9e6f193454fbdf2c48b2771ada478b5da26d7 Mon Sep 17 00:00:00 2001 From: glepnir Date: Fri, 5 Jun 2026 18:37:07 +0800 Subject: [PATCH] fix(option): allow empty/blank edges in 'winborder' #40112 Problem: The comma form of 'winborder' is split with copy_option_part(), whose skip_to_option_part() eats spaces after a comma, and empty fields are rejected. Solution: Split the comma form literally on ',', keeping empty fields and single-space fields. --- runtime/doc/options.txt | 9 ++++++--- runtime/lua/vim/_meta/options.gen.lua | 9 ++++++--- src/nvim/api/win_config.c | 25 +++++++++---------------- src/nvim/options.lua | 9 ++++++--- test/functional/ui/float_spec.lua | 12 +++++++++++- 5 files changed, 38 insertions(+), 26 deletions(-) diff --git a/runtime/doc/options.txt b/runtime/doc/options.txt index d439b34f6d..1e3b9ed804 100644 --- a/runtime/doc/options.txt +++ b/runtime/doc/options.txt @@ -7579,9 +7579,12 @@ A jump table for the options with a short description can be found at |Q_op|. - "shadow": Drop shadow effect, by blending with the background. - "single": Single-line box. - "solid": Adds padding by a single whitespace cell. - - custom: comma-separated list of exactly 8 characters in clockwise - order starting from topleft. Example: >lua - vim.o.winborder='+,-,+,|,+,-,+,|' + - custom: comma-separated list of exactly 8 entries in clockwise + order starting from topleft. Each entry may be a single char, a + single space (filled with the background), or empty (no border on + that side). Example: >lua + vim.o.winborder = '+,-,+,|,+,-,+,|' + vim.o.winborder = ',,, ,,,, ' -- left/right padding only < *'window'* *'wi'* diff --git a/runtime/lua/vim/_meta/options.gen.lua b/runtime/lua/vim/_meta/options.gen.lua index 520abbd8a6..60ee5a71ae 100644 --- a/runtime/lua/vim/_meta/options.gen.lua +++ b/runtime/lua/vim/_meta/options.gen.lua @@ -8256,11 +8256,14 @@ vim.wo.winbl = vim.wo.winblend --- - "shadow": Drop shadow effect, by blending with the background. --- - "single": Single-line box. --- - "solid": Adds padding by a single whitespace cell. ---- - custom: comma-separated list of exactly 8 characters in clockwise ---- order starting from topleft. Example: +--- - custom: comma-separated list of exactly 8 entries in clockwise +--- order starting from topleft. Each entry may be a single char, a +--- single space (filled with the background), or empty (no border on +--- that side). Example: --- --- ```lua ---- vim.o.winborder='+,-,+,`,+,-,+,`' +--- vim.o.winborder = '+,-,+,`,+,-,+,`' +--- vim.o.winborder = ',,, ,,,, ' -- left/right padding only --- ``` --- --- diff --git a/src/nvim/api/win_config.c b/src/nvim/api/win_config.c index 5983dda869..880b716e03 100644 --- a/src/nvim/api/win_config.c +++ b/src/nvim/api/win_config.c @@ -1213,27 +1213,20 @@ bool parse_winborder(WinConfig *fconfig, char *border_opt, Error *err) if (strchr(border_opt, ',')) { Array border_chars = ARRAY_DICT_INIT; char *p = border_opt; - char part[MAX_SCHAR_SIZE] = { 0 }; - int count = 0; - - while (*p != NUL) { - if (count >= 8) { + while (true) { + if (border_chars.size >= 8) { api_free_array(border_chars); return false; } - - size_t part_len = copy_option_part(&p, part, sizeof(part), ","); - if (part_len == 0 || part[0] == NUL) { - api_free_array(border_chars); - return false; + char *comma = strchr(p, ','); + size_t part_len = comma != NULL ? (size_t)(comma - p) : strlen(p); + ADD(border_chars, STRING_OBJ(cbuf_to_string(p, part_len))); + if (comma == NULL) { + break; } - - String str = cstr_to_string(part); - ADD(border_chars, STRING_OBJ(str)); - count++; + p = comma + 1; } - - if (count != 8) { + if (border_chars.size != 8) { api_free_array(border_chars); return false; } diff --git a/src/nvim/options.lua b/src/nvim/options.lua index 076e6a6d4d..295af7a334 100644 --- a/src/nvim/options.lua +++ b/src/nvim/options.lua @@ -10602,9 +10602,12 @@ local options = { - "shadow": Drop shadow effect, by blending with the background. - "single": Single-line box. - "solid": Adds padding by a single whitespace cell. - - custom: comma-separated list of exactly 8 characters in clockwise - order starting from topleft. Example: >lua - vim.o.winborder='+,-,+,|,+,-,+,|' + - custom: comma-separated list of exactly 8 entries in clockwise + order starting from topleft. Each entry may be a single char, a + single space (filled with the background), or empty (no border on + that side). Example: >lua + vim.o.winborder = '+,-,+,|,+,-,+,|' + vim.o.winborder = ',,, ,,,, ' -- left/right padding only < ]=], short_desc = N_('border of floating window'), diff --git a/test/functional/ui/float_spec.lua b/test/functional/ui/float_spec.lua index 0dc8e8a479..b62b2af9bd 100644 --- a/test/functional/ui/float_spec.lua +++ b/test/functional/ui/float_spec.lua @@ -11478,8 +11478,18 @@ describe('float window', function() winid = api.nvim_open_win(buf, false, config) eq('●', api.nvim_win_get_config(winid).border[1]) + -- Single-space border char. + command([[lua vim.opt.winborder=",,, ,,,, "]]) + winid = api.nvim_open_win(buf, false, config) + eq({ '', '', '', ' ', '', '', '', ' ' }, api.nvim_win_get_config(winid).border) + + -- Trailing comma hides the last side + command([[set winborder=+,-,+,\|,+,-,+,]]) + winid = api.nvim_open_win(buf, false, config) + eq({ '+', '-', '+', '|', '+', '-', '+', '' }, api.nvim_win_get_config(winid).border) + command('fclose!') + eq('Vim(set):E474: Invalid argument: winborder=,,', pcall_err(command, 'set winborder=,,')) - eq('Vim(set):E474: Invalid argument: winborder=+,-,+,|,+,-,+,', pcall_err(command, [[set winborder=+,-,+,\|,+,-,+,]])) eq('Vim(set):E474: Invalid argument: winborder=custom', pcall_err(command, 'set winborder=custom')) end)