]> granicus.if.org Git - vim/commitdiff
patch 8.1.1359: text property wrong after :substitute with backslash v8.1.1359
authorBram Moolenaar <Bram@vim.org>
Sun, 19 May 2019 20:53:40 +0000 (22:53 +0200)
committerBram Moolenaar <Bram@vim.org>
Sun, 19 May 2019 20:53:40 +0000 (22:53 +0200)
Problem:    Text property wrong after :substitute with backslash.
Solution:   Adjust text property columns when removing backslashes.
            (closes #4397)

src/change.c
src/edit.c
src/ex_cmds.c
src/misc1.c
src/ops.c
src/proto/textprop.pro
src/testdir/test_textprop.vim
src/textprop.c
src/version.c
src/vim.h

index fa8c42538fa2f42334071c4ca1fc53ada808f263..b43ba357456001ce331467654d3bffc5251b863c 100644 (file)
@@ -684,7 +684,7 @@ inserted_bytes(linenr_T lnum, colnr_T col, int added UNUSED)
 {
 #ifdef FEAT_TEXT_PROP
     if (curbuf->b_has_textprop && added != 0)
-       adjust_prop_columns(lnum, col, added, FALSE);
+       adjust_prop_columns(lnum, col, added, 0);
 #endif
 
     changed_bytes(lnum, col);
index be195fc1ae76bcc304e91a95ebf35f59da0e70c8..8a008cbfd441b4c6afcfc79317876922340e49e7 100644 (file)
@@ -4104,7 +4104,7 @@ replace_do_bs(int limit_col)
 
            --text_prop_frozen;
            adjust_prop_columns(curwin->w_cursor.lnum, curwin->w_cursor.col,
-                                          (int)(len_now - len_before), FALSE);
+                                          (int)(len_now - len_before), 0);
        }
 #endif
     }
index ff86d1cd47293d981ceab93b05744cd2342f30f3..df5dcd01ffbea895b5398e42eed853211124de58 100644 (file)
@@ -5189,7 +5189,7 @@ do_sub(exarg_T *eap)
            int         skip_match = FALSE;
            linenr_T    sub_firstlnum;  /* nr of first sub line */
 #ifdef FEAT_TEXT_PROP
-           int         save_for_undo = TRUE;
+           int         apc_flags = APC_SAVE_FOR_UNDO | APC_SUBSTITUTE;
 #endif
 
            /*
@@ -5612,8 +5612,9 @@ do_sub(exarg_T *eap)
                        // undo first, unless done already.
                        if (adjust_prop_columns(lnum, regmatch.startpos[0].col,
                              sublen - 1 - (regmatch.endpos[0].col
-                                  - regmatch.startpos[0].col), save_for_undo))
-                           save_for_undo = FALSE;
+                                                  - regmatch.startpos[0].col),
+                                                                   apc_flags))
+                           apc_flags &= ~APC_SAVE_FOR_UNDO;
                    }
 #endif
                }
@@ -5715,7 +5716,20 @@ do_sub(exarg_T *eap)
                for (p1 = new_end; *p1; ++p1)
                {
                    if (p1[0] == '\\' && p1[1] != NUL)  /* remove backslash */
+                   {
                        STRMOVE(p1, p1 + 1);
+#ifdef FEAT_TEXT_PROP
+                       if (curbuf->b_has_textprop)
+                       {
+                           // When text properties are changed, need to save
+                           // for undo first, unless done already.
+                           if (adjust_prop_columns(lnum,
+                                       (colnr_T)(p1 - new_start), -1,
+                                       apc_flags))
+                               apc_flags &= ~APC_SAVE_FOR_UNDO;
+                       }
+#endif
+                   }
                    else if (*p1 == CAR)
                    {
                        if (u_inssub(lnum) == OK)   // prepare for undo
index 1eac5189aeda2b1ca33329d356d89341ac84a069..e76e4a4a374c256ccbd6a9d93c72fec59452b879 100644 (file)
@@ -441,7 +441,7 @@ set_indent(
            // the old indent, when decreasing indent it behaves like spaces
            // were deleted at the new indent.
            adjust_prop_columns(curwin->w_cursor.lnum,
-                (colnr_T)(added > 0 ? (p - oldline) : ind_len), added, FALSE);
+                (colnr_T)(added > 0 ? (p - oldline) : ind_len), added, 0);
        }
 #endif
        retval = TRUE;
