[PATCH v3] syntax: Add command to control how foldlevel is computed for a line
On 1/30/2017 2:26 PM, Brad King wrote: On 10/17/2016 04:45 PM, Bram Moolenaar wrote: :syntax foldlevel [start | minimum] Thanks. I suppose that's the best way to do it. Here is a revised patch series that now includes tests for the new command. It also updates runtime/syntax/vim.vim to highlight the command syntax. I've posted an updated patch series as a PR: https://github.com/vim/vim/pull/6087 This message is just to connect the history of the work. Changes in v3: * Running just `syntax foldlevel` now responds with the current setting. * Adding extra arguments after `syntax foldlevel ` is now an error. * Dropped the `runtime/syntax/c.vim` patch so there is no change to default behavior in this series. Thanks, -Brad -- -- You received this message from the "vim_dev" maillist. Do not top-post! Type your reply below the text you are replying to. For more information, visit http://www.vim.org/maillist.php --- You received this message because you are subscribed to the Google Groups "vim_dev" group. To unsubscribe from this group and stop receiving emails from it, send an email to vim_dev+unsubscr...@googlegroups.com. To view this discussion on the web visit https://groups.google.com/d/msgid/vim_dev/ca5d69d5-a0e0-3ca0-380e-cc192aa525ad%40kitware.com.
[PATCH v2] syntax: Add command to control how foldlevel is computed for a line
On 10/17/2016 04:45 PM, Bram Moolenaar wrote: >> :syntax foldlevel [start | minimum] > > Thanks. I suppose that's the best way to do it. Here is a revised patch series that now includes tests for the new command. It also updates runtime/syntax/vim.vim to highlight the command syntax. Thanks, -Brad -- -- You received this message from the "vim_dev" maillist. Do not top-post! Type your reply below the text you are replying to. For more information, visit http://www.vim.org/maillist.php --- You received this message because you are subscribed to the Google Groups "vim_dev" group. To unsubscribe from this group and stop receiving emails from it, send an email to vim_dev+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout. >From 5892ea62008d11ad24c07d875c8c4cefa5503c64 Mon Sep 17 00:00:00 2001 Message-Id: <5892ea62008d11ad24c07d875c8c4cefa5503c64.1485803991.git.brad.k...@kitware.com> From: Brad King <brad.k...@kitware.com> Date: Sun, 22 Jan 2017 22:31:35 -0500 Subject: [PATCH v2 1/3] syntax: Add command to control how foldlevel is computed for a line With `foldmethod=syntax` the foldlevel of a line is computed based on syntax items on the line. Previously we always used the level of the syntax item containing the start of the line. This works well in cases such as: if (...) { ... } else if (...) { ... } else { ... } which folds like this: +--- 3 lines: if (...) {--- +--- 3 lines: else if (...) {-- +--- 3 lines: else {--- However, the code: if (...) { ... } else if (...) { ... } else { ... } folds like this: +--- 7 lines: if (...) {--- We can make the latter case fold like this: +--- 2 lines: if (...) {--- +--- 2 lines: } else if (...) { +--- 3 lines: } else {- by choosing on each line the lowest fold level that is followed by a higher fold level. Add a syntax command :syntax foldlevel [start | minimum] to choose between these two methods of computing the foldlevel of a line. --- runtime/doc/syntax.txt | 19 +++ src/structs.h | 5 +++ src/syntax.c| 64 ++--- src/testdir/test_syntax.vim | 77 - 4 files changed, 160 insertions(+), 5 deletions(-) diff --git a/runtime/doc/syntax.txt b/runtime/doc/syntax.txt index e300983f0..c2804ecd9 100644 --- a/runtime/doc/syntax.txt +++ b/runtime/doc/syntax.txt @@ -3482,6 +3482,23 @@ DEFINING CASE *:syn-case* *E390* :sy[ntax] case 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. + + {not meaningful when Vim was compiled without |+folding| feature} + + SPELL CHECKING *:syn-spell* :sy[ntax] spell [toplevel | notoplevel | default] @@ -3945,6 +3962,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 ends. If the start and end are within the same line, there is no fold. 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} diff --git a/src/structs.h b/src/structs.h index af0a6fd2b..97f30bb56 100644 --- a/src/structs.h +++ b/src/structs.h @@ -1736,6 +1736,10 @@ typedef struct list_stack_S #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) @@ -1787,6 +1791,7 @@ typedef struct { hashtab_T b_keywtab_ic; /* idem, ignore case */ int b_syn_error; /* TRUE when error occurred in HL */ int b_syn_ic; /* ignore case for :syn cmds */ +int b_syn_foldlevel; /* how to compute foldlevel on a line */
Re: [PATCH] syntax: Add command to control how foldlevel is computed for a line
On 10/18/2016 08:27 AM, Brad King wrote: > On 10/17/2016 04:45 PM, Bram Moolenaar wrote: >> Thanks. I suppose that's the best way to do it. > > Great. Here is a revised patch. Ping. Thanks, -Brad -- -- You received this message from the "vim_dev" maillist. Do not top-post! Type your reply below the text you are replying to. For more information, visit http://www.vim.org/maillist.php --- You received this message because you are subscribed to the Google Groups "vim_dev" group. To unsubscribe from this group and stop receiving emails from it, send an email to vim_dev+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout.
[PATCH] runtime/syntax/c.vim: Start new folds on '} ... {'
On 10/18/2016 08:27 AM, Brad King wrote: > Here is a revised patch. That patch to add the "syntax foldlevel" command enables the attached update to the C syntax rules. I don't think there is any reason to make it optional within the C syntax rules because the change only makes code styles using attached braces fold like code styles that give braces their own lines. The latter style is not affected at all. Once these are integrated I can update syntax rules for other languages and send patches to their respective maintainers. Thanks, -Brad -- -- You received this message from the "vim_dev" maillist. Do not top-post! Type your reply below the text you are replying to. For more information, visit http://www.vim.org/maillist.php --- You received this message because you are subscribed to the Google Groups "vim_dev" group. To unsubscribe from this group and stop receiving emails from it, send an email to vim_dev+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout. >From 85f3175da34663bc49a1b4fa95c45651938d346d Mon Sep 17 00:00:00 2001 Message-Id: <85f3175da34663bc49a1b4fa95c45651938d346d.1476822940.git.brad.k...@kitware.com> From: Brad King <brad.k...@kitware.com> Date: Tue, 18 Oct 2016 16:27:22 -0400 Subject: [PATCH] runtime/syntax/c.vim: Start new folds on '} ... {' Update the C syntax rules so that the code if (...) { ... } else if (...) { ... } else { ... } folds like this: +--- 2 lines: if (...) {--- +--- 2 lines: } else if (...) { +--- 3 lines: } else {- even though the nesting level at the start of the `else` lines does not change. This makes folding of code using attached braces consistent with the same code using braces on their own line. --- runtime/syntax/c.vim | 3 +++ 1 file changed, 3 insertions(+) diff --git a/runtime/syntax/c.vim b/runtime/syntax/c.vim index 57d99ab..c92b206 100644 --- a/runtime/syntax/c.vim +++ b/runtime/syntax/c.vim @@ -13,6 +13,9 @@ set cpo let s:ft = matchstr(, '^\([^.]\)\+') +" Start new folds on lines of the form '} ... {' +syn foldlevel minimum + " A bunch of useful C keywords syn keyword cStatement goto break return continue asm syn keyword cLabel case default -- 2.9.3
Re: [PATCH] syntax: Add command to control how foldlevel is computed for a line
On 10/17/2016 04:45 PM, Bram Moolenaar wrote: > Brad King wrote: >> I've revised the change to add a new syntax command: >> >> :syntax foldlevel [start | minimum] >> >> that can be used to enable this. > > Thanks. I suppose that's the best way to do it. Great. I realized that the "syntax foldlevel" command itself should not be conditioned on FEAT_FOLDING because clients should not have to switch on the existence of the feature before calling it. Here is a revised patch. Now the documentation simply says that the command is not meaningful when folding is not available. Thanks, -Brad -- -- You received this message from the "vim_dev" maillist. Do not top-post! Type your reply below the text you are replying to. For more information, visit http://www.vim.org/maillist.php --- You received this message because you are subscribed to the Google Groups "vim_dev" group. To unsubscribe from this group and stop receiving emails from it, send an email to vim_dev+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout. >From 617860554d40293a40ef757b4404073769fe0bca Mon Sep 17 00:00:00 2001 Message-Id: <617860554d40293a40ef757b4404073769fe0bca.1476793464.git.brad.k...@kitware.com> From: Brad King <brad.k...@kitware.com> Date: Mon, 17 Oct 2016 13:42:53 -0400 Subject: [PATCH] syntax: Add command to control how foldlevel is computed for a line With `foldmethod=syntax` the foldlevel of a line is computed based on syntax items on the line. Previously we always used the level of the syntax item containing the start of the line. This works well in cases such as: if (...) { ... } else if (...) { ... } else { ... } which folds like this: +--- 3 lines: if (...) {--- +--- 3 lines: else if (...) {-- +--- 3 lines: else {--- However, the code: if (...) { ... } else if (...) { ... } else { ... } folds like this: +--- 7 lines: if (...) {--- We can make the latter case fold like this: +--- 2 lines: if (...) {--- +--- 2 lines: } else if (...) { +--- 3 lines: } else {- by choosing on each line the lowest fold level that is followed by a higher fold level. Add a syntax command :syntax foldlevel [start | minimum] to choose between these two methods of computing the foldlevel of a line. --- runtime/doc/syntax.txt | 19 +++ src/structs.h | 5 src/syntax.c | 64 ++ 3 files changed, 84 insertions(+), 4 deletions(-) diff --git a/runtime/doc/syntax.txt b/runtime/doc/syntax.txt index ae80a44..177f645 100644 --- a/runtime/doc/syntax.txt +++ b/runtime/doc/syntax.txt @@ -3480,6 +3480,23 @@ DEFINING CASE *:syn-case* *E390* items until the next ":syntax case" command are affected. +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. + + {not meaningful when Vim was compiled without |+folding| feature} + + SPELL CHECKING *:syn-spell* :sy[ntax] spell [toplevel | notoplevel | default] @@ -3938,6 +3955,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 ends. If the start and end are within the same line, there is no fold. 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} diff --git a/src/structs.h b/src/structs.h index 7a4d7fb..184f316 100644 --- a/src/structs.h +++ b/src/structs.h @@ -1710,6 +1710,10 @@ typedef struct list_stack_S #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) @@ -1761,6 +1765,7 @@ typedef struct { hashtab_T b_keywtab_ic; /* ide
[PATCH] syntax: Add command to control how foldlevel is computed for a line
On 10/14/2016 04:04 PM, Bram Moolenaar wrote: > Either this needs to be donein the C syntax, or we need an folding > option to enable this behavior. Thanks for taking a look. It can't currently be done purely in syntax definitions so I've revised the change to add a new syntax command: :syntax foldlevel [start | minimum] that can be used to enable this. With this we will later be able to edit `runtime/syntax/c.vim` (and possibly others) to add: syntax foldlevel minimum (possibly guarded by an option) in order to get this folding behavior. Thanks, -Brad -- -- You received this message from the "vim_dev" maillist. Do not top-post! Type your reply below the text you are replying to. For more information, visit http://www.vim.org/maillist.php --- You received this message because you are subscribed to the Google Groups "vim_dev" group. To unsubscribe from this group and stop receiving emails from it, send an email to vim_dev+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout. >From c43347369e3eebc63613801052002c1c89383abd Mon Sep 17 00:00:00 2001 Message-Id: <c43347369e3eebc63613801052002c1c89383abd.1476727922.git.brad.k...@kitware.com> From: Brad King <brad.k...@kitware.com> Date: Mon, 17 Oct 2016 13:42:53 -0400 Subject: [PATCH] syntax: Add command to control how foldlevel is computed for a line With `foldmethod=syntax` the foldlevel of a line is computed based on syntax items on the line. Previously we always used the level of the syntax item containing the start of the line. This works well in cases such as: if (...) { ... } else if (...) { ... } else { ... } which folds like this: +--- 3 lines: if (...) {--- +--- 3 lines: else if (...) {-- +--- 3 lines: else {--- However, the code: if (...) { ... } else if (...) { ... } else { ... } folds like this: +--- 7 lines: if (...) {--- We can make the latter case fold like this: +--- 2 lines: if (...) {--- +--- 2 lines: } else if (...) { +--- 3 lines: } else {- by choosing on each line the lowest fold level that is followed by a higher fold level. Add a syntax command :syntax foldlevel [start | minimum] to choose between these two methods of computing the foldlevel of a line. --- runtime/doc/syntax.txt | 19 ++ src/structs.h | 7 + src/syntax.c | 70 +++--- 3 files changed, 92 insertions(+), 4 deletions(-) diff --git a/runtime/doc/syntax.txt b/runtime/doc/syntax.txt index ae80a44..2cf4b54 100644 --- a/runtime/doc/syntax.txt +++ b/runtime/doc/syntax.txt @@ -3480,6 +3480,23 @@ DEFINING CASE *:syn-case* *E390* items until the next ":syntax case" command are affected. +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. + + {not available when Vim was compiled without |+folding| feature} + + SPELL CHECKING *:syn-spell* :sy[ntax] spell [toplevel | notoplevel | default] @@ -3938,6 +3955,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 ends. If the start and end are within the same line, there is no fold. 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} diff --git a/src/structs.h b/src/structs.h index 7a4d7fb..6a76cf1 100644 --- a/src/structs.h +++ b/src/structs.h @@ -1710,6 +1710,12 @@ typedef struct list_stack_S #define SYNSPL_TOP 1 /* spell check toplevel text */ #define SYNSPL_NOTOP 2 /* don't spell check toplevel text */ +#ifdef FEAT_FOLDING +/* 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 */ +#endif + /* avoid #ifdefs for when b_spell is not available */ #ifdef FEAT_SPELL # define B_SPELL(buf) ((buf)->b_spell) @@ -1786,6 +1792,7 @@ typedef struct { # ifdef FEAT_FOLDING int b_syn_folditems; /* number of p
[PATCH] syntax: Improve foldlevel on lines where it changes horizontally
Hi Folks, I'd like to improve C-syntax folding for a common code format style. With `foldmethod=syntax` the code: if (...) { ... } else if (...) { ... } else { ... } folds like this: +--- 3 lines: if (...) {--- +--- 3 lines: else if (...) {-- +--- 3 lines: else {--- However, the code: if (...) { ... } else if (...) { ... } else { ... } folds like this: +--- 7 lines: if (...) {--- We can make the latter case fold like this: +--- 2 lines: if (...) {--- +--- 2 lines: } else if (...) { +--- 3 lines: } else {- by choosing on each line the lowest fold level that is followed by a higher fold level. Please see patch attached. FWIW I've been running with this patch for months to test it. Thanks, -Brad -- -- You received this message from the "vim_dev" maillist. Do not top-post! Type your reply below the text you are replying to. For more information, visit http://www.vim.org/maillist.php --- You received this message because you are subscribed to the Google Groups "vim_dev" group. To unsubscribe from this group and stop receiving emails from it, send an email to vim_dev+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout. >From 5f1a9107cf9a9732d7f827cd66928b8565fe6a72 Mon Sep 17 00:00:00 2001 Message-Id: <5f1a9107cf9a9732d7f827cd66928b8565fe6a72.1476457236.git.brad.k...@kitware.com> From: Brad King <brad.k...@kitware.com> Date: Wed, 11 May 2016 21:51:34 -0400 Subject: [PATCH] syntax: Improve foldlevel on lines where it changes horizontally With `foldmethod=syntax` the code: if (...) { ... } else if (...) { ... } else { ... } folds like this: +--- 3 lines: if (...) {--- +--- 3 lines: else if (...) {-- +--- 3 lines: else {--- However, the code: if (...) { ... } else if (...) { ... } else { ... } folds like this: +--- 7 lines: if (...) {--- We can make the latter case fold like this: +--- 2 lines: if (...) {--- +--- 2 lines: } else if (...) { +--- 3 lines: } else {- by choosing on each line the lowest fold level that is followed by a higher fold level. --- src/syntax.c | 33 + 1 file changed, 29 insertions(+), 4 deletions(-) diff --git a/src/syntax.c b/src/syntax.c index 75ede36..c0c87f8 100644 --- a/src/syntax.c +++ b/src/syntax.c @@ -6537,6 +6537,17 @@ 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". */ @@ -6544,16 +6555,30 @@ 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) { 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. */ + cur_level = syn_cur_foldlevel(); + level = cur_level; + low_level = cur_level; + + /* Find the lowest fold level that is followed by a higher one. */ + 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) { -- 2.9.3