# HG changeset patch # User Christian Brabandt # Date 1484667005 -3600 # Node ID 4ee16e5e2e26296627d7038b440e94589a348c81 # Parent 9a75c8a1b8b17de4c9f696dd85ea5374fa3a576b patch 8.0.0198: some syntax arguments take effect even after "if 0" commit https://github.com/vim/vim/commit/de318c5c35ed0d65fd2a07196cb8acd5ee6d9bf8 Author: Bram Moolenaar Date: Tue Jan 17 16:27:10 2017 +0100 patch 8.0.0198: some syntax arguments take effect even after "if 0" Problem: Some syntax arguments take effect even after "if 0". (Taylor Venable) Solution: Properly skip the syntax statements. Make "syn case" and "syn conceal" report the current state. Fix that "syn clear" didn't reset the conceal flag. Add tests for :syntax skipping properly. diff --git a/src/syntax.c b/src/syntax.c --- a/src/syntax.c +++ b/src/syntax.c @@ -462,7 +462,7 @@ static void syn_clear_keyword(int id, ha static void clear_keywtab(hashtab_T *ht); static void add_keyword(char_u *name, int id, int flags, short *cont_in_list, short *next_list, int conceal_char); static char_u *get_group_name(char_u *arg, char_u **name_end); -static char_u *get_syn_options(char_u *arg, syn_opt_arg_T *opt, int *conceal_char); +static char_u *get_syn_options(char_u *arg, syn_opt_arg_T *opt, int *conceal_char, int skip); static void syn_cmd_include(exarg_T *eap, int syncing); static void syn_cmd_iskeyword(exarg_T *eap, int syncing); static void syn_cmd_keyword(exarg_T *eap, int syncing); @@ -481,7 +481,7 @@ static int syn_add_cluster(char_u *name) static void init_syn_patterns(void); static char_u *get_syn_pattern(char_u *arg, synpat_T *ci); static void syn_cmd_sync(exarg_T *eap, int syncing); -static int get_id_list(char_u **arg, int keylen, short **list); +static int get_id_list(char_u **arg, int keylen, short **list, int skip); static void syn_combine_list(short **clstr1, short **clstr2, int list_op); static void syn_incl_toplevel(int id, int *flagsp); @@ -3434,7 +3434,14 @@ syn_cmd_conceal(exarg_T *eap UNUSED, int return; next = skiptowhite(arg); - if (STRNICMP(arg, "on", 2) == 0 && next - arg == 2) + if (*arg == NUL) + { + if (curwin->w_s->b_syn_conceal) + MSG(_("syn conceal on")); + else + MSG(_("syn conceal off")); + } + else if (STRNICMP(arg, "on", 2) == 0 && next - arg == 2) curwin->w_s->b_syn_conceal = TRUE; else if (STRNICMP(arg, "off", 3) == 0 && next - arg == 3) curwin->w_s->b_syn_conceal = FALSE; @@ -3457,7 +3464,14 @@ syn_cmd_case(exarg_T *eap, int syncing U return; next = skiptowhite(arg); - if (STRNICMP(arg, "match", 5) == 0 && next - arg == 5) + if (*arg == NUL) + { + if (curwin->w_s->b_syn_ic) + MSG(_("syntax case ignore")); + else + MSG(_("syntax case match")); + } + else if (STRNICMP(arg, "match", 5) == 0 && next - arg == 5) curwin->w_s->b_syn_ic = FALSE; else if (STRNICMP(arg, "ignore", 6) == 0 && next - arg == 6) curwin->w_s->b_syn_ic = TRUE; @@ -3479,7 +3493,16 @@ syn_cmd_spell(exarg_T *eap, int syncing return; next = skiptowhite(arg); - if (STRNICMP(arg, "toplevel", 8) == 0 && next - arg == 8) + if (*arg == NUL) + { + if (curwin->w_s->b_syn_spell == SYNSPL_TOP) + MSG(_("syntax spell toplevel")); + else if (curwin->w_s->b_syn_spell == SYNSPL_NOTOP) + MSG(_("syntax spell notoplevel")); + else + MSG(_("syntax spell default")); + } + else 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) curwin->w_s->b_syn_spell = SYNSPL_NOTOP; @@ -3556,6 +3579,9 @@ syntax_clear(synblock_T *block) block->b_syn_ic = FALSE; /* Use case, by default */ block->b_syn_spell = SYNSPL_DEFAULT; /* default spell checking */ block->b_syn_containedin = FALSE; +#ifdef FEAT_CONCEAL + block->b_syn_conceal = FALSE; +#endif /* free the keywords */ clear_keywtab(&block->b_keywtab); @@ -4543,7 +4569,8 @@ get_group_name( get_syn_options( char_u *arg, /* next argument to be checked */ syn_opt_arg_T *opt, /* various things */ - int *conceal_char UNUSED) + int *conceal_char UNUSED, + int skip) /* TRUE if skipping over command */ { char_u *gname_start, *gname; int syn_id; @@ -4626,17 +4653,17 @@ get_syn_options( EMSG(_("E395: contains argument not accepted here")); return NULL; } - if (get_id_list(&arg, 8, &opt->cont_list) == FAIL) + if (get_id_list(&arg, 8, &opt->cont_list, skip) == FAIL) return NULL; } else if (flagtab[fidx].argtype == 2) { - if (get_id_list(&arg, 11, &opt->cont_in_list) == FAIL) + if (get_id_list(&arg, 11, &opt->cont_in_list, skip) == FAIL) return NULL; } else if (flagtab[fidx].argtype == 3) { - if (get_id_list(&arg, 9, &opt->next_list) == FAIL) + if (get_id_list(&arg, 9, &opt->next_list, skip) == FAIL) return NULL; } else if (flagtab[fidx].argtype == 11 && arg[5] == '=') @@ -4846,7 +4873,10 @@ syn_cmd_keyword(exarg_T *eap, int syncin if (rest != NULL) { - syn_id = syn_check_group(arg, (int)(group_name_end - arg)); + if (eap->skip) + syn_id = -1; + else + syn_id = syn_check_group(arg, (int)(group_name_end - arg)); if (syn_id != 0) /* allocate a buffer, for removing backslashes in the keyword */ keyword_copy = alloc((unsigned)STRLEN(rest) + 1); @@ -4868,7 +4898,8 @@ syn_cmd_keyword(exarg_T *eap, int syncin p = keyword_copy; for ( ; rest != NULL && !ends_excmd(*rest); rest = skipwhite(rest)) { - rest = get_syn_options(rest, &syn_opt_arg, &conceal_char); + rest = get_syn_options(rest, &syn_opt_arg, &conceal_char, + eap->skip); if (rest == NULL || ends_excmd(*rest)) break; /* Copy the keyword, removing backslashes, and add a NUL. */ @@ -4981,7 +5012,7 @@ syn_cmd_match( syn_opt_arg.cont_list = NULL; syn_opt_arg.cont_in_list = NULL; syn_opt_arg.next_list = NULL; - rest = get_syn_options(rest, &syn_opt_arg, &conceal_char); + rest = get_syn_options(rest, &syn_opt_arg, &conceal_char, eap->skip); /* get the pattern. */ init_syn_patterns(); @@ -4991,7 +5022,7 @@ syn_cmd_match( syn_opt_arg.flags |= HL_HAS_EOL; /* Get options after the pattern */ - rest = get_syn_options(rest, &syn_opt_arg, &conceal_char); + rest = get_syn_options(rest, &syn_opt_arg, &conceal_char, eap->skip); if (rest != NULL) /* all arguments are valid */ { @@ -5117,7 +5148,7 @@ syn_cmd_region( while (rest != NULL && !ends_excmd(*rest)) { /* Check for option arguments */ - rest = get_syn_options(rest, &syn_opt_arg, &conceal_char); + rest = get_syn_options(rest, &syn_opt_arg, &conceal_char, eap->skip); if (rest == NULL || ends_excmd(*rest)) break; @@ -5628,12 +5659,13 @@ syn_cmd_cluster(exarg_T *eap, int syncin break; clstr_list = NULL; - if (get_id_list(&rest, opt_len, &clstr_list) == FAIL) + if (get_id_list(&rest, opt_len, &clstr_list, eap->skip) == FAIL) { EMSG2(_(e_invarg2), rest); break; } - syn_combine_list(&SYN_CLSTR(curwin->w_s)[scl_id].scl_list, + if (scl_id >= 0) + syn_combine_list(&SYN_CLSTR(curwin->w_s)[scl_id].scl_list, &clstr_list, list_op); got_clstr = TRUE; } @@ -5931,8 +5963,9 @@ syn_cmd_sync(exarg_T *eap, int syncing U get_id_list( char_u **arg, int keylen, /* length of keyword */ - short **list) /* where to store the resulting list, if not + short **list, /* where to store the resulting list, if not NULL, the list is silently skipped! */ + int skip) { char_u *p = NULL; char_u *end; @@ -6015,7 +6048,8 @@ get_id_list( } else if (name[1] == '@') { - id = syn_check_cluster(name + 2, (int)(end - p - 1)); + if (!skip) + id = syn_check_cluster(name + 2, (int)(end - p - 1)); } else { diff --git a/src/testdir/test_syntax.vim b/src/testdir/test_syntax.vim --- a/src/testdir/test_syntax.vim +++ b/src/testdir/test_syntax.vim @@ -162,3 +162,134 @@ func Test_syntax_completion() call feedkeys(":syn match \\\"\", 'tx') call assert_match('^"syn match Boolean Character ', @:) endfunc + +func Test_syntax_arg_skipped() + syn clear + syntax case ignore + if 0 + syntax case match + endif + call assert_match('case ignore', execute('syntax case')) + + syn keyword Foo foo + call assert_match('Foo', execute('syntax')) + syn clear + call assert_match('case match', execute('syntax case')) + call assert_notmatch('Foo', execute('syntax')) + + if has('conceal') + syn clear + syntax conceal on + if 0 + syntax conceal off + endif + call assert_match('conceal on', execute('syntax conceal')) + syn clear + call assert_match('conceal off', execute('syntax conceal')) + endif + + syntax region Tar start=// + if 0 + syntax region NotTest start=// contains=@Spell + endif + call assert_match('Tar', execute('syntax')) + call assert_notmatch('NotTest', execute('syntax')) + call assert_notmatch('Spell', execute('syntax')) + + hi Foo ctermfg=blue + let a = execute('hi Foo') + if 0 + syntax rest + endif + call assert_equal(a, execute('hi Foo')) + + set ft=tags + syn off + if 0 + syntax enable + endif + call assert_match('No Syntax items defined', execute('syntax')) + syntax enable + call assert_match('tagComment', execute('syntax')) + set ft= + + syn clear + if 0 + syntax include @Spell nothing + endif + call assert_notmatch('Spell', execute('syntax')) + + syn clear + syn iskeyword 48-57,$,_ + call assert_match('48-57,$,_', execute('syntax iskeyword')) + if 0 + syn clear + syn iskeyword clear + endif + call assert_match('48-57,$,_', execute('syntax iskeyword')) + syn iskeyword clear + call assert_match('not set', execute('syntax iskeyword')) + syn iskeyword 48-57,$,_ + syn clear + call assert_match('not set', execute('syntax iskeyword')) + + syn clear + syn keyword Foo foo + if 0 + syn keyword NotAdded bar + endif + call assert_match('Foo', execute('syntax')) + call assert_notmatch('NotAdded', execute('highlight')) + + syn clear + syn keyword Foo foo + call assert_match('Foo', execute('syntax')) + call assert_match('Foo', execute('syntax list')) + call assert_notmatch('Foo', execute('if 0 | syntax | endif')) + call assert_notmatch('Foo', execute('if 0 | syntax list | endif')) + + syn clear + syn match Fopi /asdf/ + if 0 + syn match Fopx /asdf/ + endif + call assert_match('Fopi', execute('syntax')) + call assert_notmatch('Fopx', execute('syntax')) + + syn clear + syn spell toplevel + call assert_match('spell toplevel', execute('syntax spell')) + if 0 + syn spell notoplevel + endif + call assert_match('spell toplevel', execute('syntax spell')) + syn spell notoplevel + call assert_match('spell notoplevel', execute('syntax spell')) + syn spell default + call assert_match('spell default', execute('syntax spell')) + + syn clear + if 0 + syntax cluster Spell + endif + call assert_notmatch('Spell', execute('syntax')) + + syn clear + syn keyword Foo foo + syn sync ccomment + syn sync maxlines=5 + if 0 + syn sync maxlines=11 + endif + call assert_match('on C-style comments', execute('syntax sync')) + call assert_match('maximal 5 lines', execute('syntax sync')) + syn clear + syn keyword Foo foo + if 0 + syn sync ccomment + endif + call assert_notmatch('on C-style comments', execute('syntax sync')) + + syn clear +endfunc + diff --git a/src/version.c b/src/version.c --- a/src/version.c +++ b/src/version.c @@ -765,6 +765,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ /**/ + 198, +/**/ 197, /**/ 196,