mirror of
https://github.com/vim/vim.git
synced 2025-09-24 03:44:06 -04:00
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:
@@ -3636,6 +3636,26 @@ DEFINING CASE *:syn-case* *E390*
|
|||||||
:sy[ntax] case
|
:sy[ntax] case
|
||||||
Show either "syntax case match" or "syntax case ignore" (translated).
|
Show either "syntax case match" or "syntax case ignore" (translated).
|
||||||
|
|
||||||
|
|
||||||
|
DEFINING FOLDLEVEL *:syn-foldlevel*
|
||||||
|
|
||||||
|
:sy[ntax] foldlevel [start | minimum]
|
||||||
|
This defines how the foldlevel of a line is computed when using
|
||||||
|
foldmethod=syntax (see |fold-syntax| and |:syn-fold|):
|
||||||
|
|
||||||
|
start: Use level of item containing start of line.
|
||||||
|
minimum: Use lowest local-minimum level of items on line.
|
||||||
|
|
||||||
|
The default is 'start'. Use 'minimum' to search a line horizontally
|
||||||
|
for the lowest level contained on the line that is followed by a
|
||||||
|
higher level. This produces more natural folds when syntax items
|
||||||
|
may close and open horizontally within a line.
|
||||||
|
|
||||||
|
:sy[ntax] foldlevel
|
||||||
|
Show either "syntax foldlevel start" or "syntax foldlevel minimum".
|
||||||
|
|
||||||
|
{not meaningful when Vim was compiled without |+folding| feature}
|
||||||
|
|
||||||
SPELL CHECKING *:syn-spell*
|
SPELL CHECKING *:syn-spell*
|
||||||
|
|
||||||
:sy[ntax] spell [toplevel | notoplevel | default]
|
:sy[ntax] spell [toplevel | notoplevel | default]
|
||||||
@@ -4099,6 +4119,8 @@ This will make each {} block form one fold.
|
|||||||
The fold will start on the line where the item starts, and end where the item
|
The fold will start on the line where the item starts, and end where the item
|
||||||
ends. If the start and end are within the same line, there is no fold.
|
ends. If the start and end are within the same line, there is no fold.
|
||||||
The 'foldnestmax' option limits the nesting of syntax folds.
|
The 'foldnestmax' option limits the nesting of syntax folds.
|
||||||
|
See |:syn-foldlevel| to control how the foldlevel of a line is computed
|
||||||
|
from its syntax items.
|
||||||
{not available when Vim was compiled without |+folding| feature}
|
{not available when Vim was compiled without |+folding| feature}
|
||||||
|
|
||||||
|
|
||||||
|
@@ -2266,6 +2266,10 @@ typedef struct
|
|||||||
#define SYNSPL_TOP 1 // spell check toplevel text
|
#define SYNSPL_TOP 1 // spell check toplevel text
|
||||||
#define SYNSPL_NOTOP 2 // don't 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
|
// avoid #ifdefs for when b_spell is not available
|
||||||
#ifdef FEAT_SPELL
|
#ifdef FEAT_SPELL
|
||||||
# define B_SPELL(buf) ((buf)->b_spell)
|
# define B_SPELL(buf) ((buf)->b_spell)
|
||||||
@@ -2360,6 +2364,7 @@ typedef struct {
|
|||||||
int b_syn_slow; // TRUE when 'redrawtime' reached
|
int b_syn_slow; // TRUE when 'redrawtime' reached
|
||||||
# endif
|
# endif
|
||||||
int b_syn_ic; // ignore case for :syn cmds
|
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
|
int b_syn_spell; // SYNSPL_ values
|
||||||
garray_T b_syn_patterns; // table for syntax patterns
|
garray_T b_syn_patterns; // table for syntax patterns
|
||||||
garray_T b_syn_clusters; // table for syntax clusters
|
garray_T b_syn_clusters; // table for syntax clusters
|
||||||
|
89
src/syntax.c
89
src/syntax.c
@@ -30,6 +30,8 @@
|
|||||||
static char *(spo_name_tab[SPO_COUNT]) =
|
static char *(spo_name_tab[SPO_COUNT]) =
|
||||||
{"ms=", "me=", "hs=", "he=", "rs=", "re=", "lc="};
|
{"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.
|
* The patterns that are being searched for are stored in a syn_pattern.
|
||||||
* A match item consists of one 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)
|
else if (STRNICMP(arg, "off", 3) == 0 && next - arg == 3)
|
||||||
curwin->w_s->b_syn_conceal = FALSE;
|
curwin->w_s->b_syn_conceal = FALSE;
|
||||||
else
|
else
|
||||||
semsg(_("E390: Illegal argument: %s"), arg);
|
semsg(_(e_illegal_arg), arg);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3370,7 +3372,49 @@ syn_cmd_case(exarg_T *eap, int syncing UNUSED)
|
|||||||
else if (STRNICMP(arg, "ignore", 6) == 0 && next - arg == 6)
|
else if (STRNICMP(arg, "ignore", 6) == 0 && next - arg == 6)
|
||||||
curwin->w_s->b_syn_ic = TRUE;
|
curwin->w_s->b_syn_ic = TRUE;
|
||||||
else
|
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;
|
curwin->w_s->b_syn_spell = SYNSPL_DEFAULT;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
semsg(_("E390: Illegal argument: %s"), arg);
|
semsg(_(e_illegal_arg), arg);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3476,6 +3520,7 @@ syntax_clear(synblock_T *block)
|
|||||||
block->b_syn_slow = FALSE; // clear previous timeout
|
block->b_syn_slow = FALSE; // clear previous timeout
|
||||||
#endif
|
#endif
|
||||||
block->b_syn_ic = FALSE; // Use case, by default
|
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_spell = SYNSPL_DEFAULT; // default spell checking
|
||||||
block->b_syn_containedin = FALSE;
|
block->b_syn_containedin = FALSE;
|
||||||
#ifdef FEAT_CONCEAL
|
#ifdef FEAT_CONCEAL
|
||||||
@@ -6192,6 +6237,7 @@ static struct subcommand subcommands[] =
|
|||||||
{"cluster", syn_cmd_cluster},
|
{"cluster", syn_cmd_cluster},
|
||||||
{"conceal", syn_cmd_conceal},
|
{"conceal", syn_cmd_conceal},
|
||||||
{"enable", syn_cmd_enable},
|
{"enable", syn_cmd_enable},
|
||||||
|
{"foldlevel", syn_cmd_foldlevel},
|
||||||
{"include", syn_cmd_include},
|
{"include", syn_cmd_include},
|
||||||
{"iskeyword", syn_cmd_iskeyword},
|
{"iskeyword", syn_cmd_iskeyword},
|
||||||
{"keyword", syn_cmd_keyword},
|
{"keyword", syn_cmd_keyword},
|
||||||
@@ -6489,6 +6535,18 @@ syn_get_stack_item(int i)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(FEAT_FOLDING) || defined(PROTO)
|
#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".
|
* 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)
|
syn_get_foldlevel(win_T *wp, long lnum)
|
||||||
{
|
{
|
||||||
int level = 0;
|
int level = 0;
|
||||||
int i;
|
int low_level;
|
||||||
|
int cur_level;
|
||||||
|
|
||||||
// Return quickly when there are no fold items at all.
|
// Return quickly when there are no fold items at all.
|
||||||
if (wp->w_s->b_syn_folditems != 0
|
if (wp->w_s->b_syn_folditems != 0
|
||||||
@@ -6508,9 +6567,25 @@ syn_get_foldlevel(win_T *wp, long lnum)
|
|||||||
{
|
{
|
||||||
syntax_start(wp, lnum);
|
syntax_start(wp, lnum);
|
||||||
|
|
||||||
for (i = 0; i < current_state.ga_len; ++i)
|
// Start with the fold level at the start of the line.
|
||||||
if (CUR_STATE(i).si_flags & HL_FOLD)
|
level = syn_cur_foldlevel();
|
||||||
++level;
|
|
||||||
|
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)
|
if (level > wp->w_p_fdn)
|
||||||
{
|
{
|
||||||
|
@@ -160,7 +160,7 @@ endfunc
|
|||||||
|
|
||||||
func Test_syntax_completion()
|
func Test_syntax_completion()
|
||||||
call feedkeys(":syn \<C-A>\<C-B>\"\<CR>", 'tx')
|
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 feedkeys(":syn case \<C-A>\<C-B>\"\<CR>", 'tx')
|
||||||
call assert_equal('"syn case ignore match', @:)
|
call assert_equal('"syn case ignore match', @:)
|
||||||
@@ -691,4 +691,87 @@ func Test_syntax_after_bufdo()
|
|||||||
call delete('Xddd.c')
|
call delete('Xddd.c')
|
||||||
endfunc
|
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
|
" vim: shiftwidth=2 sts=2 expandtab
|
||||||
|
@@ -746,6 +746,8 @@ static char *(features[]) =
|
|||||||
|
|
||||||
static int included_patches[] =
|
static int included_patches[] =
|
||||||
{ /* Add new patch number below this line */
|
{ /* Add new patch number below this line */
|
||||||
|
/**/
|
||||||
|
865,
|
||||||
/**/
|
/**/
|
||||||
864,
|
864,
|
||||||
/**/
|
/**/
|
||||||
|
Reference in New Issue
Block a user