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); } while (c == K_IGNORE);
input_disable_events(); input_disable_events();
if (c == K_EVENT) { // Don't want K_EVENT with cursorhold for the second key, e.g., after
c = lastc; // CTRL-V.
queue_process_events(loop.events); did_cursorhold = true;
continue;
}
/* Don't want K_CURSORHOLD for the second key, e.g., after CTRL-V. */
did_cursorhold = TRUE;
if (p_hkmap && KeyTyped) if (p_hkmap && KeyTyped)
c = hkmap(c); /* Hebrew mode mapping */ c = hkmap(c); /* Hebrew mode mapping */
@ -974,9 +969,8 @@ doESCkey:
case K_IGNORE: /* Something mapped to nothing */ case K_IGNORE: /* Something mapped to nothing */
break; break;
case K_CURSORHOLD: /* Didn't type something for a while. */ case K_EVENT: // some event
apply_autocmds(EVENT_CURSORHOLDI, NULL, NULL, FALSE, curbuf); queue_process_events(loop.events);
did_cursorhold = TRUE;
break; break;
case K_HOME: /* <Home> */ case K_HOME: /* <Home> */
@ -1223,9 +1217,10 @@ normalchar:
break; break;
} /* end of switch (c) */ } /* end of switch (c) */
/* If typed something may trigger CursorHoldI again. */ // If typed something may trigger CursorHoldI again.
if (c != K_CURSORHOLD) if (c != K_EVENT) {
did_cursorhold = FALSE; did_cursorhold = false;
}
/* If the cursor was moved we didn't just insert a space */ /* If the cursor was moved we didn't just insert a space */
if (arrow_used) if (arrow_used)

View File

@ -283,7 +283,6 @@ static struct key_name_entry {
{K_ZERO, (char_u *)"Nul"}, {K_ZERO, (char_u *)"Nul"},
{K_SNR, (char_u *)"SNR"}, {K_SNR, (char_u *)"SNR"},
{K_PLUG, (char_u *)"Plug"}, {K_PLUG, (char_u *)"Plug"},
{K_CURSORHOLD, (char_u *)"CursorHold"},
{K_PASTE, (char_u *)"Paste"}, {K_PASTE, (char_u *)"Paste"},
{0, NULL} {0, NULL}
}; };

View File

