Skip to content

Commit e2e69e4

Browse files
committed
patch 8.0.1041: bogus characters when indenting during visual-block append
Problem: Bogus characters appear when indenting kicks in while doing a visual-block append. Solution: Recompute when indenting is done. (Christian Brabandt)
1 parent 3653822 commit e2e69e4

11 files changed

Lines changed: 70 additions & 20 deletions

File tree

runtime/doc/visual.txt

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -314,8 +314,8 @@ Visual-block Insert *v_b_I*
314314
With a blockwise selection, I{string}<ESC> will insert {string} at the start
315315
of block on every line of the block, provided that the line extends into the
316316
block. Thus lines that are short will remain unmodified. TABs are split to
317-
retain visual columns.
318-
See |v_b_I_example|.
317+
retain visual columns. Works only for adding text to a line, not for
318+
deletions. See |v_b_I_example|.
319319

320320
Visual-block Append *v_b_A*
321321
With a blockwise selection, A{string}<ESC> will append {string} to the end of
@@ -331,6 +331,7 @@ See |v_b_A_example|.
331331
Note: "I" and "A" behave differently for lines that don't extend into the
332332
selected block. This was done intentionally, so that you can do it the way
333333
you want.
334+
Works only for adding text to a line, not for deletions.
334335

335336
Visual-block change *v_b_c*
336337
All selected text in the block will be replaced by the same text string. When

src/charset.c

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1535,6 +1535,22 @@ skipwhite(char_u *q)
15351535
return p;
15361536
}
15371537

1538+
/*
1539+
* getwhitecols: return the number of whitespace
1540+
* columns (bytes) at the start of a given line
1541+
*/
1542+
int
1543+
getwhitecols_curline()
1544+
{
1545+
return getwhitecols(ml_get_curline());
1546+
}
1547+
1548+
int
1549+
getwhitecols(char_u *p)
1550+
{
1551+
return skipwhite(p) - p;
1552+
}
1553+
15381554
/*
15391555
* skip over digits
15401556
*/

