Problem: Cannot use 'indentexpr' for Lisp indenting.
Solution: Add the 'lispoptions' option.
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
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|
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);
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)
}
}
+/*
+ * 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'.
*/
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)
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);
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;
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'
#endif
, BV_KP
, BV_LISP
+ , BV_LOP
, BV_LW
, BV_MENC
, BV_MA
#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
# 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)
#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
{"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},
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);
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)
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);
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
static int included_patches[] =
{ /* Add new patch number below this line */
+/**/
+ 761,
/**/
760,
/**/