@ -242,7 +242,6 @@ enum key_extra {
, KE_X2RELEASE , KE_X2RELEASE
, KE_DROP /* DnD data is available */ , KE_DROP /* DnD data is available */
, KE_CURSORHOLD /* CursorHold event */
, KE_NOP /* doesn't do something */ , KE_NOP /* doesn't do something */
, KE_FOCUSGAINED /* focus gained */ , KE_FOCUSGAINED /* focus gained */
, KE_FOCUSLOST /* focus lost */ , KE_FOCUSLOST /* focus lost */
@ -437,7 +436,6 @@ enum key_extra {
#define K_FOCUSGAINED TERMCAP2KEY(KS_EXTRA, KE_FOCUSGAINED) #define K_FOCUSGAINED TERMCAP2KEY(KS_EXTRA, KE_FOCUSGAINED)
#define K_FOCUSLOST TERMCAP2KEY(KS_EXTRA, KE_FOCUSLOST) #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_EVENT TERMCAP2KEY(KS_EXTRA, KE_EVENT)
#define K_PASTE TERMCAP2KEY(KS_EXTRA, KE_PASTE) #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_SELECT, nv_select, 0, 0},
{K_F8, farsi_fkey, 0, 0}, {K_F8, farsi_fkey, 0, 0},
{K_F9, 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[]. */ /* Number of commands in nv_cmds[]. */
@ -492,8 +492,8 @@ static void normal_prepare(NormalState *s)
s->set_prevcount = true; s->set_prevcount = true;
} }
// Restore counts from before receiving K_CURSORHOLD. This means after // Restore counts from before receiving K_EVENT. This means after
// typing "3", handling K_CURSORHOLD and then typing "2" we get "32", not // typing "3", handling K_EVENT and then typing "2" we get "32", not
// "3 * 2". // "3 * 2".
if (s->oa.prev_opcount > 0 || s->oa.prev_count0 > 0) { if (s->oa.prev_opcount > 0 || s->oa.prev_count0 > 0) {
s->ca.opcount = s->oa.prev_opcount; 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 // 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_opcount = s->ca.opcount;
s->oa.prev_count0 = s->ca.count0; s->oa.prev_count0 = s->ca.count0;
} else if (s->ca.opcount != 0) { } else if (s->ca.opcount != 0) {
@ -891,7 +891,7 @@ getcount:
if (need_flushbuf) { if (need_flushbuf) {
ui_flush(); ui_flush();
} }
if (s->ca.cmdchar != K_IGNORE) { if (s->ca.cmdchar != K_IGNORE && s->ca.cmdchar != K_EVENT) {
did_cursorhold = false; did_cursorhold = false;
} }
@ -1022,7 +1022,7 @@ normal_end:
} }
if (s->oa.op_type == OP_NOP && s->oa.regname == 0 if (s->oa.op_type == OP_NOP && s->oa.regname == 0
&& s->ca.cmdchar != K_CURSORHOLD) { && s->ca.cmdchar != K_EVENT) {
clear_showcmd(); clear_showcmd();
} }
@ -3147,7 +3147,7 @@ bool add_to_showcmd(int c)
K_RIGHTMOUSE, K_RIGHTDRAG, K_RIGHTRELEASE, K_RIGHTMOUSE, K_RIGHTDRAG, K_RIGHTRELEASE,
K_MOUSEDOWN, K_MOUSEUP, K_MOUSELEFT, K_MOUSERIGHT, K_MOUSEDOWN, K_MOUSEUP, K_MOUSELEFT, K_MOUSERIGHT,
K_X1MOUSE, K_X1DRAG, K_X1RELEASE, K_X2MOUSE, K_X2DRAG, K_X2RELEASE, K_X1MOUSE, K_X1DRAG, K_X1RELEASE, K_X2MOUSE, K_X2DRAG, K_X2RELEASE,
K_CURSORHOLD, K_EVENT,
0 0
}; };
@ -7567,16 +7567,11 @@ static void nv_open(cmdarg_T *cap)
n_opencmd(cap); n_opencmd(cap);
} }
/* // Handle an arbitrary event in normal mode
* Trigger CursorHold event. static void nv_event(cmdarg_T *cap)
* 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)
{ {
apply_autocmds(EVENT_CURSORHOLD, NULL, NULL, false, curbuf); queue_process_events(loop.events);
did_cursorhold = true; cap->retval |= CA_COMMAND_BUSY; // don't call edit() now
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.toplevel = toplevel;
s.oa = *oap; s.oa = *oap;
normal_prepare(&s); normal_prepare(&s);
input_enable_events(); input_enable_events();
int c = safe_vgetc(); int c = safe_vgetc();
input_disable_events(); input_disable_events();
if (c == K_EVENT) {
queue_process_events(loop.events);
goto end;
}
(void)normal_execute(&s, c); (void)normal_execute(&s, c);
end:
*oap = s.oa; *oap = s.oa;
} }

View File

@ -36,8 +36,8 @@ typedef struct oparg_S {
bool block_mode; /* current operator is Visual block mode */ bool block_mode; /* current operator is Visual block mode */
colnr_T start_vcol; /* start col for block mode operator */ colnr_T start_vcol; /* start col for block mode operator */
colnr_T end_vcol; /* end 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_opcount; // ca.opcount saved for K_EVENT
long prev_count0; /* ca.count0 saved for K_CURSORHOLD */ long prev_count0; // ca.count0 saved for K_EVENT
} oparg_T; } oparg_T;
/* /*

View File

@ -73,6 +73,21 @@ void input_stop(void)
stream_close(&read_stream, NULL); 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 // Low level input function
int os_inchar(uint8_t *buf, int maxlen, int ms, int tb_change_cnt) 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 { } else {
if ((result = inbuf_poll((int)p_ut)) == kInputNone) { if ((result = inbuf_poll((int)p_ut)) == kInputNone) {
if (trigger_cursorhold() && maxlen >= 3 if (trigger_cursorhold() && !typebuf_changed(tb_change_cnt)) {
&& !typebuf_changed(tb_change_cnt)) { create_cursorhold_event();
buf[0] = K_SPECIAL; } else {
buf[1] = KS_EXTRA; before_blocking();
buf[2] = KE_CURSORHOLD; result = inbuf_poll(-1);
return 3;
} }
before_blocking();
result = inbuf_poll(-1);
} }
} }

View File

@ -247,33 +247,21 @@ describe('vim_* functions', function()
~ | ~ |
{1:very fail} | {1:very fail} |
]]) ]])
helpers.wait()
-- shows up to &cmdheight lines -- shows up to &cmdheight lines
nvim_async('err_write', 'more fail\n') nvim_async('err_write', 'more fail\ntoo fail\n')
nvim_async('err_write', 'too fail\n')
screen:expect([[ screen:expect([[
~ | ~ |
~ | ~ |
~ | ~ |
~ | ~ |
~ | ~ |
{1:very fail} |
{1:more 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} | {1:too fail} |
{2:Press ENTER or type command to continue}^ | {2:Press ENTER or type command to continue}^ |
]]) ]])
feed('<cr>') -- exit the press ENTER screen
end) end)
end) end)