Skip to content

Commit 49846fb

Browse files
committed
patch 9.0.0761: cannot use 'indentexpr' for Lisp indenting
Problem: Cannot use 'indentexpr' for Lisp indenting. Solution: Add the 'lispoptions' option.
1 parent 297164c commit 49846fb

File tree

11 files changed

+95
-24
lines changed

11 files changed

+95
-24
lines changed

runtime/doc/options.txt

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4621,7 +4621,7 @@ A jump table for the options with a short description can be found at |Q_op|.
46214621
in Insert mode as specified with the 'indentkeys' option.
46224622
When this option is not empty, it overrules the 'cindent' and
46234623
'smartindent' indenting. When 'lisp' is set, this option is
4624-
overridden by the Lisp indentation algorithm.
4624+
is only used when 'lispoptions' contains "expr:1".
46254625
When 'paste' is set this option is not used for indenting.
46264626
The expression is evaluated with |v:lnum| set to the line number for
46274627
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|.
50635063
calling an external program if 'equalprg' is empty.
50645064
This option is not used when 'paste' is set.
50655065

5066+
*'lispoptions'* *'lop'*
5067+
'lispoptions' 'lop' string (default "")
5068+
local to buffer
5069+
Comma-separated list of items that influence the Lisp indenting when
5070+
enabled with the |'lisp'| option. Currently only one item is
5071+
supported:
5072+
expr:1 use 'indentexpr' for Lisp indenting when it is set
5073+
expr:0 do not use 'indentexpr' for Lisp indenting (default)
5074+
Note that when using 'indentexpr' the `=` operator indents all the
5075+
lines, otherwise the first line is not indented (Vi-compatible).
5076+
50665077
*'lispwords'* *'lw'*
50675078
'lispwords' 'lw' string (default is very long)
50685079
global or local to buffer |global-local|

src/buffer.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2390,6 +2390,7 @@ free_buf_options(
23902390
clear_string_option(&buf->b_p_ft);
23912391
clear_string_option(&buf->b_p_cink);
23922392
clear_string_option(&buf->b_p_cino);
2393+
clear_string_option(&buf->b_p_lop);
23932394
clear_string_option(&buf->b_p_cinsd);
23942395
clear_string_option(&buf->b_p_cinw);
23952396
clear_string_option(&buf->b_p_cpt);

src/change.c

Lines changed: 16 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2269,20 +2269,23 @@ open_line(
22692269
else
22702270
vreplace_mode = 0;
22712271

2272-
if (!p_paste
2273-
&& leader == NULL
2274-
&& curbuf->b_p_lisp
2275-
&& curbuf->b_p_ai)
2272+
if (!p_paste)
22762273
{
2277-
// do lisp indenting
2278-
fixthisline(get_lisp_indent);
2279-
ai_col = (colnr_T)getwhitecols_curline();
2280-
}
2281-
else if (do_cindent)
2282-
{
2283-
// do 'cindent' or 'indentexpr' indenting
2284-
do_c_expr_indent();
2285-
ai_col = (colnr_T)getwhitecols_curline();
2274+
if (leader == NULL
2275+
&& !use_indentexpr_for_lisp()
2276+
&& curbuf->b_p_lisp
2277+
&& curbuf->b_p_ai)
2278+
{
2279+
// do lisp indenting
2280+
fixthisline(get_lisp_indent);
2281+
ai_col = (colnr_T)getwhitecols_curline();
2282+
}
2283+
else if (do_cindent || (curbuf->b_p_ai && use_indentexpr_for_lisp()))
2284+
{
2285+
// do 'cindent' or 'indentexpr' indenting
2286+
do_c_expr_indent();
2287+
ai_col = (colnr_T)getwhitecols_curline();
2288+
}
22862289
}
22872290

22882291
if (vreplace_mode != 0)

src/indent.c

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2196,19 +2196,39 @@ fixthisline(int (*get_the_indent)(void))
21962196
}
21972197
}
21982198

