aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPřemysl Eric Janouch <p@janouch.name>2022-10-05 00:16:57 +0200
committerPřemysl Eric Janouch <p@janouch.name>2022-10-05 00:55:59 +0200
commit26ed2dbc77dea089f769180940d452353826eee7 (patch)
tree93fcd37e81f88975c786642976624a11f684906b
parent4b7258cba0dc71cfc7d3adef1b5dd7f9e610c28b (diff)
downloadxK-26ed2dbc77dea089f769180940d452353826eee7.tar.gz
xK-26ed2dbc77dea089f769180940d452353826eee7.tar.xz
xK-26ed2dbc77dea089f769180940d452353826eee7.zip
xC: fully synchronize input history with frontends
The missing parts were: - frontends to client - client to frontends after the initial sync - frontend to other frontends
-rw-r--r--xC.c116
1 files changed, 96 insertions, 20 deletions
diff --git a/xC.c b/xC.c
index dd4dc0c..200d159 100644
--- a/xC.c
+++ b/xC.c
@@ -228,11 +228,13 @@ struct input_vtable
/// Create a new input buffer
input_buffer_t (*buffer_new) (void *input);
/// Destroy an input buffer
- void (*buffer_destroy) (void *input, input_buffer_t buffer);
+ void (*buffer_destroy) (void *input, input_buffer_t);
/// Switch to a different input buffer
- void (*buffer_switch) (void *input, input_buffer_t buffer);
+ void (*buffer_switch) (void *input, input_buffer_t);
/// Return all history lines in the locale encoding
- struct strv (*buffer_history) (void *input, input_buffer_t buffer);
+ struct strv (*buffer_get_history) (void *input, input_buffer_t);
+ /// Add a history line in the locale encoding
+ void (*buffer_add_history) (void *input, input_buffer_t, const char *);
/// Register a function that can be bound to character sequences
void (*register_fn) (void *input,
@@ -260,7 +262,8 @@ 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_history) \
+ XX (buffer_new) XX (buffer_destroy) XX (buffer_switch) \
+ XX (buffer_get_history) XX (buffer_add_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)
@@ -564,6 +567,7 @@ input_rl_buffer_switch (void *input, input_buffer_t input_buffer)
{
struct input_rl *self = input;
struct input_rl_buffer *buffer = input_buffer;
+
// There could possibly be occurences of the current undo list in some
// history entry. We either need to free the undo list, or move it
// somewhere else to load back later, as the buffer we're switching to
@@ -587,8 +591,9 @@ input_rl_buffer_switch (void *input, input_buffer_t input_buffer)
}
static struct strv
-input_rl_buffer_history (void *input, input_buffer_t input_buffer)
+input_rl_buffer_get_history (void *input, input_buffer_t input_buffer)
{
+ (void) input;
struct input_rl_buffer *buffer = input_buffer;
HIST_ENTRY **p =
buffer->history ? buffer->history->entries : history_list();
@@ -599,6 +604,25 @@ input_rl_buffer_history (void *input, input_buffer_t input_buffer)
}
static void
+input_rl_buffer_add_history (void *input, input_buffer_t input_buffer,
+ const char *line)
+{
+ (void) input;
+ struct input_rl_buffer *buffer = input_buffer;
+
+ // For inactive buffers, we'd have to either alloc_history_entry(),
+ // construe a timestamp, and manually insert it into saved HISTORY_STATEs,
+ // or temporarily switch histories.
+ if (!buffer->history)
+ {
+ bool at_end = history_offset == history_length;
+ add_history (line);
+ if (at_end)
+ next_history ();
+ }
+}
+
+static void
input_rl__buffer_destroy_wo_history (struct input_rl_buffer *self)
{
free (self->history);
@@ -1069,13 +1093,15 @@ input_el_buffer_switch (void *input, input_buffer_t input_buffer)
self->current = buffer;
el_wset (self->editline, EL_HIST, history, buffer->history);
+ // We only know how to reset the history position to be at the end.
input_el__start_over (self);
input_el__restore_buffer (self, buffer);
}
static struct strv
-input_el_buffer_history (void *input, input_buffer_t input_buffer)
+input_el_buffer_get_history (void *input, input_buffer_t input_buffer)
{
+ (void) input;
struct input_el_buffer *buffer = input_buffer;
struct strv v = strv_make ();
HistEventW ev;
@@ -1097,6 +1123,26 @@ input_el_buffer_history (void *input, input_buffer_t input_buffer)
}
static void
+input_el_buffer_add_history (void *input, input_buffer_t input_buffer,
+ const char *line)
+{
+ (void) input;
+ struct input_el_buffer *buffer = input_buffer;
+
+ // When currently iterating history, this makes editline's internal
+ // history pointer wrongly point to a newer entry.
+ size_t len = mbstowcs (NULL, line, 0);
+ if (len++ != (size_t) -1)
+ {
+ wchar_t *wc = xcalloc (len, sizeof *wc);
+ wc[mbstowcs (wc, line, len)] = 0;
+ HistEventW ev;
+ (void) history_w (buffer->history, &ev, H_ENTER, wc);
+ free (wc);
+ }
+}
+
+static void
input_el_buffer_destroy (void *input, input_buffer_t input_buffer)
{
struct input_el *self = input;
@@ -2899,12 +2945,15 @@ relay_send (struct client *c)
}
static void
-relay_broadcast (struct app_context *ctx)
+relay_broadcast_except (struct app_context *ctx, struct client *exception)
{
LIST_FOR_EACH (struct client, c, ctx->clients)
- relay_send (c);
+ if (c != exception)
+ relay_send (c);
}
+#define relay_broadcast(ctx) relay_broadcast_except ((ctx), NULL)
+
static struct relay_event_message *
relay_prepare (struct app_context *ctx)
{
@@ -3131,16 +3180,13 @@ relay_prepare_buffer_activate (struct app_context *ctx, struct buffer *buffer)
static void
relay_prepare_buffer_input (struct app_context *ctx, struct buffer *buffer,
- const char *locale_input)
+ const char *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
@@ -15305,12 +15351,18 @@ on_pending_input (struct app_context *ctx)
poller_idle_reset (&ctx->input_event);
for (size_t i = 0; i < ctx->pending_input.len; i++)
{
- char *input = iconv_xstrdup
- (ctx->term_to_utf8, ctx->pending_input.vector[i], -1, NULL);
- if (input)
- process_input (ctx, ctx->current_buffer, input);
- else
+ char *input = iconv_xstrdup (ctx->term_to_utf8,
+ ctx->pending_input.vector[i], -1, NULL);
+ if (!input)
+ {
print_error ("character conversion failed for: %s", "user input");
+ continue;
+ }
+
+ relay_prepare_buffer_input (ctx, ctx->current_buffer, input);
+ relay_broadcast (ctx);
+
+ process_input (ctx, ctx->current_buffer, input);
free (input);
}
strv_reset (&ctx->pending_input);
@@ -15362,11 +15414,21 @@ static void
client_resync_buffer_input (struct client *c, struct buffer *buffer)
{
struct strv history =
- CALL_ (c->ctx->input, buffer_history, buffer->input_data);
+ CALL_ (c->ctx->input, buffer_get_history, buffer->input_data);
for (size_t i = 0; i < history.len; i++)
{
- relay_prepare_buffer_input (c->ctx, buffer, history.vector[i]);
+ char *input = iconv_xstrdup (c->ctx->term_to_utf8,
+ history.vector[i], -1, NULL);
+ if (!input)
+ {
+ print_error ("character conversion failed for: %s",
+ "user input history");
+ continue;
+ }
+
+ relay_prepare_buffer_input (c->ctx, buffer, input);
relay_send (c);
+ free (input);
}
strv_free (&history);
}
@@ -15463,6 +15525,20 @@ out:
}
static void
+client_process_buffer_input
+ (struct client *c, struct buffer *buffer, const char *input)
+{
+ char *mb = iconv_xstrdup (c->ctx->term_from_utf8, (char *) input, -1, NULL);
+ CALL_ (c->ctx->input, buffer_add_history, buffer->input_data, mb);
+ free (mb);
+
+ relay_prepare_buffer_input (c->ctx, buffer, input);
+ relay_broadcast_except (c->ctx, c);
+
+ process_input (c->ctx, buffer, input);
+}
+
+static void
client_process_buffer_log
(struct client *c, uint32_t seq, struct buffer *buffer)
{
@@ -15544,7 +15620,7 @@ client_process_message (struct client *c,
buffer_activate (c->ctx, buffer);
break;
case RELAY_COMMAND_BUFFER_INPUT:
- process_input (c->ctx, buffer, m->data.buffer_input.text.str);
+ client_process_buffer_input (c, buffer, m->data.buffer_input.text.str);
break;
case RELAY_COMMAND_BUFFER_TOGGLE_UNIMPORTANT:
buffer_toggle_unimportant (c->ctx, buffer);