From c4707e2803c26885d1938d320db5b368a221ffea Mon Sep 17 00:00:00 2001 From: Přemysl Eric Janouch
Date: Fri, 30 Sep 2022 17:16:16 +0200 Subject: xC/xP: send buffer input history during sync This transfer is currenly quite simplistic, but it paves the way for further extensions. --- xC.c | 70 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++- xC.lxdr | 4 ++++ xP/public/xP.js | 9 ++++++++ 3 files changed, 82 insertions(+), 1 deletion(-) diff --git a/xC.c b/xC.c index 5aadb17..3a7b8c1 100644 --- a/xC.c +++ b/xC.c @@ -231,6 +231,8 @@ struct input_vtable void (*buffer_destroy) (void *input, input_buffer_t buffer); /// Switch to a different input buffer void (*buffer_switch) (void *input, input_buffer_t buffer); + /// Return all history lines in the locale encoding + struct strv (*buffer_history) (void *input, input_buffer_t buffer); /// Register a function that can be bound to character sequences void (*register_fn) (void *input, @@ -258,7 +260,7 @@ struct input_vtable #define INPUT_VTABLE(XX) \ XX (start) XX (stop) XX (prepare) XX (destroy) \ XX (hide) XX (show) XX (get_prompt) XX (set_prompt) XX (ding) \ - XX (buffer_new) XX (buffer_destroy) XX (buffer_switch) \ + XX (buffer_new) XX (buffer_destroy) XX (buffer_switch) XX (buffer_history) \ XX (register_fn) XX (bind) XX (bind_control) XX (bind_meta) \ XX (get_line) XX (clear_line) XX (insert) \ XX (on_tty_resized) XX (on_tty_readable) @@ -584,6 +586,19 @@ input_rl_buffer_switch (void *input, input_buffer_t input_buffer) self->current = buffer; } +static struct strv +input_rl_buffer_history (void *input, input_buffer_t input_buffer) +{ + struct input_rl *self = input; + struct input_rl_buffer *buffer = input_buffer; + HIST_ENTRY **p = + buffer->history ? buffer->history->entries : history_list(); + struct strv v = strv_make (); + while (p && *p) + strv_append (&v, (*p++)->line); + return v; +} + static void input_rl__buffer_destroy_wo_history (struct input_rl_buffer *self) { @@ -1059,6 +1074,30 @@ input_el_buffer_switch (void *input, input_buffer_t input_buffer) input_el__restore_buffer (self, buffer); } +static struct strv +input_el_buffer_history (void *input, input_buffer_t input_buffer) +{ + struct input_el *self = input; + struct input_el_buffer *buffer = input_buffer; + struct strv v = strv_make (); + HistEventW ev; + if (history_w (buffer->history, &ev, H_LAST) < 0) + return v; + + do + { + size_t len = wcstombs (NULL, ev.str, 0); + if (len++ == (size_t) -1) + continue; + + char *mb = xmalloc (len); + mb[wcstombs (mb, ev.str, len)] = 0; + strv_append_owned (&v, mb); + } + while (history_w (buffer->history, &ev, H_PREV) >= 0); + return v; +} + static void input_el_buffer_destroy (void *input, input_buffer_t input_buffer) { @@ -3092,6 +3131,20 @@ relay_prepare_buffer_activate (struct app_context *ctx, struct buffer *buffer) e->buffer_name = str_from_cstr (buffer->name); } +static void +relay_prepare_buffer_input (struct app_context *ctx, struct buffer *buffer, + const char *locale_input) +{ + struct relay_event_message *m = relay_prepare (ctx); + struct relay_event_data_buffer_input *e = &m->data.buffer_input; + e->event = RELAY_EVENT_BUFFER_INPUT; + e->buffer_name = str_from_cstr (buffer->name); + char *input = iconv_xstrdup (ctx->term_to_utf8, + (char *) locale_input, -1, NULL); + e->text = str_from_cstr (input); + free (input); +} + static void relay_prepare_buffer_clear (struct app_context *ctx, struct buffer *buffer) @@ -15307,6 +15360,19 @@ init_poller_events (struct app_context *ctx) // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +static void +client_resync_buffer_input (struct client *c, struct buffer *buffer) +{ + struct strv history = + CALL_ (c->ctx->input, buffer_history, buffer->input_data); + for (size_t i = 0; i < history.len; i++) + { + relay_prepare_buffer_input (c->ctx, buffer, history.vector[i]); + relay_send (c); + } + strv_free (&history); +} + static void client_resync (struct client *c) { @@ -15325,6 +15391,8 @@ client_resync (struct client *c) relay_prepare_buffer_stats (c->ctx, buffer); relay_send (c); + client_resync_buffer_input (c, buffer); + LIST_FOR_EACH (struct buffer_line, line, buffer->lines) { relay_prepare_buffer_line (c->ctx, buffer, line, false); diff --git a/xC.lxdr b/xC.lxdr index 3057404..af0f170 100644 --- a/xC.lxdr +++ b/xC.lxdr @@ -59,6 +59,7 @@ struct EventMessage { BUFFER_RENAME, BUFFER_REMOVE, BUFFER_ACTIVATE, + BUFFER_INPUT, BUFFER_CLEAR, SERVER_UPDATE, SERVER_RENAME, @@ -153,6 +154,9 @@ struct EventMessage { string buffer_name; case BUFFER_ACTIVATE: string buffer_name; + case BUFFER_INPUT: + string buffer_name; + string text; case BUFFER_CLEAR: string buffer_name; diff --git a/xP/public/xP.js b/xP/public/xP.js index a7b7b11..795641d 100644 --- a/xP/public/xP.js +++ b/xP/public/xP.js @@ -387,6 +387,15 @@ rpcEventHandlers.set(Relay.Event.BufferActivate, e => { } }) +rpcEventHandlers.set(Relay.Event.BufferInput, e => { + let b = buffers.get(e.bufferName) + if (b === undefined) + return + if (b.historyAt == b.history.length) + b.historyAt++ + b.history.push(e.text) +}) + rpcEventHandlers.set(Relay.Event.BufferClear, e => { let b = buffers.get(e.bufferName) if (b !== undefined) -- cgit v1.2.3-70-g09d2