This allows you to
:highlight link BoldComment Comment cterm=bold
It's the analog of the :syntax combine option.
This makes things much easier on color scheme designers. As in the above
example, they can create a base highlight group (Comment) and then link a
number of related groups to it with minor modifications (BoldComment, etc.).
If the user ever changes Comment's color, BoldComment's color changes too.
--
You received this message from the "vim_dev" maillist.
Do not top-post! Type your reply below the text you are replying to.
For more information, visit http://www.vim.org/maillist.php
diff --git a/runtime/doc/syntax.txt b/runtime/doc/syntax.txt
index a8a66a4..437cc73 100644
--- a/runtime/doc/syntax.txt
+++ b/runtime/doc/syntax.txt
@@ -4727,7 +4727,7 @@ group, and give the color attributes only for that group.
To set a link:
- :hi[ghlight][!] [default] link {from-group} {to-group}
+ :hi[ghlight][!] [default] link {from-group} {to-group} {key}={attr} ..
To remove a link:
@@ -4736,6 +4736,8 @@ To remove a link:
Notes: *E414*
- If the {from-group} and/or {to-group} doesn't exist, it is created. You
don't get an error message for a non-existing group.
+- Settings given in the {key}={attr} list take precedence over the same
+ variables set in {to-group}.
- As soon as you use a ":highlight" command for a linked group, the link is
removed.
- If there are already highlight settings for the {from-group}, the link is
diff --git a/src/syntax.c b/src/syntax.c
index abaa025..32258a9 100644
--- a/src/syntax.c
+++ b/src/syntax.c
@@ -59,10 +59,11 @@ struct hl_group
#endif
};
-#define SG_TERM 1 /* term has been set */
-#define SG_CTERM 2 /* cterm has been set */
-#define SG_GUI 4 /* gui has been set */
-#define SG_LINK 8 /* link has been set */
+#define SG_TERM 0x01 /* term has been set */
+#define SG_CTERM 0x02 /* cterm has been set */
+#define SG_GUI 0x04 /* gui has been set */
+#define SG_LINK 0x08 /* link has been set */
+#define SG_INHERIT 0x10 /* link has been set */
static garray_T highlight_ga; /* highlight groups for 'highlight' option */
@@ -4015,7 +4016,10 @@ syn_list_one(id, syncing, link_only)
if (HL_TABLE()[id - 1].sg_link && (did_header || link_only) && !got_int)
{
(void)syn_list_header(did_header, 999, id);
- msg_puts_attr((char_u *)"links to", attr);
+ if (HL_TABLE()[id - 1].sg_set & SG_INHERIT)
+ msg_puts_attr((char_u *)"inherits from", attr);
+ else
+ msg_puts_attr((char_u *)"links to", attr);
msg_putchar(' ');
msg_outtrans(HL_TABLE()[HL_TABLE()[id - 1].sg_link - 1].sg_name);
}
@@ -6931,71 +6935,6 @@ do_highlight(line, forceit, init)
return;
}
- /*
- * Handle ":highlight link {from} {to}" command.
- */
- if (dolink)
- {
- char_u *from_start = linep;
- char_u *from_end;
- char_u *to_start;
- char_u *to_end;
- int from_id;
- int to_id;
-
- from_end = skiptowhite(from_start);
- to_start = skipwhite(from_end);
- to_end = skiptowhite(to_start);
-
- if (ends_excmd(*from_start) || ends_excmd(*to_start))
- {
- EMSG2(_("E412: Not enough arguments: \":highlight link %s\""),
- from_start);
- return;
- }
-
- if (!ends_excmd(*skipwhite(to_end)))
- {
- EMSG2(_("E413: Too many arguments: \":highlight link %s\""), from_start);
- return;
- }
-
- from_id = syn_check_group(from_start, (int)(from_end - from_start));
- if (STRNCMP(to_start, "NONE", 4) == 0)
- to_id = 0;
- else
- to_id = syn_check_group(to_start, (int)(to_end - to_start));
-
- if (from_id > 0 && (!init || HL_TABLE()[from_id - 1].sg_set == 0))
- {
- /*
- * Don't allow a link when there already is some highlighting
- * for the group, unless '!' is used
- */
- if (to_id > 0 && !forceit && !init
- && hl_has_settings(from_id - 1, dodefault))
- {
- if (sourcing_name == NULL && !dodefault)
- EMSG(_("E414: group has settings, highlight link ignored"));
- }
- else
- {
- if (!init)
- HL_TABLE()[from_id - 1].sg_set |= SG_LINK;
- HL_TABLE()[from_id - 1].sg_link = to_id;
-#ifdef FEAT_EVAL
- HL_TABLE()[from_id - 1].sg_scriptID = current_SID;
-#endif
- redraw_all_later(SOME_VALID);
- }
- }
-
- /* Only call highlight_changed() once, after sourcing a syntax file */
- need_highlight_changed = TRUE;
-
- return;
- }
-
if (doclear)
{
/*
@@ -7074,7 +7013,18 @@ do_highlight(line, forceit, init)
/*
* Find the group name in the table. If it does not exist yet, add it.
*/
- id = syn_check_group(line, (int)(name_end - line));
+ if (dolink)
+ {
+ /*
+ * If we're linking the current name is 'link', not the highlight group.
+ * Isolate the actual highlight group.
+ */
+ name_end = skiptowhite(linep);
+ id = syn_check_group(linep, (int)(name_end - linep));
+ linep = skipwhite(name_end);
+ }
+ else
+ id = syn_check_group(line, (int)(name_end - line));
if (id == 0) /* failed (out of memory) */
return;
idx = id - 1; /* index is ID minus one */
@@ -7083,6 +7033,50 @@ do_highlight(line, forceit, init)
if (dodefault && hl_has_settings(idx, TRUE))
return;
+ /*
+ * Handle the 'highlight link {child} {parent}' command.
+ */
+ if (dolink)
+ {
+ char_u *parent_end;
+ int parent_id;
+
+ parent_end = skiptowhite(linep);
+
+ if (ends_excmd(*linep))
+ {
+ EMSG2(_("E412: Not enough arguments: \":highlight %s\""), line);
+ return;
+ }
+
+ if (STRNCMP(linep, "NONE", 4) == 0)
+ parent_id = 0;
+ else
+ parent_id = syn_check_group(linep, (int)(parent_end - linep));
+
+ if (!init || HL_TABLE()[idx].sg_set == 0)
+ {
+ /*
+ * Don't allow a link when there already is some highlighting
+ * for the group, unless '!' is used
+ */
+ if (parent_id > 0 && !forceit && !init
+ && hl_has_settings(idx, dodefault))
+ {
+ if (sourcing_name == NULL && !dodefault)
+ EMSG(_("E414: group has settings, highlight inherit ignored"));
+ }
+ else
+ {
+ if (!init)
+ HL_TABLE()[idx].sg_set |= SG_LINK;
+ HL_TABLE()[idx].sg_link = parent_id;
+ }
+ }
+
+ linep = skipwhite(parent_end);
+ }
+
if (STRCMP(HL_TABLE()[idx].sg_name_u, "NORMAL") == 0)
is_normal_group = TRUE;
#ifdef FEAT_GUI_X11
@@ -7698,10 +7692,13 @@ do_highlight(line, forceit, init)
}
/*
- * When highlighting has been given for a group, don't link it.
+ * When highlighting has been given for a group mark it as an inheritor.
*/
if (!init || !(HL_TABLE()[idx].sg_set & SG_LINK))
- HL_TABLE()[idx].sg_link = 0;
+ if (dolink)
+ HL_TABLE()[idx].sg_set |= SG_INHERIT;
+ else
+ HL_TABLE()[idx].sg_link = 0;
/*
* Continue with next argument.
@@ -8569,7 +8566,10 @@ highlight_list_one(id)
{
(void)syn_list_header(didh, 9999, id);
didh = TRUE;
- msg_puts_attr((char_u *)"links to", hl_attr(HLF_D));
+ if (sgp->sg_set & SG_INHERIT)
+ msg_puts_attr((char_u *)"inherits from", hl_attr(HLF_D));
+ else
+ msg_puts_attr((char_u *)"links to", hl_attr(HLF_D));
msg_putchar(' ');
msg_outtrans(HL_TABLE()[HL_TABLE()[id - 1].sg_link - 1].sg_name);
}
@@ -9074,6 +9074,28 @@ syn_unadd_group()
}
/*
+ * Helper function to get the appropriate attr from an hl_group.
+ */
+ int
+sg_getattr(sgp)
+ struct hl_group* sgp;
+{
+#ifdef FEAT_GUI
+ /*
+ * Only use GUI attr when the GUI is being used.
+ */
+ if (gui.in_use)
+ return sgp->sg_gui_attr;
+ else
+#endif
+ if (t_colors > 1)
+ return sgp->sg_cterm_attr;
+ else
+ return sgp->sg_term_attr;
+}
+
+
+/*
* Translate a group ID to highlight attributes.
*/
int
@@ -9082,23 +9104,28 @@ syn_id2attr(hl_id)
{
int attr;
struct hl_group *sgp;
+ int count;
hl_id = syn_get_final_id(hl_id);
sgp = &HL_TABLE()[hl_id - 1]; /* index is ID minus one */
-#ifdef FEAT_GUI
/*
- * Only use GUI attr when the GUI is being used.
+ * Accumulate attributes from all inheriting links up to the final link.
+ * Look out for loops! Break after 100 links.
*/
- if (gui.in_use)
- attr = sgp->sg_gui_attr;
+ if (sgp->sg_set & SG_INHERIT)
+ {
+ attr = 0;
+ for (count = 100; --count >= 0; )
+ {
+ attr = hl_combine_attr(sg_getattr(sgp), attr);
+ if (sgp->sg_link == 0 || sgp->sg_link > highlight_ga.ga_len)
+ break;
+ sgp = &HL_TABLE()[sgp->sg_link - 1];
+ }
+ }
else
-#endif
- if (t_colors > 1)
- attr = sgp->sg_cterm_attr;
- else
- attr = sgp->sg_term_attr;
-
+ attr = sg_getattr(sgp);
return attr;
}
@@ -9114,13 +9141,39 @@ syn_id2colors(hl_id, fgp, bgp)
guicolor_T *bgp;
{
struct hl_group *sgp;
+ int attr;
+ int count;
hl_id = syn_get_final_id(hl_id);
sgp = &HL_TABLE()[hl_id - 1]; /* index is ID minus one */
- *fgp = sgp->sg_gui_fg;
- *bgp = sgp->sg_gui_bg;
- return sgp->sg_gui;
+ /*
+ * If it's an inheritor group and some colors aren't set, keep looking up
+ * the chain for the colors.
+ * Look out for loops! Break after 100 links.
+ */
+ if (sgp->sg_set & SG_INHERIT)
+ {
+ attr = 0;
+ for (count = 100; --count >= 0; )
+ {
+ attr = hl_combine_attr(sgp->sg_gui, attr);
+ if (*fgp == INVALCOLOR)
+ *fgp = sgp->sg_gui_fg;
+ if (*bgp == INVALCOLOR)
+ *bgp = sgp->sg_gui_fg;
+ if (sgp->sg_link == 0 || sgp->sg_link > highlight_ga.ga_len)
+ break;
+ sgp = &HL_TABLE()[sgp->sg_link - 1];
+ }
+ }
+ else
+ {
+ *fgp = sgp->sg_gui_fg;
+ *bgp = sgp->sg_gui_bg;
+ attr = sgp->sg_gui;
+ }
+ return attr;
}
#endif
@@ -9144,7 +9197,8 @@ syn_get_final_id(hl_id)
for (count = 100; --count >= 0; )
{
sgp = &HL_TABLE()[hl_id - 1]; /* index is ID minus one */
- if (sgp->sg_link == 0 || sgp->sg_link > highlight_ga.ga_len)
+ if (sgp->sg_set & SG_INHERIT
+ || sgp->sg_link == 0 || sgp->sg_link > highlight_ga.ga_len)
break;
hl_id = sgp->sg_link;
}