diff --git a/runtime/doc/options.txt b/runtime/doc/options.txt index c7fbde64fd..65ed54f046 100644 --- a/runtime/doc/options.txt +++ b/runtime/doc/options.txt @@ -1370,6 +1370,7 @@ A jump table for the options with a short description can be found at |Q_op|. 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 diff --git a/src/indent.c b/src/indent.c index b74bae6e69..a1012d2689 100644 --- 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) { diff --git a/src/option.c b/src/option.c index 169f92998a..0a75c2417c 100644 --- a/src/option.c +++ b/src/option.c @@ -7052,6 +7052,18 @@ get_bkc_value(buf_T *buf) return buf->b_bkc_flags ? buf->b_bkc_flags : bkc_flags; } +/* + * 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. */ diff --git a/src/proto/option.pro b/src/proto/option.pro index 2390f58776..a099624d5d 100644 --- 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); diff --git a/src/testdir/test_breakindent.vim b/src/testdir/test_breakindent.vim index 0c143b1943..2ac127dd54 100644 --- 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 \" + 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 diff --git a/src/version.c b/src/version.c index 1dd5c96fd4..5869c2694a 100644 --- a/src/version.c +++ b/src/version.c @@ -750,6 +750,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 4093, /**/ 4092, /**/