mirror of
https://github.com/neovim/neovim.git
synced 2024-12-20 03:05:11 -07:00
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)
e2e69e4813
This commit is contained in:
parent
fe57a8a4e4
commit
d677ae5f64
@ -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
|
||||
|
@ -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.
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user