Skip to content

Commit f3333b0

Browse files
committed
patch 8.1.1359: text property wrong after :substitute with backslash
Problem: Text property wrong after :substitute with backslash. Solution: Adjust text property columns when removing backslashes. (closes #4397)
1 parent 386b43e commit f3333b0

10 files changed

Lines changed: 72 additions & 17 deletions

File tree

src/change.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -684,7 +684,7 @@ inserted_bytes(linenr_T lnum, colnr_T col, int added UNUSED)
684684
{
685685
#ifdef FEAT_TEXT_PROP
686686
if (curbuf->b_has_textprop && added != 0)
687-
adjust_prop_columns(lnum, col, added, FALSE);
687+
adjust_prop_columns(lnum, col, added, 0);
688688
#endif
689689

690690
changed_bytes(lnum, col);

src/edit.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4104,7 +4104,7 @@ replace_do_bs(int limit_col)
41044104

41054105
--text_prop_frozen;
41064106
adjust_prop_columns(curwin->w_cursor.lnum, curwin->w_cursor.col,
4107-
(int)(len_now - len_before), FALSE);
4107+
(int)(len_now - len_before), 0);
41084108
}
41094109
#endif
41104110
}

src/ex_cmds.c

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5189,7 +5189,7 @@ do_sub(exarg_T *eap)
51895189
int skip_match = FALSE;
51905190
linenr_T sub_firstlnum; /* nr of first sub line */
51915191
#ifdef FEAT_TEXT_PROP
5192-
int save_for_undo = TRUE;
5192+
int apc_flags = APC_SAVE_FOR_UNDO | APC_SUBSTITUTE;
51935193
#endif
51945194

51955195
/*
@@ -5612,8 +5612,9 @@ do_sub(exarg_T *eap)
56125612
// undo first, unless done already.
56135613
if (adjust_prop_columns(lnum, regmatch.startpos[0].col,
56145614
sublen - 1 - (regmatch.endpos[0].col
5615-
- regmatch.startpos[0].col), save_for_undo))
5616-
save_for_undo = FALSE;
5615+
- regmatch.startpos[0].col),
5616+
apc_flags))
5617+
apc_flags &= ~APC_SAVE_FOR_UNDO;
56175618
}
56185619
#endif
56195620
}
@@ -5715,7 +5716,20 @@ do_sub(exarg_T *eap)
57155716
for (p1 = new_end; *p1; ++p1)
57165717
{
57175718
if (p1[0] == '\\' && p1[1] != NUL) /* remove backslash */
5719+
{
57185720
STRMOVE(p1, p1 + 1);
5721+
#ifdef FEAT_TEXT_PROP
5722+
if (curbuf->b_has_textprop)
5723+
{
5724+
// When text properties are changed, need to save
5725+
// for undo first, unless done already.
5726+
if (adjust_prop_columns(lnum,
5727+
(colnr_T)(p1 - new_start), -1,
5728+
apc_flags))
5729+
apc_flags &= ~APC_SAVE_FOR_UNDO;
5730+
}
5731+
#endif
5732+
}
57195733
else if (*p1 == CAR)
57205734
{
57215735
if (u_inssub(lnum) == OK) // prepare for undo

src/misc1.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -441,7 +441,7 @@ set_indent(
441441
// the old indent, when decreasing indent it behaves like spaces
442442
// were deleted at the new indent.
443443
adjust_prop_columns(curwin->w_cursor.lnum,
444-
(colnr_T)(added > 0 ? (p - oldline) : ind_len), added, FALSE);
444+
(colnr_T)(added > 0 ? (p - oldline) : ind_len), added, 0);
445445
}
446446
#endif
447447
retval = TRUE;

src/ops.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1937,7 +1937,7 @@ op_delete(oparg_T *oap)
19371937

19381938
#ifdef FEAT_TEXT_PROP
19391939
if (curbuf->b_has_textprop && n != 0)
1940-
adjust_prop_columns(lnum, bd.textcol, -n, FALSE);
1940+
adjust_prop_columns(lnum, bd.textcol, -n, 0);
19411941
#endif
19421942
}
19431943

src/proto/textprop.pro

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ void f_prop_type_get(typval_T *argvars, typval_T *rettv);
1313
void f_prop_type_list(typval_T *argvars, typval_T *rettv);
1414
void clear_global_prop_types(void);
1515
void clear_buf_prop_types(buf_T *buf);
16-
int adjust_prop_columns(linenr_T lnum, colnr_T col, int bytes_added, int save_for_undo);
16+
int adjust_prop_columns(linenr_T lnum, colnr_T col, int bytes_added, int flags);
1717
void adjust_props_for_split(linenr_T lnum_props, linenr_T lnum_top, int kept, int deleted);
1818
void adjust_props_for_join(linenr_T lnum, textprop_T **prop_line, int *prop_length, long col, int removed);
1919
void join_prop_lines(linenr_T lnum, char_u *newp, textprop_T **prop_lines, int *prop_lengths, int count);

