diff options
| author | ZyX <kp-pav@yandex.ru> | 2017-12-03 16:49:30 +0300 | 
|---|---|---|
| committer | ZyX <kp-pav@yandex.ru> | 2017-12-03 16:49:30 +0300 | 
| commit | c49e22d3964d6c7ae1c24e8ad01b5fec4ca40b57 (patch) | |
| tree | b7e59c416d1435725c65f8952b6e55c70544d97e /src/nvim/syntax.c | |
| parent | 62108c3b0be46936c83f6d4c98b44ceb5e6f77fd (diff) | |
| parent | 27a577586eace687c47e7398845178208cae524a (diff) | |
| download | rneovim-c49e22d3964d6c7ae1c24e8ad01b5fec4ca40b57.tar.gz rneovim-c49e22d3964d6c7ae1c24e8ad01b5fec4ca40b57.tar.bz2 rneovim-c49e22d3964d6c7ae1c24e8ad01b5fec4ca40b57.zip  | |
Merge branch 'master' into s-dash-stdin
Diffstat (limited to 'src/nvim/syntax.c')
| -rw-r--r-- | src/nvim/syntax.c | 885 | 
1 files changed, 445 insertions, 440 deletions
diff --git a/src/nvim/syntax.c b/src/nvim/syntax.c index 0a27d9dd92..bc7362af72 100644 --- a/src/nvim/syntax.c +++ b/src/nvim/syntax.c @@ -1,3 +1,6 @@ +// This is an open source non-commercial project. Dear PVS-Studio, please check +// it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com +  /*   * syntax.c: code for syntax highlighting   */ @@ -39,42 +42,50 @@  #include "nvim/ui.h"  #include "nvim/os/os.h"  #include "nvim/os/time.h" +#include "nvim/api/private/helpers.h"  static bool did_syntax_onoff = false; -// Structure that stores information about a highlight group. -// The ID of a highlight group is also called group ID.  It is the index in -// the highlight_ga array PLUS ONE. +/// Structure that stores information about a highlight group. +/// The ID of a highlight group is also called group ID.  It is the index in +/// the highlight_ga array PLUS ONE.  struct hl_group { -  char_u      *sg_name;         // highlight group name -  char_u      *sg_name_u;       // uppercase of sg_name -  int sg_attr;                  // Screen attr -  int sg_link;                  // link to this highlight group ID -  int sg_set;                   // combination of SG_* flags -  scid_T sg_scriptID;           // script in which the group was last set +  char_u      *sg_name;         ///< highlight group name +  char_u      *sg_name_u;       ///< uppercase of sg_name +  int sg_attr;                  ///< Screen attr @see ATTR_ENTRY +  int sg_link;                  ///< link to this highlight group ID +  int sg_set;                   ///< combination of flags in \ref SG_SET +  scid_T sg_scriptID;           ///< script in which the group was last set    // for terminal UIs -  int sg_cterm;                 // "cterm=" highlighting attr -  int sg_cterm_fg;              // terminal fg color number + 1 -  int sg_cterm_bg;              // terminal bg color number + 1 -  int sg_cterm_bold;            // bold attr was set for light color +  int sg_cterm;                 ///< "cterm=" highlighting attr +  int sg_cterm_fg;              ///< terminal fg color number + 1 +  int sg_cterm_bg;              ///< terminal bg color number + 1 +  int sg_cterm_bold;            ///< bold attr was set for light color    // for RGB UIs -  int sg_gui;                   // "gui=" highlighting attributes -  RgbValue sg_rgb_fg;           // RGB foreground color -  RgbValue sg_rgb_bg;           // RGB background color -  RgbValue sg_rgb_sp;           // RGB special color -  uint8_t *sg_rgb_fg_name;      // RGB foreground color name -  uint8_t *sg_rgb_bg_name;      // RGB background color name -  uint8_t *sg_rgb_sp_name;      // RGB special color name +  int sg_gui;                   ///< "gui=" highlighting attributes +                                ///< (combination of \ref HL_ATTRIBUTES) +  RgbValue sg_rgb_fg;           ///< RGB foreground color +  RgbValue sg_rgb_bg;           ///< RGB background color +  RgbValue sg_rgb_sp;           ///< RGB special color +  uint8_t *sg_rgb_fg_name;      ///< RGB foreground color name +  uint8_t *sg_rgb_bg_name;      ///< RGB background color name +  uint8_t *sg_rgb_sp_name;      ///< RGB special color name  }; +/// \addtogroup SG_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 +/// @} -// highlight groups for 'highlight' option +// builtin |highlight-groups|  static garray_T highlight_ga = GA_EMPTY_INIT_VALUE; -#define HL_TABLE() ((struct hl_group *)((highlight_ga.ga_data))) +static inline struct hl_group * HL_TABLE(void) +{ +  return ((struct hl_group *)((highlight_ga.ga_data))); +}  #define MAX_HL_ID       20000   /* maximum value for a highlight ID. */ @@ -93,10 +104,8 @@ static int include_none = 0;    /* when 1 include "nvim/None" */  static int include_default = 0; /* when 1 include "nvim/default" */  static int include_link = 0;    /* when 2 include "nvim/link" and "clear" */ -/* - * The "term", "cterm" and "gui" arguments can be any combination of the - * following names, separated by commas (but no spaces!). - */ +/// The "term", "cterm" and "gui" arguments can be any combination of the +/// following names, separated by commas (but no spaces!).  static char *(hl_name_table[]) =  {"bold", "standout", "underline", "undercurl",   "italic", "reverse", "inverse", "NONE"}; @@ -302,6 +311,8 @@ static keyentry_T dumkey;  #define HIKEY2KE(p)   ((keyentry_T *)((p) - (dumkey.keyword - (char_u *)&dumkey)))  #define HI2KE(hi)      HIKEY2KE((hi)->hi_key) +// -V:HI2KE:782 +  /*   * To reduce the time spent in keepend(), remember at which level in the state   * stack the first item with "keepend" is present.  When "-1", there is no @@ -1406,14 +1417,14 @@ static int syn_stack_equal(synstate_T *sp)          /* If the pointer is different it can still be the           * same text.  Compare the strings, ignore case when           * the start item has the sp_ic flag set. */ -        if (bsx->matches[j] == NULL -            || six->matches[j] == NULL) +        if (bsx->matches[j] == NULL || six->matches[j] == NULL) {            break; -        if ((SYN_ITEMS(syn_block)[CUR_STATE(i).si_idx]).sp_ic -            ? mb_stricmp(bsx->matches[j], -                six->matches[j]) != 0 -            : STRCMP(bsx->matches[j], six->matches[j]) != 0) +        } +        if (mb_strcmp_ic((SYN_ITEMS(syn_block)[CUR_STATE(i).si_idx]).sp_ic, +                         (const char *)bsx->matches[j], +                         (const char *)six->matches[j]) != 0) {            break; +        }        }      }      if (j != NSUBEXP) @@ -1657,8 +1668,9 @@ syn_current_attr (       * If we found a match after the last column, use it.       */      if (next_match_idx >= 0 && next_match_col >= (int)current_col -        && next_match_col != MAXCOL) -      (void)push_next_match(NULL); +        && next_match_col != MAXCOL) { +      (void)push_next_match(); +    }      current_finished = TRUE;      current_state_stored = FALSE; @@ -1765,8 +1777,9 @@ syn_current_attr (                    cur_si->si_trans_id = CUR_STATE(                        current_state.ga_len - 2).si_trans_id;                  } -              } else +              } else {                  cur_si->si_attr = syn_id2attr(syn_id); +              }                cur_si->si_cont_list = NULL;                cur_si->si_next_list = next_list;                check_keepend(); @@ -1976,9 +1989,10 @@ syn_current_attr (               * endless loop). */              GA_APPEND(int, &zero_width_next_ga, next_match_idx);              next_match_idx = -1; -          } else -            cur_si = push_next_match(cur_si); -          found_match = TRUE; +          } else { +            cur_si = push_next_match(); +          } +          found_match = true;          }        }      } @@ -2158,9 +2172,10 @@ static int did_match_already(int idx, garray_T *gap)  /*   * Push the next match onto the stack.   */ -static stateitem_T *push_next_match(stateitem_T *cur_si) +static stateitem_T *push_next_match(void)  { -  synpat_T    *spp; +  stateitem_T *cur_si; +  synpat_T *spp;    int save_flags;    spp = &(SYN_ITEMS(syn_block)[next_match_idx]); @@ -3259,9 +3274,10 @@ static void syn_cmd_clear(exarg_T *eap, int syncing)        syntax_sync_clear();      else {        syntax_clear(curwin->w_s); -      if (curwin->w_s == &curwin->w_buffer->b_s) -        do_unlet((char_u *)"b:current_syntax", TRUE); -      do_unlet((char_u *)"w:current_syntax", TRUE); +      if (curwin->w_s == &curwin->w_buffer->b_s) { +        do_unlet(S_LEN("b:current_syntax"), true); +      } +      do_unlet(S_LEN("w:current_syntax"), true);      }    } else {      /* @@ -3337,7 +3353,7 @@ static void syn_cmd_enable(exarg_T *eap, int syncing)  {    set_internal_string_var((char_u *)"syntax_cmd", (char_u *)"enable");    syn_cmd_onoff(eap, "syntax"); -  do_unlet((char_u *)"g:syntax_cmd", TRUE); +  do_unlet(S_LEN("g:syntax_cmd"), true);  }  /* @@ -3350,7 +3366,7 @@ static void syn_cmd_reset(exarg_T *eap, int syncing)    if (!eap->skip) {      set_internal_string_var((char_u *)"syntax_cmd", (char_u *)"reset");      do_cmdline_cmd("runtime! syntax/syncolor.vim"); -    do_unlet((char_u *)"g:syntax_cmd", TRUE); +    do_unlet(S_LEN("g:syntax_cmd"), true);    }  } @@ -3993,10 +4009,10 @@ get_syn_options (  {    char_u      *gname_start, *gname;    int syn_id; -  int len; +  int len = 0;    char        *p;    int fidx; -  static struct flag { +  static const struct flag {      char    *name;      int argtype;      int flags; @@ -4019,7 +4035,7 @@ get_syn_options (                    {"cCoOnNtTaAiInNsS",        1,      0},                    {"cCoOnNtTaAiInNeEdDiInN",  2,      0},                    {"nNeExXtTgGrRoOuUpP",      3,      0},}; -  static char *first_letters = "cCoOkKeEtTsSgGdDfFnN"; +  static const char *const first_letters = "cCoOkKeEtTsSgGdDfFnN";    if (arg == NULL)              /* already detected error */      return NULL; @@ -4039,9 +4055,10 @@ get_syn_options (      for (fidx = ARRAY_SIZE(flagtab); --fidx >= 0; ) {        p = flagtab[fidx].name;        int i; -      for (i = 0, len = 0; p[i] != NUL; i += 2, ++len) +      for (i = 0, len = 0; p[i] != NUL; i += 2, ++len) {          if (arg[len] != p[i] && arg[len] != p[i + 1])            break; +      }        if (p[i] == NUL && (ascii_iswhite(arg[len])                            || (flagtab[fidx].argtype > 0                                ? arg[len] == '=' @@ -4241,83 +4258,81 @@ static void syn_cmd_keyword(exarg_T *eap, int syncing)    if (rest != NULL) {      syn_id = syn_check_group(arg, (int)(group_name_end - arg)); -    if (syn_id != 0) -      /* allocate a buffer, for removing backslashes in the keyword */ +    if (syn_id != 0) { +      // Allocate a buffer, for removing backslashes in the keyword.        keyword_copy = xmalloc(STRLEN(rest) + 1); -    syn_opt_arg.flags = 0; -    syn_opt_arg.keyword = TRUE; -    syn_opt_arg.sync_idx = NULL; -    syn_opt_arg.has_cont_list = FALSE; -    syn_opt_arg.cont_in_list = NULL; -    syn_opt_arg.next_list = NULL; - -    /* -     * The options given apply to ALL keywords, so all options must be -     * found before keywords can be created. -     * 1: collect the options and copy the keywords to keyword_copy. -     */ -    cnt = 0; -    p = keyword_copy; -    for (; rest != NULL && !ends_excmd(*rest); rest = skipwhite(rest)) { -      rest = get_syn_options(rest, &syn_opt_arg, &conceal_char); -      if (rest == NULL || ends_excmd(*rest)) -        break; -      /* Copy the keyword, removing backslashes, and add a NUL. */ -      while (*rest != NUL && !ascii_iswhite(*rest)) { -        if (*rest == '\\' && rest[1] != NUL) -          ++rest; -        *p++ = *rest++; -      } -      *p++ = NUL; -      ++cnt;      } +    if (keyword_copy != NULL) { +      syn_opt_arg.flags = 0; +      syn_opt_arg.keyword = true; +      syn_opt_arg.sync_idx = NULL; +      syn_opt_arg.has_cont_list = false; +      syn_opt_arg.cont_in_list = NULL; +      syn_opt_arg.next_list = NULL; + +      // The options given apply to ALL keywords, so all options must be +      // found before keywords can be created. +      // 1: collect the options and copy the keywords to keyword_copy. +      cnt = 0; +      p = keyword_copy; +      for (; rest != NULL && !ends_excmd(*rest); rest = skipwhite(rest)) { +        rest = get_syn_options(rest, &syn_opt_arg, &conceal_char); +        if (rest == NULL || ends_excmd(*rest)) { +          break; +        } +        // Copy the keyword, removing backslashes, and add a NUL. +        while (*rest != NUL && !ascii_iswhite(*rest)) { +          if (*rest == '\\' && rest[1] != NUL) { +            rest++; +          } +          *p++ = *rest++; +        } +        *p++ = NUL; +        cnt++; +      } -    if (!eap->skip) { -      /* Adjust flags for use of ":syn include". */ -      syn_incl_toplevel(syn_id, &syn_opt_arg.flags); +      if (!eap->skip) { +        // Adjust flags for use of ":syn include". +        syn_incl_toplevel(syn_id, &syn_opt_arg.flags); -      /* -       * 2: Add an entry for each keyword. -       */ -      for (kw = keyword_copy; --cnt >= 0; kw += STRLEN(kw) + 1) { -        for (p = vim_strchr(kw, '[');; ) { -          if (p != NULL) -            *p = NUL; -          add_keyword(kw, syn_id, syn_opt_arg.flags, -              syn_opt_arg.cont_in_list, -              syn_opt_arg.next_list, conceal_char); -          if (p == NULL) -            break; -          if (p[1] == NUL) { -            EMSG2(_("E789: Missing ']': %s"), kw); -            goto error; -          } -          if (p[1] == ']') { -            if (p[2] != NUL) { -              EMSG3(_("E890: trailing char after ']': %s]%s"), -                    kw, &p[2]); +        // 2: Add an entry for each keyword. +        for (kw = keyword_copy; --cnt >= 0; kw += STRLEN(kw) + 1) { +          for (p = vim_strchr(kw, '[');; ) { +            if (p != NULL) { +              *p = NUL; +            } +            add_keyword(kw, syn_id, syn_opt_arg.flags, +                        syn_opt_arg.cont_in_list, +                        syn_opt_arg.next_list, conceal_char); +            if (p == NULL) { +              break; +            } +            if (p[1] == NUL) { +              emsgf(_("E789: Missing ']': %s"), kw);                goto error;              } -            kw = p + 1; -            break;   // skip over the "]" -          } -          if (has_mbyte) { -            int l = (*mb_ptr2len)(p + 1); +            if (p[1] == ']') { +              if (p[2] != NUL) { +                emsgf(_("E890: trailing char after ']': %s]%s"), +                      kw, &p[2]); +                goto error; +              } +              kw = p + 1; +              break;   // skip over the "]" +            } +            const int l = (*mb_ptr2len)(p + 1);              memmove(p, p + 1, l);              p += l; -          } else { -            p[0] = p[1]; -            ++p;            }          }        } -    }  error: -    xfree(keyword_copy); -    xfree(syn_opt_arg.cont_in_list); -    xfree(syn_opt_arg.next_list); +      xfree(keyword_copy); +      xfree(syn_opt_arg.cont_in_list); +      xfree(syn_opt_arg.next_list); +    }    }    if (rest != NULL) @@ -5241,12 +5256,10 @@ get_id_list (          /*           * Handle full group name.           */ -        if (vim_strpbrk(name + 1, (char_u *)"\\.*^$~[") == NULL) +        if (vim_strpbrk(name + 1, (char_u *)"\\.*^$~[") == NULL) {            id = syn_check_group(name + 1, (int)(end - p)); -        else { -          /* -           * Handle match of regexp with group names. -           */ +        } else { +          // Handle match of regexp with group names.            *name = '^';            STRCAT(name, "$");            regmatch.regprog = vim_regcomp(name, RE_MAGIC); @@ -5537,10 +5550,10 @@ void ex_ownsyntax(exarg_T *eap)      set_internal_string_var((char_u *)"w:current_syntax", new_value);    } -  /* restore value of b:current_syntax */ -  if (old_value == NULL) -    do_unlet((char_u *)"b:current_syntax", TRUE); -  else { +  // Restore value of b:current_syntax. +  if (old_value == NULL) { +    do_unlet(S_LEN("b:current_syntax"), true); +  } else {      set_internal_string_var((char_u *)"b:current_syntax", old_value);      xfree(old_value);    } @@ -5556,8 +5569,10 @@ bool syntax_present(win_T *win)  static enum { -  EXP_SUBCMD,       /* expand ":syn" sub-commands */ -  EXP_CASE          /* expand ":syn case" arguments */ +  EXP_SUBCMD,       // expand ":syn" sub-commands +  EXP_CASE,         // expand ":syn case" arguments +  EXP_SPELL,        // expand ":syn spell" arguments +  EXP_SYNC          // expand ":syn sync" arguments  } expand_what;  /* @@ -5573,58 +5588,77 @@ void reset_expand_highlight(void)   * Handle command line completion for :match and :echohl command: Add "None"   * as highlight group.   */ -void set_context_in_echohl_cmd(expand_T *xp, char_u *arg) +void set_context_in_echohl_cmd(expand_T *xp, const char *arg)  {    xp->xp_context = EXPAND_HIGHLIGHT; -  xp->xp_pattern = arg; +  xp->xp_pattern = (char_u *)arg;    include_none = 1;  }  /*   * Handle command line completion for :syntax command.   */ -void set_context_in_syntax_cmd(expand_T *xp, char_u *arg) +void set_context_in_syntax_cmd(expand_T *xp, const char *arg)  { -  char_u      *p; - -  /* Default: expand subcommands */ +  // Default: expand subcommands.    xp->xp_context = EXPAND_SYNTAX;    expand_what = EXP_SUBCMD; -  xp->xp_pattern = arg; +  xp->xp_pattern = (char_u *)arg;    include_link = 0;    include_default = 0;    /* (part of) subcommand already typed */    if (*arg != NUL) { -    p = skiptowhite(arg); -    if (*p != NUL) {                /* past first word */ -      xp->xp_pattern = skipwhite(p); -      if (*skiptowhite(xp->xp_pattern) != NUL) +    const char *p = (const char *)skiptowhite((const char_u *)arg); +    if (*p != NUL) {  // Past first word. +      xp->xp_pattern = skipwhite((const char_u *)p); +      if (*skiptowhite(xp->xp_pattern) != NUL) {          xp->xp_context = EXPAND_NOTHING; -      else if (STRNICMP(arg, "case", p - arg) == 0) +      } else if (STRNICMP(arg, "case", p - arg) == 0) {          expand_what = EXP_CASE; -      else if (  STRNICMP(arg, "keyword", p - arg) == 0 +      } else if (STRNICMP(arg, "spell", p - arg) == 0) { +        expand_what = EXP_SPELL; +      } else if (STRNICMP(arg, "sync", p - arg) == 0) { +        expand_what = EXP_SYNC; +      } else if (STRNICMP(arg, "keyword", p - arg) == 0                   || STRNICMP(arg, "region", p - arg) == 0                   || STRNICMP(arg, "match", p - arg) == 0 -                 || STRNICMP(arg, "list", p - arg) == 0) +                 || STRNICMP(arg, "list", p - arg) == 0) {          xp->xp_context = EXPAND_HIGHLIGHT; -      else +      } else {          xp->xp_context = EXPAND_NOTHING; +      }      }    }  } -static char *(case_args[]) = {"match", "ignore", NULL}; -  /*   * Function given to ExpandGeneric() to obtain the list syntax names for   * expansion.   */  char_u *get_syntax_name(expand_T *xp, int idx)  { -  if (expand_what == EXP_SUBCMD) -    return (char_u *)subcommands[idx].name; -  return (char_u *)case_args[idx]; +  switch (expand_what) { +    case EXP_SUBCMD: +        return (char_u *)subcommands[idx].name; +    case EXP_CASE: { +        static char *case_args[] = { "match", "ignore", NULL }; +        return (char_u *)case_args[idx]; +    } +    case EXP_SPELL: { +        static char *spell_args[] = +        { "toplevel", "notoplevel", "default", NULL }; +        return (char_u *)spell_args[idx]; +    } +    case EXP_SYNC: { +        static char *sync_args[] = +        { "ccomment", "clear", "fromstart", +         "linebreaks=", "linecont", "lines=", "match", +         "maxlines=", "minlines=", "region", NULL }; +        return (char_u *)sync_args[idx]; +    } +  } +  return NULL;  } @@ -5835,9 +5869,12 @@ static void syntime_report(void)      }    } -  /* sort on total time */ -  qsort(ga.ga_data, (size_t)ga.ga_len, sizeof(time_entry_T), -      syn_compare_syntime); +  // Sort on total time. Skip if there are no items to avoid passing NULL +  // pointer to qsort(). +  if (ga.ga_len > 1) { +    qsort(ga.ga_data, (size_t)ga.ga_len, sizeof(time_entry_T), +          syn_compare_syntime); +  }    MSG_PUTS_TITLE(_(            "  TOTAL      COUNT  MATCH   SLOWEST     AVERAGE   NAME               PATTERN")); @@ -5896,6 +5933,8 @@ static void syntime_report(void)  static char *highlight_init_both[] =  {    "Conceal      ctermbg=DarkGrey ctermfg=LightGrey guibg=DarkGrey guifg=LightGrey", +  "Cursor       guibg=fg guifg=bg", +  "lCursor      guibg=fg guifg=bg",    "DiffText     cterm=bold ctermbg=Red gui=bold guibg=Red",    "ErrorMsg     ctermbg=DarkRed ctermfg=White guibg=Red guifg=White",    "IncSearch    cterm=reverse gui=reverse", @@ -5912,6 +5951,7 @@ static char *highlight_init_both[] =    "default link EndOfBuffer NonText",    "default link QuickFixLine Search",    "default link Substitute Search", +  "default link Whitespace NonText",    NULL  }; @@ -5945,6 +5985,7 @@ static char *highlight_init_light[] =    "Title        ctermfg=DarkMagenta gui=bold guifg=Magenta",    "Visual       guibg=LightGrey",    "WarningMsg   ctermfg=DarkRed guifg=Red", +  "Normal       gui=NONE",    NULL  }; @@ -5978,23 +6019,25 @@ static char *highlight_init_dark[] =    "Title        ctermfg=LightMagenta gui=bold guifg=Magenta",    "Visual       guibg=DarkGrey",    "WarningMsg   ctermfg=LightRed guifg=Red", +  "Normal       gui=NONE",    NULL  }; -void  -init_highlight ( -    int both,                   /* include groups where 'bg' doesn't matter */ -    int reset                  /* clear group first */ -) + +/// Load colors from a file if "g:colors_name" is set, otherwise load builtin +/// colors +/// +/// @param both include groups where 'bg' doesn't matter +/// @param reset clear groups first +void +init_highlight(int both, int reset)  {    int i;    char        **pp;    static int had_both = FALSE; -  /* -   * Try finding the color scheme file.  Used when a color file was loaded -   * and 'background' or 't_Co' is changed. -   */ +  // Try finding the color scheme file.  Used when a color file was loaded +  // and 'background' or 't_Co' is changed.    char_u *p = get_var_value("g:colors_name");    if (p != NULL) {      // Value of g:colors_name could be freed in load_colors() and make @@ -6013,33 +6056,34 @@ init_highlight (    if (both) {      had_both = TRUE;      pp = highlight_init_both; -    for (i = 0; pp[i] != NULL; ++i) -      do_highlight((char_u *)pp[i], reset, TRUE); -  } else if (!had_both) -    /* Don't do anything before the call with both == TRUE from main(). -     * Not everything has been setup then, and that call will overrule -     * everything anyway. */ +    for (i = 0; pp[i] != NULL; i++) { +      do_highlight((char_u *)pp[i], reset, true); +    } +  } else if (!had_both) { +    // Don't do anything before the call with both == TRUE from main(). +    // Not everything has been setup then, and that call will overrule +    // everything anyway.      return; +  } -  if (*p_bg == 'l') -    pp = highlight_init_light; -  else -    pp = highlight_init_dark; -  for (i = 0; pp[i] != NULL; ++i) -    do_highlight((char_u *)pp[i], reset, TRUE); +  pp = (*p_bg == 'l') ?  highlight_init_light : highlight_init_dark; + +  for (i = 0; pp[i] != NULL; i++) { +    do_highlight((char_u *)pp[i], reset, true); +  }    /* Reverse looks ugly, but grey may not work for 8 colors.  Thus let it     * depend on the number of colors available.     * With 8 colors brown is equal to yellow, need to use black for Search fg     * to avoid Statement highlighted text disappears.     * Clear the attributes, needed when changing the t_Co value. */ -  if (t_colors > 8) +  if (t_colors > 8) {      do_highlight(          (char_u *)(*p_bg == 'l'                     ? "Visual cterm=NONE ctermbg=LightGrey" -                   : "Visual cterm=NONE ctermbg=DarkGrey"), FALSE, -        TRUE); -  else { +                   : "Visual cterm=NONE ctermbg=DarkGrey"), false, +        true); +  } else {      do_highlight((char_u *)"Visual cterm=reverse ctermbg=NONE",          FALSE, TRUE);      if (*p_bg == 'l') @@ -6093,18 +6137,13 @@ int load_colors(char_u *name)    return retval;  } -/* - * Handle the ":highlight .." command. - * When using ":hi clear" this is called recursively for each group with - * "forceit" and "init" both TRUE. - */ -void  -do_highlight ( -    char_u *line, -    int forceit, -    int init                   /* TRUE when called for initializing */ -) -{ + +/// Handle the ":highlight .." command. +/// When using ":hi clear" this is called recursively for each group with +/// "forceit" and "init" both TRUE. +/// @param init TRUE when called for initializing +void +do_highlight(char_u *line, int forceit, int init) {    char_u      *name_end;    char_u      *linep;    char_u      *key_start; @@ -6121,15 +6160,16 @@ do_highlight (    int dolink = FALSE;    int error = FALSE;    int color; -  int is_normal_group = FALSE;                  /* "Normal" group */ +  bool is_normal_group = false;   // "Normal" group    /*     * If no argument, list current highlighting.     */    if (ends_excmd(*line)) { -    for (int i = 1; i <= highlight_ga.ga_len && !got_int; ++i) -      /* TODO: only call when the group has attributes set */ +    for (int i = 1; i <= highlight_ga.ga_len && !got_int; i++) { +      // todo(vim): only call when the group has attributes set        highlight_list_one(i); +    }      return;    } @@ -6231,7 +6271,7 @@ do_highlight (       */      line = linep;      if (ends_excmd(*line)) { -      do_unlet((char_u *)"colors_name", TRUE); +      do_unlet(S_LEN("colors_name"), true);        restore_cterm_colors();        /* @@ -6257,12 +6297,12 @@ do_highlight (      return;    idx = id - 1;                         /* index is ID minus one */ -  /* Return if "default" was used and the group already has settings. */ -  if (dodefault && hl_has_settings(idx, TRUE)) +  // Return if "default" was used and the group already has settings +  if (dodefault && hl_has_settings(idx, true)) {      return; +  } -  if (STRCMP(HL_TABLE()[idx].sg_name_u, "NORMAL") == 0) -    is_normal_group = TRUE; +  is_normal_group = (STRCMP(HL_TABLE()[idx].sg_name_u, "NORMAL") == 0);    /* Clear the highlighting for ":hi clear {group}" and ":hi clear". */    if (doclear || (forceit && init)) { @@ -6271,7 +6311,7 @@ do_highlight (        HL_TABLE()[idx].sg_set = 0;    } -  if (!doclear) +  if (!doclear) {      while (!ends_excmd(*linep)) {        key_start = linep;        if (*linep == '=') { @@ -6377,12 +6417,12 @@ do_highlight (            }          }        } else if (STRCMP(key, "FONT") == 0)   { -        /* in non-GUI fonts are simply ignored */ -      } else if (STRCMP(key, -                     "CTERMFG") == 0 || STRCMP(key, "CTERMBG") == 0)   { +        // in non-GUI fonts are simply ignored +      } else if (STRCMP(key, "CTERMFG") == 0 || STRCMP(key, "CTERMBG") == 0) {          if (!init || !(HL_TABLE()[idx].sg_set & SG_CTERM)) { -          if (!init) +          if (!init) {              HL_TABLE()[idx].sg_set |= SG_CTERM; +          }            /* When setting the foreground color, and previously the "bold"             * flag was set for a light color, reset it now */ @@ -6476,9 +6516,10 @@ do_highlight (                     * colors (on some terminals, e.g. "linux") */                    if (color & 8) {                      HL_TABLE()[idx].sg_cterm |= HL_BOLD; -                    HL_TABLE()[idx].sg_cterm_bold = TRUE; -                  } else +                    HL_TABLE()[idx].sg_cterm_bold = true; +                  } else {                      HL_TABLE()[idx].sg_cterm &= ~HL_BOLD; +                  }                  }                  color &= 7;             // truncate to 8 colors                } else if (t_colors == 16 || t_colors == 88 || t_colors >= 256) { @@ -6510,16 +6551,16 @@ do_highlight (                if (!ui_rgb_attached()) {                  must_redraw = CLEAR;                  if (color >= 0) { -                  if (t_colors < 16) +                  if (t_colors < 16) {                      i = (color == 0 || color == 4); -                  else +                  } else {                      i = (color < 7 || color == 8); -                  /* Set the 'background' option if the value is -                   * wrong. */ -                  if (i != (*p_bg == 'd')) -                    set_option_value((char_u *)"bg", 0L, -                        i ?  (char_u *)"dark" -                        : (char_u *)"light", 0); +                  } +                  // Set the 'background' option if the value is +                  // wrong. +                  if (i != (*p_bg == 'd')) { +                    set_option_value("bg", 0L, (i ? "dark" : "light"), 0); +                  }                  }                }              } @@ -6590,38 +6631,40 @@ do_highlight (        /*         * When highlighting has been given for a group, don't link it.         */ -      if (!init || !(HL_TABLE()[idx].sg_set & SG_LINK)) +      if (!init || !(HL_TABLE()[idx].sg_set & SG_LINK)) {          HL_TABLE()[idx].sg_link = 0; +      }        /*         * Continue with next argument.         */        linep = skipwhite(linep);      } +  }    /*     * If there is an error, and it's a new entry, remove it from the table.     */ -  if (error && idx == highlight_ga.ga_len) +  if (error && idx == highlight_ga.ga_len) {      syn_unadd_group(); -  else { -    if (is_normal_group) { -      HL_TABLE()[idx].sg_attr = 0; +  } else { +    if (!error && is_normal_group) {        // Need to update all groups, because they might be using "bg" and/or        // "fg", which have been changed now.        highlight_attr_set_all();        // If the normal group has changed, it is simpler to refresh every UI        ui_refresh(); -    } else +    } else {        set_hl_attr(idx); +    }      HL_TABLE()[idx].sg_scriptID = current_SID;      redraw_all_later(NOT_VALID);    }    xfree(key);    xfree(arg); -  /* Only call highlight_changed() once, after sourcing a syntax file */ -  need_highlight_changed = TRUE; +  // Only call highlight_changed() once, after sourcing a syntax file +  need_highlight_changed = true;  }  #if defined(EXITFREE) @@ -6694,22 +6737,21 @@ static void highlight_clear(int idx)  } -/* - * Table with the specifications for an attribute number. - * Note that this table is used by ALL buffers.  This is required because the - * GUI can redraw at any time for any buffer. - */ +/// Table with the specifications for an attribute number. +/// Note that this table is used by ALL buffers.  This is required because the +/// GUI can redraw at any time for any buffer.  static garray_T attr_table = GA_EMPTY_INIT_VALUE; -#define ATTR_ENTRY(idx) ((attrentry_T *)attr_table.ga_data)[idx] +static inline attrentry_T * ATTR_ENTRY(int idx) +{ +  return &((attrentry_T *)attr_table.ga_data)[idx]; +} -/* - * Return the attr number for a set of colors and font. - * Add a new entry to the term_attr_table, attr_table or gui_attr_table - * if the combination is new. - * Return 0 for error. - */ +/// Return the attr number for a set of colors and font. +/// Add a new entry to the term_attr_table, attr_table or gui_attr_table +/// if the combination is new. +/// @return 0 for error.  int get_attr_entry(attrentry_T *aep)  {    garray_T *table = &attr_table; @@ -6793,7 +6835,7 @@ int hl_combine_attr(int char_attr, int prim_attr)  {    attrentry_T *char_aep = NULL;    attrentry_T *spell_aep; -  attrentry_T new_en; +  attrentry_T new_en = ATTRENTRY_INIT;    if (char_attr == 0) {      return prim_attr; @@ -6809,8 +6851,6 @@ int hl_combine_attr(int char_attr, int prim_attr)    if (char_aep != NULL) {      // Copy all attributes from char_aep to the new entry      new_en = *char_aep; -  } else { -    memset(&new_en, 0, sizeof(new_en));    }    spell_aep = syn_cterm_attr2entry(prim_attr); @@ -6841,17 +6881,25 @@ int hl_combine_attr(int char_attr, int prim_attr)    return get_attr_entry(&new_en);  } +/// \note this function does not apply exclusively to cterm attr contrary +/// to what its name implies +/// \warn don't call it with attr 0 (i.e., the null attribute)  attrentry_T *syn_cterm_attr2entry(int attr)  {    attr -= ATTR_OFF; -  if (attr >= attr_table.ga_len)          /* did ":syntax clear" */ +  if (attr >= attr_table.ga_len) { +    // did ":syntax clear"      return NULL; -  return &(ATTR_ENTRY(attr)); +  } +  return ATTR_ENTRY(attr);  } +/// \addtogroup LIST_XXX +/// @{  #define LIST_ATTR   1  #define LIST_STRING 2  #define LIST_INT    3 +/// @}  static void highlight_list_one(int id)  { @@ -6890,7 +6938,13 @@ static void highlight_list_one(int id)      last_set_msg(sgp->sg_scriptID);  } -static int highlight_list_arg(int id, int didh, int type, int iarg, char_u *sarg, char *name) +/// Outputs a highlight when doing ":hi MyHighlight" +/// +/// @param type one of \ref LIST_XXX +/// @param iarg integer argument used if \p type == LIST_INT +/// @param sarg string used if \p type == LIST_STRING +static int highlight_list_arg(int id, int didh, int type, int iarg, +                              char_u *sarg, const char *name)  {    char_u buf[100];    char_u      *ts; @@ -6930,21 +6984,21 @@ static int highlight_list_arg(int id, int didh, int type, int iarg, char_u *sarg    return didh;  } -/* - * Return "1" if highlight group "id" has attribute "flag". - * Return NULL otherwise. - */ -char_u * -highlight_has_attr ( -    int id, -    int flag, -    int modec              // 'g' for GUI, 'c' for cterm -) +/// Check whether highlight group has attribute +/// +/// @param[in]  id  Highlight group to check. +/// @param[in]  flag  Attribute to check. +/// @param[in]  modec  'g' for GUI, 'c' for term. +/// +/// @return "1" if highlight group has attribute, NULL otherwise. +const char *highlight_has_attr(const int id, const int flag, const int modec) +  FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_PURE  {    int attr; -  if (id <= 0 || id > highlight_ga.ga_len) +  if (id <= 0 || id > highlight_ga.ga_len) {      return NULL; +  }    if (modec == 'g') {      attr = HL_TABLE()[id - 1].sg_gui; @@ -6952,39 +7006,42 @@ highlight_has_attr (      attr = HL_TABLE()[id - 1].sg_cterm;    } -  if (attr & flag) -    return (char_u *)"1"; -  return NULL; +  return (attr & flag) ? "1" : NULL;  } -/* - * Return color name of highlight group "id". - */ -char_u * -highlight_color ( -    int id, -    char_u *what,      /* "font", "fg", "bg", "sp", "fg#", "bg#" or "sp#" */ -    int modec              /* 'g' for GUI, 'c' for cterm, 't' for term */ -) +/// Return color name of the given highlight group +/// +/// @param[in]  id  Highlight group to work with. +/// @param[in]  what  What to return: one of "font", "fg", "bg", "sp", "fg#", +///                   "bg#" or "sp#". +/// @param[in]  modec  'g' for GUI, 'c' for cterm and 't' for term. +/// +/// @return color name, possibly in a static buffer. Buffer will be overwritten +///         on next highlight_color() call. May return NULL. +const char *highlight_color(const int id, const char *const what, +                            const int modec) +  FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_NONNULL_ALL  { -  static char_u name[20]; +  static char name[20];    int n; -  int fg = FALSE; -  int sp = FALSE; -  int font = FALSE; +  bool fg = false; +  bool sp = false; +  bool font = false; -  if (id <= 0 || id > highlight_ga.ga_len) +  if (id <= 0 || id > highlight_ga.ga_len) {      return NULL; +  } -  if (TOLOWER_ASC(what[0]) == 'f' && TOLOWER_ASC(what[1]) == 'g') -    fg = TRUE; -  else if (TOLOWER_ASC(what[0]) == 'f' && TOLOWER_ASC(what[1]) == 'o' -           && TOLOWER_ASC(what[2]) == 'n' && TOLOWER_ASC(what[3]) == 't') -    font = TRUE; -  else if (TOLOWER_ASC(what[0]) == 's' && TOLOWER_ASC(what[1]) == 'p') -    sp = TRUE; -  else if (!(TOLOWER_ASC(what[0]) == 'b' && TOLOWER_ASC(what[1]) == 'g')) +  if (TOLOWER_ASC(what[0]) == 'f' && TOLOWER_ASC(what[1]) == 'g') { +    fg = true; +  } else if (TOLOWER_ASC(what[0]) == 'f' && TOLOWER_ASC(what[1]) == 'o' +             && TOLOWER_ASC(what[2]) == 'n' && TOLOWER_ASC(what[3]) == 't') { +    font = true; +  } else if (TOLOWER_ASC(what[0]) == 's' && TOLOWER_ASC(what[1]) == 'p') { +    sp = true; +  } else if (!(TOLOWER_ASC(what[0]) == 'b' && TOLOWER_ASC(what[1]) == 'g')) {      return NULL; +  }    if (modec == 'g') {      if (what[2] == '#' && ui_rgb_attached()) {        if (fg) { @@ -6997,19 +7054,20 @@ highlight_color (        if (n < 0 || n > 0xffffff) {          return NULL;        } -      snprintf((char *)name, sizeof(name), "#%06x", n); +      snprintf(name, sizeof(name), "#%06x", n);        return name;      }      if (fg) { -      return HL_TABLE()[id - 1].sg_rgb_fg_name; +      return (const char *)HL_TABLE()[id - 1].sg_rgb_fg_name;      }      if (sp) { -      return HL_TABLE()[id - 1].sg_rgb_sp_name; +      return (const char *)HL_TABLE()[id - 1].sg_rgb_sp_name;      } -    return HL_TABLE()[id - 1].sg_rgb_bg_name; +    return (const char *)HL_TABLE()[id - 1].sg_rgb_bg_name;    } -  if (font || sp) +  if (font || sp) {      return NULL; +  }    if (modec == 'c') {      if (fg) {        n = HL_TABLE()[id - 1].sg_cterm_fg - 1; @@ -7019,31 +7077,30 @@ highlight_color (      if (n < 0) {        return NULL;      } -    snprintf((char *)name, sizeof(name), "%d", n); +    snprintf(name, sizeof(name), "%d", n);      return name;    } -  /* term doesn't have color */ +  // term doesn't have color.    return NULL;  } -/* - * Output the syntax list header. - * Return TRUE when started a new line. - */ -static int  -syn_list_header ( -    int did_header,                 /* did header already */ -    int outlen,                     /* length of string that comes */ -    int id                         /* highlight group id */ -) +/// Output the syntax list header. +/// +/// @param did_header did header already +/// @param outlen length of string that comes +/// @param id highlight group id +/// @return true when started a new line. +static int +syn_list_header(int did_header, int outlen, int id)  {    int endcol = 19;    int newline = TRUE;    if (!did_header) {      msg_putchar('\n'); -    if (got_int) -      return TRUE; +    if (got_int) { +      return true; +    }      msg_outtrans(HL_TABLE()[id - 1].sg_name);      endcol = 15;    } else if (msg_col + outlen + 1 >= Columns)   { @@ -7071,21 +7128,14 @@ syn_list_header (    return newline;  } -/* - * Set the attribute numbers for a highlight group. - * Called after one of the attributes has changed. - */ -static void  -set_hl_attr ( -    int idx                    /* index in array */ -) +/// Set the attribute numbers for a highlight group. +/// Called after one of the attributes has changed. +/// @param idx corrected highlight index +static void set_hl_attr(int idx)  { -  attrentry_T at_en; +  attrentry_T at_en = ATTRENTRY_INIT;    struct hl_group     *sgp = HL_TABLE() + idx; -  /* The "Normal" group doesn't need an attribute number */ -  if (sgp->sg_name_u != NULL && STRCMP(sgp->sg_name_u, "NORMAL") == 0) -    return;    at_en.cterm_ae_attr = sgp->sg_cterm;    at_en.cterm_fg_color = sgp->sg_cterm_fg; @@ -7109,11 +7159,11 @@ set_hl_attr (    }  } -/* - * Lookup a highlight group name and return it's ID. - * If it is not found, 0 is returned. - */ -int syn_name2id(char_u *name) +/// Lookup a highlight group name and return its ID. +/// +/// @param highlight name e.g. 'Cursor', 'Normal' +/// @return the highlight id, else 0 if \p name does not exist +int syn_name2id(const char_u *name)  {    int i;    char_u name_u[200]; @@ -7133,7 +7183,7 @@ int syn_name2id(char_u *name)  /*   * Return TRUE if highlight group "name" exists.   */ -int highlight_exists(char_u *name) +int highlight_exists(const char_u *name)  {    return syn_name2id(name) > 0;  } @@ -7161,12 +7211,13 @@ int syn_namen2id(char_u *linep, int len)    return id;  } -/* - * Find highlight group name in the table and return it's ID. - * The argument is a pointer to the name and the length of the name. - * If it doesn't exist yet, a new entry is created. - * Return 0 for failure. - */ +/// Find highlight group name in the table and return its ID. +/// If it doesn't exist yet, a new entry is created. +/// +/// @param pp Highlight group name +/// @param len length of \p pp +/// +/// @return 0 for failure else the id of the group  int syn_check_group(char_u *pp, int len)  {    char_u  *name = vim_strnsave(pp, len); @@ -7179,11 +7230,11 @@ int syn_check_group(char_u *pp, int len)    return id;  } -/* - * Add new highlight group and return it's ID. - * "name" must be an allocated string, it will be consumed. - * Return 0 for failure. - */ +/// Add new highlight group and return it's ID. +/// +/// @param name must be an allocated string, it will be consumed. +/// @return 0 for failure, else the allocated group id +/// @see syn_check_group syn_unadd_group  static int syn_add_group(char_u *name)  {    char_u      *p; @@ -7221,25 +7272,26 @@ static int syn_add_group(char_u *name)    struct hl_group* hlgp = GA_APPEND_VIA_PTR(struct hl_group, &highlight_ga);    memset(hlgp, 0, sizeof(*hlgp));    hlgp->sg_name = name; +  hlgp->sg_rgb_bg = -1; +  hlgp->sg_rgb_fg = -1; +  hlgp->sg_rgb_sp = -1;    hlgp->sg_name_u = vim_strsave_up(name);    return highlight_ga.ga_len;               /* ID is index plus one */  } -/* - * When, just after calling syn_add_group(), an error is discovered, this - * function deletes the new name. - */ +/// When, just after calling syn_add_group(), an error is discovered, this +/// function deletes the new name.  static void syn_unadd_group(void)  { -  --highlight_ga.ga_len; +  highlight_ga.ga_len--;    xfree(HL_TABLE()[highlight_ga.ga_len].sg_name);    xfree(HL_TABLE()[highlight_ga.ga_len].sg_name_u);  } -/* - * Translate a group ID to highlight attributes. - */ + +/// Translate a group ID to highlight attributes. +/// @see syn_cterm_attr2entry  int syn_id2attr(int hl_id)  {    struct hl_group     *sgp; @@ -7293,110 +7345,34 @@ static void highlight_attr_set_all(void)    }  } -/* - * Translate the 'highlight' option into attributes in highlight_attr[] and - * set up the user highlights User1..9. A set of - * corresponding highlights to use on top of HLF_SNC is computed. - * Called only when the 'highlight' option has been changed and upon first - * screen redraw after any :highlight command. - * Return FAIL when an invalid flag is found in 'highlight'.  OK otherwise. - */ -int highlight_changed(void) +/// Tranlate highlight groups into attributes in highlight_attr[] and set up +/// the user highlights User1..9. A set of corresponding highlights to use on +/// top of HLF_SNC is computed.  Called only when nvim starts and upon first +/// screen redraw after any :highlight command. +void highlight_changed(void)  { -  int hlf; -  int i; -  char_u      *p;    int attr; -  char_u      *end;    int id;    char_u userhl[10];    int id_SNC = -1;    int id_S = -1;    int hlcnt; -  static int hl_flags[HLF_COUNT] = HL_FLAGS;    need_highlight_changed = FALSE; -  /* -   * Clear all attributes. -   */ -  for (hlf = 0; hlf < (int)HLF_COUNT; ++hlf) -    highlight_attr[hlf] = 0; - -  /* -   * First set all attributes to their default value. -   * Then use the attributes from the 'highlight' option. -   */ -  for (i = 0; i < 2; ++i) { -    if (i) -      p = p_hl; -    else -      p = get_highlight_default(); -    if (p == NULL)          /* just in case */ -      continue; - -    while (*p) { -      for (hlf = 0; hlf < (int)HLF_COUNT; ++hlf) -        if (hl_flags[hlf] == *p) -          break; -      ++p; -      if (hlf == (int)HLF_COUNT || *p == NUL) -        return FAIL; - -      /* -       * Allow several hl_flags to be combined, like "bu" for -       * bold-underlined. -       */ -      attr = 0; -      bool colon = false; -      for (; *p && *p != ','; ++p) {  // parse upto comma -        if (ascii_iswhite(*p)) {  // ignore white space -          continue; -        } - -        if (colon)          /* Combination with ':' is not allowed. */ -          return FAIL; - -        switch (*p) { -        case 'b':   attr |= HL_BOLD; -          break; -        case 'i':   attr |= HL_ITALIC; -          break; -        case '-': -        case 'n':                                   /* no highlighting */ -          break; -        case 'r':   attr |= HL_INVERSE; -          break; -        case 's':   attr |= HL_STANDOUT; -          break; -        case 'u':   attr |= HL_UNDERLINE; -          break; -        case 'c':   attr |= HL_UNDERCURL; -          break; -        case ':':   ++p;                            /* highlight group name */ -          if (attr || *p == NUL)                         /* no combinations */ -            return FAIL; -          colon = true; -          end = vim_strchr(p, ','); -          if (end == NULL) -            end = p + STRLEN(p); -          id = syn_check_group(p, (int)(end - p)); -          if (id == 0) -            return FAIL; -          attr = syn_id2attr(id); -          p = end - 1; -          if (hlf == (int)HLF_SNC) -            id_SNC = syn_get_final_id(id); -          else if (hlf == (int)HLF_S) -            id_S = syn_get_final_id(id); -          break; -        default:    return FAIL; -        } -      } -      highlight_attr[hlf] = attr; - -      p = skip_to_option_part(p);           /* skip comma and spaces */ +  /// Translate builtin highlight groups into attributes for quick lookup. +  for (int hlf = 0; hlf < (int)HLF_COUNT; hlf++) { +    id = syn_check_group((char_u *)hlf_names[hlf], STRLEN(hlf_names[hlf])); +    if (id == 0) { +      abort(); +    } +    attr = syn_id2attr(id); +    if (hlf == (int)HLF_SNC) { +      id_SNC = syn_get_final_id(id); +    } else if (hlf == (int)HLF_S) { +      id_S = syn_get_final_id(id);      } +    highlight_attr[hlf] = attr;    }    /* Setup the user highlights @@ -7461,49 +7437,47 @@ int highlight_changed(void)      }    }    highlight_ga.ga_len = hlcnt; - -  return OK;  }  /*   * Handle command line completion for :highlight command.   */ -void set_context_in_highlight_cmd(expand_T *xp, char_u *arg) +void set_context_in_highlight_cmd(expand_T *xp, const char *arg)  { -  char_u      *p; - -  /* Default: expand group names */ +  // Default: expand group names.    xp->xp_context = EXPAND_HIGHLIGHT; -  xp->xp_pattern = arg; +  xp->xp_pattern = (char_u *)arg;    include_link = 2;    include_default = 1;    /* (part of) subcommand already typed */    if (*arg != NUL) { -    p = skiptowhite(arg); -    if (*p != NUL) {                    /* past "default" or group name */ +    const char *p = (const char *)skiptowhite((const char_u *)arg); +    if (*p != NUL) {  // Past "default" or group name.        include_default = 0; -      if (STRNCMP("default", arg, p - arg) == 0) { -        arg = skipwhite(p); -        xp->xp_pattern = arg; -        p = skiptowhite(arg); +      if (strncmp("default", arg, p - arg) == 0) { +        arg = (const char *)skipwhite((const char_u *)p); +        xp->xp_pattern = (char_u *)arg; +        p = (const char *)skiptowhite((const char_u *)arg);        }        if (*p != NUL) {                          /* past group name */          include_link = 0; -        if (arg[1] == 'i' && arg[0] == 'N') +        if (arg[1] == 'i' && arg[0] == 'N') {            highlight_list(); -        if (STRNCMP("link", arg, p - arg) == 0 -            || STRNCMP("clear", arg, p - arg) == 0) { -          xp->xp_pattern = skipwhite(p); -          p = skiptowhite(xp->xp_pattern); -          if (*p != NUL) {                      /* past first group name */ -            xp->xp_pattern = skipwhite(p); -            p = skiptowhite(xp->xp_pattern); +        } +        if (strncmp("link", arg, p - arg) == 0 +            || strncmp("clear", arg, p - arg) == 0) { +          xp->xp_pattern = skipwhite((const char_u *)p); +          p = (const char *)skiptowhite(xp->xp_pattern); +          if (*p != NUL) {  // Past first group name. +            xp->xp_pattern = skipwhite((const char_u *)p); +            p = (const char *)skiptowhite(xp->xp_pattern);            }          } -        if (*p != NUL)                          /* past group name(s) */ +        if (*p != NUL) {  // Past group name(s).            xp->xp_context = EXPAND_NOTHING; +        }        }      }    } @@ -8240,7 +8214,14 @@ color_name_table_T color_name_table[] = {    { NULL, 0 },  }; -RgbValue name_to_color(uint8_t *name) + +/// Translate to RgbValue if \p name is an hex value (e.g. #XXXXXX), +/// else look into color_name_table to translate a color name to  its +/// hex value +/// +/// @param[in] name string value to convert to RGB +/// return the hex value or -1 if could not find a correct value +RgbValue name_to_color(const uint8_t *name)  {    if (name[0] == '#' && isxdigit(name[1]) && isxdigit(name[2]) @@ -8263,6 +8244,30 @@ RgbValue name_to_color(uint8_t *name)    return -1;  } +/// Gets highlight description for id `attr_id` as a map. +Dictionary hl_get_attr_by_id(Integer attr_id, Boolean rgb, Error *err) +{ +  HlAttrs attrs = HLATTRS_INIT; +  Dictionary dic = ARRAY_DICT_INIT; + +  if (attr_id == 0) { +    goto end; +  } + +  attrentry_T *aep = syn_cterm_attr2entry((int)attr_id); +  if (!aep) { +    api_set_error(err, kErrorTypeException, +                  "Invalid attribute id: %" PRId64, attr_id); +    return dic; +  } + +  attrs = attrentry2hlattrs(aep, rgb); + +end: +  return hlattrs2dict(attrs); +} + +  /**************************************  *  End of Highlighting stuff	      *  **************************************/  | 
