From 06ded1330c9c721f140dffa479f01de72e4393db Mon Sep 17 00:00:00 2001 From: "Justin M. Keyes" Date: Mon, 13 Jul 2026 16:19:32 -0400 Subject: [PATCH] refactor(core): group Visual-mode globals in `VisualExtent` #40722 --- src/nvim/globals.h | 8 +++---- src/nvim/normal.c | 18 +++++++-------- src/nvim/normal_defs.h | 11 +++++++++ src/nvim/ops.c | 51 +++++++++++++++++------------------------- 4 files changed, 44 insertions(+), 44 deletions(-) diff --git a/src/nvim/globals.h b/src/nvim/globals.h index 9f74783aeb..d5e58a63c3 100644 --- a/src/nvim/globals.h +++ b/src/nvim/globals.h @@ -13,6 +13,7 @@ #include "nvim/insert_defs.h" #include "nvim/macros_defs.h" #include "nvim/menu_defs.h" +#include "nvim/normal_defs.h" #include "nvim/os/os_defs.h" #include "nvim/runtime_defs.h" #include "nvim/state_defs.h" @@ -472,10 +473,9 @@ EXTERN int VIsual_mode INIT( = 'v'); /// true when redoing Visual. EXTERN bool redo_VIsual_busy INIT( = false); -// The Visual area is remembered for reselection. -EXTERN int resel_VIsual_mode INIT( = NUL); // 'v', 'V', or Ctrl-V -EXTERN linenr_T resel_VIsual_line_count; // number of lines -EXTERN colnr_T resel_VIsual_vcol; // nr of cols or end col +// Remember the previous Visual area, for reselection ("gv"). Also seeds operator-redo. +// mode == NUL: no previous Visual area. +EXTERN VisualExtent resel_VIsual; /// When pasting text with the middle mouse button in visual mode with /// restart_edit set, remember where it started so we can set Ins.start. diff --git a/src/nvim/normal.c b/src/nvim/normal.c index ed15474568..9dc1ece393 100644 --- a/src/nvim/normal.c +++ b/src/nvim/normal.c @@ -5039,7 +5039,7 @@ static void nv_visual(cmdarg_T *cap) } redraw_curbuf_later(UPD_INVERTED); // update the inversion } else { // start Visual mode - if (cap->count0 > 0 && resel_VIsual_mode != NUL) { + if (cap->count0 > 0 && resel_VIsual.mode != NUL) { // use previously selected part VIsual = curwin->w_cursor; @@ -5055,25 +5055,25 @@ static void nv_visual(cmdarg_T *cap) } // For V and ^V, we multiply the number of lines even if there // was only one -- webb - if (resel_VIsual_mode != 'v' || resel_VIsual_line_count > 1) { - curwin->w_cursor.lnum += resel_VIsual_line_count * cap->count0 - 1; + if (resel_VIsual.mode != 'v' || resel_VIsual.line_count > 1) { + curwin->w_cursor.lnum += resel_VIsual.line_count * cap->count0 - 1; check_cursor(curwin); } - VIsual_mode = resel_VIsual_mode; + VIsual_mode = resel_VIsual.mode; if (VIsual_mode == 'v') { - if (resel_VIsual_line_count <= 1) { + if (resel_VIsual.line_count <= 1) { update_curswant_force(); assert(cap->count0 >= INT_MIN && cap->count0 <= INT_MAX); - curwin->w_curswant += resel_VIsual_vcol * cap->count0; + curwin->w_curswant += resel_VIsual.vcol * cap->count0; if (*p_sel != 'e') { curwin->w_curswant--; } } else { - curwin->w_curswant = resel_VIsual_vcol; + curwin->w_curswant = resel_VIsual.vcol; } coladvance(curwin, curwin->w_curswant); } - if (resel_VIsual_vcol == MAXCOL) { + if (resel_VIsual.vcol == MAXCOL) { curwin->w_curswant = MAXCOL; coladvance(curwin, MAXCOL); } else if (VIsual_mode == Ctrl_V) { @@ -5082,7 +5082,7 @@ static void nv_visual(cmdarg_T *cap) curwin->w_cursor.lnum = VIsual.lnum; update_curswant_force(); assert(cap->count0 >= INT_MIN && cap->count0 <= INT_MAX); - curwin->w_curswant += resel_VIsual_vcol * cap->count0 - 1; + curwin->w_curswant += resel_VIsual.vcol * cap->count0 - 1; curwin->w_cursor.lnum = lnum; if (*p_sel == 'e') { curwin->w_curswant++; diff --git a/src/nvim/normal_defs.h b/src/nvim/normal_defs.h index 1b04ef2f25..cc3aca56cf 100644 --- a/src/nvim/normal_defs.h +++ b/src/nvim/normal_defs.h @@ -66,6 +66,17 @@ enum { CA_NO_ADJ_OP_END = 2, ///< don't adjust operator end }; +/// A Visual selection's mode and extent (line/column span, not absolute positions), so it can be +/// re-applied starting at the cursor: for "gv" reselect (`resel_VIsual`) and Visual-operator redo +/// (`redo_VIsual`). +typedef struct { + int mode; ///< 'v', 'V', or Ctrl-V + linenr_T line_count; ///< number of lines + colnr_T vcol; ///< number of cols or end column (MAXCOL: to end of line) + int count; ///< count for the Visual operator + int arg; ///< extra argument +} VisualExtent; + /// Replacement for nchar used by nv_replace(). enum { REPLACE_CR_NCHAR = -1, diff --git a/src/nvim/ops.c b/src/nvim/ops.c index 2807c5aeca..b2c5e3ed2b 100644 --- a/src/nvim/ops.c +++ b/src/nvim/ops.c @@ -3259,15 +3259,6 @@ static void get_op_vcol(oparg_T *oap, colnr_T redo_VIsual_vcol, bool initial) oap->start = curwin->w_cursor; } -/// Information for redoing the previous Visual selection. -typedef struct { - int rv_mode; ///< 'v', 'V', or Ctrl-V - linenr_T rv_line_count; ///< number of lines - colnr_T rv_vcol; ///< number of cols or end column - int rv_count; ///< count for Visual operator - int rv_arg; ///< extra argument -} redo_VIsual_T; - static bool is_ex_cmdchar(cmdarg_T *cap) { return cap->cmdchar == ':' || cap->cmdchar == K_COMMAND; @@ -3281,7 +3272,7 @@ void do_pending_operator(cmdarg_T *cap, int old_col, bool gui_yank) int lbr_saved = curwin->w_p_lbr; // The visual area is remembered for redo - static redo_VIsual_T redo_VIsual = { NUL, 0, 0, 0, 0 }; + static VisualExtent redo_VIsual = { NUL, 0, 0, 0, 0 }; pos_T old_cursor = curwin->w_cursor; @@ -3370,25 +3361,25 @@ void do_pending_operator(cmdarg_T *cap, int old_col, bool gui_yank) if (redo_VIsual_busy) { // Redo of an operation on a Visual area. Use the same size from - // redo_VIsual.rv_line_count and redo_VIsual.rv_vcol. + // redo_VIsual.line_count and redo_VIsual.vcol. oap->start = curwin->w_cursor; - curwin->w_cursor.lnum += redo_VIsual.rv_line_count - 1; + curwin->w_cursor.lnum += redo_VIsual.line_count - 1; curwin->w_cursor.lnum = MIN(curwin->w_cursor.lnum, curbuf->b_ml.ml_line_count); - VIsual_mode = redo_VIsual.rv_mode; - if (redo_VIsual.rv_vcol == MAXCOL || VIsual_mode == 'v') { + VIsual_mode = redo_VIsual.mode; + if (redo_VIsual.vcol == MAXCOL || VIsual_mode == 'v') { if (VIsual_mode == 'v') { - if (redo_VIsual.rv_line_count <= 1) { + if (redo_VIsual.line_count <= 1) { validate_virtcol(curwin); - curwin->w_curswant = curwin->w_virtcol + redo_VIsual.rv_vcol - 1; + curwin->w_curswant = curwin->w_virtcol + redo_VIsual.vcol - 1; } else { - curwin->w_curswant = redo_VIsual.rv_vcol; + curwin->w_curswant = redo_VIsual.vcol; } } else { curwin->w_curswant = MAXCOL; } coladvance(curwin, curwin->w_curswant); } - cap->count0 = redo_VIsual.rv_count; + cap->count0 = redo_VIsual.count; cap->count1 = (cap->count0 == 0 ? 1 : cap->count0); } else if (VIsual_active) { if (!gui_yank) { @@ -3473,14 +3464,14 @@ void do_pending_operator(cmdarg_T *cap, int old_col, bool gui_yank) virtual_op = virtual_active(curwin); if (VIsual_active || redo_VIsual_busy) { - get_op_vcol(oap, redo_VIsual.rv_vcol, true); + get_op_vcol(oap, redo_VIsual.vcol, true); if (!redo_VIsual_busy && !gui_yank) { // Prepare to reselect and redo Visual: this is based on the // size of the Visual text - resel_VIsual_mode = VIsual_mode; + resel_VIsual.mode = VIsual_mode; if (curwin->w_curswant == MAXCOL) { - resel_VIsual_vcol = MAXCOL; + resel_VIsual.vcol = MAXCOL; } else { if (VIsual_mode != Ctrl_V) { getvvcol(curwin, &(oap->end), NULL, NULL, &oap->end_vcol, 0); @@ -3489,12 +3480,12 @@ void do_pending_operator(cmdarg_T *cap, int old_col, bool gui_yank) if (VIsual_mode != Ctrl_V) { getvvcol(curwin, &(oap->start), &oap->start_vcol, NULL, NULL, 0); } - resel_VIsual_vcol = oap->end_vcol - oap->start_vcol + 1; + resel_VIsual.vcol = oap->end_vcol - oap->start_vcol + 1; } else { - resel_VIsual_vcol = oap->end_vcol; + resel_VIsual.vcol = oap->end_vcol; } } - resel_VIsual_line_count = oap->line_count; + resel_VIsual.line_count = oap->line_count; } // can't redo yank (unless 'y' is in 'cpoptions') and ":" @@ -3535,11 +3526,9 @@ void do_pending_operator(cmdarg_T *cap, int old_col, bool gui_yank) } } if (!redo_VIsual_busy) { - redo_VIsual.rv_mode = resel_VIsual_mode; - redo_VIsual.rv_vcol = resel_VIsual_vcol; - redo_VIsual.rv_line_count = resel_VIsual_line_count; - redo_VIsual.rv_count = cap->count0; - redo_VIsual.rv_arg = cap->arg; + redo_VIsual = resel_VIsual; + redo_VIsual.count = cap->count0; + redo_VIsual.arg = cap->arg; } } @@ -3794,7 +3783,7 @@ void do_pending_operator(cmdarg_T *cap, int old_col, bool gui_yank) break; case OP_FUNCTION: { - redo_VIsual_T save_redo_VIsual = redo_VIsual; + VisualExtent save_redo_VIsual = redo_VIsual; // Restore linebreak, so that when the user edits it looks as before. restore_lbr(lbr_saved); @@ -3889,7 +3878,7 @@ void do_pending_operator(cmdarg_T *cap, int old_col, bool gui_yank) } else { VIsual_active = true; restore_lbr(lbr_saved); - op_addsub(oap, (linenr_T)cap->count1, redo_VIsual.rv_arg); + op_addsub(oap, (linenr_T)cap->count1, redo_VIsual.arg); VIsual_active = false; } check_cursor_col(curwin);