mirror of
https://github.com/neovim/neovim.git
synced 2025-02-25 18:55:25 -06:00
input: Remove CURSORHOLD key
Refactor input.c, normal.c and edit.c to use the K_EVENT special key to trigger the CURSORHOLD event. In normal and edit mode, K_EVENT is treated as K_CURSORHOLD, which enables better handling of arbitrary actions in those states(eg: In normal mode the previous operator counts will be restored). Also fix a test in vim_spec.lua. The test had a wrong assumption: cmdheight is only used to determine when the press enter screen will be shown, not to limit how many lines or control pagination.
This commit is contained in:
parent
d8055f8eab
commit
e5165bae11
@ -626,14 +626,9 @@ edit (
|
||||
} while (c == K_IGNORE);
|
||||
input_disable_events();
|
||||
|
||||
if (c == K_EVENT) {
|
||||
c = lastc;
|
||||
queue_process_events(loop.events);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Don't want K_CURSORHOLD for the second key, e.g., after CTRL-V. */
|
||||
did_cursorhold = TRUE;
|
||||
// Don't want K_EVENT with cursorhold for the second key, e.g., after
|
||||
// CTRL-V.
|
||||
did_cursorhold = true;
|
||||
|
||||
if (p_hkmap && KeyTyped)
|
||||
c = hkmap(c); /* Hebrew mode mapping */
|
||||
@ -974,9 +969,8 @@ doESCkey:
|
||||
case K_IGNORE: /* Something mapped to nothing */
|
||||
break;
|
||||
|
||||
case K_CURSORHOLD: /* Didn't type something for a while. */
|
||||
apply_autocmds(EVENT_CURSORHOLDI, NULL, NULL, FALSE, curbuf);
|
||||
did_cursorhold = TRUE;
|
||||
case K_EVENT: // some event
|
||||
queue_process_events(loop.events);
|
||||
break;
|
||||
|
||||
case K_HOME: /* <Home> */
|
||||
@ -1223,9 +1217,10 @@ normalchar:
|
||||
break;
|
||||
} /* end of switch (c) */
|
||||
|
||||
/* If typed something may trigger CursorHoldI again. */
|
||||
if (c != K_CURSORHOLD)
|
||||
did_cursorhold = FALSE;
|
||||
// If typed something may trigger CursorHoldI again.
|
||||
if (c != K_EVENT) {
|
||||
did_cursorhold = false;
|
||||
}
|
||||
|
||||
/* If the cursor was moved we didn't just insert a space */
|
||||
if (arrow_used)
|
||||
|
@ -283,7 +283,6 @@ static struct key_name_entry {
|
||||
{K_ZERO, (char_u *)"Nul"},
|
||||
{K_SNR, (char_u *)"SNR"},
|
||||
{K_PLUG, (char_u *)"Plug"},
|
||||
{K_CURSORHOLD, (char_u *)"CursorHold"},
|
||||
{K_PASTE, (char_u *)"Paste"},
|
||||
{0, NULL}
|
||||
};
|
||||
|
@ -242,7 +242,6 @@ enum key_extra {
|
||||
, KE_X2RELEASE
|
||||
|
||||
, KE_DROP /* DnD data is available */
|
||||
, KE_CURSORHOLD /* CursorHold event */
|
||||
, KE_NOP /* doesn't do something */
|
||||
, KE_FOCUSGAINED /* focus gained */
|
||||
, KE_FOCUSLOST /* focus lost */
|
||||
@ -437,7 +436,6 @@ enum key_extra {
|
||||
#define K_FOCUSGAINED TERMCAP2KEY(KS_EXTRA, KE_FOCUSGAINED)
|
||||
#define K_FOCUSLOST TERMCAP2KEY(KS_EXTRA, KE_FOCUSLOST)
|
||||
|
||||
#define K_CURSORHOLD TERMCAP2KEY(KS_EXTRA, KE_CURSORHOLD)
|
||||
#define K_EVENT TERMCAP2KEY(KS_EXTRA, KE_EVENT)
|
||||
#define K_PASTE TERMCAP2KEY(KS_EXTRA, KE_PASTE)
|
||||
|
||||
|
@ -336,7 +336,7 @@ static const struct nv_cmd {
|
||||
{K_SELECT, nv_select, 0, 0},
|
||||
{K_F8, farsi_fkey, 0, 0},
|
||||
{K_F9, farsi_fkey, 0, 0},
|
||||
{K_CURSORHOLD, nv_cursorhold, NV_KEEPREG, 0},
|
||||
{K_EVENT, nv_event, NV_KEEPREG, 0},
|
||||
};
|
||||
|
||||
/* Number of commands in nv_cmds[]. */
|
||||
@ -492,8 +492,8 @@ static void normal_prepare(NormalState *s)
|
||||
s->set_prevcount = true;
|
||||
}
|
||||
|
||||
// Restore counts from before receiving K_CURSORHOLD. This means after
|
||||
// typing "3", handling K_CURSORHOLD and then typing "2" we get "32", not
|
||||
// Restore counts from before receiving K_EVENT. This means after
|
||||
// typing "3", handling K_EVENT and then typing "2" we get "32", not
|
||||
// "3 * 2".
|
||||
if (s->oa.prev_opcount > 0 || s->oa.prev_count0 > 0) {
|
||||
s->ca.opcount = s->oa.prev_opcount;
|
||||
@ -616,9 +616,9 @@ getcount:
|
||||
}
|
||||
}
|
||||
|
||||
if (c == K_CURSORHOLD) {
|
||||
if (c == K_EVENT) {
|
||||
// Save the count values so that ca.opcount and ca.count0 are exactly
|
||||
// the same when coming back here after handling K_CURSORHOLD.
|
||||
// the same when coming back here after handling K_EVENT.
|
||||
s->oa.prev_opcount = s->ca.opcount;
|
||||
s->oa.prev_count0 = s->ca.count0;
|
||||
} else if (s->ca.opcount != 0) {
|
||||
@ -891,7 +891,7 @@ getcount:
|
||||
if (need_flushbuf) {
|
||||
ui_flush();
|
||||
}
|
||||
if (s->ca.cmdchar != K_IGNORE) {
|
||||
if (s->ca.cmdchar != K_IGNORE && s->ca.cmdchar != K_EVENT) {
|
||||
did_cursorhold = false;
|
||||
}
|
||||
|
||||
@ -1022,7 +1022,7 @@ normal_end:
|
||||
}
|
||||
|
||||
if (s->oa.op_type == OP_NOP && s->oa.regname == 0
|
||||
&& s->ca.cmdchar != K_CURSORHOLD) {
|
||||
&& s->ca.cmdchar != K_EVENT) {
|
||||
clear_showcmd();
|
||||
}
|
||||
|
||||
@ -3147,7 +3147,7 @@ bool add_to_showcmd(int c)
|
||||
K_RIGHTMOUSE, K_RIGHTDRAG, K_RIGHTRELEASE,
|
||||
K_MOUSEDOWN, K_MOUSEUP, K_MOUSELEFT, K_MOUSERIGHT,
|
||||
K_X1MOUSE, K_X1DRAG, K_X1RELEASE, K_X2MOUSE, K_X2DRAG, K_X2RELEASE,
|
||||
K_CURSORHOLD,
|
||||
K_EVENT,
|
||||
0
|
||||
};
|
||||
|
||||
@ -7567,16 +7567,11 @@ static void nv_open(cmdarg_T *cap)
|
||||
n_opencmd(cap);
|
||||
}
|
||||
|
||||
/*
|
||||
* Trigger CursorHold event.
|
||||
* When waiting for a character for 'updatetime' K_CURSORHOLD is put in the
|
||||
* input buffer. "did_cursorhold" is set to avoid retriggering.
|
||||
*/
|
||||
static void nv_cursorhold(cmdarg_T *cap)
|
||||
// Handle an arbitrary event in normal mode
|
||||
static void nv_event(cmdarg_T *cap)
|
||||
{
|
||||
apply_autocmds(EVENT_CURSORHOLD, NULL, NULL, false, curbuf);
|
||||
did_cursorhold = true;
|
||||
cap->retval |= CA_COMMAND_BUSY; /* don't call edit() now */
|
||||
queue_process_events(loop.events);
|
||||
cap->retval |= CA_COMMAND_BUSY; // don't call edit() now
|
||||
}
|
||||
|
||||
/*
|
||||
@ -7594,18 +7589,9 @@ void normal_cmd(oparg_T *oap, bool toplevel)
|
||||
s.toplevel = toplevel;
|
||||
s.oa = *oap;
|
||||
normal_prepare(&s);
|
||||
|
||||
input_enable_events();
|
||||
int c = safe_vgetc();
|
||||
input_disable_events();
|
||||
|
||||
if (c == K_EVENT) {
|
||||
queue_process_events(loop.events);
|
||||
goto end;
|
||||
}
|
||||
|
||||
(void)normal_execute(&s, c);
|
||||
|
||||
end:
|
||||
*oap = s.oa;
|
||||
}
|
||||
|
@ -36,8 +36,8 @@ typedef struct oparg_S {
|
||||
bool block_mode; /* current operator is Visual block mode */
|
||||
colnr_T start_vcol; /* start col for block mode operator */
|
||||
colnr_T end_vcol; /* end col for block mode operator */
|
||||
long prev_opcount; /* ca.opcount saved for K_CURSORHOLD */
|
||||
long prev_count0; /* ca.count0 saved for K_CURSORHOLD */
|
||||
long prev_opcount; // ca.opcount saved for K_EVENT
|
||||
long prev_count0; // ca.count0 saved for K_EVENT
|
||||
} oparg_T;
|
||||
|
||||
/*
|
||||
|
@ -73,6 +73,21 @@ void input_stop(void)
|
||||
stream_close(&read_stream, NULL);
|
||||
}
|
||||
|
||||
static void cursorhold_event(void **argv)
|
||||
{
|
||||
event_T event = State & INSERT ? EVENT_CURSORHOLDI : EVENT_CURSORHOLD;
|
||||
apply_autocmds(event, NULL, NULL, false, curbuf);
|
||||
did_cursorhold = true;
|
||||
}
|
||||
|
||||
static void create_cursorhold_event(void)
|
||||
{
|
||||
// If the queue had any items, this function should not have been
|
||||
// called(inbuf_poll would return kInputAvail)
|
||||
assert(queue_empty(loop.events));
|
||||
queue_put(loop.events, cursorhold_event, 0);
|
||||
}
|
||||
|
||||
// Low level input function
|
||||
int os_inchar(uint8_t *buf, int maxlen, int ms, int tb_change_cnt)
|
||||
{
|
||||
@ -87,16 +102,12 @@ int os_inchar(uint8_t *buf, int maxlen, int ms, int tb_change_cnt)
|
||||
}
|
||||
} else {
|
||||
if ((result = inbuf_poll((int)p_ut)) == kInputNone) {
|
||||
if (trigger_cursorhold() && maxlen >= 3
|
||||
&& !typebuf_changed(tb_change_cnt)) {
|
||||
buf[0] = K_SPECIAL;
|
||||
buf[1] = KS_EXTRA;
|
||||
buf[2] = KE_CURSORHOLD;
|
||||
return 3;
|
||||
if (trigger_cursorhold() && !typebuf_changed(tb_change_cnt)) {
|
||||
create_cursorhold_event();
|
||||
} else {
|
||||
before_blocking();
|
||||
result = inbuf_poll(-1);
|
||||
}
|
||||
|
||||
before_blocking();
|
||||
result = inbuf_poll(-1);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -247,33 +247,21 @@ describe('vim_* functions', function()
|
||||
~ |
|
||||
{1:very fail} |
|
||||
]])
|
||||
helpers.wait()
|
||||
|
||||
-- shows up to &cmdheight lines
|
||||
nvim_async('err_write', 'more fail\n')
|
||||
nvim_async('err_write', 'too fail\n')
|
||||
nvim_async('err_write', 'more fail\ntoo fail\n')
|
||||
screen:expect([[
|
||||
~ |
|
||||
~ |
|
||||
~ |
|
||||
~ |
|
||||
~ |
|
||||
{1:very fail} |
|
||||
{1:more fail} |
|
||||
{2:Press ENTER or type command to continue}^ |
|
||||
]])
|
||||
|
||||
-- shows the rest after return
|
||||
feed('<cr>')
|
||||
screen:expect([[
|
||||
~ |
|
||||
~ |
|
||||
~ |
|
||||
{1:very fail} |
|
||||
{1:more fail} |
|
||||
{2:Press ENTER or type command to continue} |
|
||||
{1:too fail} |
|
||||
{2:Press ENTER or type command to continue}^ |
|
||||
]])
|
||||
feed('<cr>') -- exit the press ENTER screen
|
||||
end)
|
||||
end)
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user