summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBram Moolenaar <Bram@vim.org>2022-10-15 16:05:33 +0100
committerBram Moolenaar <Bram@vim.org>2022-10-15 16:05:33 +0100
commit49846fb1a31de99f49d6a7e70efe685197423c84 (patch)
tree98b3debbaafbd79b05fe941382086792c1aab8ba
parent297164cb7972beff35e375ccac4fbad8196ccbd7 (diff)
patch 9.0.0761: cannot use 'indentexpr' for Lisp indentingv9.0.0761
Problem: Cannot use 'indentexpr' for Lisp indenting. Solution: Add the 'lispoptions' option.
-rw-r--r--runtime/doc/options.txt13
-rw-r--r--src/buffer.c1
-rw-r--r--src/change.c29
-rw-r--r--src/indent.c28
-rw-r--r--src/option.c3
-rw-r--r--src/option.h2
-rw-r--r--src/optiondefs.h16
-rw-r--r--src/optionstr.c9
-rw-r--r--src/proto/indent.pro1
-rw-r--r--src/testdir/test_lispindent.vim15
-rw-r--r--src/version.c2
11 files changed, 95 insertions, 24 deletions
diff --git a/runtime/doc/options.txt b/runtime/doc/options.txt
index 6f479bdc95..9ecb64e59a 100644
--- a/runtime/doc/options.txt
+++ b/runtime/doc/options.txt
@@ -4621,7 +4621,7 @@ A jump table for the options with a short description can be found at |Q_op|.
in Insert mode as specified with the 'indentkeys' option.
When this option is not empty, it overrules the 'cindent' and
'smartindent' indenting. When 'lisp' is set, this option is
- overridden by the Lisp indentation algorithm.
+ is only used when 'lispoptions' contains "expr:1".
When 'paste' is set this option is not used for indenting.
The expression is evaluated with |v:lnum| set to the line number for
which the indent is to be computed. The cursor is also in this line
@@ -5063,6 +5063,17 @@ A jump table for the options with a short description can be found at |Q_op|.
calling an external program if 'equalprg' is empty.
This option is not used when 'paste' is set.
+ *'lispoptions'* *'lop'*
+'lispoptions' 'lop' string (default "")
+ local to buffer
+ Comma-separated list of items that influence the Lisp indenting when
+ enabled with the |'lisp'| option. Currently only one item is
+ supported:
+ expr:1 use 'indentexpr' for Lisp indenting when it is set
+ expr:0 do not use 'indentexpr' for Lisp indenting (default)
+ Note that when using 'indentexpr' the `=` operator indents all the
+ lines, otherwise the first line is not indented (Vi-compatible).
+
*'lispwords'* *'lw'*
'lispwords' 'lw' string (default is very long)
global or local to buffer |global-local|
diff --git a/src/buffer.c b/src/buffer.c
index 5f8512ae92..0849b70997 100644
--- a/src/buffer.c
+++ b/src/buffer.c
@@ -2390,6 +2390,7 @@ free_buf_options(
clear_string_option(&buf->b_p_ft);
clear_string_option(&buf->b_p_cink);
clear_string_option(&buf->b_p_cino);
+ clear_string_option(&buf->b_p_lop);
clear_string_option(&buf->b_p_cinsd);
clear_string_option(&buf->b_p_cinw);
clear_string_option(&buf->b_p_cpt);
diff --git a/src/change.c b/src/change.c
index c409acdadd..f036a3767c 100644
--- a/src/change.c
+++ b/src/change.c
@@ -2269,20 +2269,23 @@ open_line(
else
vreplace_mode = 0;
- if (!p_paste
- && leader == NULL
- && curbuf->b_p_lisp
- && curbuf->b_p_ai)
+ if (!p_paste)
{
- // do lisp indenting
- fixthisline(get_lisp_indent);
- ai_col = (colnr_T)getwhitecols_curline();
- }
- else if (do_cindent)
- {
- // do 'cindent' or 'indentexpr' indenting
- do_c_expr_indent();
- ai_col = (colnr_T)getwhitecols_curline();
+ if (leader == NULL
+ && !use_indentexpr_for_lisp()
+ && curbuf->b_p_lisp
+ && curbuf->b_p_ai)
+ {
+ // do lisp indenting
+ fixthisline(get_lisp_indent);
+ ai_col = (colnr_T)getwhitecols_curline();
+ }
+ else if (do_cindent || (curbuf->b_p_ai && use_indentexpr_for_lisp()))
+ {
+ // do 'cindent' or 'indentexpr' indenting
+ do_c_expr_indent();
+ ai_col = (colnr_T)getwhitecols_curline();
+ }
}
if (vreplace_mode != 0)
diff --git a/src/indent.c b/src/indent.c
index c6e3aaf33d..aaf3caafc4 100644
--- a/src/indent.c
+++ b/src/indent.c
@@ -2197,18 +2197,38 @@ fixthisline(int (*get_the_indent)(void))
}
/*
+ * Return TRUE if 'indentexpr' should be used for Lisp indenting.
+ * Caller may want to check 'autoindent'.
+ */
+ int
+use_indentexpr_for_lisp(void)
+{
+#ifdef FEAT_EVAL
+ return curbuf->b_p_lisp
+ && *curbuf->b_p_inde != NUL
+ && STRCMP(curbuf->b_p_lop, "expr:1") == 0;
+#else
+ return FALSE;
+#endif
+}
+
+/*
* Fix indent for 'lisp' and 'cindent'.
*/
void
fix_indent(void)
{
if (p_paste)
- return;
+ return; // no auto-indenting when 'paste' is set
if (curbuf->b_p_lisp && curbuf->b_p_ai)
- fixthisline(get_lisp_indent);
- else
- if (cindent_on())
+ {
+ if (use_indentexpr_for_lisp())
do_c_expr_indent();
+ else
+ fixthisline(get_lisp_indent);
+ }
+ else if (cindent_on())
+ do_c_expr_indent();
}
#if defined(FEAT_EVAL) || defined(PROTO)
diff --git a/src/option.c b/src/option.c
index 85a55f987c..3297810080 100644
--- a/src/option.c
+++ b/src/option.c
@@ -5518,6 +5518,7 @@ get_varp(struct vimoption *p)
case PV_KEY: return (char_u *)&(curbuf->b_p_key);
#endif
case PV_LISP: return (char_u *)&(curbuf->b_p_lisp);
+ case PV_LOP: return (char_u *)&(curbuf->b_p_lop);
case PV_ML: return (char_u *)&(curbuf->b_p_ml);
case PV_MPS: return (char_u *)&(curbuf->b_p_mps);
case PV_MA: return (char_u *)&(curbuf->b_p_ma);
@@ -6047,6 +6048,8 @@ buf_copy_options(buf_T *buf, int flags)
COPY_OPT_SCTX(buf, BV_CINO);
buf->b_p_cinsd = vim_strsave(p_cinsd);
COPY_OPT_SCTX(buf, BV_CINSD);
+ buf->b_p_lop = vim_strsave(p_lop);
+ COPY_OPT_SCTX(buf, BV_LOP);
// Don't copy 'filetype', it must be detected
buf->b_p_ft = empty_option;
diff --git a/src/option.h b/src/option.h
index 6d05f0e299..e266d387ea 100644
--- a/src/option.h
+++ b/src/option.h
@@ -709,6 +709,7 @@ EXTERN char_u *p_lm; // 'langmenu'
EXTERN long p_linespace; // 'linespace'
#endif
EXTERN int p_lisp; // 'lisp'
+EXTERN char_u *p_lop; // 'lispoptions'
EXTERN char_u *p_lispwords; // 'lispwords'
EXTERN long p_ls; // 'laststatus'
EXTERN long p_stal; // 'showtabline'
@@ -1155,6 +1156,7 @@ enum
#endif
, BV_KP
, BV_LISP
+ , BV_LOP
, BV_LW
, BV_MENC
, BV_MA
diff --git a/src/optiondefs.h b/src/optiondefs.h
index db85a39891..9ea8602905 100644
--- a/src/optiondefs.h
+++ b/src/optiondefs.h
@@ -41,17 +41,17 @@
#define PV_BOMB OPT_BUF(BV_BOMB)
#define PV_CI OPT_BUF(BV_CI)
#define PV_CIN OPT_BUF(BV_CIN)
-#define PV_CINK OPT_BUF(BV_CINK)
-#define PV_CINO OPT_BUF(BV_CINO)
+#define PV_CINK OPT_BUF(BV_CINK)
+#define PV_CINO OPT_BUF(BV_CINO)
#define PV_CINSD OPT_BUF(BV_CINSD)
-#define PV_CINW OPT_BUF(BV_CINW)
+#define PV_CINW OPT_BUF(BV_CINW)
#define PV_CM OPT_BOTH(OPT_BUF(BV_CM))
#ifdef FEAT_FOLDING
# define PV_CMS OPT_BUF(BV_CMS)
#endif
#define PV_COM OPT_BUF(BV_COM)
#define PV_CPT OPT_BUF(BV_CPT)
-#define PV_DICT OPT_BOTH(OPT_BUF(BV_DICT))
+#define PV_DICT OPT_BOTH(OPT_BUF(BV_DICT))
#define PV_TSR OPT_BOTH(OPT_BUF(BV_TSR))
#define PV_CSL OPT_BUF(BV_CSL)
#ifdef FEAT_COMPL_FUNC
@@ -95,7 +95,8 @@
# define PV_KMAP OPT_BUF(BV_KMAP)
#endif
#define PV_KP OPT_BOTH(OPT_BUF(BV_KP))
-#define PV_LISP OPT_BUF(BV_LISP)
+#define PV_LISP OPT_BUF(BV_LISP)
+#define PV_LOP OPT_BUF(BV_LOP)
#define PV_LW OPT_BOTH(OPT_BUF(BV_LW))
#define PV_MENC OPT_BOTH(OPT_BUF(BV_MENC))
#define PV_MA OPT_BUF(BV_MA)
@@ -142,7 +143,7 @@
#endif
#define PV_WM OPT_BUF(BV_WM)
#ifdef FEAT_VARTABS
-# define PV_VSTS OPT_BUF(BV_VSTS)
+# define PV_VSTS OPT_BUF(BV_VSTS)
# define PV_VTS OPT_BUF(BV_VTS)
#endif
@@ -1522,6 +1523,9 @@ static struct vimoption options[] =
{"lisp", NULL, P_BOOL|P_VI_DEF,
(char_u *)&p_lisp, PV_LISP,
{(char_u *)FALSE, (char_u *)0L} SCTX_INIT},
+ {"lispoptions", "lop", P_STRING|P_ALLOCED|P_VI_DEF|P_ONECOMMA|P_NODUP,
+ (char_u *)&p_lop, PV_LOP,
+ {(char_u *)"", (char_u *)0L} SCTX_INIT},
{"lispwords", "lw", P_STRING|P_VI_DEF|P_ONECOMMA|P_NODUP,
(char_u *)&p_lispwords, PV_LW,
{(char_u *)LISPWORD_VALUE, (char_u *)0L} SCTX_INIT},
diff --git a/src/optionstr.c b/src/optionstr.c
index 32663a03e7..9e9d18f0e3 100644
--- a/src/optionstr.c
+++ b/src/optionstr.c
@@ -259,6 +259,7 @@ check_buf_options(buf_T *buf)
check_string_option(&buf->b_p_cino);
check_string_option(&buf->b_p_cinsd);
parse_cino(buf);
+ check_string_option(&buf->b_p_lop);
check_string_option(&buf->b_p_ft);
check_string_option(&buf->b_p_cinw);
check_string_option(&buf->b_p_cpt);
@@ -2102,6 +2103,14 @@ did_set_string_option(
parse_cino(curbuf);
}
+ // 'lispoptions'
+ else if (gvarp == &p_lop)
+ {
+ if (**varp != NUL && STRCMP(*varp, "expr:0") != 0
+ && STRCMP(*varp, "expr:1") != 0)
+ errmsg = e_invalid_argument;
+ }
+
#if defined(FEAT_RENDER_OPTIONS)
// 'renderoptions'
else if (varp == &p_rop)
diff --git a/src/proto/indent.pro b/src/proto/indent.pro
index 2702f40ab7..5ab338dce2 100644
--- a/src/proto/indent.pro
+++ b/src/proto/indent.pro
@@ -31,6 +31,7 @@ void ex_retab(exarg_T *eap);
int get_expr_indent(void);
int get_lisp_indent(void);
void fixthisline(int (*get_the_indent)(void));
+int use_indentexpr_for_lisp(void);
void fix_indent(void);
void f_indent(typval_T *argvars, typval_T *rettv);
void f_lispindent(typval_T *argvars, typval_T *rettv);
diff --git a/src/testdir/test_lispindent.vim b/src/testdir/test_lispindent.vim
index 3c8660e0ab..770c50115e 100644
--- a/src/testdir/test_lispindent.vim
+++ b/src/testdir/test_lispindent.vim
@@ -97,8 +97,23 @@ func Test_lispindent_with_indentexpr()
exe "normal a(x\<CR>1\<CR>2)\<Esc>"
let expected = ['(x', ' 1', ' 2)']
call assert_equal(expected, getline(1, 3))
+ " with Lisp indenting the first line is not indented
normal 1G=G
call assert_equal(expected, getline(1, 3))
+
+ %del
+ setl lispoptions=expr:1 indentexpr=5
+ exe "normal a(x\<CR>1\<CR>2)\<Esc>"
+ let expected_expr = ['(x', ' 1', ' 2)']
+ call assert_equal(expected_expr, getline(1, 3))
+ normal 2G2<<=G
+ call assert_equal(expected_expr, getline(1, 3))
+
+ setl lispoptions=expr:0
+ " with Lisp indenting the first line is not indented
+ normal 1G3<<=G
+ call assert_equal(expected, getline(1, 3))
+
bwipe!
endfunc
diff --git a/src/version.c b/src/version.c
index 0ccdf46360..6e602bea3a 100644
--- a/src/version.c
+++ b/src/version.c
@@ -696,6 +696,8 @@ static char *(features[]) =
static int included_patches[] =
{ /* Add new patch number below this line */
/**/
+ 761,
+/**/
760,
/**/
759,