]> git.ipfire.org Git - thirdparty/vim.git/commitdiff
patch 9.1.0097: 'breakindent' behaves inconsistently with 'list' and splits v9.1.0097
authorzeertzjq <zeertzjq@outlook.com>
Sun, 11 Feb 2024 16:16:19 +0000 (17:16 +0100)
committerChristian Brabandt <cb@256bit.org>
Sun, 11 Feb 2024 16:16:19 +0000 (17:16 +0100)
Problem:  'breakindent' behaves inconsistently with 'list' and splits.
Solution: Use 'listchars' from the correct window and handle caching
          properly. Move cheaper comparisons to the top.
          (zeertzjq)

closes: #14008

Signed-off-by: zeertzjq <zeertzjq@outlook.com>
Signed-off-by: Christian Brabandt <cb@256bit.org>
src/indent.c
src/proto/indent.pro
src/testdir/test_breakindent.vim
src/version.c

index 1858ecf8f3ae2d74e30d1acfbb02333c13e1595f..34d31579bd89c5629ba1781f2c2ee7d39b74e9df 100644 (file)
@@ -434,20 +434,17 @@ get_indent_buf(buf_T *buf, linenr_T lnum)
 get_indent_str(
     char_u     *ptr,
     int                ts,
-    int                list) // if TRUE, count only screen size for tabs
+    int                no_ts) // if TRUE, count a tab as ^I
 {
     int                count = 0;
 
     for ( ; *ptr; ++ptr)
     {
-       if (*ptr == TAB)
+       if (*ptr == TAB)    // count a tab for what it is worth
        {
-           if (!list || curwin->w_lcs_chars.tab1)
-               // count a tab for what it is worth
+           if (!no_ts)
                count += ts - (count % ts);
            else
-               // In list mode, when tab is not set, count screen char width
-               // for Tab, displays: ^I
                count += ptr2cells(ptr);
        }
        else if (*ptr == ' ')
@@ -462,10 +459,10 @@ get_indent_str(
 /*
  * Count the size (in window cells) of the indent in line "ptr", using
  * variable tabstops.
- * if "list" is TRUE, count only screen size for tabs.
+ * If "no_ts" is TRUE, count a tab as ^I.
  */
     int
-get_indent_str_vtab(char_u *ptr, int ts, int *vts, int list)
+get_indent_str_vtab(char_u *ptr, int ts, int *vts, int no_ts)
 {
     int                count = 0;
 
@@ -473,11 +470,9 @@ get_indent_str_vtab(char_u *ptr, int ts, int *vts, int list)
     {
        if (*ptr == TAB)    // count a tab for what it is worth
        {
-           if (!list || curwin->w_lcs_chars.tab1)
+           if (!no_ts)
                count += tabstop_padding(count, ts, vts);
            else
-               // In list mode, when tab is not set, count screen char width
-               // for Tab, displays: ^I
                count += ptr2cells(ptr);
        }
        else if (*ptr == ' ')
@@ -925,14 +920,16 @@ get_breakindent_win(
 {
     static int     prev_indent = 0;    // cached indent value
     static long            prev_ts     = 0L;   // cached tabstop value
-    static int     prev_fnum   = 0;    // cached buffer number
-    static char_u   *prev_line  = NULL;        // cached copy of "line"
-    static varnumber_T prev_tick = 0;   // changedtick of cached value
 # ifdef FEAT_VARTABS
     static int      *prev_vts = NULL;   // cached vartabs values
 # endif
-    static int      prev_list = 0;     // cached list value
+    static int     prev_fnum   = 0;    // cached buffer number
+    static char_u   *prev_line  = NULL;        // cached copy of "line"
+    static varnumber_T prev_tick = 0;   // changedtick of cached value
+    static int      prev_list = 0;     // cached list indent
     static int      prev_listopt = 0;  // cached w_p_briopt_list value
+    static int      prev_no_ts = FALSE;        // cached no_ts value
+    static unsigned prev_dy_uhex = 0;  // cached 'display' "uhex" value
     // cached formatlistpat value
     static char_u   *prev_flp = NULL;
     int                    bri = 0;
@@ -942,44 +939,53 @@ get_breakindent_win(
                                && (vim_strchr(p_cpo, CPO_NUMCOL) == NULL)
                                                ? number_width(wp) + 1 : 0);
 
-    // used cached indent, unless
-    // - buffer changed
-    // - 'tabstop' changed
-    // - buffer was changed
-    // - 'briopt_list changed' changed or
-    // - 'formatlistpattern' changed
-    // - line changed
-    // - 'vartabs' changed
+    // In list mode, if 'listchars' "tab" isn't set, a TAB is displayed as ^I.
+    int no_ts = wp->w_p_list && wp->w_lcs_chars.tab1 == NUL;
+
+    // Used cached indent, unless
+    // - buffer changed, or
+    // - 'tabstop' changed, or
+    // - 'vartabstop' changed, or
+    // - buffer was changed, or
+    // - 'breakindentopt' "list" changed, or
+    // - 'list' or 'listchars' "tab" changed, or
+    // - 'display' "uhex" flag changed, or
+    // - 'formatlistpat' changed, or
+    // - line changed.
     if (prev_fnum != wp->w_buffer->b_fnum
            || prev_ts != wp->w_buffer->b_p_ts
+# ifdef FEAT_VARTABS
+           || prev_vts != wp->w_buffer->b_p_vts_array
+# endif
            || prev_tick != CHANGEDTICK(wp->w_buffer)
            || prev_listopt != wp->w_briopt_list
+           || prev_no_ts != no_ts
+           || prev_dy_uhex != (dy_flags & DY_UHEX)
            || prev_flp == NULL
            || STRCMP(prev_flp, get_flp_value(wp->w_buffer)) != 0
            || prev_line == NULL || STRCMP(prev_line, line) != 0
-# ifdef FEAT_VARTABS
-           || prev_vts != wp->w_buffer->b_p_vts_array
-# endif
        )
     {
        prev_fnum = wp->w_buffer->b_fnum;
        vim_free(prev_line);
        prev_line = vim_strsave(line);
        prev_ts = wp->w_buffer->b_p_ts;
-       prev_tick = CHANGEDTICK(wp->w_buffer);
 # ifdef FEAT_VARTABS
        prev_vts = wp->w_buffer->b_p_vts_array;
        if (wp->w_briopt_vcol == 0)
            prev_indent = get_indent_str_vtab(line,
                                     (int)wp->w_buffer->b_p_ts,
-                                   wp->w_buffer->b_p_vts_array, wp->w_p_list);
+                                     wp->w_buffer->b_p_vts_array, no_ts);
 # else
        if (wp->w_briopt_vcol == 0)
            prev_indent = get_indent_str(line,
-                                    (int)wp->w_buffer->b_p_ts, wp->w_p_list);
+                                       (int)wp->w_buffer->b_p_ts, no_ts);
 # endif
+       prev_tick = CHANGEDTICK(wp->w_buffer);
        prev_listopt = wp->w_briopt_list;
        prev_list = 0;
+       prev_no_ts = no_ts;
+       prev_dy_uhex = (dy_flags & DY_UHEX);
        vim_free(prev_flp);
        prev_flp = vim_strsave(get_flp_value(wp->w_buffer));
        // add additional indent for numbered lists
index 5ab338dce22ebfd443550fe7a58bfa85d03d4255..bafcefc67784ff22406f97f371dc482be65f1493 100644 (file)
@@ -14,8 +14,8 @@ long get_sts_value(void);
 int get_indent(void);
 int get_indent_lnum(linenr_T lnum);
 int get_indent_buf(buf_T *buf, linenr_T lnum);
-int get_indent_str(char_u *ptr, int ts, int list);
-int get_indent_str_vtab(char_u *ptr, int ts, int *vts, int list);
+int get_indent_str(char_u *ptr, int ts, int no_ts);
+int get_indent_str_vtab(char_u *ptr, int ts, int *vts, int no_ts);
 int set_indent(int size, int flags);
 int get_number_indent(linenr_T lnum);
 int briopt_check(win_T *wp);
index ee05548222dbac85b97b7b5deac9ba71b64aeb53..9fde0f31ac6d50765f1a014d68e6e572ef1f2129 100644 (file)
@@ -424,7 +424,7 @@ func Test_breakindent12()
        \ "~               ",
        \ ]
   call s:compare_lines(expect, lines)
-  call s:close_windows('set nuw=4 listchars=')
+  call s:close_windows('set nuw=4 listchars&')
 endfunc
 
 func Test_breakindent12_vartabs()
@@ -439,7 +439,7 @@ func Test_breakindent12_vartabs()
        \ "~               ",
        \ ]
   call s:compare_lines(expect, lines)
-  call s:close_windows('set nuw=4 listchars= vts&')
+  call s:close_windows('set nuw=4 listchars& vts&')
 endfunc
 
 func Test_breakindent13()
@@ -1086,5 +1086,51 @@ func Test_linebreak_list()
   bwipe!
 endfunc
 
+func Test_breakindent_change_display_uhex()
+  call s:test_windows('setl briopt=min:0 list listchars=eol:$')
+  redraw!
+  let lines = s:screen_lines(line('.'), 20)
+  let expect = [
+        \ "^Iabcdefghijklmnopqr",
+        \ "  stuvwxyzABCDEFGHIJ",
+        \ "  KLMNOP$           "
+        \ ]
+  call s:compare_lines(expect, lines)
+  set display+=uhex
+  redraw!
+  let lines = s:screen_lines(line('.'), 20)
+  let expect = [
+        \ "<09>abcdefghijklmnop",
+        \ "    qrstuvwxyzABCDEF",
+        \ "    GHIJKLMNOP$     "
+        \ ]
+  call s:compare_lines(expect, lines)
+  set display&
+
+  call s:close_windows()
+endfunc
+
+func Test_breakindent_list_split()
+  10new
+  61vsplit
+  setlocal tabstop=8 breakindent list listchars=tab:<->,eol:$
+  put =s:input
+  30vsplit
+  setlocal listchars=eol:$
+  let expect = [
+      \ "^IabcdefghijklmnopqrstuvwxyzAB|<------>abcdefghijklmnopqrstuv",
+      \ "  CDEFGHIJKLMNOP$             |        wxyzABCDEFGHIJKLMNOP$ ",
+      \ "~                             |~                             "
+      \ ]
+  redraw!
+  let lines = s:screen_lines(line('.'), 61)
+  call s:compare_lines(expect, lines)
+  wincmd p
+  redraw!
+  let lines = s:screen_lines(line('.'), 61)
+  call s:compare_lines(expect, lines)
+
+  bwipe!
+endfunc
 
 " vim: shiftwidth=2 sts=2 expandtab
index dbbb91305134ebd0baaa41b94f7016734aacba3f..98cb8bc9bb21a2311516f8b46d90c09d21047898 100644 (file)
@@ -704,6 +704,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    97,
 /**/
     96,
 /**/