aboutsummaryrefslogtreecommitdiff
path: root/src/nvim/normal.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/nvim/normal.c')
-rw-r--r--src/nvim/normal.c215
1 files changed, 163 insertions, 52 deletions
diff --git a/src/nvim/normal.c b/src/nvim/normal.c
index a116b5a0bd..9a9cf50e48 100644
--- a/src/nvim/normal.c
+++ b/src/nvim/normal.c
@@ -1414,11 +1414,12 @@ 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 int redo_VIsual_mode = NUL; /* 'v', 'V', or Ctrl-V */
- static linenr_T redo_VIsual_line_count; /* number of lines */
- static colnr_T redo_VIsual_vcol; /* number of cols or end column */
- static long redo_VIsual_count; /* count for Visual operator */
+ // The visual area is remembered for redo
+ static int redo_VIsual_mode = NUL; // 'v', 'V', or Ctrl-V
+ static linenr_T redo_VIsual_line_count; // number of lines
+ static colnr_T redo_VIsual_vcol; // number of cols or end column
+ static long redo_VIsual_count; // count for Visual operator
+ static int redo_VIsual_arg; // extra argument
bool include_line_break = false;
old_cursor = curwin->w_cursor;
@@ -1656,6 +1657,7 @@ void do_pending_operator(cmdarg_T *cap, int old_col, bool gui_yank)
redo_VIsual_vcol = resel_VIsual_vcol;
redo_VIsual_line_count = resel_VIsual_line_count;
redo_VIsual_count = cap->count0;
+ redo_VIsual_arg = cap->arg;
}
}
@@ -1705,10 +1707,7 @@ void do_pending_operator(cmdarg_T *cap, int old_col, bool gui_yank)
VIsual_active = false;
setmouse();
mouse_dragging = 0;
- if (mode_displayed)
- clear_cmdline = true; /* unshow visual mode later */
- else
- clear_showcmd();
+ may_clear_cmdline();
if ((oap->op_type == OP_YANK
|| oap->op_type == OP_COLON
|| oap->op_type == OP_FUNCTION
@@ -1993,6 +1992,20 @@ void do_pending_operator(cmdarg_T *cap, int old_col, bool gui_yank)
deleteFold(oap->start.lnum, oap->end.lnum,
oap->op_type == OP_FOLDDELREC, oap->is_VIsual);
break;
+
+ case OP_NR_ADD:
+ case OP_NR_SUB:
+ if (empty_region_error) {
+ vim_beep(BO_OPER);
+ CancelRedo();
+ } else {
+ VIsual_active = true;
+ curwin->w_p_lbr = lbr_saved;
+ op_addsub(oap, cap->count1, redo_VIsual_arg);
+ VIsual_active = false;
+ }
+ check_cursor_col();
+ break;
default:
clearopbeep(oap);
}
@@ -2334,8 +2347,9 @@ do_mouse (
if (mouse_row == 0 && firstwin->w_winrow > 0) {
if (is_drag) {
if (in_tab_line) {
- c1 = TabPageIdxs[mouse_col];
- tabpage_move(c1 <= 0 ? 9999 : c1 - 1);
+ tabpage_move(tab_page_click_defs[mouse_col].type == kStlClickTabClose
+ ? 9999
+ : tab_page_click_defs[mouse_col].tabnr - 1);
}
return false;
}
@@ -2345,41 +2359,114 @@ do_mouse (
&& cmdwin_type == 0
&& mouse_col < Columns) {
in_tab_line = true;
- c1 = TabPageIdxs[mouse_col];
- if (c1 >= 0) {
- if ((mod_mask & MOD_MASK_MULTI_CLICK) == MOD_MASK_2CLICK) {
- /* double click opens new page */
- end_visual_mode();
- tabpage_new();
- tabpage_move(c1 == 0 ? 9999 : c1 - 1);
- } else {
- /* Go to specified tab page, or next one if not clicking
- * on a label. */
- goto_tabpage(c1);
-
- /* It's like clicking on the status line of a window. */
- if (curwin != old_curwin)
+ c1 = tab_page_click_defs[mouse_col].tabnr;
+ switch (tab_page_click_defs[mouse_col].type) {
+ case kStlClickDisabled: {
+ break;
+ }
+ case kStlClickTabClose: {
+ tabpage_T *tp;
+
+ // Close the current or specified tab page.
+ if (c1 == 999) {
+ tp = curtab;
+ } else {
+ tp = find_tabpage(c1);
+ }
+ if (tp == curtab) {
+ if (first_tabpage->tp_next != NULL) {
+ tabpage_close(false);
+ }
+ } else if (tp != NULL) {
+ tabpage_close_other(tp, false);
+ }
+ break;
+ }
+ case kStlClickTabSwitch: {
+ if ((mod_mask & MOD_MASK_MULTI_CLICK) == MOD_MASK_2CLICK) {
+ // double click opens new page
end_visual_mode();
+ tabpage_new();
+ tabpage_move(c1 == 0 ? 9999 : c1 - 1);
+ } else {
+ // Go to specified tab page, or next one if not clicking
+ // on a label.
+ goto_tabpage(c1);
+
+ // It's like clicking on the status line of a window.
+ if (curwin != old_curwin) {
+ end_visual_mode();
+ }
+ }
+ break;
+ }
+ case kStlClickFuncRun: {
+ typval_T argv[] = {
+ {
+ .v_lock = VAR_FIXED,
+ .v_type = VAR_NUMBER,
+ .vval = {
+ .v_number = (varnumber_T) tab_page_click_defs[mouse_col].tabnr
+ },
+ },
+ {
+ .v_lock = VAR_FIXED,
+ .v_type = VAR_NUMBER,
+ .vval = {
+ .v_number = (((mod_mask & MOD_MASK_MULTI_CLICK)
+ == MOD_MASK_4CLICK)
+ ? 4
+ : ((mod_mask & MOD_MASK_MULTI_CLICK)
+ == MOD_MASK_3CLICK)
+ ? 3
+ : ((mod_mask & MOD_MASK_MULTI_CLICK)
+ == MOD_MASK_2CLICK)
+ ? 2
+ : 1)
+ },
+ },
+ {
+ .v_lock = VAR_FIXED,
+ .v_type = VAR_STRING,
+ .vval = { .v_string = (char_u *) (which_button == MOUSE_LEFT
+ ? "l"
+ : which_button == MOUSE_RIGHT
+ ? "r"
+ : which_button == MOUSE_MIDDLE
+ ? "m"
+ : "?") },
+ },
+ {
+ .v_lock = VAR_FIXED,
+ .v_type = VAR_STRING,
+ .vval = {
+ .v_string = (char_u[]) {
+ (char_u) (mod_mask & MOD_MASK_SHIFT ? 's' : ' '),
+ (char_u) (mod_mask & MOD_MASK_CTRL ? 'c' : ' '),
+ (char_u) (mod_mask & MOD_MASK_ALT ? 'a' : ' '),
+ (char_u) (mod_mask & MOD_MASK_META ? 'm' : ' '),
+ NUL
+ }
+ },
+ }
+ };
+ typval_T rettv;
+ int doesrange;
+ (void) call_func((char_u *) tab_page_click_defs[mouse_col].func,
+ (int) strlen(tab_page_click_defs[mouse_col].func),
+ &rettv, ARRAY_SIZE(argv), argv,
+ curwin->w_cursor.lnum, curwin->w_cursor.lnum,
+ &doesrange, true, NULL);
+ clear_tv(&rettv);
+ break;
}
- } else if (c1 < 0) {
- tabpage_T *tp;
-
- /* Close the current or specified tab page. */
- if (c1 == -999)
- tp = curtab;
- else
- tp = find_tabpage(-c1);
- if (tp == curtab) {
- if (first_tabpage->tp_next != NULL)
- tabpage_close(false);
- } else if (tp != NULL)
- tabpage_close_other(tp, false);
}
}
return true;
} else if (is_drag && in_tab_line) {
- c1 = TabPageIdxs[mouse_col];
- tabpage_move(c1 <= 0 ? 9999 : c1 - 1);
+ tabpage_move(tab_page_click_defs[mouse_col].type == kStlClickTabClose
+ ? 9999
+ : tab_page_click_defs[mouse_col].tabnr - 1);
in_tab_line = false;
return false;
}
@@ -2852,10 +2939,7 @@ void end_visual_mode(void)
if (!virtual_active())
curwin->w_cursor.coladd = 0;
- if (mode_displayed)
- clear_cmdline = true; /* unshow visual mode later */
- else
- clear_showcmd();
+ may_clear_cmdline();
adjust_cursor_eol();
}
@@ -3121,10 +3205,19 @@ static void unshift_special(cmdarg_T *cap)
cap->cmdchar = simplify_key(cap->cmdchar, &mod_mask);
}
-/*
- * Routines for displaying a partly typed command
- */
+/// If the mode is currently displayed clear the command line or update the
+/// command displayed.
+static void may_clear_cmdline(void)
+{
+ if (mode_displayed) {
+ // unshow visual mode later
+ clear_cmdline = true;
+ } else {
+ clear_showcmd();
+ }
+}
+// Routines for displaying a partly typed command
# define SHOWCMD_BUFLEN SHOWCMD_COLS + 1 + 30
static char_u showcmd_buf[SHOWCMD_BUFLEN];
static char_u old_showcmd_buf[SHOWCMD_BUFLEN]; /* For push_showcmd() */
@@ -3503,9 +3596,16 @@ static void nv_help(cmdarg_T *cap)
*/
static void nv_addsub(cmdarg_T *cap)
{
- if (!checkclearopq(cap->oap)
- && do_addsub(cap->cmdchar, cap->count1))
+ if (!VIsual_active && cap->oap->op_type == OP_NOP) {
prep_redo_cmd(cap);
+ cap->oap->op_type = cap->cmdchar == Ctrl_A ? OP_NR_ADD : OP_NR_SUB;
+ op_addsub(cap->oap, cap->count1, cap->arg);
+ cap->oap->op_type = OP_NOP;
+ } else if (VIsual_active) {
+ nv_operator(cap);
+ } else {
+ clearop(cap->oap);
+ }
}
/*
@@ -6327,9 +6427,20 @@ static void nv_g_cmd(cmdarg_T *cap)
bool flag = false;
switch (cap->nchar) {
- /*
- * "gR": Enter virtual replace mode.
- */
+ // "g^A/g^X": Sequentially increment visually selected region.
+ case Ctrl_A:
+ case Ctrl_X:
+ if (VIsual_active) {
+ cap->arg = true;
+ cap->cmdchar = cap->nchar;
+ cap->nchar = NUL;
+ nv_addsub(cap);
+ } else {
+ clearopbeep(oap);
+ }
+ break;
+
+ // "gR": Enter virtual replace mode.
case 'R':
cap->arg = true;
nv_Replace(cap);