aboutsummaryrefslogtreecommitdiff
path: root/src/nvim/syntax.c
diff options
context:
space:
mode:
authorBrad King <brad.king@kitware.com>2020-04-06 16:12:00 -0400
committerBrad King <brad.king@kitware.com>2020-06-23 19:07:33 -0400
commit357c16515c13eac99c5f2bc1ba5ac1ccc8afceec (patch)
tree08b2ab88415bdb26baf2e1ea9c1449ff3a9d9adf /src/nvim/syntax.c
parentee3605aed450f6ee7fe8fd62ed372e1aa3919c4c (diff)
downloadrneovim-357c16515c13eac99c5f2bc1ba5ac1ccc8afceec.tar.gz
rneovim-357c16515c13eac99c5f2bc1ba5ac1ccc8afceec.tar.bz2
rneovim-357c16515c13eac99c5f2bc1ba5ac1ccc8afceec.zip
vim-patch:8.2.0865 syntax: Add command to control how foldlevel is computed
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. https://github.com/vim/vim/commit/e35a52aee718c881bdfa69a47a1068df6ab6c60a 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.
Diffstat (limited to 'src/nvim/syntax.c')
-rw-r--r--src/nvim/syntax.c54
1 files changed, 54 insertions, 0 deletions
diff --git a/src/nvim/syntax.c b/src/nvim/syntax.c
index 41b8ebe4a2..4aa7c21ce4 100644
--- a/src/nvim/syntax.c
+++ b/src/nvim/syntax.c
@@ -3079,6 +3079,41 @@ static void syn_cmd_case(exarg_T *eap, int syncing)
}
}
+/// Handle ":syntax foldlevel" command.
+static void syn_cmd_foldlevel(exarg_T *eap, int syncing)
+{
+ 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 {
+ EMSG2(_(e_illegal_arg), arg);
+ return;
+ }
+
+ arg = skipwhite(arg_end);
+ if (*arg != NUL) {
+ EMSG2(_(e_illegal_arg), arg);
+ }
+}
+
/*
* Handle ":syntax spell" command.
*/
@@ -3163,6 +3198,7 @@ void syntax_clear(synblock_T *block)
block->b_syn_error = false; // clear previous error
block->b_syn_slow = false; // clear previous timeout
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;
block->b_syn_conceal = false;
@@ -5487,6 +5523,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 },
@@ -5789,7 +5826,24 @@ int syn_get_foldlevel(win_T *wp, long lnum)
&& !wp->w_s->b_syn_slow) {
syntax_start(wp, lnum);
+ // 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.
+ int cur_level = level;
+ int 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) {
level = wp->w_p_fdn;