refactor(core): group Visual-mode globals in VisualExtent #40722

This commit is contained in:
Justin M. Keyes
2026-07-13 16:19:32 -04:00
committed by GitHub
parent 73bb6a8a5e
commit 06ded1330c
4 changed files with 44 additions and 44 deletions

View File

@@ -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.

View File

@@ -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++;

View File

@@ -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,

View File

@@ -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);