aboutsummaryrefslogtreecommitdiff
path: root/src/nvim/edit.c
diff options
context:
space:
mode:
authorvanaigr <vanaigranov@gmail.com>2024-03-25 16:12:56 -0500
committerGitHub <noreply@github.com>2024-03-26 05:12:56 +0800
commit14839c5d18c2bef7bdd41944b059603a8589523e (patch)
treee48e021cb36184087bc012bcd0a0ed5fb1b7ca80 /src/nvim/edit.c
parenta7bbda121d035d050b449b4dc63bd6ae027e248d (diff)
downloadrneovim-14839c5d18c2bef7bdd41944b059603a8589523e.tar.gz
rneovim-14839c5d18c2bef7bdd41944b059603a8589523e.tar.bz2
rneovim-14839c5d18c2bef7bdd41944b059603a8589523e.zip
fix(edit): backspace adds extra spaces for inline virtual text (#28005)
Problem: Backspace adds extra spaces for inline virtual text. Solution: Ignore virtual text and wrapping when backspacing.
Diffstat (limited to 'src/nvim/edit.c')
-rw-r--r--src/nvim/edit.c103
1 files changed, 53 insertions, 50 deletions
diff --git a/src/nvim/edit.c b/src/nvim/edit.c
index df0c075306..0cbc895328 100644
--- a/src/nvim/edit.c
+++ b/src/nvim/edit.c
@@ -3673,23 +3673,6 @@ static void ins_del(void)
AppendCharToRedobuff(K_DEL);
}
-// Delete one character for ins_bs().
-static void ins_bs_one(colnr_T *vcolp)
-{
- dec_cursor();
- getvcol(curwin, &curwin->w_cursor, vcolp, NULL, NULL);
- if (State & REPLACE_FLAG) {
- // Don't delete characters before the insert point when in
- // Replace mode
- if (curwin->w_cursor.lnum != Insstart.lnum
- || curwin->w_cursor.col >= Insstart.col) {
- replace_do_bs(-1);
- }
- } else {
- del_char(false);
- }
-}
-
/// Handle Backspace, delete-word and delete-line in Insert mode.
///
/// @param c character that was typed
@@ -3846,42 +3829,69 @@ static bool ins_bs(int c, int mode, int *inserted_space_p)
// Handle deleting one 'shiftwidth' or 'softtabstop'.
if (mode == BACKSPACE_CHAR
&& ((p_sta && in_indent)
- || ((get_sts_value() != 0
- || tabstop_count(curbuf->b_p_vsts_array))
+ || ((get_sts_value() != 0 || tabstop_count(curbuf->b_p_vsts_array))
&& curwin->w_cursor.col > 0
&& (*(get_cursor_pos_ptr() - 1) == TAB
|| (*(get_cursor_pos_ptr() - 1) == ' '
&& (!*inserted_space_p || arrow_used)))))) {
- colnr_T vcol;
- colnr_T want_vcol;
-
*inserted_space_p = false;
- // Compute the virtual column where we want to be. Since
- // 'showbreak' may get in the way, need to get the last column of
- // the previous character.
- getvcol(curwin, &curwin->w_cursor, &vcol, NULL, NULL);
- colnr_T start_vcol = vcol;
- dec_cursor();
- getvcol(curwin, &curwin->w_cursor, NULL, NULL, &want_vcol);
- inc_cursor();
- if (p_sta && in_indent) {
- int ts = get_sw_value(curbuf);
- want_vcol = (want_vcol / ts) * ts;
+
+ bool const use_ts = !curwin->w_p_list || curwin->w_p_lcs_chars.tab1;
+ char *const line = ml_get_buf(curbuf, curwin->w_cursor.lnum);
+ char *const end_ptr = line + curwin->w_cursor.col;
+
+ colnr_T vcol = 0;
+ colnr_T space_vcol = 0;
+ StrCharInfo sci = utf_ptr2StrCharInfo(line);
+ StrCharInfo space_sci = sci;
+ bool prev_space = false;
+ while (sci.ptr < end_ptr) {
+ bool cur_space = ascii_iswhite(sci.chr.value);
+ if (!prev_space && cur_space) {
+ space_sci = sci;
+ space_vcol = vcol;
+ }
+ vcol += charsize_nowrap(curbuf, use_ts, vcol, sci.chr.value);
+ sci = utfc_next(sci);
+ prev_space = cur_space;
+ }
+
+ colnr_T want_vcol = vcol - 1;
+ if (want_vcol <= 0) {
+ want_vcol = 0;
+ } else if (p_sta && in_indent) {
+ want_vcol = want_vcol - want_vcol % get_sw_value(curbuf);
} else {
- want_vcol = tabstop_start(want_vcol,
- get_sts_value(),
- curbuf->b_p_vsts_array);
+ want_vcol = tabstop_start(want_vcol, get_sts_value(), curbuf->b_p_vsts_array);
}
- // delete characters until we are at or before want_vcol
- while (vcol > want_vcol && curwin->w_cursor.col > 0
- && (cc = (uint8_t)(*(get_cursor_pos_ptr() - 1)), ascii_iswhite(cc))) {
- ins_bs_one(&vcol);
+ while (true) {
+ int size = charsize_nowrap(curbuf, use_ts, space_vcol, space_sci.chr.value);
+ if (space_vcol + size > want_vcol) {
+ break;
+ }
+ space_vcol += size;
+ space_sci = utfc_next(space_sci);
}
+ colnr_T const want_col = (int)(space_sci.ptr - line);
- // insert extra spaces until we are at want_vcol
- while (vcol < want_vcol) {
- // Remember the first char we inserted
+ // Delete characters until we are at or before want_col.
+ while (curwin->w_cursor.col > want_col) {
+ dec_cursor();
+ if (State & REPLACE_FLAG) {
+ // Don't delete characters before the insert point when in Replace mode.
+ if (curwin->w_cursor.lnum != Insstart.lnum
+ || curwin->w_cursor.col >= Insstart.col) {
+ replace_do_bs(-1);
+ }
+ } else {
+ del_char(false);
+ }
+ }
+
+ // Insert extra spaces until we are at want_vcol.
+ for (; space_vcol < want_vcol; space_vcol++) {
+ // Remember the first char we inserted.
if (curwin->w_cursor.lnum == Insstart_orig.lnum
&& curwin->w_cursor.col < Insstart_orig.col) {
Insstart_orig.col = curwin->w_cursor.col;
@@ -3895,13 +3905,6 @@ static bool ins_bs(int c, int mode, int *inserted_space_p)
replace_push(NUL);
}
}
- getvcol(curwin, &curwin->w_cursor, &vcol, NULL, NULL);
- }
-
- // If we are now back where we started delete one character. Can
- // happen when using 'sts' and 'linebreak'.
- if (vcol >= start_vcol) {
- ins_bs_one(&vcol);
}
} else {
// Delete up to starting point, start of line or previous word.