2199+
/*
2200+
* Return TRUE if 'indentexpr' should be used for Lisp indenting.
2201+
* Caller may want to check 'autoindent'.
2202+
*/
2203+
int
2204+
use_indentexpr_for_lisp(void)
2205+
{
2206+
#ifdef FEAT_EVAL
2207+
return curbuf->b_p_lisp
2208+
&& *curbuf->b_p_inde != NUL
2209+
&& STRCMP(curbuf->b_p_lop, "expr:1") == 0;
2210+
#else
2211+
return FALSE;
2212+
#endif
2213+
}
2214+
21992215
/*
22002216
* Fix indent for 'lisp' and 'cindent'.
22012217
*/
22022218
void
22032219
fix_indent(void)
22042220
{
22052221
if (p_paste)
2206-
return;
2222+
return; // no auto-indenting when 'paste' is set
22072223
if (curbuf->b_p_lisp && curbuf->b_p_ai)
2208-
fixthisline(get_lisp_indent);
2209-
else
2210-
if (cindent_on())
2224+
{
2225+
if (use_indentexpr_for_lisp())
22112226
do_c_expr_indent();
2227+
else
2228+
fixthisline(get_lisp_indent);
2229+
}
2230+
else if (cindent_on())
2231+
do_c_expr_indent();
22122232
}
22132233

22142234
#if defined(FEAT_EVAL) || defined(PROTO)

src/option.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5518,6 +5518,7 @@ get_varp(struct vimoption *p)
55185518
case PV_KEY: return (char_u *)&(curbuf->b_p_key);
55195519
#endif
55205520
case PV_LISP: return (char_u *)&(curbuf->b_p_lisp);
5521+
case PV_LOP: return (char_u *)&(curbuf->b_p_lop);
55215522
case PV_ML: return (char_u *)&(curbuf->b_p_ml);
55225523
case PV_MPS: return (char_u *)&(curbuf->b_p_mps);
55235524
case PV_MA: return (char_u *)&(curbuf->b_p_ma);
@@ -6047,6 +6048,8 @@ buf_copy_options(buf_T *buf, int flags)
60476048
COPY_OPT_SCTX(buf, BV_CINO);
60486049
buf->b_p_cinsd = vim_strsave(p_cinsd);
60496050
COPY_OPT_SCTX(buf, BV_CINSD);
6051+
buf->b_p_lop = vim_strsave(p_lop);
6052+
COPY_OPT_SCTX(buf, BV_LOP);
60506053

60516054
// Don't copy 'filetype', it must be detected
60526055
buf->b_p_ft = empty_option;

src/option.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -709,6 +709,7 @@ EXTERN char_u *p_lm; // 'langmenu'
709709
EXTERN long p_linespace; // 'linespace'
710710
#endif
711711
EXTERN int p_lisp; // 'lisp'
712+
EXTERN char_u *p_lop; // 'lispoptions'
712713
EXTERN char_u *p_lispwords; // 'lispwords'
713714
EXTERN long p_ls; // 'laststatus'
714715
EXTERN long p_stal; // 'showtabline'
@@ -1155,6 +1156,7 @@ enum
11551156
#endif
11561157
, BV_KP
11571158
, BV_LISP
1159+
, BV_LOP
11581160
, BV_LW
11591161
, BV_MENC
11601162
, BV_MA

src/optiondefs.h

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -41,17 +41,17 @@
4141
#define PV_BOMB OPT_BUF(BV_BOMB)
4242
#define PV_CI OPT_BUF(BV_CI)
4343
#define PV_CIN OPT_BUF(BV_CIN)
44-
#define PV_CINK OPT_BUF(BV_CINK)
45-
#define PV_CINO OPT_BUF(BV_CINO)
44+
#define PV_CINK OPT_BUF(BV_CINK)
45+
#define PV_CINO OPT_BUF(BV_CINO)
4646
#define PV_CINSD OPT_BUF(BV_CINSD)
47-
#define PV_CINW OPT_BUF(BV_CINW)
47+
#define PV_CINW OPT_BUF(BV_CINW)
4848
#define PV_CM OPT_BOTH(OPT_BUF(BV_CM))
4949
#ifdef FEAT_FOLDING
5050
# define PV_CMS OPT_BUF(BV_CMS)
5151
#endif
5252
#define PV_COM OPT_BUF(BV_COM)
5353
#define PV_CPT OPT_BUF(BV_CPT)
54-
#define PV_DICT OPT_BOTH(OPT_BUF(BV_DICT))
54+
#define PV_DICT OPT_BOTH(OPT_BUF(BV_DICT))
5555
#define PV_TSR OPT_BOTH(OPT_BUF(BV_TSR))
5656
#define PV_CSL OPT_BUF(BV_CSL)
5757
#ifdef FEAT_COMPL_FUNC
@@ -95,7 +95,8 @@
9595
# define PV_KMAP OPT_BUF(BV_KMAP)
9696
#endif
9797
#define PV_KP OPT_BOTH(OPT_BUF(BV_KP))
98-
#define PV_LISP OPT_BUF(BV_LISP)
98+
#define PV_LISP OPT_BUF(BV_LISP)
99+
#define PV_LOP OPT_BUF(BV_LOP)
99100
#define PV_LW OPT_BOTH(OPT_BUF(BV_LW))
100101
#define PV_MENC OPT_BOTH(OPT_BUF(BV_MENC))
101102
#define PV_MA OPT_BUF(BV_MA)
@@ -142,7 +143,7 @@
142143
#endif
143144
#define PV_WM OPT_BUF(BV_WM)
144145
#ifdef FEAT_VARTABS
145-
# define PV_VSTS OPT_BUF(BV_VSTS)
146+
# define PV_VSTS OPT_BUF(BV_VSTS)
146147
# define PV_VTS OPT_BUF(BV_VTS)
147148
#endif
148149