src/edit.c

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5182,7 +5182,7 @@ ins_complete(int c, int enable_pum)
51825182
* first non_blank in the line, if it is not a wordchar
51835183
* include it to get a better pattern, but then we don't
51845184
* want the "\\<" prefix, check it bellow */
5185-
compl_col = (colnr_T)(skipwhite(line) - line);
5185+
compl_col = (colnr_T)getwhitecols(line);
51865186
compl_startpos.col = compl_col;
51875187
compl_startpos.lnum = curwin->w_cursor.lnum;
51885188
compl_cont_status &= ~CONT_SOL; /* clear SOL if present */
@@ -5348,7 +5348,7 @@ ins_complete(int c, int enable_pum)
53485348
}
53495349
else if (CTRL_X_MODE_LINE_OR_EVAL(ctrl_x_mode))
53505350
{
5351-
compl_col = (colnr_T)(skipwhite(line) - line);
5351+
compl_col = (colnr_T)getwhitecols(line);
53525352
compl_length = (int)curs_col - (int)compl_col;
53535353
if (compl_length < 0) /* cursor in indent: empty pattern */
53545354
compl_length = 0;
@@ -8208,8 +8208,7 @@ in_cinkeys(
82088208
{
82098209
/* "0=word": Check if there are only blanks before the
82108210
* word. */
8211-
line = ml_get_curline();
8212-
if ((int)(skipwhite(line) - line) !=
8211+
if (getwhitecols(line) !=
82138212
(int)(curwin->w_cursor.col - (p - look)))
82148213
match = FALSE;
82158214
}

src/misc1.c

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1589,8 +1589,7 @@ open_line(
15891589
&& curbuf->b_p_ai)
15901590
{
15911591
fixthisline(get_lisp_indent);
1592-
p = ml_get_curline();
1593-
ai_col = (colnr_T)(skipwhite(p) - p);
1592+
ai_col = (colnr_T)getwhitecols_curline();
15941593
}
15951594
#endif
15961595
#ifdef FEAT_CINDENT
@@ -1608,8 +1607,7 @@ open_line(
16081607
: KEY_OPEN_BACK, ' ', linewhite(curwin->w_cursor.lnum)))
16091608
{
16101609
do_c_expr_indent();
1611-
p = ml_get_curline();
1612-
ai_col = (colnr_T)(skipwhite(p) - p);
1610+
ai_col = (colnr_T)getwhitecols_curline();
16131611
}
16141612
#endif
16151613
#if defined(FEAT_VREPLACE) && (defined(FEAT_LISP) || defined(FEAT_CINDENT))

src/ops.c

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2507,6 +2507,7 @@ op_insert(oparg_T *oap, long count1)
25072507
{
25082508
long ins_len, pre_textlen = 0;
25092509
char_u *firstline, *ins_text;
2510+
colnr_T ind_pre, ind_post;
25102511
struct block_def bd;
25112512
int i;
25122513
pos_T t1;
@@ -2541,7 +2542,10 @@ op_insert(oparg_T *oap, long count1)
25412542
#endif
25422543
/* Get the info about the block before entering the text */
25432544
block_prep(oap, &bd, oap->start.lnum, TRUE);
2545+
/* Get indent information */
2546+
ind_pre = (colnr_T)getwhitecols_curline();
25442547
firstline = ml_get(oap->start.lnum) + bd.textcol;
2548+
25452549
if (oap->op_type == OP_APPEND)
25462550
firstline += bd.textlen;
25472551
pre_textlen = (long)STRLEN(firstline);
@@ -2593,6 +2597,14 @@ op_insert(oparg_T *oap, long count1)
25932597
&& LT_POS(curbuf->b_op_start_orig, t1))
25942598
oap->start = curbuf->b_op_start_orig;
25952599

2600+
/* if indent kicked in, the firstline might have changed
2601+
* but only do that, if the indent actually increased */
2602+
ind_post = (colnr_T)getwhitecols_curline();
2603+
if (curbuf->b_op_start.col > ind_pre && ind_post > ind_pre)
2604+
{
2605+
bd.textcol += ind_post - ind_pre;
2606+
bd.start_vcol += ind_post - ind_pre;
2607+
}
25962608
/* If user has moved off this line, we don't know what to do, so do
25972609
* nothing.
25982610
* Also don't repeat the insert when Insert mode ended with CTRL-C. */
@@ -2754,7 +2766,7 @@ op_change(oparg_T *oap)
27542766
# endif
27552767
firstline = ml_get(oap->start.lnum);
27562768
pre_textlen = (long)STRLEN(firstline);
2757-
pre_indent = (long)(skipwhite(firstline) - firstline);
2769+
pre_indent = (long)getwhitecols(firstline);
27582770
bd.textcol = curwin->w_cursor.col;
27592771
}
27602772
#endif
@@ -2779,7 +2791,7 @@ op_change(oparg_T *oap)
27792791
firstline = ml_get(oap->start.lnum);
27802792
if (bd.textcol > (colnr_T)pre_indent)
27812793
{
2782-
long new_indent = (long)(skipwhite(firstline) - firstline);
2794+
long new_indent = (long)getwhitecols(firstline);
27832795

27842796
pre_textlen += new_indent - pre_indent;
27852797
bd.textcol += new_indent - pre_indent;
@@ -5065,8 +5077,7 @@ format_lines(
50655077
#endif
50665078
if (second_indent > 0) /* the "leader" for FO_Q_SECOND */
50675079
{
5068-
char_u *p = ml_get_curline();
5069-
int indent = (int)(skipwhite(p) - p);
5080+
int indent = getwhitecols_curline();
50705081

50715082
if (indent > 0)
50725083
{

src/proto/charset.pro

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,8 @@ colnr_T getvcol_nolist(pos_T *posp);
3535
void getvvcol(win_T *wp, pos_T *pos, colnr_T *start, colnr_T *cursor, colnr_T *end);
3636
void getvcols(win_T *wp, pos_T *pos1, pos_T *pos2, colnr_T *left, colnr_T *right);
3737
char_u *skipwhite(char_u *q);
38+
int getwhitecols_curline(void);
39+
int getwhitecols(char_u *p);
3840
char_u *skipdigits(char_u *q);
3941
char_u *skipbin(char_u *q);
4042
char_u *skiphex(char_u *q);

src/proto/misc1.pro

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
/* misc1.c */
2+
int get_whitespace_line_start(linenr_T lnum);
23
int get_indent(void);
34
int get_indent_lnum(linenr_T lnum);
45
int get_indent_buf(buf_T *buf, linenr_T lnum);

src/screen.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3463,7 +3463,7 @@ win_line(
34633463
{
34643464
/* For checking first word with a capital skip white space. */
34653465
if (cap_col == 0)
3466-
cap_col = (int)(skipwhite(line) - line);
3466+
cap_col = getwhitecols(line);
34673467

34683468
/* To be able to spell-check over line boundaries copy the end of the
34693469
* current line into nextline[]. Above the start of the next line was

src/spell.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1625,11 +1625,11 @@ spell_move_to(
16251625

16261626
/* For checking first word with a capital skip white space. */
16271627
if (capcol == 0)
1628-
capcol = (int)(skipwhite(line) - line);
1628+
capcol = getwhitecols(line);
16291629
else if (curline && wp == curwin)
16301630
{
16311631
/* For spellbadword(): check if first word needs a capital. */
1632-
col = (int)(skipwhite(line) - line);
1632+
col = getwhitecols(line);
16331633
if (check_need_cap(lnum, col))
16341634
capcol = col;
16351635

@@ -3593,7 +3593,7 @@ check_need_cap(linenr_T lnum, colnr_T col)
35933593

35943594
line = ml_get_curline();
35953595
endcol = 0;
3596-
if ((int)(skipwhite(line) - line) >= (int)col)
3596+
if (getwhitecols(line) >= (int)col)
35973597
{
35983598
/* At start of line, check if previous line is empty or sentence
35993599
* ends there. */

src/testdir/test_cindent.vim

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ func Test_cino_extern_c()
7171
bwipe!
7272
endfunc
7373

74-
func! Test_cindent_rawstring()
74+
func Test_cindent_rawstring()
7575
new
7676
setl cindent
7777
call feedkeys("i" .
@@ -81,5 +81,25 @@ func! Test_cindent_rawstring()
8181
\ "statement;\<Esc>", "x")
8282
call assert_equal("\tstatement;", getline(line('.')))
8383
bw!
84-
endfunction
84+
endfunc
85+
86+
func Test_cindent_expr()
87+
new
88+
func! MyIndentFunction()
89+
return v:lnum == 1 ? shiftwidth() : 0
90+
endfunc
91+
setl expandtab sw=8 indentkeys+=; indentexpr=MyIndentFunction()
92+
call setline(1, ['var_a = something()', 'b = something()'])
93+
call cursor(1, 1)
94+
call feedkeys("^\<c-v>j$A;\<esc>", 'tnix')
95+
call assert_equal([' var_a = something();', 'b = something();'], getline(1, '$'))
96+
97+
%d
98+
call setline(1, [' var_a = something()', ' b = something()'])
99+
call cursor(1, 1)
100+
call feedkeys("^\<c-v>j$A;\<esc>", 'tnix')
101+
call assert_equal([' var_a = something();', ' b = something()'], getline(1, '$'))
102+
bw!
103+
endfunc
104+
85105
" vim: shiftwidth=2 sts=2 expandtab

0 commit comments

Comments
 (0)