diff options
-rw-r--r-- | runtime/doc/visual.txt | 5 | ||||
-rw-r--r-- | src/nvim/charset.c | 14 | ||||
-rw-r--r-- | src/nvim/edit.c | 7 | ||||
-rw-r--r-- | src/nvim/misc1.c | 6 | ||||
-rw-r--r-- | src/nvim/ops.c | 19 | ||||
-rw-r--r-- | src/nvim/screen.c | 2 | ||||
-rw-r--r-- | src/nvim/spell.c | 6 | ||||
-rw-r--r-- | src/nvim/testdir/test_cindent.vim | 24 |
8 files changed, 62 insertions, 21 deletions
diff --git a/runtime/doc/visual.txt b/runtime/doc/visual.txt index 176ce562d8..a9eb21192e 100644 --- a/runtime/doc/visual.txt +++ b/runtime/doc/visual.txt @@ -302,8 +302,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 @@ -319,6 +319,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/nvim/charset.c b/src/nvim/charset.c index f1b3be6b46..4e8bb3b0d7 100644 --- a/src/nvim/charset.c +++ b/src/nvim/charset.c @@ -30,7 +30,7 @@ #include "nvim/state.h" #include "nvim/strings.h" #include "nvim/path.h" - +#include "nvim/cursor.h" #ifdef INCLUDE_GENERATED_DECLARATIONS # include "charset.c.generated.h" @@ -1465,6 +1465,18 @@ char_u *skipwhite(const char_u *q) return (char_u *)p; } +// getwhitecols: return the number of whitespace +// columns (bytes) at the start of a given line +intptr_t getwhitecols_curline(void) +{ + return getwhitecols(get_cursor_line_ptr()); +} + +intptr_t getwhitecols(const char_u *p) +{ + return skipwhite(p) - p; +} + /// Skip over digits /// /// @param[in] q String to skip digits in. diff --git a/src/nvim/edit.c b/src/nvim/edit.c index 085f12473e..be2797ee3e 100644 --- a/src/nvim/edit.c +++ b/src/nvim/edit.c @@ -4506,7 +4506,7 @@ static int ins_complete(int c, bool 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 */ @@ -4625,7 +4625,7 @@ static int ins_complete(int c, bool 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; @@ -6963,8 +6963,7 @@ bool in_cinkeys(int keytyped, int when, bool line_is_empty) if (match && try_match_word && !try_match) { /* "0=word": Check if there are only blanks before the * word. */ - line = get_cursor_line_ptr(); - if ((int)(skipwhite(line) - line) != + if (getwhitecols(line) != (int)(curwin->w_cursor.col - (p - look))) match = FALSE; } diff --git a/src/nvim/misc1.c b/src/nvim/misc1.c index 84d8c995a6..e87c754eb8 100644 --- a/src/nvim/misc1.c +++ b/src/nvim/misc1.c @@ -884,8 +884,7 @@ open_line ( && curbuf->b_p_lisp && curbuf->b_p_ai) { fixthisline(get_lisp_indent); - p = get_cursor_line_ptr(); - ai_col = (colnr_T)(skipwhite(p) - p); + ai_col = (colnr_T)getwhitecols_curline(); } /* * May do indenting after opening a new line. @@ -898,8 +897,7 @@ open_line ( ? KEY_OPEN_FORW : KEY_OPEN_BACK, ' ', linewhite(curwin->w_cursor.lnum))) { do_c_expr_indent(); - p = get_cursor_line_ptr(); - ai_col = (colnr_T)(skipwhite(p) - p); + ai_col = (colnr_T)getwhitecols_curline(); } if (vreplace_mode != 0) State = vreplace_mode; diff --git a/src/nvim/ops.c b/src/nvim/ops.c index ff02d82ff3..f3661b2045 100644 --- a/src/nvim/ops.c +++ b/src/nvim/ops.c @@ -2014,6 +2014,7 @@ void 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; @@ -2044,7 +2045,10 @@ void op_insert(oparg_T *oap, long count1) } // 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); @@ -2091,6 +2095,14 @@ void op_insert(oparg_T *oap, long count1) 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. */ @@ -2216,7 +2228,7 @@ int op_change(oparg_T *oap) } 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; } @@ -2237,7 +2249,7 @@ int op_change(oparg_T *oap) // the indent, exclude that indent change from the inserted text. 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 += (colnr_T)(new_indent - pre_indent); @@ -4122,8 +4134,7 @@ format_lines ( mark_col_adjust(curwin->w_cursor.lnum, (colnr_T)0, 0L, (long)-next_leader_len); } else if (second_indent > 0) { /* the "leader" for FO_Q_SECOND */ - char_u *p = get_cursor_line_ptr(); - int indent = (int)(skipwhite(p) - p); + int indent = (int)getwhitecols_curline(); if (indent > 0) { (void)del_bytes(indent, FALSE, FALSE); diff --git a/src/nvim/screen.c b/src/nvim/screen.c index ec48bf5dcf..e1bc8556f9 100644 --- a/src/nvim/screen.c +++ b/src/nvim/screen.c @@ -2462,7 +2462,7 @@ win_line ( if (has_spell) { /* For checking first word with a capital skip white space. */ if (cap_col == 0) - cap_col = (int)(skipwhite(line) - line); + cap_col = (int)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/nvim/spell.c b/src/nvim/spell.c index 1cb679245b..c05a1d107a 100644 --- a/src/nvim/spell.c +++ b/src/nvim/spell.c @@ -1399,10 +1399,10 @@ spell_move_to ( // For checking first word with a capital skip white space. if (capcol == 0) - capcol = (int)(skipwhite(line) - line); + capcol = (int)getwhitecols(line); else if (curline && wp == curwin) { // For spellbadword(): check if first word needs a capital. - col = (int)(skipwhite(line) - line); + col = (int)getwhitecols(line); if (check_need_cap(lnum, col)) capcol = col; @@ -2976,7 +2976,7 @@ static bool check_need_cap(linenr_T lnum, colnr_T col) line = get_cursor_line_ptr(); 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. if (lnum == 1) diff --git a/src/nvim/testdir/test_cindent.vim b/src/nvim/testdir/test_cindent.vim index d352e8feff..7c2c5e341c 100644 --- a/src/nvim/testdir/test_cindent.vim +++ b/src/nvim/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 |