@@ -1522,6 +1523,9 @@ static struct vimoption options[] =
15221523
{"lisp", NULL, P_BOOL|P_VI_DEF,
15231524
(char_u *)&p_lisp, PV_LISP,
15241525
{(char_u *)FALSE, (char_u *)0L} SCTX_INIT},
1526+
{"lispoptions", "lop", P_STRING|P_ALLOCED|P_VI_DEF|P_ONECOMMA|P_NODUP,
1527+
(char_u *)&p_lop, PV_LOP,
1528+
{(char_u *)"", (char_u *)0L} SCTX_INIT},
15251529
{"lispwords", "lw", P_STRING|P_VI_DEF|P_ONECOMMA|P_NODUP,
15261530
(char_u *)&p_lispwords, PV_LW,
15271531
{(char_u *)LISPWORD_VALUE, (char_u *)0L} SCTX_INIT},

src/optionstr.c

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -259,6 +259,7 @@ check_buf_options(buf_T *buf)
259259
check_string_option(&buf->b_p_cino);
260260
check_string_option(&buf->b_p_cinsd);
261261
parse_cino(buf);
262+
check_string_option(&buf->b_p_lop);
262263
check_string_option(&buf->b_p_ft);
263264
check_string_option(&buf->b_p_cinw);
264265
check_string_option(&buf->b_p_cpt);
@@ -2102,6 +2103,14 @@ did_set_string_option(
21022103
parse_cino(curbuf);
21032104
}
21042105

2106+
// 'lispoptions'
2107+
else if (gvarp == &p_lop)
2108+
{
2109+
if (**varp != NUL && STRCMP(*varp, "expr:0") != 0
2110+
&& STRCMP(*varp, "expr:1") != 0)
2111+
errmsg = e_invalid_argument;
2112+
}
2113+
21052114
#if defined(FEAT_RENDER_OPTIONS)
21062115
// 'renderoptions'
21072116
else if (varp == &p_rop)

src/proto/indent.pro

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ void ex_retab(exarg_T *eap);
3131
int get_expr_indent(void);
3232
int get_lisp_indent(void);
3333
void fixthisline(int (*get_the_indent)(void));
34+
int use_indentexpr_for_lisp(void);
3435
void fix_indent(void);
3536
void f_indent(typval_T *argvars, typval_T *rettv);
3637
void f_lispindent(typval_T *argvars, typval_T *rettv);

src/testdir/test_lispindent.vim

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,8 +97,23 @@ func Test_lispindent_with_indentexpr()
9797
exe "normal a(x\<CR>1\<CR>2)\<Esc>"
9898
let expected = ['(x', ' 1', ' 2)']
9999
call assert_equal(expected, getline(1, 3))
100+
" with Lisp indenting the first line is not indented
100101
normal 1G=G
101102
call assert_equal(expected, getline(1, 3))
103+
104+
%del
105+
setl lispoptions=expr:1 indentexpr=5
106+
exe "normal a(x\<CR>1\<CR>2)\<Esc>"
107+
let expected_expr = ['(x', ' 1', ' 2)']
108+
call assert_equal(expected_expr, getline(1, 3))
109+
normal 2G2<<=G
110+
call assert_equal(expected_expr, getline(1, 3))
111+
112+
setl lispoptions=expr:0
113+
" with Lisp indenting the first line is not indented
114+
normal 1G3<<=G
115+
call assert_equal(expected, getline(1, 3))
116+
102117
bwipe!
103118
endfunc
104119

0 commit comments

Comments
 (0)