changeset 25248:cf0774d010b7 v8.2.3160

patch 8.2.3160: 'breakindent' does not work well for bulleted lists Commit: https://github.com/vim/vim/commit/4a0b85ad0193ac162e2d8458e4b1c5ad2e2b0193 Author: Christian Brabandt <cb@256bit.org> Date: Wed Jul 14 20:00:27 2021 +0200 patch 8.2.3160: 'breakindent' does not work well for bulleted lists Problem: 'breakindent' does not work well for bulleted and numbered lists. Solution: Add the "list" entry to 'breakindentopt'. (Christian Brabandt, closes #8564, closes #1661)
author Bram Moolenaar <Bram@vim.org>
date Wed, 14 Jul 2021 20:15:04 +0200
parents df8387c6b8dd
children 9f8fefe5aabe
files runtime/doc/options.txt src/indent.c src/structs.h src/testdir/test_breakindent.vim src/version.c
diffstat 5 files changed, 100 insertions(+), 1 deletions(-) [+]
line wrap: on
line diff
--- a/runtime/doc/options.txt
+++ b/runtime/doc/options.txt
@@ -1326,7 +1326,10 @@ A jump table for the options with a shor
 			    continuation (positive).
 		sbr	    Display the 'showbreak' value before applying the
 			    additional indent.
-	The default value for min is 20 and shift is 0.
+		list:{n}    Adds an additional indent for lines that match a 
+			    numbered or bulleted list (using the
+			    'formatlistpat' setting).
+	The default value for min is 20, shift and list is 0.
 
 						*'browsedir'* *'bsdir'*
 'browsedir' 'bsdir'	string	(default: "last")
--- a/src/indent.c
+++ b/src/indent.c
@@ -854,6 +854,7 @@ briopt_check(win_T *wp)
     int		bri_shift = 0;
     long	bri_min = 20;
     int		bri_sbr = FALSE;
+    int		bri_list = 0;
 
     p = wp->w_p_briopt;
     while (*p != NUL)
@@ -874,6 +875,11 @@ briopt_check(win_T *wp)
 	    p += 3;
 	    bri_sbr = TRUE;
 	}
+	else if (STRNCMP(p, "list:", 5) == 0)
+	{
+	    p += 5;
+	    bri_list = getdigits(&p);
+	}
 	if (*p != ',' && *p != NUL)
 	    return FAIL;
 	if (*p == ',')
@@ -883,6 +889,7 @@ briopt_check(win_T *wp)
     wp->w_briopt_shift = bri_shift;
     wp->w_briopt_min   = bri_min;
     wp->w_briopt_sbr   = bri_sbr;
+    wp->w_briopt_list  = bri_list;
 
     return OK;
 }
@@ -941,9 +948,25 @@ get_breakindent_win(
     // Add offset for number column, if 'n' is in 'cpoptions'
     bri += win_col_off2(wp);
 
+    // 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);
+	if (regmatch.regprog != NULL)
+	{
+	    if (vim_regexec(&regmatch, line, 0))
+		bri += wp->w_briopt_list;
+	    vim_regfree(regmatch.regprog);
+	}
+    }
+
     // never indent past left window margin
     if (bri < 0)
 	bri = 0;
+
     // always leave at least bri_min characters on the left,
     // if text width is sufficient
     else if (bri > eff_wwidth - wp->w_briopt_min)
--- a/src/structs.h
+++ b/src/structs.h
@@ -3671,6 +3671,7 @@ struct window_S
     int		w_briopt_min;	    // minimum width for breakindent
     int		w_briopt_shift;	    // additional shift for breakindent
     int		w_briopt_sbr;	    // sbr in 'briopt'
+    int		w_briopt_list;      // additional indent for lists
 #endif
 
     // transform a pointer to a "onebuf" option into a "allbuf" option
--- a/src/testdir/test_breakindent.vim
+++ b/src/testdir/test_breakindent.vim
@@ -15,6 +15,10 @@ func s:screen_lines(lnum, width) abort
   return ScreenLines([a:lnum, a:lnum + 2], a:width)
 endfunc
 
+func s:screen_lines2(lnums, lnume, width) abort
+  return ScreenLines([a:lnums, a:lnume], a:width)
+endfunc
+
 func s:compare_lines(expect, actual)
   call assert_equal(join(a:expect, "\n"), join(a:actual, "\n"))
 endfunc
@@ -708,4 +712,70 @@ func Test_breakindent20_cpo_n_nextpage()
   call s:close_windows('set breakindent& briopt& cpo& number&')
 endfunc
 
+func Test_breakindent20_list()
+  call s:test_windows('setl breakindent breakindentopt= linebreak')
+  " default:
+  call setline(1, ['  1.  Congress shall make no law',
+        \ '  2.) Congress shall make no law',
+        \ '  3.] Congress shall make no law'])
+  norm! 1gg
+  redraw!
+  let lines = s:screen_lines2(1, 6, 20)
+  let expect = [
+	\ "  1.  Congress      ",
+	\ "shall make no law   ",
+	\ "  2.) Congress      ",
+	\ "shall make no law   ",
+	\ "  3.] Congress      ",
+	\ "shall make no law   ",
+	\ ]
+  call s:compare_lines(expect, lines)
+  " set mininum indent
+  setl briopt=min:5
+  redraw!
+  let lines = s:screen_lines2(1, 6, 20)
+  let expect = [
+	\ "  1.  Congress      ",
+	\ "  shall make no law ",
+	\ "  2.) Congress      ",
+	\ "  shall make no law ",
+	\ "  3.] Congress      ",
+	\ "  shall make no law ",
+	\ ]
+  call s:compare_lines(expect, lines)
+  " set additional handing indent
+  setl briopt+=list:4
+  redraw!
+  let expect = [
+	\ "  1.  Congress      ",
+	\ "      shall make no ",
+	\ "      law           ",
+	\ "  2.) Congress      ",
+	\ "      shall make no ",
+	\ "      law           ",
+	\ "  3.] Congress      ",
+	\ "      shall make no ",
+	\ "      law           ",
+	\ ]
+  let lines = s:screen_lines2(1, 9, 20)
+  call s:compare_lines(expect, lines)
+  " reset linebreak option
+  " Note: it indents by one additional
+  " space, because of the leading space.
+  setl linebreak&vim list listchars=eol:$,space:_
+  redraw!
+  let expect = [
+	\ "__1.__Congress_shall",
+	\ "      _make_no_law$ ",
+	\ "__2.)_Congress_shall",
+	\ "      _make_no_law$ ",
+	\ "__3.]_Congress_shall",
+	\ "      _make_no_law$ ",
+	\ ]
+  let lines = s:screen_lines2(1, 6, 20)
+  call s:compare_lines(expect, lines)
+
+  call s:close_windows('set breakindent& briopt& linebreak& list& listchars&')
+endfunc
+
 " vim: shiftwidth=2 sts=2 expandtab
--- a/src/version.c
+++ b/src/version.c
@@ -756,6 +756,8 @@ static char *(features[]) =
 static int included_patches[] =
 {   /* Add new patch number below this line */
 /**/
+    3160,
+/**/
     3159,
 /**/
     3158,