diff options
Diffstat (limited to 'src/nvim/ops.c')
-rw-r--r-- | src/nvim/ops.c | 185 |
1 files changed, 169 insertions, 16 deletions
diff --git a/src/nvim/ops.c b/src/nvim/ops.c index fbbdfdcd82..1631204840 100644 --- a/src/nvim/ops.c +++ b/src/nvim/ops.c @@ -49,6 +49,7 @@ #include "nvim/undo.h" #include "nvim/macros.h" #include "nvim/window.h" +#include "nvim/lib/kvec.h" #include "nvim/os/input.h" #include "nvim/os/time.h" @@ -126,6 +127,30 @@ static char opchars[][3] = { Ctrl_X, NUL, false }, // OP_NR_SUB }; +char *nvim_lltoa(int64_t val, int base) +{ + static char buf[64] = { 0 }; + + int i = 62; + int sign = (val < 0); + if (sign) { + val = -val; + } + + if (val == 0) { + return "0"; + } + + for (; val && i ; i--, val /= base) { + buf[i] = "0123456789abcdef"[val % base]; + } + + if (sign) { + buf[i--] = '-'; + } + return &buf[i+1]; +} + /* * Translate a command name into an operator type. * Must only be called with a valid operator name! @@ -306,6 +331,20 @@ void shift_line( change_indent(INDENT_SET, count, false, NUL, call_changed_bytes); } else { (void)set_indent(count, call_changed_bytes ? SIN_CHANGED : 0); + + colnr_T col_amount; + colnr_T mincol = (curwin->w_cursor.col + 1) -p_sw; + if (left) { + col_amount = -p_sw; + } else { + col_amount = p_sw; + } + extmark_col_adjust(curbuf, + curwin->w_cursor.lnum, + mincol, + 0, + col_amount, + kExtmarkUndo); } } @@ -479,6 +518,13 @@ static void shift_block(oparg_T *oap, int amount) State = oldstate; curwin->w_cursor.col = oldcol; p_ri = old_p_ri; + + colnr_T col_amount = p_sw; + if (left) { + col_amount = -col_amount; + } + extmark_col_adjust(curbuf, curwin->w_cursor.lnum, + curwin->w_cursor.col, 0, col_amount, kExtmarkUndo); } /* @@ -623,10 +669,19 @@ void op_reindent(oparg_T *oap, Indenter how) amount = how(); /* get the indent for this line */ if (amount >= 0 && set_indent(amount, SIN_UNDO)) { - /* did change the indent, call changed_lines() later */ - if (first_changed == 0) + // did change the indent, call changed_lines() later + if (first_changed == 0) { first_changed = curwin->w_cursor.lnum; + } last_changed = curwin->w_cursor.lnum; + + // Adjust extmarks + extmark_col_adjust(curbuf, + curwin->w_cursor.lnum, + 0, // mincol + 0, // lnum_amount + amount, // col_amount + kExtmarkUndo); } } ++curwin->w_cursor.lnum; @@ -1614,13 +1669,15 @@ int op_delete(oparg_T *oap) curpos = curwin->w_cursor; // remember curwin->w_cursor curwin->w_cursor.lnum++; - del_lines(oap->line_count - 2, false); + del_lines(oap->line_count - 2, true); // delete from start of line until op_end n = (oap->end.col + 1 - !oap->inclusive); curwin->w_cursor.col = 0; (void)del_bytes((colnr_T)n, !virtual_op, oap->op_type == OP_DELETE && !oap->is_VIsual); + extmark_col_adjust(curbuf, curwin->w_cursor.lnum, + (colnr_T)0, 0L, (long)-n, kExtmarkUndo); curwin->w_cursor = curpos; // restore curwin->w_cursor (void)do_join(2, false, false, false, false); } @@ -1632,10 +1689,41 @@ setmarks: if (oap->motion_type == kMTBlockWise) { curbuf->b_op_end.lnum = oap->end.lnum; curbuf->b_op_end.col = oap->start.col; - } else + } else { curbuf->b_op_end = oap->start; + } curbuf->b_op_start = oap->start; + // TODO(timeyyy): refactor: Move extended marks + // + 1 to change to buf mode, + // and + 1 because we only move marks after the deleted col + colnr_T mincol = oap->start.col + 1 + 1; + colnr_T endcol; + if (oap->motion_type == kMTBlockWise) { + // TODO(timeyyy): refactor extmark_col_adjust to take lnumstart, lnum_end ? + endcol = bd.end_vcol + 1; + for (lnum = curwin->w_cursor.lnum; lnum <= oap->end.lnum; lnum++) { + extmark_col_adjust_delete(curbuf, lnum, mincol, endcol, + kExtmarkUndo, 0); + } + + // Delete characters within one line, + // The case with multiple lines is handled by do_join + } else if (oap->motion_type == kMTCharWise && oap->line_count == 1) { + // + 1 to change to buf mode, then plus 1 to fit function requirements + endcol = oap->end.col + 1 + 1; + + lnum = curwin->w_cursor.lnum; + if (oap->is_VIsual == false) { + // for some reason we required this :/ + endcol = endcol - 1; + // for some reason we required this :/ + if (endcol < mincol) { + endcol = mincol; + } + } + extmark_col_adjust_delete(curbuf, lnum, mincol, endcol, kExtmarkUndo, 0); + } return OK; } @@ -2031,8 +2119,8 @@ bool swapchar(int op_type, pos_T *pos) pos_T sp = curwin->w_cursor; curwin->w_cursor = *pos; - /* don't use del_char(), it also removes composing chars */ - del_bytes(utf_ptr2len(get_cursor_pos_ptr()), FALSE, FALSE); + // don't use del_char(), it also removes composing chars + del_bytes(utf_ptr2len(get_cursor_pos_ptr()), false, false); ins_char(nc); curwin->w_cursor = sp; } else { @@ -2105,8 +2193,9 @@ void op_insert(oparg_T *oap, long count1) * values in "bd". */ if (u_save_cursor() == FAIL) return; - for (i = 0; i < bd.endspaces; i++) + for (i = 0; i < bd.endspaces; i++) { ins_char(' '); + } bd.textlen += bd.endspaces; } } else { @@ -2224,6 +2313,10 @@ void op_insert(oparg_T *oap, long count1) xfree(ins_text); } } + colnr_T col = oap->start.col; + for (linenr_T lnum = oap->start.lnum; lnum <= oap->end.lnum; lnum++) { + extmark_col_adjust(curbuf, lnum, col, 0, 1, kExtmarkUndo); + } } /* @@ -2694,6 +2787,34 @@ static void do_autocmd_textyankpost(oparg_T *oap, yankreg_T *reg) } + +// Function length couldn't be over 500 lines.. +static void extmarks_do_put(int dir, + size_t totlen, + MotionType y_type, + linenr_T lnum, + colnr_T col) +{ + // adjust extmarks + colnr_T col_amount; + if (dir == FORWARD) { + col_amount = (colnr_T)(totlen-1); + } else { + col_amount = (colnr_T)totlen; + } + // Move extmark with char put + if (y_type == kMTCharWise) { + extmark_col_adjust(curbuf, lnum, col, 0, col_amount, kExtmarkUndo); + // Move extmark with blockwise put + } else if (y_type == kMTBlockWise) { + for (lnum = curbuf->b_op_start.lnum; + lnum <= curbuf->b_op_end.lnum; + lnum++) { + extmark_col_adjust(curbuf, lnum, col, 0, col_amount, kExtmarkUndo); + } + } +} + /* * Put contents of register "regname" into the text. * Caller must check "regname" to be valid! @@ -2708,8 +2829,8 @@ void do_put(int regname, yankreg_T *reg, int dir, long count, int flags) char_u *oldp; int yanklen; size_t totlen = 0; // init for gcc - linenr_T lnum; - colnr_T col; + linenr_T lnum = 0; + colnr_T col = 0; size_t i; // index in y_array[] MotionType y_type; size_t y_size; @@ -3286,11 +3407,11 @@ error: curbuf->b_op_start.lnum++; } // Skip mark_adjust when adding lines after the last one, there - // can't be marks there. But still needed in diff mode. + // can't be marks there. if (curbuf->b_op_start.lnum + (y_type == kMTCharWise) - 1 + nr_lines - < curbuf->b_ml.ml_line_count || curwin->w_p_diff) { + < curbuf->b_ml.ml_line_count) { mark_adjust(curbuf->b_op_start.lnum + (y_type == kMTCharWise), - (linenr_T)MAXLNUM, nr_lines, 0L, false); + (linenr_T)MAXLNUM, nr_lines, 0L, false, kExtmarkUndo); } // note changed text for displaying and folding @@ -3352,6 +3473,8 @@ end: /* If the cursor is past the end of the line put it at the end. */ adjust_cursor_eol(); + + extmarks_do_put(dir, totlen, y_type, lnum, col); } /* @@ -3745,6 +3868,12 @@ int do_join(size_t count, * column. This is not Vi compatible, but Vi deletes the marks, thus that * should not really be a problem. */ + + linenr_T lnum; + colnr_T mincol; + long lnum_amount; + long col_amount; + for (t = (linenr_T)count - 1;; t--) { cend -= currsize; memmove(cend, curr, (size_t)currsize); @@ -3756,12 +3885,18 @@ int do_join(size_t count, // If deleting more spaces than adding, the cursor moves no more than // what is added if it is inside these spaces. const int spaces_removed = (int)((curr - curr_start) - spaces[t]); + lnum = curwin->w_cursor.lnum + t; + mincol = (colnr_T)0; + lnum_amount = (linenr_T)-t; + col_amount = (long)(cend - newp - spaces_removed); + + mark_col_adjust(lnum, mincol, lnum_amount, col_amount, spaces_removed, + kExtmarkUndo); - mark_col_adjust(curwin->w_cursor.lnum + t, (colnr_T)0, (linenr_T)-t, - (long)(cend - newp - spaces_removed), spaces_removed); if (t == 0) { break; } + curr = curr_start = ml_get((linenr_T)(curwin->w_cursor.lnum + t - 1)); if (remove_comments) curr += comments[t - 1]; @@ -3769,6 +3904,7 @@ int do_join(size_t count, curr = skipwhite(curr); currsize = (int)STRLEN(curr); } + ml_replace(curwin->w_cursor.lnum, newp, false); if (setmark) { @@ -4189,14 +4325,14 @@ format_lines( if (next_leader_len > 0) { (void)del_bytes(next_leader_len, false, false); mark_col_adjust(curwin->w_cursor.lnum, (colnr_T)0, 0L, - (long)-next_leader_len, 0); + (long)-next_leader_len, 0, kExtmarkUndo); } else if (second_indent > 0) { // the "leader" for FO_Q_SECOND int indent = (int)getwhitecols_curline(); if (indent > 0) { (void)del_bytes(indent, FALSE, FALSE); mark_col_adjust(curwin->w_cursor.lnum, - (colnr_T)0, 0L, (long)-indent, 0); + (colnr_T)0, 0L, (long)-indent, 0, kExtmarkUndo); } } curwin->w_cursor.lnum--; @@ -4862,6 +4998,23 @@ int do_addsub(int op_type, pos_T *pos, int length, linenr_T Prenum1) curbuf->b_op_end.col--; } + if (did_change) { + extmark_col_adjust_delete(curbuf, + pos->lnum, + startpos.col + 2, + endpos.col + 1 + length, + kExtmarkUndo, + 0); + long col_amount = (long)strlen(nvim_lltoa((int64_t)n, 10)); + col_amount = negative ? col_amount + 1 : col_amount; + extmark_col_adjust(curbuf, + pos->lnum, + startpos.col + 1, + 0, + col_amount, + kExtmarkUndo); + } + theend: if (visual) { curwin->w_cursor = save_cursor; |