Add test for where feature

This commit is contained in:
Andy K. Massimino
2021-10-09 13:04:25 -04:00
parent 9f764e4011
commit 5960027665
7 changed files with 929 additions and 0 deletions

View File

@@ -0,0 +1,78 @@
VIM LICENSE
I) There are no restrictions on distributing unmodified copies of Vim except
that they must include this license text. You can also distribute
unmodified parts of Vim, likewise unrestricted except that they must
include this license text. You are also allowed to include executables
that you made from the unmodified Vim sources, plus your own usage
examples and Vim scripts.
II) It is allowed to distribute a modified (or extended) version of Vim,
including executables and/or source code, when the following four
conditions are met:
1) This license text must be included unmodified.
2) The modified Vim must be distributed in one of the following five ways:
a) If you make changes to Vim yourself, you must clearly describe in
the distribution how to contact you. When the maintainer asks you
(in any way) for a copy of the modified Vim you distributed, you
must make your changes, including source code, available to the
maintainer without fee. The maintainer reserves the right to
include your changes in the official version of Vim. What the
maintainer will do with your changes and under what license they
will be distributed is negotiable. If there has been no negotiation
then this license, or a later version, also applies to your changes.
The current maintainer is Bram Moolenaar <Bram@vim.org>. If this
changes it will be announced in appropriate places (most likely
vim.sf.net, www.vim.org and/or comp.editors). When it is completely
impossible to contact the maintainer, the obligation to send him
your changes ceases. Once the maintainer has confirmed that he has
received your changes they will not have to be sent again.
b) If you have received a modified Vim that was distributed as
mentioned under a) you are allowed to further distribute it
unmodified, as mentioned at I). If you make additional changes the
text under a) applies to those changes.
c) Provide all the changes, including source code, with every copy of
the modified Vim you distribute. This may be done in the form of a
context diff. You can choose what license to use for new code you
add. The changes and their license must not restrict others from
making their own changes to the official version of Vim.
d) When you have a modified Vim which includes changes as mentioned
under c), you can distribute it without the source code for the
changes if the following three conditions are met:
- The license that applies to the changes permits you to distribute
the changes to the Vim maintainer without fee or restriction, and
permits the Vim maintainer to include the changes in the official
version of Vim without fee or restriction.
- You keep the changes for at least three years after last
distributing the corresponding modified Vim. When the maintainer
or someone who you distributed the modified Vim to asks you (in
any way) for the changes within this period, you must make them
available to him.
- You clearly describe in the distribution how to contact you. This
contact information must remain valid for at least three years
after last distributing the corresponding modified Vim, or as long
as possible.
e) When the GNU General Public License (GPL) applies to the changes,
you can distribute the modified Vim under the GNU GPL version 2 or
any later version.
3) A message must be added, at least in the output of the ":version"
command and in the intro screen, such that the user of the modified Vim
is able to see that it was modified. When distributing as mentioned
under 2)e) adding the message is only required for as far as this does
not conflict with the license used for the changes.
4) The contact information as required under 2)a) and 2)d) must not be
removed or changed, except that the person himself can make
corrections.
III) If you distribute a modified version of Vim, you are encouraged to use
the Vim license for your changes and make them available to the
maintainer, including the source code. The preferred way to do this is
by e-mail or by uploading the files to a server and e-mailing the URL.
If the number of changes is small (e.g., a modified Makefile) e-mailing a
context diff will do. The e-mail address to be used is
<maintainer@vim.org>
IV) It is not allowed to remove this license from the distribution of the Vim
sources, parts of it or from a modified version. You may use this
license for previous Vim releases instead of the license that they came
with, at your option.

View File

@@ -0,0 +1,10 @@
.PHONY: test
MYVIM ?= nvim --headless
INMAKE := 1
export INMAKE
test:
$(MYVIM) -u test.vim
rm *.out

View File

