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
This commit is contained in:
parent
4b7258cba0
commit
26ed2dbc77
116
xC.c
116
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();
|
||||
@ -598,6 +603,25 @@ input_rl_buffer_history (void *input, input_buffer_t input_buffer)
|
||||
return v;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
@ -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;
|
||||
@ -1096,6 +1122,26 @@ input_el_buffer_history (void *input, input_buffer_t input_buffer)
|
||||
return v;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
@ -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);
|
||||
}
|
||||
@ -15462,6 +15524,20 @@ out:
|
||||
relay_send (c);
|
||||
}
|
||||
|
||||
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);
|
||||
|
Loading…
Reference in New Issue
Block a user