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/src/buffer.c b/src/buffer.c
index 5f8512a..0849b70 100644
--- a/src/buffer.c
+++ b/src/buffer.c
@@ -2390,6 +2390,7 @@
     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 c409acd..f036a37 100644
--- a/src/change.c
+++ b/src/change.c
@@ -2269,20 +2269,23 @@
     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 c6e3aaf..aaf3caa 100644
--- a/src/indent.c
+++ b/src/indent.c
@@ -2197,18 +2197,38 @@
 }
 
 /*
+ * 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 85a55f9..3297810 100644
--- a/src/option.c
+++ b/src/option.c
@@ -5518,6 +5518,7 @@
 	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 @@
 	    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 6d05f0e..e266d38 100644
--- a/src/option.h
+++ b/src/option.h
@@ -709,6 +709,7 @@
 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 @@
 #endif
     , BV_KP
     , BV_LISP
+    , BV_LOP
     , BV_LW
     , BV_MENC
     , BV_MA
diff --git a/src/optiondefs.h b/src/optiondefs.h
index db85a39..9ea8602 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 @@
     {"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 32663a0..9e9d18f 100644
--- a/src/optionstr.c
+++ b/src/optionstr.c
@@ -259,6 +259,7 @@
     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 @@
 	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 2702f40..5ab338d 100644
--- a/src/proto/indent.pro
+++ b/src/proto/indent.pro
@@ -31,6 +31,7 @@
 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 3c8660e..770c501 100644
--- a/src/testdir/test_lispindent.vim
+++ b/src/testdir/test_lispindent.vim
@@ -97,8 +97,23 @@
   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 0ccdf46..6e602be 100644
--- a/src/version.c
+++ b/src/version.c
@@ -696,6 +696,8 @@
 static int included_patches[] =
 {   /* Add new patch number below this line */
 /**/
+    761,
+/**/
     760,
 /**/
     759,