@@ -0,0 +1,811 @@
void
normal_cmd(
oparg_T *oap,
int toplevel UNUSED) // TRUE when called from main()
{
cmdarg_T ca; // command arguments
int c;
int ctrl_w = FALSE; // got CTRL-W command
int old_col = curwin->w_curswant;
#ifdef FEAT_CMDL_INFO
int need_flushbuf; // need to call out_flush()
#endif
pos_T old_pos; // cursor position before command
int mapped_len;
static int old_mapped_len = 0;
int idx;
#ifdef FEAT_EVAL
int set_prevcount = FALSE;
#endif
int save_did_cursorhold = did_cursorhold;
CLEAR_FIELD(ca); // also resets ca.retval
ca.oap = oap;
// Use a count remembered from before entering an operator. After typing
// "3d" we return from normal_cmd() and come back here, the "3" is
// remembered in "opcount".
ca.opcount = opcount;
/*
* If there is an operator pending, then the command we take this time
* will terminate it. Finish_op tells us to finish the operation before
* returning this time (unless the operation was cancelled).
*/
#ifdef CURSOR_SHAPE
c = finish_op;
#endif
finish_op = (oap->op_type != OP_NOP);
#ifdef CURSOR_SHAPE
if (finish_op != c)
{
ui_cursor_shape(); // may show different cursor shape
# ifdef FEAT_MOUSESHAPE
update_mouseshape(-1);
# endif
}
#endif
// When not finishing an operator and no register name typed, reset the
// count.
if (!finish_op && !oap->regname)
{
ca.opcount = 0;
#ifdef FEAT_EVAL
set_prevcount = TRUE;
#endif
}
// Restore counts from before receiving K_CURSORHOLD. This means after
// typing "3", handling K_CURSORHOLD and then typing "2" we get "32", not
// "3 * 2".
if (oap->prev_opcount > 0 || oap->prev_count0 > 0)
{
ca.opcount = oap->prev_opcount;
ca.count0 = oap->prev_count0;
oap->prev_opcount = 0;
oap->prev_count0 = 0;
}
mapped_len = typebuf_maplen();
State = NORMAL_BUSY;
#ifdef USE_ON_FLY_SCROLL
dont_scroll = FALSE; // allow scrolling here
#endif
#ifdef FEAT_EVAL
// Set v:count here, when called from main() and not a stuffed
// command, so that v:count can be used in an expression mapping
// when there is no count. Do set it for redo.
if (toplevel && readbuf1_empty())
set_vcount_ca(&ca, &set_prevcount);
#endif
/*
* Get the command character from the user.
*/
c = safe_vgetc();
LANGMAP_ADJUST(c, get_real_state() != SELECTMODE);
/*
* If a mapping was started in Visual or Select mode, remember the length
* 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 && mapped_len == 0 && typebuf_maplen() > 0))
old_mapped_len = typebuf_maplen();
if (c == NUL)
c = K_ZERO;
/*
* In Select mode, typed text replaces the selection.
*/
if (VIsual_active
&& VIsual_select
&& (vim_isprintc(c) || c == NL || c == CAR || c == K_KENTER))
{
// Fake a "c"hange command. When "restart_edit" is set (e.g., because
// 'insertmode' is set) fake a "d"elete command, Insert mode will
// restart automatically.
// Insert the typed character in the typeahead buffer, so that it can
// be mapped in Insert mode. Required for ":lmap" to work.
ins_char_typebuf(vgetc_char, vgetc_mod_mask);
if (restart_edit != 0)
c = 'd';
else
c = 'c';
msg_nowait = TRUE; // don't delay going to insert mode
old_mapped_len = 0; // do go to Insert mode
}
#ifdef FEAT_CMDL_INFO
need_flushbuf = add_to_showcmd(c);
#endif
getcount:
if (!(VIsual_active && VIsual_select))
{
/*
* Handle a count before a command and compute ca.count0.
* Note that '0' is a command and not the start of a count, but it's
* part of a count after other digits.
*/
while ( (c >= '1' && c <= '9')
|| (ca.count0 != 0 && (c == K_DEL || c == K_KDEL || c == '0')))
{
if (c == K_DEL || c == K_KDEL)
{
ca.count0 /= 10;
#ifdef FEAT_CMDL_INFO
del_from_showcmd(4); // delete the digit and ~@%
#endif
}
else
ca.count0 = ca.count0 * 10 + (c - '0');
if (ca.count0 < 0) // overflow
ca.count0 = 999999999L;
#ifdef FEAT_EVAL
// Set v:count here, when called from main() and not a stuffed
// command, so that v:count can be used in an expression mapping
// right after the count. Do set it for redo.
if (toplevel && readbuf1_empty())
set_vcount_ca(&ca, &set_prevcount);
#endif
if (ctrl_w)
{
++no_mapping;
++allow_keys; // no mapping for nchar, but keys
}
++no_zero_mapping; // don't map zero here
c = plain_vgetc();
LANGMAP_ADJUST(c, TRUE);
--no_zero_mapping;
if (ctrl_w)
{
--no_mapping;
--allow_keys;
}
#ifdef FEAT_CMDL_INFO
need_flushbuf |= add_to_showcmd(c);
#endif
}
/*
* If we got CTRL-W there may be a/another count
*/
if (c == Ctrl_W && !ctrl_w && oap->op_type == OP_NOP)
{
ctrl_w = TRUE;
ca.opcount = ca.count0; // remember first count
ca.count0 = 0;
++no_mapping;
++allow_keys; // no mapping for nchar, but keys
c = plain_vgetc(); // get next character
LANGMAP_ADJUST(c, TRUE);
--no_mapping;
--allow_keys;
#ifdef FEAT_CMDL_INFO
need_flushbuf |= add_to_showcmd(c);
#endif
goto getcount; // jump back
}
}
if (c == K_CURSORHOLD)
{
// Save the count values so that ca.opcount and ca.count0 are exactly
// the same when coming back here after handling K_CURSORHOLD.
oap->prev_opcount = ca.opcount;
oap->prev_count0 = ca.count0;
}
else if (ca.opcount != 0)
{
/*
* If we're in the middle of an operator (including after entering a
* yank buffer with '"') AND we had a count before the operator, then
* that count overrides the current value of ca.count0.
* What this means effectively, is that commands like "3dw" get turned
* into "d3w" which makes things fall into place pretty neatly.
* If you give a count before AND after the operator, they are
* multiplied.
*/
if (ca.count0)
ca.count0 *= ca.opcount;
else
ca.count0 = ca.opcount;
if (ca.count0 < 0) // overflow
ca.count0 = 999999999L;
}
/*
* Always remember the count. It will be set to zero (on the next call,
* above) when there is no pending operator.
* When called from main(), save the count for use by the "count" built-in
* variable.
*/
ca.opcount = ca.count0;
ca.count1 = (ca.count0 == 0 ? 1 : ca.count0);
#ifdef FEAT_EVAL
/*
* Only set v:count when called from main() and not a stuffed command.
* Do set it for redo.
*/
if (toplevel && readbuf1_empty())
set_vcount(ca.count0, ca.count1, set_prevcount);
#endif
/*
* Find the command character in the table of commands.
* For CTRL-W we already got nchar when looking for a count.
*/
if (ctrl_w)
{
ca.nchar = c;
ca.cmdchar = Ctrl_W;
}
else
ca.cmdchar = c;
idx = find_command(ca.cmdchar);
if (idx < 0)
{
// Not a known command: beep.
clearopbeep(oap);
goto normal_end;
}
if (text_locked() && (nv_cmds[idx].cmd_flags & NV_NCW))
{
// This command is not allowed while editing a cmdline: beep.
clearopbeep(oap);
text_locked_msg();
goto normal_end;
}
if ((nv_cmds[idx].cmd_flags & NV_NCW) && curbuf_locked())
goto normal_end;
/*
* In Visual/Select mode, a few keys are handled in a special way.
*/
if (VIsual_active)
{
// when 'keymodel' contains "stopsel" may stop Select/Visual mode
if (km_stopsel
&& (nv_cmds[idx].cmd_flags & NV_STS)
&& !(mod_mask & MOD_MASK_SHIFT))
{
end_visual_mode();
redraw_curbuf_later(INVERTED);
}
// Keys that work different when 'keymodel' contains "startsel"
if (km_startsel)
{
if (nv_cmds[idx].cmd_flags & NV_SS)
{
unshift_special(&ca);
idx = find_command(ca.cmdchar);
if (idx < 0)
{
// Just in case
clearopbeep(oap);
goto normal_end;
}
}
else if ((nv_cmds[idx].cmd_flags & NV_SSS)
&& (mod_mask & MOD_MASK_SHIFT))
mod_mask &= ~MOD_MASK_SHIFT;
}
}
#ifdef FEAT_RIGHTLEFT
if (curwin->w_p_rl && KeyTyped && !KeyStuffed
&& (nv_cmds[idx].cmd_flags & NV_RL))
{
// Invert horizontal movements and operations. Only when typed by the
// user directly, not when the result of a mapping or "x" translated
// to "dl".
switch (ca.cmdchar)
{
case 'l': ca.cmdchar = 'h'; break;
case K_RIGHT: ca.cmdchar = K_LEFT; break;
case K_S_RIGHT: ca.cmdchar = K_S_LEFT; break;
case K_C_RIGHT: ca.cmdchar = K_C_LEFT; break;
case 'h': ca.cmdchar = 'l'; break;
case K_LEFT: ca.cmdchar = K_RIGHT; break;
case K_S_LEFT: ca.cmdchar = K_S_RIGHT; break;
case K_C_LEFT: ca.cmdchar = K_C_RIGHT; break;
case '>': ca.cmdchar = '<'; break;
case '<': ca.cmdchar = '>'; break;
}
idx = find_command(ca.cmdchar);
}
#endif
/*
* Get an additional character if we need one.
*/
if ((nv_cmds[idx].cmd_flags & NV_NCH)
&& (((nv_cmds[idx].cmd_flags & NV_NCH_NOP) == NV_NCH_NOP
&& oap->op_type == OP_NOP)
|| (nv_cmds[idx].cmd_flags & NV_NCH_ALW) == NV_NCH_ALW
|| (ca.cmdchar == 'q'
&& oap->op_type == OP_NOP
&& reg_recording == 0
&& reg_executing == 0)
|| ((ca.cmdchar == 'a' || ca.cmdchar == 'i')
&& (oap->op_type != OP_NOP || VIsual_active))))
{
int *cp;
int repl = FALSE; // get character for replace mode
int lit = FALSE; // get extra character literally
int langmap_active = FALSE; // using :lmap mappings
int lang; // getting a text character
#ifdef HAVE_INPUT_METHOD
int save_smd; // saved value of p_smd
#endif
++no_mapping;
++allow_keys; // no mapping for nchar, but allow key codes
// Don't generate a CursorHold event here, most commands can't handle
// it, e.g., nv_replace(), nv_csearch().
did_cursorhold = TRUE;
if (ca.cmdchar == 'g')
{
/*
* For 'g' get the next character now, so that we can check for
* "gr", "g'" and "g`".
*/
ca.nchar = plain_vgetc();
LANGMAP_ADJUST(ca.nchar, TRUE);
#ifdef FEAT_CMDL_INFO
need_flushbuf |= add_to_showcmd(ca.nchar);
#endif
if (ca.nchar == 'r' || ca.nchar == '\'' || ca.nchar == '`'
|| ca.nchar == Ctrl_BSL)
{
cp = &ca.extra_char; // need to get a third character
if (ca.nchar != 'r')
lit = TRUE; // get it literally
else
repl = TRUE; // get it in replace mode
}
else
cp = NULL; // no third character needed
}
else
{
if (ca.cmdchar == 'r') // get it in replace mode
repl = TRUE;
cp = &ca.nchar;
}
lang = (repl || (nv_cmds[idx].cmd_flags & NV_LANG));
/*
* Get a second or third character.
*/
if (cp != NULL)
{
if (repl)
{
State = REPLACE; // pretend Replace mode
#ifdef CURSOR_SHAPE
ui_cursor_shape(); // show different cursor shape
#endif
}
if (lang && curbuf->b_p_iminsert == B_IMODE_LMAP)
{
// Allow mappings defined with ":lmap".
--no_mapping;
--allow_keys;
if (repl)
State = LREPLACE;
else
State = LANGMAP;
langmap_active = TRUE;
}
#ifdef HAVE_INPUT_METHOD
save_smd = p_smd;
p_smd = FALSE; // Don't let the IM code show the mode here
if (lang && curbuf->b_p_iminsert == B_IMODE_IM)
im_set_active(TRUE);
#endif
if ((State & INSERT) && !p_ek)
{
#ifdef FEAT_JOB_CHANNEL
ch_log_output = TRUE;
#endif
// Disable bracketed paste and modifyOtherKeys here, we won't
// recognize the escape sequences with 'esckeys' off.
out_str(T_BD);
out_str(T_CTE);
}
*cp = plain_vgetc();
if ((State & INSERT) && !p_ek)
{
#ifdef FEAT_JOB_CHANNEL
ch_log_output = TRUE;
#endif
// Re-enable bracketed paste mode and modifyOtherKeys
out_str(T_BE);
out_str(T_CTI);
}
if (langmap_active)
{
// Undo the decrement done above
++no_mapping;
++allow_keys;
State = NORMAL_BUSY;
}
#ifdef HAVE_INPUT_METHOD
if (lang)
{
if (curbuf->b_p_iminsert != B_IMODE_LMAP)
im_save_status(&curbuf->b_p_iminsert);
im_set_active(FALSE);
}
p_smd = save_smd;
#endif
State = NORMAL_BUSY;
#ifdef FEAT_CMDL_INFO
need_flushbuf |= add_to_showcmd(*cp);
#endif
if (!lit)
{
#ifdef FEAT_DIGRAPHS
// Typing CTRL-K gets a digraph.
if (*cp == Ctrl_K
&& ((nv_cmds[idx].cmd_flags & NV_LANG)
|| cp == &ca.extra_char)
&& vim_strchr(p_cpo, CPO_DIGRAPH) == NULL)
{
c = get_digraph(FALSE);
if (c > 0)
{
*cp = c;
# ifdef FEAT_CMDL_INFO
// Guessing how to update showcmd here...
del_from_showcmd(3);
need_flushbuf |= add_to_showcmd(*cp);
# endif
}
}
#endif
// adjust chars > 127, except after "tTfFr" commands
LANGMAP_ADJUST(*cp, !lang);
#ifdef FEAT_RIGHTLEFT
// adjust Hebrew mapped char
if (p_hkmap && lang && KeyTyped)
*cp = hkmap(*cp);
#endif
}
/*
* When the next character is CTRL-\ a following CTRL-N means the
* command is aborted and we go to Normal mode.
*/
if (cp == &ca.extra_char
&& ca.nchar == Ctrl_BSL
&& (ca.extra_char == Ctrl_N || ca.extra_char == Ctrl_G))
{
ca.cmdchar = Ctrl_BSL;
ca.nchar = ca.extra_char;
idx = find_command(ca.cmdchar);
}
else if ((ca.nchar == 'n' || ca.nchar == 'N') && ca.cmdchar == 'g')
ca.oap->op_type = get_op_type(*cp, NUL);
else if (*cp == Ctrl_BSL)
{
long towait = (p_ttm >= 0 ? p_ttm : p_tm);
// There is a busy wait here when typing "f<C-\>" and then
// something different from CTRL-N. Can't be avoided.
while ((c = vpeekc()) <= 0 && towait > 0L)
{
do_sleep(towait > 50L ? 50L : towait, FALSE);
towait -= 50L;
}
if (c > 0)
{
c = plain_vgetc();
if (c != Ctrl_N && c != Ctrl_G)
vungetc(c);
else
{
ca.cmdchar = Ctrl_BSL;
ca.nchar = c;
idx = find_command(ca.cmdchar);
}
}
}
// When getting a text character and the next character is a
// multi-byte character, it could be a composing character.
// However, don't wait for it to arrive. Also, do enable mapping,
// because if it's put back with vungetc() it's too late to apply
// mapping.
--no_mapping;
while (enc_utf8 && lang && (c = vpeekc()) > 0
&& (c >= 0x100 || MB_BYTE2LEN(vpeekc()) > 1))
{
c = plain_vgetc();
if (!utf_iscomposing(c))
{
vungetc(c); // it wasn't, put it back
break;
}
else if (ca.ncharC1 == 0)
ca.ncharC1 = c;
else
ca.ncharC2 = c;
}
++no_mapping;
}
--no_mapping;
--allow_keys;
}
#ifdef FEAT_CMDL_INFO
/*
* Flush the showcmd characters onto the screen so we can see them while
* the command is being executed. Only do this when the shown command was
* actually displayed, otherwise this will slow down a lot when executing
* mappings.
*/
if (need_flushbuf)
out_flush();
#endif
if (ca.cmdchar != K_IGNORE)
{
if (ex_normal_busy)
did_cursorhold = save_did_cursorhold;
else
did_cursorhold = FALSE;
}
State = NORMAL;
if (ca.nchar == ESC)
{
clearop(oap);
if (restart_edit == 0 && goto_im())
restart_edit = 'a';
goto normal_end;
}
if (ca.cmdchar != K_IGNORE)
{
msg_didout = FALSE; // don't scroll screen up for normal command
msg_col = 0;
}
old_pos = curwin->w_cursor; // remember where cursor was
// When 'keymodel' contains "startsel" some keys start Select/Visual
// mode.
if (!VIsual_active && km_startsel)
{
if (nv_cmds[idx].cmd_flags & NV_SS)
{
start_selection();
unshift_special(&ca);
idx = find_command(ca.cmdchar);
}
else if ((nv_cmds[idx].cmd_flags & NV_SSS)
&& (mod_mask & MOD_MASK_SHIFT))
{
start_selection();
mod_mask &= ~MOD_MASK_SHIFT;
}
}
/*
* Execute the command!
* Call the command function found in the commands table.
*/
ca.arg = nv_cmds[idx].cmd_arg;
(nv_cmds[idx].cmd_func)(&ca);
/*
* If we didn't start or finish an operator, reset oap->regname, unless we
* need it later.
*/
if (!finish_op
&& !oap->op_type
&& (idx < 0 || !(nv_cmds[idx].cmd_flags & NV_KEEPREG)))
{
clearop(oap);
#ifdef FEAT_EVAL
reset_reg_var();
#endif
}
// 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. But not for K_IGNORE or
* K_MOUSEMOVE.
*/
if (ca.cmdchar != K_IGNORE && ca.cmdchar != K_MOUSEMOVE)
do_pending_operator(&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)))
&& oap->regname == 0
&& !(ca.retval & CA_COMMAND_BUSY)
&& stuff_empty()
&& typebuf_typed()
&& emsg_silent == 0
&& !in_assert_fails
&& !did_wait_return
&& oap->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.
// First update w_topline.
setcursor();
update_screen(0);
// now reset it, otherwise it's put in the history again
keep_msg = kmsg;
kmsg = vim_strsave(keep_msg);
if (kmsg != NULL)
{
msg_attr((char *)kmsg, keep_msg_attr);
vim_free(kmsg);
}
}
setcursor();
#ifdef CURSOR_SHAPE
ui_cursor_shape(); // may show different cursor shape
#endif
cursor_on();
out_flush();
if (msg_scroll || emsg_on_display)
ui_delay(1003L, TRUE); // wait at least one second
ui_delay(3003L, 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;
#ifdef FEAT_EVAL
if (finish_op)
reset_reg_var();
#endif
// Reset finish_op, in case it was set
#ifdef CURSOR_SHAPE
c = finish_op;
#endif
finish_op = FALSE;
#ifdef CURSOR_SHAPE
// Redraw the cursor with another shape, if we were in Operator-pending
// mode or did a replace command.
if (c || ca.cmdchar == 'r')
{
ui_cursor_shape(); // may show different cursor shape
# ifdef FEAT_MOUSESHAPE
update_mouseshape(-1);
# endif
}
#endif
#ifdef FEAT_CMDL_INFO
if (oap->op_type == OP_NOP && oap->regname == 0
&& ca.cmdchar != K_CURSORHOLD)
clear_showcmd();
#endif
checkpcmark(); // check if we moved since setting pcmark
vim_free(ca.searchbuf);
if (has_mbyte)
mb_adjust_cursor();
if (curwin->w_p_scb && toplevel)
{
validate_cursor(); // may need to update w_leftcol
do_check_scrollbind(TRUE);
}
if (curwin->w_p_crb && toplevel)
{
validate_cursor(); // may need to update w_leftcol
do_check_cursorbind();
}
#ifdef FEAT_TERMINAL
// don't go to Insert mode if a terminal has a running job
if (term_job_running(curbuf->b_term))
restart_edit = 0;
#endif
/*
* 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 ( oap->op_type == OP_NOP
&& ((restart_edit != 0 && !VIsual_active && old_mapped_len == 0)
|| restart_VIsual_select == 1)
&& !(ca.retval & CA_COMMAND_BUSY)
&& stuff_empty()
&& oap->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 = ca.opcount;
}

View File

@@ -0,0 +1,24 @@
set nocompatible
source ../common/bootstrap.vim
edit +161 normal.c
redir! > test1.out
sil MatchupWhereAmI?
redir END
redir! > test2.out
normal! j
sil MatchupWhereAmI?
redir END
redir! > test3.out
normal! k
sil MatchupWhereAmI??
redir END
call assert_equal(readfile('test1.out'), readfile('test1.good'))
call assert_equal(readfile('test2.out'), readfile('test2.good'))
call assert_equal(readfile('test3.out'), readfile('test3.good'))
call matchup#test#finished()

View File

@@ -0,0 +1 @@
match-up: loading...normal_cmd( … { ▶ if (!(VIsual … { ▶ while ( ( … { ▶ if (ctrl_w) … {

View File

@@ -0,0 +1 @@
match-up: loading...normal_cmd( … { ▶ if (!(VIsual … { ▶ while ( ( … { ▶ if (ctrl_w) … {

View File

@@ -0,0 +1,4 @@
match-up: loading...normal_cmd( … {
if (!(VIsual_active && VIsual_select)) … {
while ( (c >= '1' && c <= '9') … {
if (ctrl_w) … {