aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/nvim/normal.c318
1 files changed, 168 insertions, 150 deletions
diff --git a/src/nvim/normal.c b/src/nvim/normal.c
index 3b23c4e7dc..de884acdcb 100644
--- a/src/nvim/normal.c
+++ b/src/nvim/normal.c
@@ -70,6 +70,7 @@ typedef struct normal_state {
VimState state;
linenr_T conceal_old_cursor_line;
linenr_T conceal_new_cursor_line;
+ bool command_finished;
bool ctrl_w;
bool need_flushbuf;
bool conceal_update_lines;
@@ -82,8 +83,11 @@ typedef struct normal_state {
oparg_T oa; // operator arguments
cmdarg_T ca; // command arguments
int mapped_len;
+ int old_mapped_len;
int idx;
int c;
+ int old_col;
+ pos_T old_pos;
} NormalState;
/*
@@ -800,13 +804,157 @@ static bool normal_get_command_count(NormalState *s)
return false;
}
+static void normal_finish_command(NormalState *s)
+{
+ if (s->command_finished) {
+ goto normal_end;
+ }
+
+ // If we didn't start or finish an operator, reset oap->regname, unless we
+ // need it later.
+ if (!finish_op
+ && !s->oa.op_type
+ && (s->idx < 0 || !(nv_cmds[s->idx].cmd_flags & NV_KEEPREG))) {
+ clearop(&s->oa);
+ set_reg_var(get_default_register_name());
+ }
+
+ // Get the length of mapped chars again after typing a count, second
+ // character or "z333<cr>".
+ if (s->old_mapped_len > 0) {
+ s->old_mapped_len = typebuf_maplen();
+ }
+
+ // If an operation is pending, handle it...
+ do_pending_operator(&s->ca, s->old_col, false);
+
+ // Wait for a moment when a message is displayed that will be overwritten
+ // by the mode message.
+ // In Visual mode and with "^O" in Insert mode, a short message will be
+ // overwritten by the mode message. Wait a bit, until a key is hit.
+ // In Visual mode, it's more important to keep the Visual area updated
+ // than keeping a message (e.g. from a /pat search).
+ // Only do this if the command was typed, not from a mapping.
+ // Don't wait when emsg_silent is non-zero.
+ // Also wait a bit after an error message, e.g. for "^O:".
+ // Don't redraw the screen, it would remove the message.
+ if (((p_smd && msg_silent == 0 && (restart_edit != 0 || (VIsual_active
+ && s->old_pos.lnum == curwin->w_cursor.lnum
+ && s->old_pos.col == curwin->w_cursor.col))
+ && (clear_cmdline || redraw_cmdline)
+ && (msg_didout || (msg_didany && msg_scroll))
+ && !msg_nowait
+ && KeyTyped) || (restart_edit != 0 && !VIsual_active && (msg_scroll
+ || emsg_on_display)))
+ && s->oa.regname == 0
+ && !(s->ca.retval & CA_COMMAND_BUSY)
+ && stuff_empty()
+ && typebuf_typed()
+ && emsg_silent == 0
+ && !did_wait_return
+ && s->oa.op_type == OP_NOP) {
+ int save_State = State;
+
+ // Draw the cursor with the right shape here
+ if (restart_edit != 0) {
+ State = INSERT;
+ }
+
+ // If need to redraw, and there is a "keep_msg", redraw before the
+ // delay
+ if (must_redraw && keep_msg != NULL && !emsg_on_display) {
+ char_u *kmsg;
+
+ kmsg = keep_msg;
+ keep_msg = NULL;
+ // showmode() will clear keep_msg, but we want to use it anyway
+ update_screen(0);
+ // now reset it, otherwise it's put in the history again
+ keep_msg = kmsg;
+ msg_attr(kmsg, keep_msg_attr);
+ xfree(kmsg);
+ }
+ setcursor();
+ ui_flush();
+ if (msg_scroll || emsg_on_display) {
+ os_delay(1000L, true); // wait at least one second
+ }
+ os_delay(3000L, false); // wait up to three seconds
+ State = save_State;
+
+ msg_scroll = false;
+ emsg_on_display = false;
+ }
+
+ // Finish up after executing a Normal mode command.
+normal_end:
+
+ msg_nowait = false;
+
+ // Reset finish_op, in case it was set
+ s->c = finish_op;
+ finish_op = false;
+ // Redraw the cursor with another shape, if we were in Operator-pending
+ // mode or did a replace command.
+ if (s->c || s->ca.cmdchar == 'r') {
+ ui_cursor_shape(); // may show different cursor shape
+ }
+
+ if (s->oa.op_type == OP_NOP && s->oa.regname == 0
+ && s->ca.cmdchar != K_EVENT) {
+ clear_showcmd();
+ }
+
+ checkpcmark(); // check if we moved since setting pcmark
+ xfree(s->ca.searchbuf);
+
+ if (has_mbyte) {
+ mb_adjust_cursor();
+ }
+
+ if (curwin->w_p_scb && s->toplevel) {
+ validate_cursor(); // may need to update w_leftcol
+ do_check_scrollbind(true);
+ }
+
+ if (curwin->w_p_crb && s->toplevel) {
+ validate_cursor(); // may need to update w_leftcol
+ do_check_cursorbind();
+ }
+
+ // May restart edit(), if we got here with CTRL-O in Insert mode (but not
+ // if still inside a mapping that started in Visual mode).
+ // May switch from Visual to Select mode after CTRL-O command.
+ if (s->oa.op_type == OP_NOP
+ && ((restart_edit != 0 && !VIsual_active && s->old_mapped_len == 0)
+ || restart_VIsual_select == 1)
+ && !(s->ca.retval & CA_COMMAND_BUSY)
+ && stuff_empty()
+ && s->oa.regname == 0) {
+ if (restart_VIsual_select == 1) {
+ VIsual_select = true;
+ showmode();
+ restart_VIsual_select = 0;
+ }
+ if (restart_edit != 0 && !VIsual_active && s->old_mapped_len == 0) {
+ (void)edit(restart_edit, false, 1L);
+ }
+ }
+
+ if (restart_VIsual_select == 2) {
+ restart_VIsual_select = 1;
+ }
+
+ // Save count before an operator for next time
+ opcount = s->ca.opcount;
+}
+
static int normal_execute(VimState *state, int key)
{
NormalState *s = (NormalState *)state;
+ s->command_finished = false;
s->ctrl_w = false; /* got CTRL-W command */
- int old_col = curwin->w_curswant;
- pos_T old_pos; /* cursor position before command */
- static int old_mapped_len = 0;
+ s->old_col = curwin->w_curswant;
s->c = key;
LANGMAP_ADJUST(s->c, true);
@@ -815,10 +963,10 @@ static int normal_execute(VimState *state, int key)
// of the mapping. This is used below to not return to Insert mode for as
// long as the mapping is being executed.
if (restart_edit == 0) {
- old_mapped_len = 0;
- } else if (old_mapped_len || (VIsual_active && s->mapped_len == 0
+ s->old_mapped_len = 0;
+ } else if (s->old_mapped_len || (VIsual_active && s->mapped_len == 0
&& typebuf_maplen() > 0)) {
- old_mapped_len = typebuf_maplen();
+ s->old_mapped_len = typebuf_maplen();
}
if (s->c == NUL) {
@@ -840,7 +988,7 @@ static int normal_execute(VimState *state, int key)
s->c = 'c';
}
msg_nowait = true; // don't delay going to insert mode
- old_mapped_len = 0; // do go to Insert mode
+ s->old_mapped_len = 0; // do go to Insert mode
}
s->need_flushbuf = add_to_showcmd(s->c);
@@ -894,23 +1042,27 @@ static int normal_execute(VimState *state, int key)
if (s->idx < 0) {
// Not a known command: beep.
clearopbeep(&s->oa);
- goto normal_end;
+ s->command_finished = true;
+ goto finish;
}
if (text_locked() && (nv_cmds[s->idx].cmd_flags & NV_NCW)) {
// This command is not allowed while editing a cmdline: beep.
clearopbeep(&s->oa);
text_locked_msg();
- goto normal_end;
+ s->command_finished = true;
+ goto finish;
}
if ((nv_cmds[s->idx].cmd_flags & NV_NCW) && curbuf_locked()) {
- goto normal_end;
+ s->command_finished = true;
+ goto finish;
}
// In Visual/Select mode, a few keys are handled in a special way.
if (VIsual_active && normal_handle_special_visual_command(s)) {
- goto normal_end;
+ s->command_finished = true;
+ goto finish;
}
if (curwin->w_p_rl && KeyTyped && !KeyStuffed
@@ -944,7 +1096,8 @@ static int normal_execute(VimState *state, int key)
if (restart_edit == 0 && goto_im()) {
restart_edit = 'a';
}
- goto normal_end;
+ s->command_finished = true;
+ goto finish;
}
if (s->ca.cmdchar != K_IGNORE) {
@@ -952,7 +1105,7 @@ static int normal_execute(VimState *state, int key)
msg_col = 0;
}
- old_pos = curwin->w_cursor; // remember where cursor was
+ s->old_pos = curwin->w_cursor; // remember where cursor was
// When 'keymodel' contains "startsel" some keys start Select/Visual
// mode.
@@ -973,143 +1126,8 @@ static int normal_execute(VimState *state, int key)
s->ca.arg = nv_cmds[s->idx].cmd_arg;
(nv_cmds[s->idx].cmd_func)(&s->ca);
- // If we didn't start or finish an operator, reset oap->regname, unless we
- // need it later.
- if (!finish_op
- && !s->oa.op_type
- && (s->idx < 0 || !(nv_cmds[s->idx].cmd_flags & NV_KEEPREG))) {
- clearop(&s->oa);
- set_reg_var(get_default_register_name());
- }
-
- // Get the length of mapped chars again after typing a count, second
- // character or "z333<cr>".
- if (old_mapped_len > 0) {
- old_mapped_len = typebuf_maplen();
- }
-
- // If an operation is pending, handle it...
- do_pending_operator(&s->ca, old_col, false);
-
- // Wait for a moment when a message is displayed that will be overwritten
- // by the mode message.
- // In Visual mode and with "^O" in Insert mode, a short message will be
- // overwritten by the mode message. Wait a bit, until a key is hit.
- // In Visual mode, it's more important to keep the Visual area updated
- // than keeping a message (e.g. from a /pat search).
- // Only do this if the command was typed, not from a mapping.
- // Don't wait when emsg_silent is non-zero.
- // Also wait a bit after an error message, e.g. for "^O:".
- // Don't redraw the screen, it would remove the message.
- if (((p_smd && msg_silent == 0 && (restart_edit != 0 || (VIsual_active
- && old_pos.lnum == curwin->w_cursor.lnum
- && old_pos.col == curwin->w_cursor.col))
- && (clear_cmdline || redraw_cmdline)
- && (msg_didout || (msg_didany && msg_scroll))
- && !msg_nowait
- && KeyTyped) || (restart_edit != 0 && !VIsual_active && (msg_scroll
- || emsg_on_display)))
- && s->oa.regname == 0
- && !(s->ca.retval & CA_COMMAND_BUSY)
- && stuff_empty()
- && typebuf_typed()
- && emsg_silent == 0
- && !did_wait_return
- && s->oa.op_type == OP_NOP) {
- int save_State = State;
-
- // Draw the cursor with the right shape here
- if (restart_edit != 0) {
- State = INSERT;
- }
-
- // If need to redraw, and there is a "keep_msg", redraw before the
- // delay
- if (must_redraw && keep_msg != NULL && !emsg_on_display) {
- char_u *kmsg;
-
- kmsg = keep_msg;
- keep_msg = NULL;
- // showmode() will clear keep_msg, but we want to use it anyway
- update_screen(0);
- // now reset it, otherwise it's put in the history again
- keep_msg = kmsg;
- msg_attr(kmsg, keep_msg_attr);
- xfree(kmsg);
- }
- setcursor();
- ui_flush();
- if (msg_scroll || emsg_on_display) {
- os_delay(1000L, true); // wait at least one second
- }
- os_delay(3000L, false); // wait up to three seconds
- State = save_State;
-
- msg_scroll = false;
- emsg_on_display = false;
- }
-
- // Finish up after executing a Normal mode command.
-normal_end:
-
- msg_nowait = false;
-
- // Reset finish_op, in case it was set
- s->c = finish_op;
- finish_op = false;
- // Redraw the cursor with another shape, if we were in Operator-pending
- // mode or did a replace command.
- if (s->c || s->ca.cmdchar == 'r') {
- ui_cursor_shape(); // may show different cursor shape
- }
-
- if (s->oa.op_type == OP_NOP && s->oa.regname == 0
- && s->ca.cmdchar != K_EVENT) {
- clear_showcmd();
- }
-
- checkpcmark(); // check if we moved since setting pcmark
- xfree(s->ca.searchbuf);
-
- if (has_mbyte) {
- mb_adjust_cursor();
- }
-
- if (curwin->w_p_scb && s->toplevel) {
- validate_cursor(); // may need to update w_leftcol
- do_check_scrollbind(true);
- }
-
- if (curwin->w_p_crb && s->toplevel) {
- validate_cursor(); // may need to update w_leftcol
- do_check_cursorbind();
- }
-
- // May restart edit(), if we got here with CTRL-O in Insert mode (but not
- // if still inside a mapping that started in Visual mode).
- // May switch from Visual to Select mode after CTRL-O command.
- if (s->oa.op_type == OP_NOP
- && ((restart_edit != 0 && !VIsual_active && old_mapped_len == 0)
- || restart_VIsual_select == 1)
- && !(s->ca.retval & CA_COMMAND_BUSY)
- && stuff_empty()
- && s->oa.regname == 0) {
- if (restart_VIsual_select == 1) {
- VIsual_select = true;
- showmode();
- restart_VIsual_select = 0;
- }
- if (restart_edit != 0 && !VIsual_active && old_mapped_len == 0) {
- (void)edit(restart_edit, false, 1L);
- }
- }
-
- if (restart_VIsual_select == 2) {
- restart_VIsual_select = 1;
- }
-
- // Save count before an operator for next time
- opcount = s->ca.opcount;
+finish:
+ normal_finish_command(s);
return 1;
}