diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/structs.h | 5 | ||||
| -rw-r--r-- | src/syntax.c | 89 | ||||
| -rw-r--r-- | src/testdir/test_syntax.vim | 85 | ||||
| -rw-r--r-- | src/version.c | 2 |
4 files changed, 173 insertions, 8 deletions
diff --git a/src/structs.h b/src/structs.h index 9968e9205..8fb14d759 100644 --- a/src/structs.h +++ b/src/structs.h @@ -2266,6 +2266,10 @@ typedef struct #define SYNSPL_TOP 1 // spell check toplevel text #define SYNSPL_NOTOP 2 // don't spell check toplevel text +// values for b_syn_foldlevel: how to compute foldlevel on a line +#define SYNFLD_START 0 // use level of item at start of line +#define SYNFLD_MINIMUM 1 // use lowest local minimum level on line + // avoid #ifdefs for when b_spell is not available #ifdef FEAT_SPELL # define B_SPELL(buf) ((buf)->b_spell) @@ -2360,6 +2364,7 @@ typedef struct { int b_syn_slow; // TRUE when 'redrawtime' reached # endif int b_syn_ic; // ignore case for :syn cmds + int b_syn_foldlevel; // how to compute foldlevel on a line int b_syn_spell; // SYNSPL_ values garray_T b_syn_patterns; // table for syntax patterns garray_T b_syn_clusters; // table for syntax clusters diff --git a/src/syntax.c b/src/syntax.c index cda1f953b..f2f74a181 100644 --- a/src/syntax.c +++ b/src/syntax.c @@ -30,6 +30,8 @@ static char *(spo_name_tab[SPO_COUNT]) = {"ms=", "me=", "hs=", "he=", "rs=", "re=", "lc="}; +static char e_illegal_arg[] = N_("E390: Illegal argument: %s"); + /* * The patterns that are being searched for are stored in a syn_pattern. * A match item consists of one pattern. @@ -3340,7 +3342,7 @@ syn_cmd_conceal(exarg_T *eap UNUSED, int syncing UNUSED) else if (STRNICMP(arg, "off", 3) == 0 && next - arg == 3) curwin->w_s->b_syn_conceal = FALSE; else - semsg(_("E390: Illegal argument: %s"), arg); + semsg(_(e_illegal_arg), arg); #endif } @@ -3370,7 +3372,49 @@ syn_cmd_case(exarg_T *eap, int syncing UNUSED) else if (STRNICMP(arg, "ignore", 6) == 0 && next - arg == 6) curwin->w_s->b_syn_ic = TRUE; else - semsg(_("E390: Illegal argument: %s"), arg); + semsg(_(e_illegal_arg), arg); +} + +/* + * Handle ":syntax foldlevel" command. + */ + static void +syn_cmd_foldlevel(exarg_T *eap, int syncing UNUSED) +{ + char_u *arg = eap->arg; + char_u *arg_end; + + eap->nextcmd = find_nextcmd(arg); + if (eap->skip) + return; + + if (*arg == NUL) + { + switch (curwin->w_s->b_syn_foldlevel) + { + case SYNFLD_START: msg(_("syntax foldlevel start")); break; + case SYNFLD_MINIMUM: msg(_("syntax foldlevel minimum")); break; + default: break; + } + return; + } + + arg_end = skiptowhite(arg); + if (STRNICMP(arg, "start", 5) == 0 && arg_end - arg == 5) + curwin->w_s->b_syn_foldlevel = SYNFLD_START; + else if (STRNICMP(arg, "minimum", 7) == 0 && arg_end - arg == 7) + curwin->w_s->b_syn_foldlevel = SYNFLD_MINIMUM; + else + { + semsg(_(e_illegal_arg), arg); + return; + } + + arg = skipwhite(arg_end); + if (*arg != NUL) + { + semsg(_(e_illegal_arg), arg); + } } /* @@ -3404,7 +3448,7 @@ syn_cmd_spell(exarg_T *eap, int syncing UNUSED) curwin->w_s->b_syn_spell = SYNSPL_DEFAULT; else { - semsg(_("E390: Illegal argument: %s"), arg); + semsg(_(e_illegal_arg), arg); return; } @@ -3476,6 +3520,7 @@ syntax_clear(synblock_T *block) block->b_syn_slow = FALSE; // clear previous timeout #endif block->b_syn_ic = FALSE; // Use case, by default + block->b_syn_foldlevel = SYNFLD_START; block->b_syn_spell = SYNSPL_DEFAULT; // default spell checking block->b_syn_containedin = FALSE; #ifdef FEAT_CONCEAL @@ -6192,6 +6237,7 @@ static struct subcommand subcommands[] = {"cluster", syn_cmd_cluster}, {"conceal", syn_cmd_conceal}, {"enable", syn_cmd_enable}, + {"foldlevel", syn_cmd_foldlevel}, {"include", syn_cmd_include}, {"iskeyword", syn_cmd_iskeyword}, {"keyword", syn_cmd_keyword}, @@ -6489,6 +6535,18 @@ syn_get_stack_item(int i) #endif #if defined(FEAT_FOLDING) || defined(PROTO) + static int +syn_cur_foldlevel(void) +{ + int level = 0; + int i; + + for (i = 0; i < current_state.ga_len; ++i) + if (CUR_STATE(i).si_flags & HL_FOLD) + ++level; + return level; +} + /* * Function called to get folding level for line "lnum" in window "wp". */ @@ -6496,7 +6554,8 @@ syn_get_stack_item(int i) syn_get_foldlevel(win_T *wp, long lnum) { int level = 0; - int i; + int low_level; + int cur_level; // Return quickly when there are no fold items at all. if (wp->w_s->b_syn_folditems != 0 @@ -6508,9 +6567,25 @@ syn_get_foldlevel(win_T *wp, long lnum) { syntax_start(wp, lnum); - for (i = 0; i < current_state.ga_len; ++i) - if (CUR_STATE(i).si_flags & HL_FOLD) - ++level; + // Start with the fold level at the start of the line. + level = syn_cur_foldlevel(); + + if (wp->w_s->b_syn_foldlevel == SYNFLD_MINIMUM) + { + // Find the lowest fold level that is followed by a higher one. + cur_level = level; + low_level = cur_level; + while (!current_finished) + { + (void)syn_current_attr(FALSE, FALSE, NULL, FALSE); + cur_level = syn_cur_foldlevel(); + if (cur_level < low_level) + low_level = cur_level; + else if (cur_level > low_level) + level = low_level; + ++current_col; + } + } } if (level > wp->w_p_fdn) { diff --git a/src/testdir/test_syntax.vim b/src/testdir/test_syntax.vim index 024ba59a4..bbcd0d88a 100644 --- a/src/testdir/test_syntax.vim +++ b/src/testdir/test_syntax.vim @@ -160,7 +160,7 @@ endfunc func Test_syntax_completion() call feedkeys(":syn \<C-A>\<C-B>\"\<CR>", 'tx') - call assert_equal('"syn case clear cluster conceal enable include iskeyword keyword list manual match off on region reset spell sync', @:) + call assert_equal('"syn case clear cluster conceal enable foldlevel include iskeyword keyword list manual match off on region reset spell sync', @:) call feedkeys(":syn case \<C-A>\<C-B>\"\<CR>", 'tx') call assert_equal('"syn case ignore match', @:) @@ -691,4 +691,87 @@ func Test_syntax_after_bufdo() call delete('Xddd.c') endfunc +func Test_syntax_foldlevel() + new + call setline(1, [ + \ 'void f(int a)', + \ '{', + \ ' if (a == 1) {', + \ ' a = 0;', + \ ' } else if (a == 2) {', + \ ' a = 1;', + \ ' } else {', + \ ' a = 2;', + \ ' }', + \ ' if (a > 0) {', + \ ' if (a == 1) {', + \ ' a = 0;', + \ ' } /* missing newline */ } /* end of outer if */ else {', + \ ' a = 1;', + \ ' }', + \ ' if (a == 1)', + \ ' {', + \ ' a = 0;', + \ ' }', + \ ' else if (a == 2)', + \ ' {', + \ ' a = 1;', + \ ' }', + \ ' else', + \ ' {', + \ ' a = 2;', + \ ' }', + \ '}', + \ ]) + setfiletype c + syntax on + set foldmethod=syntax + + call assert_fails('syn foldlevel start start', 'E390') + call assert_fails('syn foldlevel not_an_option', 'E390') + + set foldlevel=1 + + syn foldlevel start + redir @c + syn foldlevel + redir END + call assert_equal("\nsyntax foldlevel start", @c) + syn sync fromstart + let a = map(range(3,9), 'foldclosed(v:val)') + call assert_equal([3,3,3,3,3,3,3], a) " attached cascade folds together + let a = map(range(10,15), 'foldclosed(v:val)') + call assert_equal([10,10,10,10,10,10], a) " over-attached 'else' hidden + let a = map(range(16,27), 'foldclosed(v:val)') + let unattached_results = [-1,17,17,17,-1,21,21,21,-1,25,25,25] + call assert_equal(unattached_results, a) " unattached cascade folds separately + + syn foldlevel minimum + redir @c + syn foldlevel + redir END + call assert_equal("\nsyntax foldlevel minimum", @c) + syn sync fromstart + let a = map(range(3,9), 'foldclosed(v:val)') + call assert_equal([3,3,5,5,7,7,7], a) " attached cascade folds separately + let a = map(range(10,15), 'foldclosed(v:val)') + call assert_equal([10,10,10,13,13,13], a) " over-attached 'else' visible + let a = map(range(16,27), 'foldclosed(v:val)') + call assert_equal(unattached_results, a) " unattached cascade folds separately + + set foldlevel=2 + + syn foldlevel start + syn sync fromstart + let a = map(range(11,14), 'foldclosed(v:val)') + call assert_equal([11,11,11,-1], a) " over-attached 'else' hidden + + syn foldlevel minimum + syn sync fromstart + let a = map(range(11,14), 'foldclosed(v:val)') + call assert_equal([11,11,-1,-1], a) " over-attached 'else' visible + + quit! +endfunc + " vim: shiftwidth=2 sts=2 expandtab diff --git a/src/version.c b/src/version.c index 6f77139a3..4fc7c3c79 100644 --- a/src/version.c +++ b/src/version.c @@ -747,6 +747,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ /**/ + 865, +/**/ 864, /**/ 863, |
