1
0
forked from aniani/vim

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)
This commit is contained in:
Bram Moolenaar
2020-05-31 19:48:53 +02:00
parent d881b516da
commit e35a52aee7
5 changed files with 195 additions and 8 deletions

View File

@@ -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

View File

@@ -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)
{

View File

@@ -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

View File

@@ -746,6 +746,8 @@ static char *(features[]) =
static int included_patches[] =
{ /* Add new patch number below this line */
/**/
865,
/**/
864,
/**/