forked from aniani/vim
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)
This commit is contained in:
@@ -314,8 +314,8 @@ Visual-block Insert *v_b_I*
|
||||
With a blockwise selection, I{string}<ESC> will insert {string} at the start
|
||||
of block on every line of the block, provided that the line extends into the
|
||||
block. Thus lines that are short will remain unmodified. TABs are split to
|
||||
retain visual columns.
|
||||
See |v_b_I_example|.
|
||||
retain visual columns. Works only for adding text to a line, not for
|
||||
deletions. See |v_b_I_example|.
|
||||
|
||||
Visual-block Append *v_b_A*
|
||||
With a blockwise selection, A{string}<ESC> will append {string} to the end of
|
||||
@@ -331,6 +331,7 @@ See |v_b_A_example|.
|
||||
Note: "I" and "A" behave differently for lines that don't extend into the
|
||||
selected block. This was done intentionally, so that you can do it the way
|
||||
you want.
|
||||
Works only for adding text to a line, not for deletions.
|
||||
|
||||
Visual-block change *v_b_c*
|
||||
All selected text in the block will be replaced by the same text string. When
|
||||
|
@@ -1535,6 +1535,22 @@ skipwhite(char_u *q)
|
||||
return p;
|
||||
}
|
||||
|
||||
/*
|
||||
* getwhitecols: return the number of whitespace
|
||||
* columns (bytes) at the start of a given line
|
||||
*/
|
||||
int
|
||||
getwhitecols_curline()
|
||||
{
|
||||
return getwhitecols(ml_get_curline());
|
||||
}
|
||||
|
||||
int
|
||||
getwhitecols(char_u *p)
|
||||
{
|
||||
return skipwhite(p) - p;
|
||||
}
|
||||
|
||||
/*
|
||||
* skip over digits
|
||||
*/
|
||||
|
@@ -5182,7 +5182,7 @@ ins_complete(int c, int enable_pum)
|
||||
* first non_blank in the line, if it is not a wordchar
|
||||
* include it to get a better pattern, but then we don't
|
||||
* want the "\\<" prefix, check it bellow */
|
||||
compl_col = (colnr_T)(skipwhite(line) - line);
|
||||
compl_col = (colnr_T)getwhitecols(line);
|
||||
compl_startpos.col = compl_col;
|
||||
compl_startpos.lnum = curwin->w_cursor.lnum;
|
||||
compl_cont_status &= ~CONT_SOL; /* clear SOL if present */
|
||||
@@ -5348,7 +5348,7 @@ ins_complete(int c, int enable_pum)
|
||||
}
|
||||
else if (CTRL_X_MODE_LINE_OR_EVAL(ctrl_x_mode))
|
||||
{
|
||||
compl_col = (colnr_T)(skipwhite(line) - line);
|
||||
compl_col = (colnr_T)getwhitecols(line);
|
||||
compl_length = (int)curs_col - (int)compl_col;
|
||||
if (compl_length < 0) /* cursor in indent: empty pattern */
|
||||
compl_length = 0;
|
||||
@@ -8208,8 +8208,7 @@ in_cinkeys(
|
||||
{
|
||||
/* "0=word": Check if there are only blanks before the
|
||||
* word. */
|
||||
line = ml_get_curline();
|
||||
if ((int)(skipwhite(line) - line) !=
|
||||
if (getwhitecols(line) !=
|
||||
(int)(curwin->w_cursor.col - (p - look)))
|
||||
match = FALSE;
|
||||
}
|
||||
|
@@ -1589,8 +1589,7 @@ open_line(
|
||||
&& curbuf->b_p_ai)
|
||||
{
|
||||
fixthisline(get_lisp_indent);
|
||||
p = ml_get_curline();
|
||||
ai_col = (colnr_T)(skipwhite(p) - p);
|
||||
ai_col = (colnr_T)getwhitecols_curline();
|
||||
}
|
||||
#endif
|
||||
#ifdef FEAT_CINDENT
|
||||
@@ -1608,8 +1607,7 @@ open_line(
|
||||
: KEY_OPEN_BACK, ' ', linewhite(curwin->w_cursor.lnum)))
|
||||
{
|
||||
do_c_expr_indent();
|
||||
p = ml_get_curline();
|
||||
ai_col = (colnr_T)(skipwhite(p) - p);
|
||||
ai_col = (colnr_T)getwhitecols_curline();
|
||||
}
|
||||
#endif
|
||||
#if defined(FEAT_VREPLACE) && (defined(FEAT_LISP) || defined(FEAT_CINDENT))
|
||||
|
19
src/ops.c
19
src/ops.c
@@ -2507,6 +2507,7 @@ op_insert(oparg_T *oap, long count1)
|
||||
{
|
||||
long ins_len, pre_textlen = 0;
|
||||
char_u *firstline, *ins_text;
|
||||
colnr_T ind_pre, ind_post;
|
||||
struct block_def bd;
|
||||
int i;
|
||||
pos_T t1;
|
||||
@@ -2541,7 +2542,10 @@ op_insert(oparg_T *oap, long count1)
|
||||
#endif
|
||||
/* Get the info about the block before entering the text */
|
||||
block_prep(oap, &bd, oap->start.lnum, TRUE);
|
||||
/* Get indent information */
|
||||
ind_pre = (colnr_T)getwhitecols_curline();
|
||||
firstline = ml_get(oap->start.lnum) + bd.textcol;
|
||||
|
||||
if (oap->op_type == OP_APPEND)
|
||||
firstline += bd.textlen;
|
||||
pre_textlen = (long)STRLEN(firstline);
|
||||
@@ -2593,6 +2597,14 @@ op_insert(oparg_T *oap, long count1)
|
||||
&& LT_POS(curbuf->b_op_start_orig, t1))
|
||||
oap->start = curbuf->b_op_start_orig;
|
||||
|
||||
/* if indent kicked in, the firstline might have changed
|
||||
* but only do that, if the indent actually increased */
|
||||
ind_post = (colnr_T)getwhitecols_curline();
|
||||
if (curbuf->b_op_start.col > ind_pre && ind_post > ind_pre)
|
||||
{
|
||||
bd.textcol += ind_post - ind_pre;
|
||||
bd.start_vcol += ind_post - ind_pre;
|
||||
}
|
||||
/* If user has moved off this line, we don't know what to do, so do
|
||||
* nothing.
|
||||
* Also don't repeat the insert when Insert mode ended with CTRL-C. */
|
||||
@@ -2754,7 +2766,7 @@ op_change(oparg_T *oap)
|
||||
# endif
|
||||
firstline = ml_get(oap->start.lnum);
|
||||
pre_textlen = (long)STRLEN(firstline);
|
||||
pre_indent = (long)(skipwhite(firstline) - firstline);
|
||||
pre_indent = (long)getwhitecols(firstline);
|
||||
bd.textcol = curwin->w_cursor.col;
|
||||
}
|
||||
#endif
|
||||
@@ -2779,7 +2791,7 @@ op_change(oparg_T *oap)
|
||||
firstline = ml_get(oap->start.lnum);
|
||||
if (bd.textcol > (colnr_T)pre_indent)
|
||||
{
|
||||
long new_indent = (long)(skipwhite(firstline) - firstline);
|
||||
long new_indent = (long)getwhitecols(firstline);
|
||||
|
||||
pre_textlen += new_indent - pre_indent;
|
||||
bd.textcol += new_indent - pre_indent;
|
||||
@@ -5065,8 +5077,7 @@ format_lines(
|
||||
#endif
|
||||
if (second_indent > 0) /* the "leader" for FO_Q_SECOND */
|
||||
{
|
||||
char_u *p = ml_get_curline();
|
||||
int indent = (int)(skipwhite(p) - p);
|
||||
int indent = getwhitecols_curline();
|
||||
|
||||
if (indent > 0)
|
||||
{
|
||||
|
@@ -35,6 +35,8 @@ colnr_T getvcol_nolist(pos_T *posp);
|
||||
void getvvcol(win_T *wp, pos_T *pos, colnr_T *start, colnr_T *cursor, colnr_T *end);
|
||||
void getvcols(win_T *wp, pos_T *pos1, pos_T *pos2, colnr_T *left, colnr_T *right);
|
||||
char_u *skipwhite(char_u *q);
|
||||
int getwhitecols_curline(void);
|
||||
int getwhitecols(char_u *p);
|
||||
char_u *skipdigits(char_u *q);
|
||||
char_u *skipbin(char_u *q);
|
||||
char_u *skiphex(char_u *q);
|
||||
|
@@ -1,4 +1,5 @@
|
||||
/* misc1.c */
|
||||
int get_whitespace_line_start(linenr_T lnum);
|
||||
int get_indent(void);
|
||||
int get_indent_lnum(linenr_T lnum);
|
||||
int get_indent_buf(buf_T *buf, linenr_T lnum);
|
||||
|
@@ -3463,7 +3463,7 @@ win_line(
|
||||
{
|
||||
/* For checking first word with a capital skip white space. */
|
||||
if (cap_col == 0)
|
||||
cap_col = (int)(skipwhite(line) - line);
|
||||
cap_col = getwhitecols(line);
|
||||
|
||||
/* To be able to spell-check over line boundaries copy the end of the
|
||||
* current line into nextline[]. Above the start of the next line was
|
||||
|
@@ -1625,11 +1625,11 @@ spell_move_to(
|
||||
|
||||
/* For checking first word with a capital skip white space. */
|
||||
if (capcol == 0)
|
||||
capcol = (int)(skipwhite(line) - line);
|
||||
capcol = getwhitecols(line);
|
||||
else if (curline && wp == curwin)
|
||||
{
|
||||
/* For spellbadword(): check if first word needs a capital. */
|
||||
col = (int)(skipwhite(line) - line);
|
||||
col = getwhitecols(line);
|
||||
if (check_need_cap(lnum, col))
|
||||
capcol = col;
|
||||
|
||||
@@ -3593,7 +3593,7 @@ check_need_cap(linenr_T lnum, colnr_T col)
|
||||
|
||||
line = ml_get_curline();
|
||||
endcol = 0;
|
||||
if ((int)(skipwhite(line) - line) >= (int)col)
|
||||
if (getwhitecols(line) >= (int)col)
|
||||
{
|
||||
/* At start of line, check if previous line is empty or sentence
|
||||
* ends there. */
|
||||
|
@@ -71,7 +71,7 @@ func Test_cino_extern_c()
|
||||
bwipe!
|
||||
endfunc
|
||||
|
||||
func! Test_cindent_rawstring()
|
||||
func Test_cindent_rawstring()
|
||||
new
|
||||
setl cindent
|
||||
call feedkeys("i" .
|
||||
@@ -81,5 +81,25 @@ func! Test_cindent_rawstring()
|
||||
\ "statement;\<Esc>", "x")
|
||||
call assert_equal("\tstatement;", getline(line('.')))
|
||||
bw!
|
||||
endfunction
|
||||
endfunc
|
||||
|
||||
func Test_cindent_expr()
|
||||
new
|
||||
func! MyIndentFunction()
|
||||
return v:lnum == 1 ? shiftwidth() : 0
|
||||
endfunc
|
||||
setl expandtab sw=8 indentkeys+=; indentexpr=MyIndentFunction()
|
||||
call setline(1, ['var_a = something()', 'b = something()'])
|
||||
call cursor(1, 1)
|
||||
call feedkeys("^\<c-v>j$A;\<esc>", 'tnix')
|
||||
call assert_equal([' var_a = something();', 'b = something();'], getline(1, '$'))
|
||||
|
||||
%d
|
||||
call setline(1, [' var_a = something()', ' b = something()'])
|
||||
call cursor(1, 1)
|
||||
call feedkeys("^\<c-v>j$A;\<esc>", 'tnix')
|
||||
call assert_equal([' var_a = something();', ' b = something()'], getline(1, '$'))
|
||||
bw!
|
||||
endfunc
|
||||
|
||||
" vim: shiftwidth=2 sts=2 expandtab
|
||||
|
@@ -769,6 +769,8 @@ static char *(features[]) =
|
||||
|
||||
static int included_patches[] =
|
||||
{ /* Add new patch number below this line */
|
||||
/**/
|
||||
1041,
|
||||
/**/
|
||||
1040,
|
||||
/**/
|
||||
|
Reference in New Issue
Block a user