changeset 27128:164d59ddd48a v8.2.4093

patch 8.2.4093: cached breakindent values not initialized properly Commit: https://github.com/vim/vim/commit/c53b467473160b5cfce77277fbae414bf43e66ce Author: Christian Brabandt <cb@256bit.org> Date: Sat Jan 15 10:01:05 2022 +0000 patch 8.2.4093: cached breakindent values not initialized properly Problem: Cached breakindent values not initialized properly. Solution: Initialize and cache formatlistpat. (Christian Brabandt, closes #9526, closes #9512)
author Bram Moolenaar <Bram@vim.org>
date Sat, 15 Jan 2022 11:15:03 +0100
parents 33918a28ec46
children a4ef6b033e16
files runtime/doc/options.txt src/indent.c src/option.c src/proto/option.pro src/testdir/test_breakindent.vim src/version.c
diffstat 6 files changed, 87 insertions(+), 3 deletions(-) [+]
line wrap: on
line diff
--- a/runtime/doc/options.txt
+++ b/runtime/doc/options.txt
@@ -1370,6 +1370,7 @@ A jump table for the options with a shor
 			    text should normally be narrower. This prevents
 			    text indented almost to the right window border
 			    occupying lot of vertical space when broken.
+			    (default: 20)
 		shift:{n}   After applying 'breakindent', the wrapped line's
 			    beginning will be shifted by the given number of
 			    characters.  It permits dynamic French paragraph
--- a/src/indent.c
+++ b/src/indent.c
@@ -924,6 +924,8 @@ get_breakindent_win(
 # endif
     static int      prev_list = 0;	// cached list value
     static int      prev_listopt = 0;	// cached w_p_briopt_list value
+    // cached formatlistpat value
+    static char_u   *prev_flp = NULL;
     int		    bri = 0;
     // window width minus window margin space, i.e. what rests for text
     const int	    eff_wwidth = wp->w_width
@@ -931,10 +933,16 @@ get_breakindent_win(
 				&& (vim_strchr(p_cpo, CPO_NUMCOL) == NULL)
 						? number_width(wp) + 1 : 0);
 
-    // used cached indent, unless line, 'tabstop' or briopt_list changed
+    // used cached indent, unless
+    // - line pointer changed
+    // - 'tabstop' changed
+    // - 'briopt_list changed' changed or
+    // - 'formatlistpattern' changed
     if (prev_line != line || prev_ts != wp->w_buffer->b_p_ts
 	    || prev_tick != CHANGEDTICK(wp->w_buffer)
 	    || prev_listopt != wp->w_briopt_list
+	    || (prev_flp == NULL
+		|| (STRCMP(prev_flp, get_flp_value(wp->w_buffer)) != 0))
 # ifdef FEAT_VARTABS
 	    || prev_vts != wp->w_buffer->b_p_vts_array
 # endif
@@ -953,13 +961,16 @@ get_breakindent_win(
 				     (int)wp->w_buffer->b_p_ts, wp->w_p_list);
 # endif
 	prev_listopt = wp->w_briopt_list;
+	prev_list = 0;
+	vim_free(prev_flp);
+	prev_flp = vim_strsave(get_flp_value(wp->w_buffer));
 	// add additional indent for numbered lists
 	if (wp->w_briopt_list != 0)
 	{
 	    regmatch_T	    regmatch;
 
-	    regmatch.regprog = vim_regcomp(curbuf->b_p_flp,
-				       RE_MAGIC + RE_STRING + RE_AUTO + RE_STRICT);
+	    regmatch.regprog = vim_regcomp(prev_flp,
+				   RE_MAGIC + RE_STRING + RE_AUTO + RE_STRICT);
 
 	    if (regmatch.regprog != NULL)
 	    {
--- a/src/option.c
+++ b/src/option.c
@@ -7053,6 +7053,18 @@ get_bkc_value(buf_T *buf)
 }
 
 /*
+ * Get the local or global value of 'formatlistpat'.
+ */
+    char_u *
+get_flp_value(buf_T *buf)
+{
+    return buf->b_p_flp ? buf->b_p_flp : p_flp;
+    if (buf->b_p_flp == NULL || *buf->b_p_flp == NUL)
+	return p_flp;
+    return buf->b_p_flp;
+}
+
+/*
  * Get the local or global value of the 'virtualedit' flags.
  */
     unsigned int
--- a/src/proto/option.pro
+++ b/src/proto/option.pro
@@ -73,6 +73,7 @@ int can_bs(int what);
 long get_scrolloff_value(void);
 long get_sidescrolloff_value(void);
 unsigned int get_bkc_value(buf_T *buf);
+char_u *get_flp_value(buf_T *buf);
 unsigned int get_ve_flags(void);
 char_u *get_showbreak_value(win_T *win);
 dict_T *get_winbuf_options(int bufopt);
--- a/src/testdir/test_breakindent.vim
+++ b/src/testdir/test_breakindent.vim
@@ -849,4 +849,61 @@ func Test_window_resize_with_linebreak()
   %bw!
 endfunc
 
+func Test_no_spurious_match()
+  let s:input = printf('- y %s y %s', repeat('x', 50), repeat('x', 50))
+  call s:test_windows('setl breakindent breakindentopt=list:-1 formatlistpat=^- hls')
+  let @/ = '\%>3v[y]'
+  redraw!
+  call searchcount().total->assert_equal(1)
+  " cleanup
+  set hls&vim
+  let s:input = "\tabcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOP"
+  bwipeout!
+endfunc
+
+func Test_no_extra_indent()
+  call s:test_windows('setl breakindent breakindentopt=list:-1,min:10')
+  %d
+  let &l:formatlistpat='^\s*\d\+\.\s\+'
+  let text = 'word '
+  let len = text->strcharlen()
+  let line1 = text->repeat((winwidth(0) / len) * 2)
+  let line2 = repeat(' ', 2) .. '1. ' .. line1
+  call setline(1, [line2])
+  redraw!
+  " 1) matches formatlist pattern, so indent
+  let expect = [
+  \ "  1. word word word ",
+  \ "     word word word ",
+  \ "     word word      ",
+  \ "~                   ",
+  \ ]
+  let lines = s:screen_lines2(1, 4, 20)
+  call s:compare_lines(expect, lines)
+  " 2) change formatlist pattern
+  " -> indent adjusted
+  let &l:formatlistpat='^\s*\d\+\.'
+  let expect = [
+  \ "  1. word word word ",
+  \ "    word word word  ",
+  \ "    word word       ",
+  \ "~                   ",
+  \ ]
+  let lines = s:screen_lines2(1, 4, 20)
+  " 3) add something in front, no additional indent
+  norm! gg0
+  exe ":norm! 5iword \<esc>"
+  redraw!
+  let expect = [
+  \ "word word word word ",
+  \ "word   1. word word ",
+  \ "word word word word ",
+  \ "word word           ",
+  \ "~                   ",
+  \ ]
+  let lines = s:screen_lines2(1, 5, 20)
+  call s:compare_lines(expect, lines)
+  bwipeout!
+endfunc
+
 " vim: shiftwidth=2 sts=2 expandtab
--- a/src/version.c
+++ b/src/version.c
@@ -751,6 +751,8 @@ static char *(features[]) =
 static int included_patches[] =
 {   /* Add new patch number below this line */
 /**/
+    4093,
+/**/
     4092,
 /**/
     4091,