index a989ce21155f90ade55a78bc12152ae788dedabb..4d2692483b560c4a4fbf9d71e3974ee70854f547 100644 (file)
--- a/src/ops.c
+++ b/src/ops.c
@@ -1937,7 +1937,7 @@ op_delete(oparg_T *oap)
 
 #ifdef FEAT_TEXT_PROP
            if (curbuf->b_has_textprop && n != 0)
-               adjust_prop_columns(lnum, bd.textcol, -n, FALSE);
+               adjust_prop_columns(lnum, bd.textcol, -n, 0);
 #endif
        }
 
index 0114b4fadcabf61a4c640f7f6ebac85218aa0909..1301f31a514bfba60fb25ebb0d1848567e33435f 100644 (file)
@@ -13,7 +13,7 @@ void f_prop_type_get(typval_T *argvars, typval_T *rettv);
 void f_prop_type_list(typval_T *argvars, typval_T *rettv);
 void clear_global_prop_types(void);
 void clear_buf_prop_types(buf_T *buf);
-int adjust_prop_columns(linenr_T lnum, colnr_T col, int bytes_added, int save_for_undo);
+int adjust_prop_columns(linenr_T lnum, colnr_T col, int bytes_added, int flags);
 void adjust_props_for_split(linenr_T lnum_props, linenr_T lnum_top, int kept, int deleted);
 void adjust_props_for_join(linenr_T lnum, textprop_T **prop_line, int *prop_length, long col, int removed);
 void join_prop_lines(linenr_T lnum, char_u *newp, textprop_T **prop_lines, int *prop_lengths, int count);
index eb30c04c6c9d5430f4daf99a318a4a73fb21fe46..08b93dfc941133a82d0e983ce0688cc1df9a2650 100644 (file)
@@ -620,6 +620,25 @@ func Test_prop_undo()
   undo
   let expected[0].col = 12
   call assert_equal(expected, prop_list(1))
+  call prop_clear(1)
+
+  " substitute with backslash
+  call setline(1, 'the number 123 is highlighted.')
+  call prop_add(1, 12, {'length': 3, 'type': 'comment'})
+  let expected = [{'col': 12, 'length': 3, 'id': 0, 'type': 'comment', 'start': 1, 'end': 1} ]
+  call assert_equal(expected, prop_list(1))
+  1s/the/\The
+  call assert_equal(expected, prop_list(1))
+  1s/^/\\
+  let expected[0].col += 1
+  call assert_equal(expected, prop_list(1))
+  1s/^/\~
+  let expected[0].col += 1
+  call assert_equal(expected, prop_list(1))
+  1s/123/12\\3
+  let expected[0].length += 1
+  call assert_equal(expected, prop_list(1))
+  call prop_clear(1)
 
   bwipe!
   call prop_type_delete('comment')
index aa3e83b3549255c08a582e4ec76d73dc52acddec..15ae4945b98df781d1db25c84729af0301f3898e 100644 (file)
@@ -957,8 +957,9 @@ clear_buf_prop_types(buf_T *buf)
  * shift by "bytes_added" (can be negative).
  * Note that "col" is zero-based, while tp_col is one-based.
  * Only for the current buffer.
- * When "save_for_undo" is TRUE then call u_savesub() before making changes to
- * the line.
+ * "flags" can have:
+ * APC_SAVE_FOR_UNDO:  Call u_savesub() before making changes to the line.
+ * APC_SUBSTITUTE:     Text is replaced, not inserted.
  * Caller is expected to check b_has_textprop and "bytes_added" being non-zero.
  * Returns TRUE when props were changed.
  */
