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:
Thiago de Arruda 2015-10-05 10:13:18 -03:00
parent d8055f8eab
commit e5165bae11
7 changed files with 46 additions and 69 deletions

View File

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

View File

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

View File

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

View File

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

View File

@ -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;
/*

View File

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

View File

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