diff options
author | Thiago de Arruda <tpadilha84@gmail.com> | 2014-04-07 16:37:14 -0300 |
---|---|---|
committer | Thiago de Arruda <tpadilha84@gmail.com> | 2014-04-08 14:17:18 -0300 |
commit | fe38baed3830415bc16b7e6c718a80ebe0c29fff (patch) | |
tree | f100e84d8bd64a28daa7c3cc3e145d6949109b1b /src | |
parent | 1fc7d6a0c514257cee9fb204cb83564b17354c11 (diff) | |
download | rneovim-fe38baed3830415bc16b7e6c718a80ebe0c29fff.tar.gz rneovim-fe38baed3830415bc16b7e6c718a80ebe0c29fff.tar.bz2 rneovim-fe38baed3830415bc16b7e6c718a80ebe0c29fff.zip |
Define special key for asynchronous events
K_EVENT/KE_EVENT are used to signal any loop that reads user input(scattered
across normal.c edit.c , ex_getln.c and message.c) of asynchronous events that
were not initiated by the user.
Representing non-user asynchronous events as special keys has the following
advantages:
- We reuse the normal vim redrawing code. As far as the rest of the code in
edit.c/normal.c is concerned, it's just the user pressing another key.
- Assume less about vim tolerance for "out-of-band" modifications to its
internal state.
- We still have a very complex codebase and it's hard to predict what bugs may
be introduced by these changes. With this we implement asynchronicity in a way
that will be more "natural" to the editor and has less chance of causing
unpredictable behavior.
As the code is refactored, we will be able to treat user input as an 'event
type' and not the other way around(With this we are treating arbitrary events as
a special case of user input).
Diffstat (limited to 'src')
-rw-r--r-- | src/edit.c | 5 | ||||
-rw-r--r-- | src/ex_getln.c | 13 | ||||
-rw-r--r-- | src/getchar.c | 15 | ||||
-rw-r--r-- | src/keymap.h | 2 | ||||
-rw-r--r-- | src/message.c | 4 | ||||
-rw-r--r-- | src/normal.c | 8 | ||||
-rw-r--r-- | src/os/event.c | 94 | ||||
-rw-r--r-- | src/os/event.h | 2 | ||||
-rw-r--r-- | src/os/input.c | 20 | ||||
-rw-r--r-- | src/os/job.c | 1 |
10 files changed, 86 insertions, 78 deletions
diff --git a/src/edit.c b/src/edit.c index fcb45209cd..4a17c9aa44 100644 --- a/src/edit.c +++ b/src/edit.c @@ -52,6 +52,7 @@ #include "ui.h" #include "undo.h" #include "window.h" +#include "os/event.h" /* * definitions used for CTRL-X submode @@ -1025,7 +1026,9 @@ doESCkey: did_cursorhold = TRUE; break; - + case K_EVENT: + event_process(); + break; case K_HOME: /* <Home> */ case K_KHOME: diff --git a/src/ex_getln.c b/src/ex_getln.c index 498d53904c..51c596e1ce 100644 --- a/src/ex_getln.c +++ b/src/ex_getln.c @@ -56,6 +56,7 @@ #include "window.h" #include "ui.h" #include "os/os.h" +#include "os/event.h" /* * Variables shared between getcmdline(), redrawcmdline() and others. @@ -788,6 +789,11 @@ getcmdline ( * Big switch for a typed command line character. */ switch (c) { + case K_EVENT: + event_process(); + // Force a redraw even though the command line didn't change + shell_resized(); + goto cmdline_not_changed; case K_BS: case Ctrl_H: case K_DEL: @@ -1904,9 +1910,12 @@ redraw: continue; } - /* Ignore special key codes: mouse movement, K_IGNORE, etc. */ - if (IS_SPECIAL(c1)) + if (IS_SPECIAL(c1)) { + // Process pending events + event_process(); + // Ignore other special key codes continue; + } } if (IS_SPECIAL(c1)) diff --git a/src/getchar.c b/src/getchar.c index 93f896e1c3..736d72aa6b 100644 --- a/src/getchar.c +++ b/src/getchar.c @@ -164,6 +164,7 @@ static void map_free(mapblock_T **); static void validate_maphash(void); static void showmap(mapblock_T *mp, int local); static char_u *eval_map_expr(char_u *str, int c); +static bool is_user_input(int k); /* * Free and clear a buffer. @@ -2552,11 +2553,10 @@ fix_input_buffer ( * Don't replace K_SPECIAL when reading a script file. */ for (i = len; --i >= 0; ++p) { - if (p[0] == NUL || (p[0] == K_SPECIAL && !script - /* timeout may generate K_CURSORHOLD */ - && (i < 2 || p[1] != KS_EXTRA || p[2] != - (int)KE_CURSORHOLD) - )) { + if (p[0] == NUL + || (p[0] == K_SPECIAL + && !script + && (i < 2 || p[1] != KS_EXTRA || is_user_input(p[2])))) { memmove(p + 3, p + 1, (size_t)i); p[2] = K_THIRD(p[0]); p[1] = K_SECOND(p[0]); @@ -3816,6 +3816,11 @@ eval_map_expr ( return res; } +static bool is_user_input(int k) +{ + return k != (int)KE_EVENT && k != (int)KE_CURSORHOLD; +} + /* * Copy "p" to allocated memory, escaping K_SPECIAL and CSI so that the result * can be put in the typeahead buffer. diff --git a/src/keymap.h b/src/keymap.h index dd9138e05b..a08eb300a9 100644 --- a/src/keymap.h +++ b/src/keymap.h @@ -270,6 +270,7 @@ enum key_extra { , KE_NOP /* doesn't do something */ , KE_FOCUSGAINED /* focus gained */ , KE_FOCUSLOST /* focus lost */ + , KE_EVENT // event }; /* @@ -467,6 +468,7 @@ enum key_extra { #define K_FOCUSLOST TERMCAP2KEY(KS_EXTRA, KE_FOCUSLOST) #define K_CURSORHOLD TERMCAP2KEY(KS_EXTRA, KE_CURSORHOLD) +#define K_EVENT TERMCAP2KEY(KS_EXTRA, KE_EVENT) /* Bits for modifier mask */ /* 0x01 cannot be used, because the modifier must be 0x02 or higher */ diff --git a/src/message.c b/src/message.c index 57942de2c6..6553e0bd5f 100644 --- a/src/message.c +++ b/src/message.c @@ -35,6 +35,7 @@ #include "term.h" #include "ui.h" #include "os/os.h" +#include "os/event.h" #if defined(FEAT_FLOAT) # include <math.h> @@ -2094,6 +2095,9 @@ static int do_more_prompt(int typed_char) toscroll = 0; switch (c) { + case K_EVENT: + event_process(); + break; case BS: /* scroll one line back */ case K_BS: case 'k': diff --git a/src/normal.c b/src/normal.c index 27428d5dd0..cafb73cac6 100644 --- a/src/normal.c +++ b/src/normal.c @@ -54,6 +54,7 @@ #include "ui.h" #include "undo.h" #include "window.h" +#include "os/event.h" /* * The Visual area is remembered for reselection. @@ -177,6 +178,7 @@ static void nv_join(cmdarg_T *cap); static void nv_put(cmdarg_T *cap); static void nv_open(cmdarg_T *cap); static void nv_cursorhold(cmdarg_T *cap); +static void nv_event(cmdarg_T *cap); static char *e_noident = N_("E349: No identifier under cursor"); @@ -409,6 +411,7 @@ static const struct nv_cmd { {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[]. */ @@ -7485,3 +7488,8 @@ static void nv_cursorhold(cmdarg_T *cap) did_cursorhold = TRUE; cap->retval |= CA_COMMAND_BUSY; /* don't call edit() now */ } + +static void nv_event(cmdarg_T *cap) +{ + event_process(); +} diff --git a/src/os/event.c b/src/os/event.c index fb3fffc35a..7fc374e40e 100644 --- a/src/os/event.c +++ b/src/os/event.c @@ -20,8 +20,6 @@ KLIST_INIT(Event, Event, _destroy_event) static klist_t(Event) *event_queue; static uv_timer_t timer; static uv_prepare_t timer_prepare; -static bool poll_uv_loop(int ms); -static void process_all_events(void); static void timer_cb(uv_timer_t *handle, int); static void timer_prepare_cb(uv_prepare_t *, int); @@ -42,66 +40,8 @@ void event_init() uv_prepare_init(uv_default_loop(), &timer_prepare); } -bool event_poll(int32_t ms) -{ - int64_t remaining = ms; - uint64_t end; - bool result; - - if (ms > 0) { - // Calculate end time in nanoseconds - end = uv_hrtime() + ms * 1e6; - } - - for (;;) { - result = poll_uv_loop((int32_t)remaining); - // Process queued events - process_all_events(); - - if (ms > 0) { - // Calculate remaining time in milliseconds - remaining = (end - uv_hrtime()) / 1e6; - } - - if (input_ready() || got_int) { - // Bail out if we have pending input - return true; - } - - if (!result || (ms >= 0 && remaining <= 0)) { - // Or if we timed out - return false; - } - } -} - -// Push an event to the queue -void event_push(Event event) -{ - *kl_pushp(Event, event_queue) = event; -} - -// Runs the appropriate action for each queued event -static void process_all_events() -{ - Event event; - - while (kl_shift(Event, event_queue, &event) == 0) { - switch (event.type) { - case kEventSignal: - signal_handle(event); - break; - case kEventJobActivity: - job_handle(event); - break; - default: - abort(); - } - } -} - // Wait for some event -static bool poll_uv_loop(int32_t ms) +bool event_poll(int32_t ms) { bool timed_out; uv_run_mode run_mode = UV_RUN_ONCE; @@ -145,7 +85,37 @@ static bool poll_uv_loop(int32_t ms) uv_timer_stop(&timer); } - return input_ready() || !kl_empty(event_queue); + return input_ready() || event_is_pending(); +} + +bool event_is_pending() +{ + return !kl_empty(event_queue); +} + +// Push an event to the queue +void event_push(Event event) +{ + *kl_pushp(Event, event_queue) = event; +} + +// Runs the appropriate action for each queued event +void event_process() +{ + Event event; + + while (kl_shift(Event, event_queue, &event) == 0) { + switch (event.type) { + case kEventSignal: + signal_handle(event); + break; + case kEventJobActivity: + job_handle(event); + break; + default: + abort(); + } + } } // Set a flag in the `event_poll` loop for signaling of a timeout diff --git a/src/os/event.h b/src/os/event.h index 7aee717213..93dc96d55e 100644 --- a/src/os/event.h +++ b/src/os/event.h @@ -9,7 +9,9 @@ void event_init(void); bool event_poll(int32_t ms); +bool event_is_pending(void); void event_push(Event event); +void event_process(void); #endif // NEOVIM_OS_EVENT_H diff --git a/src/os/input.c b/src/os/input.c index 122600630d..ce1dd69fc0 100644 --- a/src/os/input.c +++ b/src/os/input.c @@ -145,9 +145,18 @@ int os_inchar(char_u *buf, int maxlen, int32_t ms, int tb_change_cnt) } } + // If there are pending events, return the keys directly + if (maxlen >= 3 && event_is_pending()) { + buf[0] = K_SPECIAL; + buf[1] = KS_EXTRA; + buf[2] = KE_EVENT; + return 3; + } + // If input was put directly in typeahead buffer bail out here. - if (typebuf_changed(tb_change_cnt)) + if (typebuf_changed(tb_change_cnt)) { return 0; + } if (result == kInputEof) { read_error_exit(); @@ -174,15 +183,12 @@ void os_breakcheck() // This is a replacement for the old `WaitForChar` function in os_unix.c static InbufPollResult inbuf_poll(int32_t ms) { - if (input_available()) + if (input_available()) { return kInputAvail; + } if (event_poll(ms)) { - if (!got_int && rbuffer.rpos == rbuffer.wpos && eof) { - return kInputEof; - } - - return kInputAvail; + return eof && rbuffer.rpos == rbuffer.wpos ? kInputEof : kInputAvail; } return kInputNone; diff --git a/src/os/job.c b/src/os/job.c index 8a02de35b7..08e8164015 100644 --- a/src/os/job.c +++ b/src/os/job.c @@ -228,7 +228,6 @@ void job_handle(Event event) job->length, job->lock == kBufferLockStdout); - shell_resized(); // restart reading job->lock = kBufferLockNone; uv_read_start((uv_stream_t *)&job->proc_stdout, alloc_cb, read_cb); |