diff options
Diffstat (limited to 'src/nvim/syntax.c')
-rw-r--r-- | src/nvim/syntax.c | 230 |
1 files changed, 153 insertions, 77 deletions
diff --git a/src/nvim/syntax.c b/src/nvim/syntax.c index 24422c71fb..1f9dbd8228 100644 --- a/src/nvim/syntax.c +++ b/src/nvim/syntax.c @@ -41,6 +41,8 @@ #include "nvim/os/os.h" #include "nvim/os/time.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. @@ -60,8 +62,10 @@ struct hl_group { 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 }; #define SG_CTERM 2 // cterm has been set @@ -2613,33 +2617,37 @@ find_endpos ( IF_SYN_TIME(&spp_skip->sp_time)); spp_skip->sp_prog = regmatch.regprog; if (r && regmatch.startpos[0].col <= best_regmatch.startpos[0].col) { - /* Add offset to skip pattern match */ + // Add offset to skip pattern match syn_add_end_off(&pos, ®match, spp_skip, SPO_ME_OFF, 1); - /* If the skip pattern goes on to the next line, there is no - * match with an end pattern in this line. */ - if (pos.lnum > startpos->lnum) + // If the skip pattern goes on to the next line, there is no + // match with an end pattern in this line. + if (pos.lnum > startpos->lnum) { break; + } - line = ml_get_buf(syn_buf, startpos->lnum, FALSE); + line = ml_get_buf(syn_buf, startpos->lnum, false); + int line_len = (int)STRLEN(line); - /* take care of an empty match or negative offset */ - if (pos.col <= matchcol) - ++matchcol; - else if (pos.col <= regmatch.endpos[0].col) + // take care of an empty match or negative offset + if (pos.col <= matchcol) { + matchcol++; + } else if (pos.col <= regmatch.endpos[0].col) { matchcol = pos.col; - else - /* Be careful not to jump over the NUL at the end-of-line */ + } else { + // Be careful not to jump over the NUL at the end-of-line for (matchcol = regmatch.endpos[0].col; - line[matchcol] != NUL && matchcol < pos.col; - ++matchcol) - ; + matchcol < line_len && matchcol < pos.col; + matchcol++) { + } + } - /* if the skip pattern includes end-of-line, break here */ - if (line[matchcol] == NUL) + // if the skip pattern includes end-of-line, break here + if (matchcol >= line_len) { break; + } - continue; /* start with first end pattern again */ + continue; // start with first end pattern again } } @@ -3004,14 +3012,19 @@ static void syn_cmd_spell(exarg_T *eap, int syncing) return; next = skiptowhite(arg); - if (STRNICMP(arg, "toplevel", 8) == 0 && next - arg == 8) + if (STRNICMP(arg, "toplevel", 8) == 0 && next - arg == 8) { curwin->w_s->b_syn_spell = SYNSPL_TOP; - else if (STRNICMP(arg, "notoplevel", 10) == 0 && next - arg == 10) + } else if (STRNICMP(arg, "notoplevel", 10) == 0 && next - arg == 10) { curwin->w_s->b_syn_spell = SYNSPL_NOTOP; - else if (STRNICMP(arg, "default", 7) == 0 && next - arg == 7) + } else if (STRNICMP(arg, "default", 7) == 0 && next - arg == 7) { curwin->w_s->b_syn_spell = SYNSPL_DEFAULT; - else + } else { EMSG2(_("E390: Illegal argument: %s"), arg); + return; + } + + // assume spell checking changed, force a redraw + redraw_win_later(curwin, NOT_VALID); } /* @@ -3281,17 +3294,28 @@ static void syn_cmd_off(exarg_T *eap, int syncing) } static void syn_cmd_onoff(exarg_T *eap, char *name) + FUNC_ATTR_NONNULL_ALL { - char buf[100]; - + did_syntax_onoff = true; eap->nextcmd = check_nextcmd(eap->arg); if (!eap->skip) { - strcpy(buf, "so "); + char buf[100]; + strncpy(buf, "so ", 4); vim_snprintf(buf + 3, sizeof(buf) - 3, SYNTAX_FNAME, name); do_cmdline_cmd(buf); } } +void syn_maybe_on(void) +{ + if (!did_syntax_onoff) { + exarg_T ea; + ea.arg = (char_u *)""; + ea.skip = false; + syn_cmd_onoff(&ea, "syntax"); + } +} + /* * Handle ":syntax [list]" command: list current syntax words. */ @@ -4183,12 +4207,16 @@ static void syn_cmd_keyword(exarg_T *eap, int syncing) break; if (p[1] == NUL) { EMSG2(_("E789: Missing ']': %s"), kw); - kw = p + 2; /* skip over the NUL */ - break; + goto error; } if (p[1] == ']') { - kw = p + 1; /* skip over the "]" */ - break; + if (p[2] != NUL) { + EMSG3(_("E890: trailing char after ']': %s]%s"), + kw, &p[2]); + goto error; + } + kw = p + 1; + break; // skip over the "]" } if (has_mbyte) { int l = (*mb_ptr2len)(p + 1); @@ -4203,6 +4231,7 @@ static void syn_cmd_keyword(exarg_T *eap, int syncing) } } +error: xfree(keyword_copy); xfree(syn_opt_arg.cont_in_list); xfree(syn_opt_arg.next_list); @@ -4455,12 +4484,10 @@ syn_cmd_region ( if (illegal || not_enough) rest = NULL; - /* - * Must have a "start" and "end" pattern. - */ - if (rest != NULL && (pat_ptrs[ITEM_START] == NULL || - pat_ptrs[ITEM_END] == NULL)) { - not_enough = TRUE; + // Must have a "start" and "end" pattern. + if (rest != NULL && (pat_ptrs[ITEM_START] == NULL + || pat_ptrs[ITEM_END] == NULL)) { + not_enough = true; rest = NULL; } @@ -4843,9 +4870,10 @@ static char_u *get_syn_pattern(char_u *arg, synpat_T *ci) int idx; char_u *cpo_save; - /* need at least three chars */ - if (arg == NULL || arg[1] == NUL || arg[2] == NUL) + // need at least three chars + if (arg == NULL || arg[0] == NUL || arg[1] == NUL || arg[2] == NUL) { return NULL; + } end = skip_regexp(arg + 1, *arg, TRUE, NULL); if (*end != *arg) { /* end delimiter not found */ @@ -4982,6 +5010,10 @@ static void syn_cmd_sync(exarg_T *eap, int syncing) curwin->w_s->b_syn_sync_maxlines = 0; } } else if (STRCMP(key, "LINECONT") == 0) { + if (*next_arg == NUL) { // missing pattern + illegal = true; + break; + } if (curwin->w_s->b_syn_linecont_pat != NULL) { EMSG(_("E403: syntax sync: line continuations pattern specified twice")); finished = TRUE; @@ -5395,8 +5427,10 @@ void ex_ownsyntax(exarg_T *eap) if (curwin->w_s == &curwin->w_buffer->b_s) { curwin->w_s = xmalloc(sizeof(synblock_T)); memset(curwin->w_s, 0, sizeof(synblock_T)); - // TODO: Keep the spell checking as it was. - curwin->w_p_spell = FALSE; /* No spell checking */ + hash_init(&curwin->w_s->b_keywtab); + hash_init(&curwin->w_s->b_keywtab_ic); + // TODO: Keep the spell checking as it was. NOLINT(readability/todo) + curwin->w_p_spell = false; // No spell checking clear_string_option(&curwin->w_s->b_p_spc); clear_string_option(&curwin->w_s->b_p_spf); clear_string_option(&curwin->w_s->b_p_spl); @@ -5507,25 +5541,29 @@ char_u *get_syntax_name(expand_T *xp, int idx) } -/* - * Function called for expression evaluation: get syntax ID at file position. - */ -int -syn_get_id ( +// Function called for expression evaluation: get syntax ID at file position. +int syn_get_id( win_T *wp, long lnum, colnr_T col, - int trans, /* remove transparency */ - bool *spellp, /* return: can do spell checking */ - int keep_state /* keep state of char at "col" */ + int trans, // remove transparency + bool *spellp, // return: can do spell checking + int keep_state // keep state of char at "col" ) { - /* When the position is not after the current position and in the same - * line of the same buffer, need to restart parsing. */ + // When the position is not after the current position and in the same + // line of the same buffer, need to restart parsing. if (wp->w_buffer != syn_buf || lnum != current_lnum - || col < current_col) + || col < current_col) { syntax_start(wp, lnum); + } else if (wp->w_buffer == syn_buf + && lnum == current_lnum + && col > current_col) { + // next_match may not be correct when moving around, e.g. with the + // "skip" expression in searchpair() + next_match_idx = -1; + } (void)get_syntax_attr(col, spellp, keep_state); @@ -6133,12 +6171,11 @@ do_highlight ( break; } - /* - * Isolate the key ("term", "ctermfg", "ctermbg", "font", "guifg" or - * "guibg"). - */ - while (*linep && !ascii_iswhite(*linep) && *linep != '=') - ++linep; + // Isolate the key ("term", "ctermfg", "ctermbg", "font", "guifg", + // "guibg" or "guisp"). + while (*linep && !ascii_iswhite(*linep) && *linep != '=') { + linep++; + } xfree(key); key = vim_strnsave_up(key_start, (int)(linep - key_start)); linep = skipwhite(linep); @@ -6334,18 +6371,14 @@ do_highlight ( } 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) { - switch (t_colors) { - case 16: - color = color_numbers_8[i]; - break; - case 88: - color = color_numbers_88[i]; - break; - case 256: - color = color_numbers_256[i]; - break; + color &= 7; // truncate to 8 colors + } else if (t_colors == 16 || t_colors == 88 || t_colors >= 256) { + if (t_colors == 88) { + color = color_numbers_88[i]; + } else if (t_colors >= 256) { + color = color_numbers_256[i]; + } else { + color = color_numbers_8[i]; } } } @@ -6365,7 +6398,7 @@ do_highlight ( HL_TABLE()[idx].sg_cterm_bg = color + 1; if (is_normal_group) { cterm_normal_bg_color = color + 1; - { + if (!ui_rgb_attached()) { must_redraw = CLEAR; if (color >= 0) { if (t_colors < 16) @@ -6420,7 +6453,23 @@ do_highlight ( normal_bg = HL_TABLE()[idx].sg_rgb_bg; } } else if (STRCMP(key, "GUISP") == 0) { - // Ignored for now + if (!init || !(HL_TABLE()[idx].sg_set & SG_GUI)) { + if (!init) + HL_TABLE()[idx].sg_set |= SG_GUI; + + xfree(HL_TABLE()[idx].sg_rgb_sp_name); + if (STRCMP(arg, "NONE") != 0) { + HL_TABLE()[idx].sg_rgb_sp_name = (uint8_t *)xstrdup((char *)arg); + HL_TABLE()[idx].sg_rgb_sp = name_to_color(arg); + } else { + HL_TABLE()[idx].sg_rgb_sp_name = NULL; + HL_TABLE()[idx].sg_rgb_sp = -1; + } + } + + if (is_normal_group) { + normal_sp = HL_TABLE()[idx].sg_rgb_sp; + } } else if (STRCMP(key, "START") == 0 || STRCMP(key, "STOP") == 0) { // Ignored for now } else { @@ -6484,6 +6533,7 @@ void restore_cterm_colors(void) { normal_fg = -1; normal_bg = -1; + normal_sp = -1; cterm_normal_fg_color = 0; cterm_normal_fg_bold = 0; cterm_normal_bg_color = 0; @@ -6500,6 +6550,7 @@ static int hl_has_settings(int idx, int check_link) || HL_TABLE()[idx].sg_cterm_bg != 0 || HL_TABLE()[idx].sg_rgb_fg_name != NULL || HL_TABLE()[idx].sg_rgb_bg_name != NULL + || HL_TABLE()[idx].sg_rgb_sp_name != NULL || (check_link && (HL_TABLE()[idx].sg_set & SG_LINK)); } @@ -6516,14 +6567,18 @@ static void highlight_clear(int idx) HL_TABLE()[idx].sg_gui = 0; HL_TABLE()[idx].sg_rgb_fg = -1; HL_TABLE()[idx].sg_rgb_bg = -1; + HL_TABLE()[idx].sg_rgb_sp = -1; xfree(HL_TABLE()[idx].sg_rgb_fg_name); HL_TABLE()[idx].sg_rgb_fg_name = NULL; xfree(HL_TABLE()[idx].sg_rgb_bg_name); HL_TABLE()[idx].sg_rgb_bg_name = NULL; - /* Clear the script ID only when there is no link, since that is not - * cleared. */ - if (HL_TABLE()[idx].sg_link == 0) + xfree(HL_TABLE()[idx].sg_rgb_sp_name); + HL_TABLE()[idx].sg_rgb_sp_name = NULL; + // Clear the script ID only when there is no link, since that is not + // cleared. + if (HL_TABLE()[idx].sg_link == 0) { HL_TABLE()[idx].sg_scriptID = 0; + } } @@ -6565,7 +6620,8 @@ int get_attr_entry(attrentry_T *aep) && aep->cterm_bg_color == taep->cterm_bg_color && aep->rgb_ae_attr == taep->rgb_ae_attr && aep->rgb_fg_color == taep->rgb_fg_color - && aep->rgb_bg_color == taep->rgb_bg_color) { + && aep->rgb_bg_color == taep->rgb_bg_color + && aep->rgb_sp_color == taep->rgb_sp_color) { return i + ATTR_OFF; } } @@ -6603,6 +6659,7 @@ int get_attr_entry(attrentry_T *aep) taep->rgb_ae_attr = aep->rgb_ae_attr; taep->rgb_fg_color = aep->rgb_fg_color; taep->rgb_bg_color = aep->rgb_bg_color; + taep->rgb_sp_color = aep->rgb_sp_color; return table->ga_len - 1 + ATTR_OFF; } @@ -6664,6 +6721,10 @@ int hl_combine_attr(int char_attr, int prim_attr) if (spell_aep->rgb_bg_color >= 0) { new_en.rgb_bg_color = spell_aep->rgb_bg_color; } + + if (spell_aep->rgb_sp_color >= 0) { + new_en.rgb_sp_color = spell_aep->rgb_sp_color; + } } return get_attr_entry(&new_en); } @@ -6701,7 +6762,7 @@ static void highlight_list_one(int id) didh = highlight_list_arg(id, didh, LIST_STRING, 0, sgp->sg_rgb_bg_name, "guibg"); didh = highlight_list_arg(id, didh, LIST_STRING, - 0, NULL, "guisp"); + 0, sgp->sg_rgb_sp_name, "guisp"); if (sgp->sg_link && !got_int) { (void)syn_list_header(didh, 9999, id); @@ -6815,8 +6876,9 @@ highlight_color ( if (modec == 'g') { if (fg) return HL_TABLE()[id - 1].sg_rgb_fg_name; - if (sp) - return NULL; + if (sp) { + return HL_TABLE()[id - 1].sg_rgb_sp_name; + } return HL_TABLE()[id - 1].sg_rgb_bg_name; } if (font || sp) @@ -6903,7 +6965,17 @@ set_hl_attr ( // before setting attr_entry->{f,g}g_color to a other than -1 at_en.rgb_fg_color = sgp->sg_rgb_fg_name ? sgp->sg_rgb_fg : -1; at_en.rgb_bg_color = sgp->sg_rgb_bg_name ? sgp->sg_rgb_bg : -1; - sgp->sg_attr = get_attr_entry(&at_en); + at_en.rgb_sp_color = sgp->sg_rgb_sp_name ? sgp->sg_rgb_sp : -1; + + if (at_en.cterm_fg_color != 0 || at_en.cterm_bg_color != 0 + || at_en.rgb_fg_color != -1 || at_en.rgb_bg_color != -1 + || at_en.rgb_sp_color != -1 || at_en.cterm_ae_attr != 0 + || at_en.rgb_ae_attr != 0) { + sgp->sg_attr = get_attr_entry(&at_en); + } else { + // If all the fields are cleared, clear the attr field back to default value + sgp->sg_attr = 0; + } } /* @@ -7234,6 +7306,10 @@ int highlight_changed(void) hlt[hlcnt + i].sg_rgb_bg = hlt[id - 1].sg_rgb_bg; } + if (hlt[id - 1].sg_rgb_sp != hlt[id_S - 1].sg_rgb_sp) { + hlt[hlcnt + i].sg_rgb_sp = hlt[id - 1].sg_rgb_sp; + } + highlight_ga.ga_len = hlcnt + i + 1; set_hl_attr(hlcnt + i); /* At long last we can apply */ highlight_stlnc[i] = syn_id2attr(hlcnt + i + 1); |