diff options
author | bfredl <bjorn.linse@gmail.com> | 2023-04-06 10:03:37 +0200 |
---|---|---|
committer | bfredl <bjorn.linse@gmail.com> | 2023-04-06 17:15:16 +0200 |
commit | 0f42aa1f2a860ce6d72a825b397fe09c875613b5 (patch) | |
tree | 97e6ba7e8d23448ecabc9c43498e229e8bcbeb33 | |
parent | 63bffae9e0ba45a6d646f78dadd1e87c8497db78 (diff) | |
download | rneovim-0f42aa1f2a860ce6d72a825b397fe09c875613b5.tar.gz rneovim-0f42aa1f2a860ce6d72a825b397fe09c875613b5.tar.bz2 rneovim-0f42aa1f2a860ce6d72a825b397fe09c875613b5.zip |
fix(highlight): use winhl=Foo:Bar even when Bar is empty
fixes #22906
-rw-r--r-- | src/nvim/api/options.c | 4 | ||||
-rw-r--r-- | src/nvim/api/private/validate.h | 9 | ||||
-rw-r--r-- | src/nvim/highlight.c | 2 | ||||
-rw-r--r-- | src/nvim/highlight_group.c | 35 | ||||
-rw-r--r-- | test/functional/ui/float_spec.lua | 47 | ||||
-rw-r--r-- | test/functional/ui/highlight_spec.lua | 17 |
6 files changed, 100 insertions, 14 deletions
diff --git a/src/nvim/api/options.c b/src/nvim/api/options.c index baeb3e88fb..3e6466626f 100644 --- a/src/nvim/api/options.c +++ b/src/nvim/api/options.c @@ -53,7 +53,7 @@ static int validate_option_value_args(Dict(option) *opts, int *scope, int *opt_t } if (HAS_KEY(opts->win)) { - VALIDATE_T("win", kObjectTypeInteger, opts->win.type, { + VALIDATE_T_HANDLE("win", kObjectTypeWindow, opts->win.type, { return FAIL; }); @@ -65,7 +65,7 @@ static int validate_option_value_args(Dict(option) *opts, int *scope, int *opt_t } if (HAS_KEY(opts->buf)) { - VALIDATE_T("buf", kObjectTypeInteger, opts->buf.type, { + VALIDATE_T_HANDLE("buf", kObjectTypeBuffer, opts->buf.type, { return FAIL; }); diff --git a/src/nvim/api/private/validate.h b/src/nvim/api/private/validate.h index 91a92c2762..a3e77ea838 100644 --- a/src/nvim/api/private/validate.h +++ b/src/nvim/api/private/validate.h @@ -67,6 +67,15 @@ } \ } while (0) +/// Checks that actual_t is either the correct handle type or a type erased handle (integer) +#define VALIDATE_T_HANDLE(name, expected_t, actual_t, code) \ + do { \ + if (expected_t != actual_t && kObjectTypeInteger != actual_t) { \ + api_err_exp(err, name, api_typename(expected_t), api_typename(actual_t)); \ + code; \ + } \ + } while (0) + #define VALIDATE_RANGE(cond, name, code) \ do { \ if (!(cond)) { \ diff --git a/src/nvim/highlight.c b/src/nvim/highlight.c index 36da057ddc..f4d851cfec 100644 --- a/src/nvim/highlight.c +++ b/src/nvim/highlight.c @@ -303,7 +303,7 @@ int hl_get_ui_attr(int ns_id, int idx, int final_id, bool optional) bool available = false; if (final_id > 0) { - int syn_attr = syn_ns_id2attr(ns_id, final_id, optional); + int syn_attr = syn_ns_id2attr(ns_id, final_id, &optional); if (syn_attr > 0) { attrs = syn_attr2entry(syn_attr); available = true; diff --git a/src/nvim/highlight_group.c b/src/nvim/highlight_group.c index a954c14924..5d9148e992 100644 --- a/src/nvim/highlight_group.c +++ b/src/nvim/highlight_group.c @@ -1988,18 +1988,23 @@ static int syn_add_group(const char *name, size_t len) /// @see syn_attr2entry int syn_id2attr(int hl_id) { - return syn_ns_id2attr(-1, hl_id, false); + bool optional = false; + return syn_ns_id2attr(-1, hl_id, &optional); } -int syn_ns_id2attr(int ns_id, int hl_id, bool optional) +int syn_ns_id2attr(int ns_id, int hl_id, bool *optional) + FUNC_ATTR_NONNULL_ALL { - hl_id = syn_ns_get_final_id(&ns_id, hl_id); + if (syn_ns_get_final_id(&ns_id, &hl_id)) { + // If the namespace explicitly defines a group to be empty, it is not optional + *optional = false; + } HlGroup *sgp = &hl_table[hl_id - 1]; // index is ID minus one int attr = ns_get_hl(&ns_id, hl_id, false, sgp->sg_set); // if a highlight group is optional, don't use the global value - if (attr >= 0 || (optional && ns_id > 0)) { + if (attr >= 0 || (*optional && ns_id > 0)) { return attr; } return sgp->sg_attr; @@ -2008,16 +2013,20 @@ int syn_ns_id2attr(int ns_id, int hl_id, bool optional) /// Translate a group ID to the final group ID (following links). int syn_get_final_id(int hl_id) { - int id = curwin->w_ns_hl_active; - return syn_ns_get_final_id(&id, hl_id); + int ns_id = curwin->w_ns_hl_active; + syn_ns_get_final_id(&ns_id, &hl_id); + return hl_id; } -int syn_ns_get_final_id(int *ns_id, int hl_id) +bool syn_ns_get_final_id(int *ns_id, int *hl_idp) { int count; + int hl_id = *hl_idp; + bool used = false; if (hl_id > highlight_ga.ga_len || hl_id < 1) { - return 0; // Can be called from eval!! + *hl_idp = 0; + return false; // Can be called from eval!! } // Follow links until there is no more. @@ -2030,8 +2039,10 @@ int syn_ns_get_final_id(int *ns_id, int hl_id) // syn_id2attr time int check = ns_get_hl(ns_id, hl_id, true, sgp->sg_set); if (check == 0) { - return hl_id; // how dare! it broke the link! + *hl_idp = hl_id; + return true; // how dare! it broke the link! } else if (check > 0) { + used = true; hl_id = check; continue; } @@ -2045,7 +2056,8 @@ int syn_ns_get_final_id(int *ns_id, int hl_id) } } - return hl_id; + *hl_idp = hl_id; + return used; } /// Refresh the color attributes of all highlight groups. @@ -2128,7 +2140,8 @@ void highlight_changed(void) abort(); } int ns_id = -1; - int final_id = syn_ns_get_final_id(&ns_id, id); + int final_id = id; + syn_ns_get_final_id(&ns_id, &final_id); if (hlf == HLF_SNC) { id_SNC = final_id; } else if (hlf == HLF_S) { diff --git a/test/functional/ui/float_spec.lua b/test/functional/ui/float_spec.lua index 32f28dce26..890678e363 100644 --- a/test/functional/ui/float_spec.lua +++ b/test/functional/ui/float_spec.lua @@ -4935,6 +4935,53 @@ describe('float window', function() end) end) + it("can use Normal as background", function() + local buf = meths.create_buf(false,false) + meths.buf_set_lines(buf,0,-1,true,{"here", "float"}) + local win = meths.open_win(buf, false, {relative='editor', width=20, height=2, row=2, col=5}) + meths.set_option_value('winhl', 'Normal:Normal', {win=win}) + + if multigrid then + screen:expect{grid=[[ + ## grid 1 + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [3:----------------------------------------]| + ## grid 2 + ^ | + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + ## grid 3 + | + ## grid 5 + here | + float | + ]], float_pos={ + [5] = {{id = 1002}, "NW", 1, 2, 5, true, 50}; + }, win_viewport={ + [2] = {win = {id = 1000}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0}; + [5] = {win = {id = 1002}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 2, sum_scroll_delta = 0}; + }} + else + screen:expect{grid=[[ + ^ | + {0:~ }| + {0:~ }here {0: }| + {0:~ }float {0: }| + {0:~ }| + {0:~ }| + | + ]]} + end + end) + describe("handles :wincmd", function() local win local expected_pos diff --git a/test/functional/ui/highlight_spec.lua b/test/functional/ui/highlight_spec.lua index dce886ac91..fedfaca7ba 100644 --- a/test/functional/ui/highlight_spec.lua +++ b/test/functional/ui/highlight_spec.lua @@ -2432,6 +2432,23 @@ describe("'winhighlight' highlight", function() | ]]} end) + + it('can link to empty highlight group', function() + command 'hi NormalNC guibg=Red' -- czerwone time + command 'set winhl=NormalNC:Normal' + command 'split' + + screen:expect{grid=[[ + ^ | + {0:~ }| + {0:~ }| + {3:[No Name] }| + | + {0:~ }| + {4:[No Name] }| + | + ]]} + end) end) describe('highlight namespaces', function() |