# HG changeset patch # User Bram Moolenaar # Date 1665846904 -7200 # Node ID 40df8a6515f667884e504ad207e5223782255e54 # Parent 46157e3ebe964e6f43087e0bc295e689366af1ae patch 9.0.0761: cannot use 'indentexpr' for Lisp indenting Commit: https://github.com/vim/vim/commit/49846fb1a31de99f49d6a7e70efe685197423c84 Author: Bram Moolenaar Date: Sat Oct 15 16:05:33 2022 +0100 patch 9.0.0761: cannot use 'indentexpr' for Lisp indenting Problem: Cannot use 'indentexpr' for Lisp indenting. Solution: Add the 'lispoptions' option. diff --git a/runtime/doc/options.txt b/runtime/doc/options.txt --- a/runtime/doc/options.txt +++ b/runtime/doc/options.txt @@ -4621,7 +4621,7 @@ A jump table for the options with a shor 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 shor 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 --- 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 --- 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 --- 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 --- 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 --- 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 --- 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 --- 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 --- 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 --- 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\1\2)\" 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\1\2)\" + 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 --- 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,