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
|
/// Create a new input buffer
|
||||||
input_buffer_t (*buffer_new) (void *input);
|
input_buffer_t (*buffer_new) (void *input);
|
||||||
/// Destroy an input buffer
|
/// 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
|
/// 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
|
/// 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
|
/// Register a function that can be bound to character sequences
|
||||||
void (*register_fn) (void *input,
|
void (*register_fn) (void *input,
|
||||||
|
@ -260,7 +262,8 @@ struct input_vtable
|
||||||
#define INPUT_VTABLE(XX) \
|
#define INPUT_VTABLE(XX) \
|
||||||
XX (start) XX (stop) XX (prepare) XX (destroy) \
|
XX (start) XX (stop) XX (prepare) XX (destroy) \
|
||||||
XX (hide) XX (show) XX (get_prompt) XX (set_prompt) XX (ding) \
|
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 (register_fn) XX (bind) XX (bind_control) XX (bind_meta) \
|
||||||
XX (get_line) XX (clear_line) XX (insert) \
|
XX (get_line) XX (clear_line) XX (insert) \
|
||||||
XX (on_tty_resized) XX (on_tty_readable)
|
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 *self = input;
|
||||||
struct input_rl_buffer *buffer = input_buffer;
|
struct input_rl_buffer *buffer = input_buffer;
|
||||||
|
|
||||||
// There could possibly be occurences of the current undo list in some
|
// 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
|
// 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
|
// 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
|
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;
|
struct input_rl_buffer *buffer = input_buffer;
|
||||||
HIST_ENTRY **p =
|
HIST_ENTRY **p =
|
||||||
buffer->history ? buffer->history->entries : history_list();
|
buffer->history ? buffer->history->entries : history_list();
|
||||||
|
@ -598,6 +603,25 @@ input_rl_buffer_history (void *input, input_buffer_t input_buffer)
|
||||||
return v;
|
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
|
static void
|
||||||
input_rl__buffer_destroy_wo_history (struct input_rl_buffer *self)
|
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;
|
self->current = buffer;
|
||||||
el_wset (self->editline, EL_HIST, history, buffer->history);
|
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__start_over (self);
|
||||||
input_el__restore_buffer (self, buffer);
|
input_el__restore_buffer (self, buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct strv
|
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 input_el_buffer *buffer = input_buffer;
|
||||||
struct strv v = strv_make ();
|
struct strv v = strv_make ();
|
||||||
HistEventW ev;
|
HistEventW ev;
|
||||||
|
@ -1096,6 +1122,26 @@ input_el_buffer_history (void *input, input_buffer_t input_buffer)
|
||||||
return v;
|
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
|
static void
|
||||||
input_el_buffer_destroy (void *input, input_buffer_t input_buffer)
|
input_el_buffer_destroy (void *input, input_buffer_t input_buffer)
|
||||||
{
|
{
|
||||||
|
@ -2899,12 +2945,15 @@ relay_send (struct client *c)
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
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)
|
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 *
|
static struct relay_event_message *
|
||||||
relay_prepare (struct app_context *ctx)
|
relay_prepare (struct app_context *ctx)
|
||||||
{
|
{
|
||||||
|
@ -3131,16 +3180,13 @@ relay_prepare_buffer_activate (struct app_context *ctx, struct buffer *buffer)
|
||||||
|
|
||||||
static void
|
static void
|
||||||
relay_prepare_buffer_input (struct app_context *ctx, struct buffer *buffer,
|
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_message *m = relay_prepare (ctx);
|
||||||
struct relay_event_data_buffer_input *e = &m->data.buffer_input;
|
struct relay_event_data_buffer_input *e = &m->data.buffer_input;
|
||||||
e->event = RELAY_EVENT_BUFFER_INPUT;
|
e->event = RELAY_EVENT_BUFFER_INPUT;
|
||||||
e->buffer_name = str_from_cstr (buffer->name);
|
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);
|
e->text = str_from_cstr (input);
|
||||||
free (input);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -15305,12 +15351,18 @@ on_pending_input (struct app_context *ctx)
|
||||||
poller_idle_reset (&ctx->input_event);
|
poller_idle_reset (&ctx->input_event);
|
||||||
for (size_t i = 0; i < ctx->pending_input.len; i++)
|
for (size_t i = 0; i < ctx->pending_input.len; i++)
|
||||||
{
|
{
|
||||||
char *input = iconv_xstrdup
|
char *input = iconv_xstrdup (ctx->term_to_utf8,
|
||||||
(ctx->term_to_utf8, ctx->pending_input.vector[i], -1, NULL);
|
ctx->pending_input.vector[i], -1, NULL);
|
||||||
if (input)
|
if (!input)
|
||||||
process_input (ctx, ctx->current_buffer, input);
|
{
|
||||||
else
|
|
||||||
print_error ("character conversion failed for: %s", "user 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);
|
free (input);
|
||||||
}
|
}
|
||||||
strv_reset (&ctx->pending_input);
|
strv_reset (&ctx->pending_input);
|
||||||
|
@ -15362,11 +15414,21 @@ static void
|
||||||
client_resync_buffer_input (struct client *c, struct buffer *buffer)
|
client_resync_buffer_input (struct client *c, struct buffer *buffer)
|
||||||
{
|
{
|
||||||
struct strv history =
|
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++)
|
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);
|
relay_send (c);
|
||||||
|
free (input);
|
||||||
}
|
}
|
||||||
strv_free (&history);
|
strv_free (&history);
|
||||||
}
|
}
|
||||||
|
@ -15462,6 +15524,20 @@ out:
|
||||||
relay_send (c);
|
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
|
static void
|
||||||
client_process_buffer_log
|
client_process_buffer_log
|
||||||
(struct client *c, uint32_t seq, struct buffer *buffer)
|
(struct client *c, uint32_t seq, struct buffer *buffer)
|
||||||
|
@ -15544,7 +15620,7 @@ client_process_message (struct client *c,
|
||||||
buffer_activate (c->ctx, buffer);
|
buffer_activate (c->ctx, buffer);
|
||||||
break;
|
break;
|
||||||
case RELAY_COMMAND_BUFFER_INPUT:
|
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;
|
break;
|
||||||
case RELAY_COMMAND_BUFFER_TOGGLE_UNIMPORTANT:
|
case RELAY_COMMAND_BUFFER_TOGGLE_UNIMPORTANT:
|
||||||
buffer_toggle_unimportant (c->ctx, buffer);
|
buffer_toggle_unimportant (c->ctx, buffer);
|
||||||
|
|
Loading…
Reference in New Issue