aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorzeertzjq <zeertzjq@outlook.com>2022-10-16 08:06:07 +0800
committerzeertzjq <zeertzjq@outlook.com>2022-10-16 08:34:55 +0800
commit19eb7054ff7b1fbc78e56e7f9ed6537b085147bc (patch)
treef10b35a7a415ebd3cbfc3b944aec96e65892becc
parentbc798dfd8cea9a5f93461e05dcb8409b6d96afc0 (diff)
downloadrneovim-19eb7054ff7b1fbc78e56e7f9ed6537b085147bc.tar.gz
rneovim-19eb7054ff7b1fbc78e56e7f9ed6537b085147bc.tar.bz2
rneovim-19eb7054ff7b1fbc78e56e7f9ed6537b085147bc.zip
vim-patch:9.0.0761: cannot use 'indentexpr' for Lisp indenting
Problem: Cannot use 'indentexpr' for Lisp indenting. Solution: Add the 'lispoptions' option. https://github.com/vim/vim/commit/49846fb1a31de99f49d6a7e70efe685197423c84 vim-patch:9.0.0762: build failure Problem: Build failure. Solution: Add missing change. https://github.com/vim/vim/commit/4b082c4bd05f504fda1acaa9d28fca55a2d04857
-rw-r--r--runtime/doc/options.txt13
-rw-r--r--src/nvim/buffer.c3
-rw-r--r--src/nvim/buffer_defs.h1
-rw-r--r--src/nvim/change.c24
-rw-r--r--src/nvim/edit.c28
-rw-r--r--src/nvim/edit.h2
-rw-r--r--src/nvim/indent.c43
-rw-r--r--src/nvim/indent.h2
-rw-r--r--src/nvim/option.c4
-rw-r--r--src/nvim/option_defs.h2
-rw-r--r--src/nvim/options.lua8
-rw-r--r--src/nvim/optionstr.c5
-rw-r--r--src/nvim/testdir/test_lispindent.vim15
13 files changed, 107 insertions, 43 deletions
diff --git a/runtime/doc/options.txt b/runtime/doc/options.txt
index a846f49781..3e056ffc28 100644
--- a/runtime/doc/options.txt
+++ b/runtime/doc/options.txt
@@ -3352,7 +3352,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
@@ -3719,6 +3719,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/nvim/buffer.c b/src/nvim/buffer.c
index 29b00bad2a..84ff2fa59b 100644
--- a/src/nvim/buffer.c
+++ b/src/nvim/buffer.c
@@ -1959,8 +1959,9 @@ void free_buf_options(buf_T *buf, int free_p_ff)
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_cinw);
+ 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);
clear_string_option(&buf->b_p_cfu);
clear_string_option(&buf->b_p_ofu);
diff --git a/src/nvim/buffer_defs.h b/src/nvim/buffer_defs.h
index 630e1d14a8..043a31bf16 100644
--- a/src/nvim/buffer_defs.h
+++ b/src/nvim/buffer_defs.h
@@ -699,6 +699,7 @@ struct file_buffer {
uint32_t b_p_fex_flags; ///< flags for 'formatexpr'
char *b_p_kp; ///< 'keywordprg'
int b_p_lisp; ///< 'lisp'
+ char *b_p_lop; ///< 'lispoptions'
char *b_p_menc; ///< 'makeencoding'
char *b_p_mps; ///< 'matchpairs'
int b_p_ml; ///< 'modeline'
diff --git a/src/nvim/change.c b/src/nvim/change.c
index c6f9e9f5c2..2424a8a2eb 100644
--- a/src/nvim/change.c
+++ b/src/nvim/change.c
@@ -1814,17 +1814,19 @@ int open_line(int dir, int flags, int second_line_indent, bool *did_do_comment)
vreplace_mode = 0;
}
- if (!p_paste
- && leader == NULL
- && 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) {
- // do 'cindent' or 'indentexpr' indenting
- do_c_expr_indent();
- ai_col = (colnr_T)getwhitecols_curline();
+ if (!p_paste) {
+ 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/nvim/edit.c b/src/nvim/edit.c
index 0e14567286..e37f967a2c 100644
--- a/src/nvim/edit.c
+++ b/src/nvim/edit.c
@@ -2993,34 +2993,6 @@ bool cindent_on(void)
return !p_paste && (curbuf->b_p_cin || *curbuf->b_p_inde != NUL);
}
-// Re-indent the current line, based on the current contents of it and the
-// surrounding lines. Fixing the cursor position seems really easy -- I'm very
-// confused what all the part that handles Control-T is doing that I'm not.
-// "get_the_indent" should be get_c_indent, get_expr_indent or get_lisp_indent.
-void fixthisline(IndentGetter get_the_indent)
-{
- int amount = get_the_indent();
-
- if (amount >= 0) {
- change_indent(INDENT_SET, amount, false, 0, true);
- if (linewhite(curwin->w_cursor.lnum)) {
- did_ai = true; // delete the indent if the line stays empty
- }
- }
-}
-
-void fix_indent(void)
-{
- if (p_paste) {
- return;
- }
- if (curbuf->b_p_lisp && curbuf->b_p_ai) {
- fixthisline(get_lisp_indent);
- } else if (cindent_on()) {
- do_c_expr_indent();
- }
-}
-
/// Check that "cinkeys" contains the key "keytyped",
/// when == '*': Only if key is preceded with '*' (indent before insert)
/// when == '!': Only if key is preceded with '!' (don't insert)
diff --git a/src/nvim/edit.h b/src/nvim/edit.h
index eda6d8c9db..91c519f015 100644
--- a/src/nvim/edit.h
+++ b/src/nvim/edit.h
@@ -4,8 +4,6 @@
#include "nvim/autocmd.h"
#include "nvim/vim.h"
-typedef int (*IndentGetter)(void);
-
// Values for in_cinkeys()
#define KEY_OPEN_FORW 0x101
#define KEY_OPEN_BACK 0x102
diff --git a/src/nvim/indent.c b/src/nvim/indent.c
index 3f5a8afbc1..3f08aa7043 100644
--- a/src/nvim/indent.c
+++ b/src/nvim/indent.c
@@ -15,6 +15,7 @@
#include "nvim/eval.h"
#include "nvim/extmark.h"
#include "nvim/indent.h"
+#include "nvim/indent_c.h"
#include "nvim/mark.h"
#include "nvim/memline.h"
#include "nvim/memory.h"
@@ -1144,3 +1145,45 @@ static int lisp_match(char_u *p)
}
return false;
}
+
+/// Re-indent the current line, based on the current contents of it and the
+/// surrounding lines. Fixing the cursor position seems really easy -- I'm very
+/// confused what all the part that handles Control-T is doing that I'm not.
+/// "get_the_indent" should be get_c_indent, get_expr_indent or get_lisp_indent.
+void fixthisline(IndentGetter get_the_indent)
+{
+ int amount = get_the_indent();
+
+ if (amount >= 0) {
+ change_indent(INDENT_SET, amount, false, 0, true);
+ if (linewhite(curwin->w_cursor.lnum)) {
+ did_ai = true; // delete the indent if the line stays empty
+ }
+ }
+}
+
+/// Return true if 'indentexpr' should be used for Lisp indenting.
+/// Caller may want to check 'autoindent'.
+bool use_indentexpr_for_lisp(void)
+{
+ return curbuf->b_p_lisp
+ && *curbuf->b_p_inde != NUL
+ && strcmp(curbuf->b_p_lop, "expr:1") == 0;
+}
+
+/// Fix indent for 'lisp' and 'cindent'.
+void fix_indent(void)
+{
+ if (p_paste) {
+ return; // no auto-indenting when 'paste' is set
+ }
+ if (curbuf->b_p_lisp && curbuf->b_p_ai) {
+ if (use_indentexpr_for_lisp()) {
+ do_c_expr_indent();
+ } else {
+ fixthisline(get_lisp_indent);
+ }
+ } else if (cindent_on()) {
+ do_c_expr_indent();
+ }
+}
diff --git a/src/nvim/indent.h b/src/nvim/indent.h
index f96732bf1c..f807bbb42b 100644
--- a/src/nvim/indent.h
+++ b/src/nvim/indent.h
@@ -3,6 +3,8 @@
#include "nvim/vim.h"
+typedef int (*IndentGetter)(void);
+
// flags for set_indent()
#define SIN_CHANGED 1 // call changed_bytes() when line changed
#define SIN_INSERT 2 // insert indent before existing text
diff --git a/src/nvim/option.c b/src/nvim/option.c
index 7202156c46..0b819aad43 100644
--- a/src/nvim/option.c
+++ b/src/nvim/option.c
@@ -4008,6 +4008,8 @@ static char_u *get_varp(vimoption_T *p)
return (char_u *)&(curbuf->b_p_fex);
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:
@@ -4414,6 +4416,8 @@ void buf_copy_options(buf_T *buf, int flags)
COPY_OPT_SCTX(buf, BV_CINO);
buf->b_p_cinsd = xstrdup(p_cinsd);
COPY_OPT_SCTX(buf, BV_CINSD);
+ buf->b_p_lop = xstrdup(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/nvim/option_defs.h b/src/nvim/option_defs.h
index 196ab865a2..c4333a6f61 100644
--- a/src/nvim/option_defs.h
+++ b/src/nvim/option_defs.h
@@ -580,6 +580,7 @@ EXTERN char_u *p_lm; // 'langmenu'
EXTERN long p_lines; // 'lines'
EXTERN long p_linespace; // 'linespace'
EXTERN int p_lisp; ///< 'lisp'
+EXTERN char *p_lop; ///< 'lispoptions'
EXTERN char_u *p_lispwords; // 'lispwords'
EXTERN long p_ls; // 'laststatus'
EXTERN long p_stal; // 'showtabline'
@@ -878,6 +879,7 @@ enum {
BV_KMAP,
BV_KP,
BV_LISP,
+ BV_LOP,
BV_LW,
BV_MENC,
BV_MA,
diff --git a/src/nvim/options.lua b/src/nvim/options.lua
index f4d6c808fa..8a883a09c3 100644
--- a/src/nvim/options.lua
+++ b/src/nvim/options.lua
@@ -1364,6 +1364,14 @@ return {
defaults={if_true=false}
},
{
+ full_name='lispoptions', abbreviation='lop',
+ short_desc=N_("options for lisp indenting"),
+ type='string', list='onecomma', scope={'buffer'},
+ deny_duplicates=true,
+ varname='p_lop', pv_name='p_lop',
+ defaults={if_true=''}
+ },
+ {
full_name='lispwords', abbreviation='lw',
short_desc=N_("words that change how lisp indenting works"),
type='string', list='onecomma', scope={'global', 'buffer'},
diff --git a/src/nvim/optionstr.c b/src/nvim/optionstr.c
index be3e137b69..43628d2842 100644
--- a/src/nvim/optionstr.c
+++ b/src/nvim/optionstr.c
@@ -228,6 +228,7 @@ void check_buf_options(buf_T *buf)
check_string_option(&buf->b_p_cink);
check_string_option(&buf->b_p_cino);
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_cinsd);
@@ -1378,6 +1379,10 @@ char *did_set_string_option(int opt_idx, char **varp, char *oldval, char *errbuf
} else if (gvarp == &p_cino) { // 'cinoptions'
// TODO(vim): recognize errors
parse_cino(curbuf);
+ } else if (gvarp == &p_lop) { // 'lispoptions'
+ if (**varp != NUL && strcmp(*varp, "expr:0") != 0 && strcmp(*varp, "expr:1") != 0) {
+ errmsg = e_invarg;
+ }
} else if (varp == &p_icm) { // 'inccommand'
if (check_opt_strings(p_icm, p_icm_values, false) != OK) {
errmsg = e_invarg;
diff --git a/src/nvim/testdir/test_lispindent.vim b/src/nvim/testdir/test_lispindent.vim
index 8987f67a80..2d6060bba3 100644
--- a/src/nvim/testdir/test_lispindent.vim
+++ b/src/nvim/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