summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBram Moolenaar <Bram@vim.org>2017-09-02 20:30:35 +0200
committerBram Moolenaar <Bram@vim.org>2017-09-02 20:30:35 +0200
commite2e69e48134cbfdedea7802810932f8592705024 (patch)
tree5de70fd649143a4e94584ef3a648b1877900b02f
parent3653822546fb0f1005c32bb5b70dc9bfacdfc954 (diff)
downloadvim-git-e2e69e48134cbfdedea7802810932f8592705024.tar.gz
patch 8.0.1041: bogus characters when indenting during visual-block appendv8.0.1041
Problem: Bogus characters appear when indenting kicks in while doing a visual-block append. Solution: Recompute when indenting is done. (Christian Brabandt)
-rw-r--r--runtime/doc/visual.txt5
-rw-r--r--src/charset.c16
-rw-r--r--src/edit.c7
-rw-r--r--src/misc1.c6
-rw-r--r--src/ops.c19
-rw-r--r--src/proto/charset.pro2
-rw-r--r--src/proto/misc1.pro1
-rw-r--r--src/screen.c2
-rw-r--r--src/spell.c6
-rw-r--r--src/testdir/test_cindent.vim24
-rw-r--r--src/version.c2
11 files changed, 70 insertions, 20 deletions
diff --git a/runtime/doc/visual.txt b/runtime/doc/visual.txt
index 0a91b9f48..59315019d 100644
--- a/runtime/doc/visual.txt
+++ b/runtime/doc/visual.txt
@@ -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
diff --git a/src/charset.c b/src/charset.c
index d649179dd..8b83f6806 100644
--- a/src/charset.c
+++ b/src/charset.c
@@ -1536,6 +1536,22 @@ skipwhite(char_u *q)
}
/*
+ * 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
*/
char_u *
diff --git a/src/edit.c b/src/edit.c
index 33c4c0071..6fd124539 100644
--- a/src/edit.c
+++ b/src/edit.c
@@ -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;
}
diff --git a/src/misc1.c b/src/misc1.c
index abc455e95..8ae75e6d8 100644
--- a/src/misc1.c
+++ b/src/misc1.c
@@ -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))
diff --git a/src/ops.c b/src/ops.c
index 5c58e523f..9ca5198d2 100644
--- a/src/ops.c
+++ b/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)
{
diff --git a/src/proto/charset.pro b/src/proto/charset.pro
index 52b741a74..bb4132fe7 100644
--- a/src/proto/charset.pro
+++ b/src/proto/charset.pro
@@ -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);
diff --git a/src/proto/misc1.pro b/src/proto/misc1.pro
index cac644969..4e299e5f9 100644
--- a/src/proto/misc1.pro
+++ b/src/proto/misc1.pro
@@ -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);
diff --git a/src/screen.c b/src/screen.c
index ca7b65836..e0d4af8fc 100644
--- a/src/screen.c
+++ b/src/screen.c
@@ -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
diff --git a/src/spell.c b/src/spell.c
index 0eb87638e..2742997c2 100644
--- a/src/spell.c
+++ b/src/spell.c
@@ -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. */
diff --git a/src/testdir/test_cindent.vim b/src/testdir/test_cindent.vim
index d352e8fef..7c2c5e341 100644
--- a/src/testdir/test_cindent.vim
+++ b/src/testdir/test_cindent.vim
@@ -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
diff --git a/src/version.c b/src/version.c
index ee6e91ce7..e59466762 100644
--- a/src/version.c
+++ b/src/version.c
@@ -770,6 +770,8 @@ static char *(features[]) =
static int included_patches[] =
{ /* Add new patch number below this line */
/**/
+ 1041,
+/**/
1040,
/**/
1039,