fix(highlight): use winhl=Foo:Bar even when Bar is empty

fixes #22906
This commit is contained in:
bfredl
2023-04-06 10:03:37 +02:00
parent 63bffae9e0
commit 0f42aa1f2a
6 changed files with 100 additions and 14 deletions

View File

@@ -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;
});

View File

@@ -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)) { \

View File

@@ -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;

View File

@@ -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) {