src/testdir/test_textprop.vim

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -620,6 +620,25 @@ func Test_prop_undo()
620620
undo
621621
let expected[0].col = 12
622622
call assert_equal(expected, prop_list(1))
623+
call prop_clear(1)
624+
625+
" substitute with backslash
626+
call setline(1, 'the number 123 is highlighted.')
627+
call prop_add(1, 12, {'length': 3, 'type': 'comment'})
628+
let expected = [{'col': 12, 'length': 3, 'id': 0, 'type': 'comment', 'start': 1, 'end': 1} ]
629+
call assert_equal(expected, prop_list(1))
630+
1s/the/\The
631+
call assert_equal(expected, prop_list(1))
632+
1s/^/\\
633+
let expected[0].col += 1
634+
call assert_equal(expected, prop_list(1))
635+
1s/^/\~
636+
let expected[0].col += 1
637+
call assert_equal(expected, prop_list(1))
638+
1s/123/12\\3
639+
let expected[0].length += 1
640+
call assert_equal(expected, prop_list(1))
641+
call prop_clear(1)
623642

624643
bwipe!
625644
call prop_type_delete('comment')

src/textprop.c

Lines changed: 25 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -957,8 +957,9 @@ clear_buf_prop_types(buf_T *buf)
957957
* shift by "bytes_added" (can be negative).
958958
* Note that "col" is zero-based, while tp_col is one-based.
959959
* Only for the current buffer.
960-
* When "save_for_undo" is TRUE then call u_savesub() before making changes to
961-
* the line.
960+
* "flags" can have:
961+
* APC_SAVE_FOR_UNDO: Call u_savesub() before making changes to the line.
962+
* APC_SUBSTITUTE: Text is replaced, not inserted.
962963
* Caller is expected to check b_has_textprop and "bytes_added" being non-zero.
963964
* Returns TRUE when props were changed.
964965
*/
@@ -967,7 +968,7 @@ adjust_prop_columns(
967968
linenr_T lnum,
968969
colnr_T col,
969970
int bytes_added,
970-
int save_for_undo)
971+
int flags)
971972
{
972973
int proplen;
973974
char_u *props;
@@ -988,15 +989,30 @@ adjust_prop_columns(
988989
wi = 0; // write index
989990
for (ri = 0; ri < proplen; ++ri)
990991
{
992+
int start_incl;
993+
991994
mch_memmove(&tmp_prop, props + ri * sizeof(textprop_T),
992995
sizeof(textprop_T));
993996
pt = text_prop_type_by_id(curbuf, tmp_prop.tp_type);
997+
start_incl = (flags & APC_SUBSTITUTE) ||
998+
(pt != NULL && (pt->pt_flags & PT_FLAG_INS_START_INCL));
994999

9951000
if (bytes_added > 0
996-
? (tmp_prop.tp_col >= col
997-
+ (pt != NULL && (pt->pt_flags & PT_FLAG_INS_START_INCL)
998-
? 2 : 1))
999-
: (tmp_prop.tp_col > col + 1))
1001+
&& (tmp_prop.tp_col >= col + (start_incl ? 2 : 1)))
1002+
{
1003+
if (tmp_prop.tp_col < col + (start_incl ? 2 : 1))
1004+
{
1005+
tmp_prop.tp_len += (tmp_prop.tp_col - 1 - col) + bytes_added;
1006+
tmp_prop.tp_col = col + 1;
1007+
}
1008+
else
1009+
tmp_prop.tp_col += bytes_added;
1010+
// Save for undo if requested and not done yet.
1011+
if ((flags & APC_SAVE_FOR_UNDO) && !dirty)
1012+
u_savesub(lnum);
1013+
dirty = TRUE;
1014+
}
1015+
else if (bytes_added <= 0 && (tmp_prop.tp_col > col + 1))
10001016
{
10011017
if (tmp_prop.tp_col + bytes_added < col + 1)
10021018
{
@@ -1006,7 +1022,7 @@ adjust_prop_columns(
10061022
else
10071023
tmp_prop.tp_col += bytes_added;
10081024
// Save for undo if requested and not done yet.
1009-
if (save_for_undo && !dirty)
1025+
if ((flags & APC_SAVE_FOR_UNDO) && !dirty)
10101026
u_savesub(lnum);
10111027
dirty = TRUE;
10121028
if (tmp_prop.tp_len <= 0)
@@ -1024,7 +1040,7 @@ adjust_prop_columns(
10241040
else
10251041
tmp_prop.tp_len += bytes_added;
10261042
// Save for undo if requested and not done yet.
1027-
if (save_for_undo && !dirty)
1043+
if ((flags & APC_SAVE_FOR_UNDO) && !dirty)
10281044
u_savesub(lnum);
10291045
dirty = TRUE;
10301046
if (tmp_prop.tp_len <= 0)

src/version.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -767,6 +767,8 @@ static char *(features[]) =
767767

768768
static int included_patches[] =
769769
{ /* Add new patch number below this line */
770+
/**/
771+
1359,
770772
/**/
771773
1358,
772774
/**/

src/vim.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2571,4 +2571,8 @@ long elapsed(DWORD start_tick);
25712571
#define SAVE_RESTORE_ICON 2
25722572
#define SAVE_RESTORE_BOTH (SAVE_RESTORE_TITLE | SAVE_RESTORE_ICON)
25732573

2574+
// Flags for adjust_prop_columns()
2575+
#define APC_SAVE_FOR_UNDO 1 // call u_savesub() before making changes
2576+
#define APC_SUBSTITUTE 2 // text is replaced, not inserted
2577+
25742578
#endif /* VIM__H */

0 commit comments

Comments
 (0)