From e35a52aee718c881bdfa69a47a1068df6ab6c60a Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Sun, 31 May 2020 19:48:53 +0200 Subject: patch 8.2.0865: syntax foldlevel is taken from the start of the line Problem: Syntax foldlevel is taken from the start of the line. Solution: Add ":syn foldlevel" to be able to use the minimal foldlevel in the line. (Brad King, closes #6087) --- src/syntax.c | 89 +++++++++++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 82 insertions(+), 7 deletions(-) (limited to 'src/syntax.c') 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) { -- cgit v1.2.1