From 61a6ac4d0066317131528f1b3ecc3b3a2599a75c Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Sat, 7 Sep 2024 11:23:54 +0200 Subject: [PATCH] patch 9.1.0720: Wrong breakindentopt=list:-1 with multibyte or TABs Problem: Wrong breakindentopt=list:-1 with multibyte chars or TABs in text matched by 'formatlistpat' (John M Devin) Solution: Use the width of the match text (zeertzjq) fixes: #15634 closes: #15635 Signed-off-by: zeertzjq Signed-off-by: Christian Brabandt --- runtime/doc/options.txt | 6 +-- src/charset.c | 4 +- src/indent.c | 16 +++++++- src/proto/charset.pro | 1 + src/testdir/test_breakindent.vim | 65 +++++++++++++++++++++++++++++--- src/version.c | 2 + 6 files changed, 83 insertions(+), 11 deletions(-) diff --git a/runtime/doc/options.txt b/runtime/doc/options.txt index 3ec8a3a80d..50c25f7b25 100644 --- a/runtime/doc/options.txt +++ b/runtime/doc/options.txt @@ -1,4 +1,4 @@ -*options.txt* For Vim version 9.1. Last change: 2024 Aug 12 +*options.txt* For Vim version 9.1. Last change: 2024 Sep 07 VIM REFERENCE MANUAL by Bram Moolenaar @@ -1491,9 +1491,9 @@ A jump table for the options with a short description can be found at |Q_op|. list:{n} Adds an additional indent for lines that match a numbered or bulleted list (using the 'formatlistpat' setting). - list:-1 Uses the length of a match with 'formatlistpat' - for indentation. (default: 0) + list:-1 Uses the width of a match with 'formatlistpat' for + indentation. column:{n} Indent at column {n}. Will overrule the other sub-options. Note: an additional indent may be added for the 'showbreak' setting. diff --git a/src/charset.c b/src/charset.c index 399f258251..e02f719c1a 100644 --- a/src/charset.c +++ b/src/charset.c @@ -739,8 +739,8 @@ chartabsize(char_u *p, colnr_T col) RET_WIN_BUF_CHARTABSIZE(curwin, curbuf, p, col) } -#ifdef FEAT_LINEBREAK - static int +#if defined(FEAT_LINEBREAK) || defined(PROTO) + int win_chartabsize(win_T *wp, char_u *p, colnr_T col) { RET_WIN_BUF_CHARTABSIZE(wp, wp->w_buffer, p, col) diff --git a/src/indent.c b/src/indent.c index 0d6fadb26d..4ba31d2aa0 100644 --- a/src/indent.c +++ b/src/indent.c @@ -1021,7 +1021,21 @@ get_breakindent_win( if (wp->w_briopt_list > 0) prev_list = wp->w_briopt_list; else - prev_indent = (*regmatch.endp - *regmatch.startp); + { + char_u *ptr = *regmatch.startp; + char_u *end_ptr = *regmatch.endp; + int indent = 0; + + // Compute the width of the matched text. + // Use win_chartabsize() so that TAB size is correct, + // while wrapping is ignored. + while (ptr < end_ptr) + { + indent += win_chartabsize(wp, ptr, indent); + MB_PTR_ADV(ptr); + } + prev_indent = indent; + } } vim_regfree(regmatch.regprog); } diff --git a/src/proto/charset.pro b/src/proto/charset.pro index a74731931d..2f64077834 100644 --- a/src/proto/charset.pro +++ b/src/proto/charset.pro @@ -16,6 +16,7 @@ int ptr2cells(char_u *p); int vim_strsize(char_u *s); int vim_strnsize(char_u *s, int len); int chartabsize(char_u *p, colnr_T col); +int win_chartabsize(win_T *wp, char_u *p, colnr_T col); int linetabsize_str(char_u *s); int linetabsize_col(int startcol, char_u *s); int win_linetabsize(win_T *wp, linenr_T lnum, char_u *line, colnr_T len); diff --git a/src/testdir/test_breakindent.vim b/src/testdir/test_breakindent.vim index b306c02078..16a11b35af 100644 --- a/src/testdir/test_breakindent.vim +++ b/src/testdir/test_breakindent.vim @@ -797,18 +797,73 @@ func Test_breakindent20_list() \ ] let lines = s:screen_lines2(1, 9, 20) call s:compare_lines(expect, lines) + + " check with TABs + call setline(1, ["\t1.\tCongress shall make no law", + \ "\t2.) Congress shall make no law", + \ "\t3.] Congress shall make no law"]) + setl tabstop=4 list listchars=tab:<-> + norm! 1gg + 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) + + setl tabstop=2 nolist + 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) + + setl tabstop& list listchars=space:_ + redraw! + let expect = [ + \ "^I1.^ICongress_ ", + \ " shall_make_no_", + \ " law ", + \ "^I2.)_Congress_ ", + \ " shall_make_no_", + \ " law ", + \ "^I3.]_Congress_ ", + \ " shall_make_no_", + \ " law ", + \ ] + let lines = s:screen_lines2(1, 9, 20) + call s:compare_lines(expect, lines) + " check formatlistpat indent with different list levels - let &l:flp = '^\s*\*\+\s\+' + let &l:flp = '^\s*\(\*\|•\)\+\s\+' + setl list&vim listchars&vim %delete _ call setline(1, ['* Congress shall make no law', - \ '*** Congress shall make no law', + \ '••• Congress shall make no law', \ '**** Congress shall make no law']) norm! 1gg redraw! let expect = [ \ "* Congress shall ", \ " make no law ", - \ "*** Congress shall ", + \ "••• Congress shall ", \ " make no law ", \ "**** Congress shall ", \ " make no law ", @@ -824,7 +879,7 @@ func Test_breakindent20_list() let expect = [ \ "* Congress shall ", \ "> make no law ", - \ "*** Congress shall ", + \ "••• Congress shall ", \ "> make no law ", \ "**** Congress shall ", \ "> make no law ", @@ -840,7 +895,7 @@ func Test_breakindent20_list() let expect = [ \ "* Congress shall ", \ "> make no law ", - \ "*** Congress shall ", + \ "••• Congress shall ", \ "> make no law ", \ "**** Congress shall ", \ "> make no law ", diff --git a/src/version.c b/src/version.c index ddbf4eb491..5c3c5efb66 100644 --- a/src/version.c +++ b/src/version.c @@ -704,6 +704,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 720, /**/ 719, /**/