@@ -967,7 +968,7 @@ adjust_prop_columns(
        linenr_T    lnum,
        colnr_T     col,
        int         bytes_added,
-       int         save_for_undo)
+       int         flags)
 {
     int                proplen;
     char_u     *props;
@@ -988,15 +989,30 @@ adjust_prop_columns(
     wi = 0; // write index
     for (ri = 0; ri < proplen; ++ri)
     {
+       int start_incl;
+
        mch_memmove(&tmp_prop, props + ri * sizeof(textprop_T),
                                                           sizeof(textprop_T));
        pt = text_prop_type_by_id(curbuf, tmp_prop.tp_type);
+       start_incl = (flags & APC_SUBSTITUTE) ||
+                      (pt != NULL && (pt->pt_flags & PT_FLAG_INS_START_INCL));
 
        if (bytes_added > 0
-               ? (tmp_prop.tp_col >= col
-                      + (pt != NULL && (pt->pt_flags & PT_FLAG_INS_START_INCL)
-                                                                     ? 2 : 1))
-               : (tmp_prop.tp_col > col + 1))
+               && (tmp_prop.tp_col >= col + (start_incl ? 2 : 1)))
+       {
+           if (tmp_prop.tp_col < col + (start_incl ? 2 : 1))
+           {
+               tmp_prop.tp_len += (tmp_prop.tp_col - 1 - col) + bytes_added;
+               tmp_prop.tp_col = col + 1;
+           }
+           else
+               tmp_prop.tp_col += bytes_added;
+           // Save for undo if requested and not done yet.
+           if ((flags & APC_SAVE_FOR_UNDO) && !dirty)
+               u_savesub(lnum);
+           dirty = TRUE;
+       }
+       else if (bytes_added <= 0 && (tmp_prop.tp_col > col + 1))
        {
            if (tmp_prop.tp_col + bytes_added < col + 1)
            {
@@ -1006,7 +1022,7 @@ adjust_prop_columns(
            else
                tmp_prop.tp_col += bytes_added;
            // Save for undo if requested and not done yet.
-           if (save_for_undo && !dirty)
+           if ((flags & APC_SAVE_FOR_UNDO) && !dirty)
                u_savesub(lnum);
            dirty = TRUE;
            if (tmp_prop.tp_len <= 0)
@@ -1024,7 +1040,7 @@ adjust_prop_columns(
            else
                tmp_prop.tp_len += bytes_added;
            // Save for undo if requested and not done yet.
-           if (save_for_undo && !dirty)
+           if ((flags & APC_SAVE_FOR_UNDO) && !dirty)
                u_savesub(lnum);
            dirty = TRUE;
            if (tmp_prop.tp_len <= 0)
index 0cd0d7caf39dc5fc57703cc4f08cefb69a4bcdec..f9962a0cfdeaab31ab8d014123d21f8d91c4cd0c 100644 (file)
@@ -767,6 +767,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    1359,
 /**/
     1358,
 /**/
index 05ad07ff6b995ed4adb799978481ee2b46298ac1..153a8c6ed9e832e2f43403985a4c09950c9543ff 100644 (file)
--- a/src/vim.h
+++ b/src/vim.h
@@ -2571,4 +2571,8 @@ long elapsed(DWORD start_tick);
 #define SAVE_RESTORE_ICON      2
 #define SAVE_RESTORE_BOTH      (SAVE_RESTORE_TITLE | SAVE_RESTORE_ICON)
 
+// Flags for adjust_prop_columns()
+#define APC_SAVE_FOR_UNDO      1   // call u_savesub() before making changes
+#define APC_SUBSTITUTE         2   // text is replaced, not inserted
+
 #endif /* VIM__H */