diff options
Diffstat (limited to 'src/nvim/highlight_group.c')
-rw-r--r-- | src/nvim/highlight_group.c | 132 |
1 files changed, 103 insertions, 29 deletions
diff --git a/src/nvim/highlight_group.c b/src/nvim/highlight_group.c index 77424de3b8..ed1f0185b7 100644 --- a/src/nvim/highlight_group.c +++ b/src/nvim/highlight_group.c @@ -79,6 +79,8 @@ typedef struct { int sg_rgb_sp_idx; ///< RGB special color index int sg_blend; ///< blend level (0-100 inclusive), -1 if unset + + int sg_parent; ///< parent of @nested.group } HlGroup; enum { @@ -183,6 +185,54 @@ static const char *highlight_init_both[] = { "default link DiagnosticSignWarn DiagnosticWarn", "default link DiagnosticSignInfo DiagnosticInfo", "default link DiagnosticSignHint DiagnosticHint", + + "default link @error Error", + "default link @text.underline Underlined", + "default link @todo Todo", + "default link @debug Debug", + + // Miscs + "default link @comment Comment", + "default link @punctuation Delimiter", + + // Constants + "default link @constant Constant", + "default link @constant.builtin Special", + "default link @constant.macro Define", + "default link @define Define", + "default link @macro Macro", + "default link @string String", + "default link @string.escape SpecialChar", + "default link @character Character", + "default link @character.special SpecialChar", + "default link @number Number", + "default link @boolean Boolean", + "default link @float Float", + + // Functions + "default link @function Function", + "default link @function.builtin Special", + "default link @function.macro Macro", + "default link @parameter Identifier", + "default link @method Function", + "default link @field Identifier", + "default link @property Identifier", + "default link @constructor Special", + + // Keywords + "default link @conditional Conditional", + "default link @repeat Repeat", + "default link @label Label", + "default link @operator Operator", + "default link @keyword Keyword", + "default link @exception Exception", + + "default link @type Type", + "default link @type.definition Typedef", + "default link @storageclass StorageClass", + "default link @structure Structure", + "default link @include Include", + "default link @preproc PreProc", NULL }; @@ -640,7 +690,7 @@ static int color_numbers_8[28] = { 0, 4, 2, 6, // Lookup the "cterm" value to be used for color with index "idx" in // color_names[]. -// "boldp" will be set to TRUE or FALSE for a foreground color when using 8 +// "boldp" will be set to kTrue or kFalse for a foreground color when using 8 // colors, otherwise it will be unchanged. int lookup_color(const int idx, const bool foreground, TriState *const boldp) { @@ -756,7 +806,7 @@ void set_hl_group(int id, HlAttrs attrs, Dict(highlight) *dict, int link_id) update: if (!updating_screen) { - redraw_all_later(NOT_VALID); + redraw_all_later(UPD_NOT_VALID); } need_highlight_changed = true; } @@ -802,14 +852,14 @@ void do_highlight(const char *line, const bool forceit, const bool init) } // Isolate the name. - name_end = (const char *)skiptowhite((const char_u *)line); + name_end = (const char *)skiptowhite(line); linep = (const char *)skipwhite(name_end); // Check for "default" argument. if (strncmp(line, "default", (size_t)(name_end - line)) == 0) { dodefault = true; line = linep; - name_end = (const char *)skiptowhite((const char_u *)line); + name_end = (const char *)skiptowhite(line); linep = (const char *)skipwhite(name_end); } @@ -841,9 +891,9 @@ void do_highlight(const char *line, const bool forceit, const bool init) int to_id; HlGroup *hlgroup = NULL; - from_end = (const char *)skiptowhite((const char_u *)from_start); + from_end = (const char *)skiptowhite(from_start); to_start = (const char *)skipwhite(from_end); - to_end = (const char *)skiptowhite((const char_u *)to_start); + to_end = (const char *)skiptowhite(to_start); if (ends_excmd((uint8_t)(*from_start)) || ends_excmd((uint8_t)(*to_start))) { @@ -893,7 +943,7 @@ void do_highlight(const char *line, const bool forceit, const bool init) hlgroup->sg_script_ctx.sc_lnum += SOURCING_LNUM; nlua_set_sctx(&hlgroup->sg_script_ctx); hlgroup->sg_cleared = false; - redraw_all_later(SOME_VALID); + redraw_all_later(UPD_SOME_VALID); // Only call highlight changed() once after multiple changes need_highlight_changed = true; @@ -916,10 +966,10 @@ void do_highlight(const char *line, const bool forceit, const bool init) } init_highlight(true, true); highlight_changed(); - redraw_all_later(NOT_VALID); + redraw_all_later(UPD_NOT_VALID); return; } - name_end = (const char *)skiptowhite((const char_u *)line); + name_end = (const char *)skiptowhite(line); linep = (const char *)skipwhite(name_end); } @@ -1004,7 +1054,7 @@ void do_highlight(const char *line, const bool forceit, const bool init) } } else { arg_start = linep; - linep = (const char *)skiptowhite((const char_u *)linep); + linep = (const char *)skiptowhite(linep); } if (linep == arg_start) { semsg(_("E417: missing argument: %s"), key_start); @@ -1156,7 +1206,7 @@ void do_highlight(const char *line, const bool forceit, const bool init) if (dark != -1 && dark != (*p_bg == 'd') && !option_was_set("bg")) { - set_option_value("bg", 0L, (dark ? "dark" : "light"), 0); + set_option_value_give_err("bg", 0L, (dark ? "dark" : "light"), 0); reset_option_was_set("bg"); } } @@ -1270,12 +1320,12 @@ void do_highlight(const char *line, const bool forceit, const bool init) // changed ui_refresh(); } else { - // TUI and newer UIs will repaint the screen themselves. NOT_VALID + // TUI and newer UIs will repaint the screen themselves. UPD_NOT_VALID // redraw below will still handle usages of guibg=fg etc. ui_default_colors_set(); } did_highlight_changed = true; - redraw_all_later(NOT_VALID); + redraw_all_later(UPD_NOT_VALID); } else { set_hl_attr(idx); } @@ -1292,7 +1342,7 @@ void do_highlight(const char *line, const bool forceit, const bool init) // redrawing. This may happen when evaluating 'statusline' changes the // StatusLine group. if (!updating_screen) { - redraw_all_later(NOT_VALID); + redraw_all_later(UPD_NOT_VALID); } need_highlight_changed = true; } @@ -1303,7 +1353,7 @@ void free_highlight(void) { ga_clear(&highlight_ga); map_destroy(cstr_t, int)(&highlight_unames); - arena_mem_free(arena_finish(&highlight_arena), NULL); + arena_mem_free(arena_finish(&highlight_arena)); } #endif @@ -1321,7 +1371,7 @@ void restore_cterm_colors(void) /// @param check_link if true also check for an existing link. /// -/// @return TRUE if highlight group "idx" has any settings. +/// @return true if highlight group "idx" has any settings. static int hl_has_settings(int idx, bool check_link) { return hl_table[idx].sg_cleared == 0 @@ -1371,7 +1421,12 @@ static void highlight_list_one(const int id) const HlGroup *sgp = &hl_table[id - 1]; // index is ID minus one bool didh = false; - if (message_filtered(sgp->sg_name)) { + if (message_filtered((char *)sgp->sg_name)) { + return; + } + + // don't list specialized groups if a parent is used instead + if (sgp->sg_parent && sgp->sg_cleared) { return; } @@ -1661,7 +1716,12 @@ static void set_hl_attr(int idx) int syn_name2id(const char *name) FUNC_ATTR_NONNULL_ALL { - return syn_name2id_len(name, STRLEN(name)); + if (name[0] == '@') { + // if we look up @aaa.bbb, we have to consider @aaa as well + return syn_check_group(name, strlen(name)); + } else { + return syn_name2id_len(name, STRLEN(name)); + } } /// Lookup a highlight group name and return its ID. @@ -1701,7 +1761,7 @@ int syn_name2attr(const char_u *name) return 0; } -/// Return TRUE if highlight group "name" exists. +/// Return true if highlight group "name" exists. int highlight_exists(const char *name) { return syn_name2id(name) > 0; @@ -1750,11 +1810,19 @@ static int syn_add_group(const char *name, size_t len) if (!vim_isprintc(c)) { emsg(_("E669: Unprintable character in group name")); return 0; - } else if (!ASCII_ISALNUM(c) && c != '_') { - // This is an error, but since there previously was no check only give a warning. + } else if (!ASCII_ISALNUM(c) && c != '_' && c != '.' && c != '@') { + // '.' and '@' are allowed characters for use with treesitter capture names. msg_source(HL_ATTR(HLF_W)); - msg(_("W18: Invalid character in group name")); - break; + emsg(_(e_highlight_group_name_invalid_char)); + return 0; + } + } + + int scoped_parent = 0; + if (len > 1 && name[0] == '@') { + char *delim = xmemrchr(name, '.', len); + if (delim) { + scoped_parent = syn_check_group(name, (size_t)(delim - name)); } } @@ -1783,6 +1851,9 @@ static int syn_add_group(const char *name, size_t len) hlgp->sg_rgb_sp_idx = kColorIdxNone; hlgp->sg_blend = -1; hlgp->sg_name_u = arena_memdupz(&highlight_arena, name, len); + hlgp->sg_parent = scoped_parent; + // will get set to false by caller if settings are added + hlgp->sg_cleared = true; vim_strup((char_u *)hlgp->sg_name_u); int id = highlight_ga.ga_len; // ID is index plus one @@ -1844,10 +1915,13 @@ int syn_ns_get_final_id(int *ns_id, int hl_id) continue; } - if (sgp->sg_link == 0 || sgp->sg_link > highlight_ga.ga_len) { + if (sgp->sg_link > 0 && sgp->sg_link <= highlight_ga.ga_len) { + hl_id = sgp->sg_link; + } else if (sgp->sg_cleared && sgp->sg_parent > 0) { + hl_id = sgp->sg_parent; + } else { break; } - hl_id = sgp->sg_link; } return hl_id; @@ -2000,13 +2074,13 @@ void set_context_in_highlight_cmd(expand_T *xp, const char *arg) // (part of) subcommand already typed if (*arg != NUL) { - const char *p = (const char *)skiptowhite((const char_u *)arg); + const char *p = (const char *)skiptowhite(arg); if (*p != NUL) { // Past "default" or group name. include_default = 0; if (strncmp("default", arg, (unsigned)(p - arg)) == 0) { arg = (const char *)skipwhite(p); xp->xp_pattern = (char *)arg; - p = (const char *)skiptowhite((const char_u *)arg); + p = (const char *)skiptowhite(arg); } if (*p != NUL) { // past group name include_link = 0; @@ -2016,10 +2090,10 @@ void set_context_in_highlight_cmd(expand_T *xp, const char *arg) if (strncmp("link", arg, (unsigned)(p - arg)) == 0 || strncmp("clear", arg, (unsigned)(p - arg)) == 0) { xp->xp_pattern = skipwhite(p); - p = (const char *)skiptowhite((char_u *)xp->xp_pattern); + p = (const char *)skiptowhite(xp->xp_pattern); if (*p != NUL) { // Past first group name. xp->xp_pattern = skipwhite(p); - p = (const char *)skiptowhite((char_u *)xp->xp_pattern); + p = (const char *)skiptowhite(xp->xp_pattern); } } if (*p != NUL) { // Past group name(s). |