]> granicus.if.org Git - vim/commitdiff
patch 8.0.1041: bogus characters when indenting during visual-block append v8.0.1041
authorBram Moolenaar <Bram@vim.org>
Sat, 2 Sep 2017 18:30:35 +0000 (20:30 +0200)
committerBram Moolenaar <Bram@vim.org>
Sat, 2 Sep 2017 18:30:35 +0000 (20:30 +0200)
Problem:    Bogus characters appear when indenting kicks in while doing a
            visual-block append.
Solution:   Recompute when indenting is done. (Christian Brabandt)

runtime/doc/visual.txt
src/charset.c
src/edit.c
src/misc1.c
src/ops.c
src/proto/charset.pro
src/proto/misc1.pro
src/screen.c
src/spell.c
src/testdir/test_cindent.vim
src/version.c

index 0a91b9f48ecf26e297a20fec79965620539a64ea..59315019d31c3c6540a4956b2ec86686f5738a00 100644 (file)
@@ -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
index d649179dd74c3b08afd9f003de74b731eb1dd8ef..8b83f680682dc2d391e8c87c3a8f78109c34c902 100644 (file)
@@ -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
  */
index 33c4c007157cb3d1248c46915c39e7325356d733..6fd1245390b10d98709c9bd22e7fef2d53a2576c 100644 (file)
@@ -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;
                }
index abc455e951a199eca6bb1dd33ed65ed0043b12b5..8ae75e6d85f3ab25885f444c3b79e1e49e00916e 100644 (file)
@@ -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))
index 5c58e523f3879d490b20d31dc8b47767265fa863..9ca5198d2733efcde2c13d86d9dd50079e05cd23 100644 (file)
--- 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)
                    {
index 52b741a740850e5505779b9e8a7e041c8382df75..bb4132fe79a4327ac57d3c985ef1cb0255f2a48d 100644 (file)
@@ -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);
index cac644969b8bfab1048ec8419b083b606f93e241..4e299e5f9ac3e548b75a4c064a4562523f5a90e7 100644 (file)
@@ -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);
index ca7b6583608ee0b0784deae9be371849f3636dc6..e0d4af8fc63f05d9ea15c419b6120e4f412c5046 100644 (file)
@@ -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
index 0eb87638eb8f6113b7d8bc1f06ddb571d0571db6..2742997c2cf34303a9b5b0bdc822799f3374f0eb 100644 (file)
@@ -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. */
index d352e8feff27f1ac4b6d1530441dbabb82708c66..7c2c5e341c0f09e171d2c511303e88099ffb24eb 100644 (file)
@@ -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
index ee6e91ce73cffbf049b4940c291fe0142f879058..e59466762a88810558181d3640fc794403e3bf0e 100644 (file)
@@ -769,6 +769,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    1041,
 /**/
     1040,
 /**/