xC: use the correct way of resetting libedit

The only remaining major annoyance is incremental search
seemingly not giving back control.
This commit is contained in:
Přemysl Eric Janouch 2022-08-29 10:29:49 +02:00
parent dbe95fa298
commit 91db8e6e54
Signed by: p
GPG Key ID: A0420B94F92B9493
1 changed files with 13 additions and 38 deletions

51
xC.c
View File

@ -761,7 +761,6 @@ struct input_el
{
struct input super; ///< Parent class
EditLine *editline; ///< The EditLine object
FILE *null; ///< Output redirect
bool active; ///< Are we a thing?
char *prompt; ///< The prompt we use
@ -1027,39 +1026,16 @@ input_el__restore (struct input_el *self)
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// XXX: Editline keeping its own history position (look for "eventno" there).
// Invoking ed-next-history through our bind from app_editline_init() seems
// like the only viable hack to get consistent history behaviour.
// Editline keeping its own history position (look for "eventno" there).
// This is the only sane way of resetting it.
static void
input_el__bottom (struct input_el *self)
input_el__start_over (struct input_el *self)
{
// First, we need to redirect output to avoid ringing the terminal bell.
// Assuming that the line has just been erased but not redisplayed
// by caller, we need to CC_REFRESH first.
input_el__redisplay (self);
wchar_t x[] = { L'g' & 31, 0 };
el_wpush (self->editline, x);
FILE *out = NULL;
el_wget (self->editline, EL_GETFP, 1, &out);
el_wset (self->editline, EL_SETFP, 1, self->null);
// Invoke hist_get() to make the history pointer's cursor match "eventno".
int down = 1, dummy_count = 0;
el_wpush (self->editline, L"\x1bn");
int dummy_count = 0;
(void) el_wgets (self->editline, &dummy_count);
// It doesn't seem like we can just retrieve the position.
HistEventW ev;
while (!history_w (self->current->history, &ev, H_PREV))
down++;
while (down--)
{
el_wpush (self->editline, L"\x1bn");
(void) el_wgets (self->editline, &dummy_count);
}
// Otherwise input may survive our erasing, reproducer: a^Rb^[^N
input_el_clear_line (self);
el_wset (self->editline, EL_SETFP, 1, out);
}
static void
@ -1075,7 +1051,7 @@ input_el_buffer_switch (void *input, input_buffer_t input_buffer)
self->current = buffer;
el_wset (self->editline, EL_HIST, history, buffer->history);
input_el__bottom (self);
input_el__start_over (self);
input_el__restore_buffer (self, buffer);
}
@ -1170,7 +1146,6 @@ input_el_destroy (void *input)
free (iter->help);
ffi_closure_free (iter);
}
fclose (self->null);
free (self->prompt);
free (self);
}
@ -1184,7 +1159,6 @@ input_el_new (void)
{
struct input_el *self = xcalloc (1, sizeof *self);
self->super.vtable = &input_el_vtable;
self->null = fopen ("/dev/null", "w");
return &self->super;
}
@ -13947,8 +13921,6 @@ on_editline_return (EditLine *editline, int key)
const LineInfoW *info = el_wline (editline);
int len = info->lastchar - info->buffer;
int point = info->cursor - info->buffer;
wchar_t *line = calloc (sizeof *info->buffer, len + 1);
memcpy (line, info->buffer, sizeof *info->buffer * len);
@ -13965,9 +13937,8 @@ on_editline_return (EditLine *editline, int key)
xstrndup (info_mb->buffer, info_mb->lastchar - info_mb->buffer));
poller_idle_set (&ctx->input_event);
el_cursor (editline, len - point);
el_wdeletestr (editline, len);
input_el__bottom (self);
// We must invoke ch_reset(), which isn't done for us with EL_UNBUFFERED.
input_el__start_over (self);
return CC_REFRESH;
}
@ -13992,8 +13963,12 @@ app_editline_init (struct input_el *self)
CALL_ (input, bind_control, 'w', "ed-delete-prev-word");
// Just what are you doing?
CALL_ (input, bind_control, 'u', "vi-kill-line-prev");
// See input_el__redisplay(), functionally important
CALL_ (input, bind_control, 'q', "ed-redisplay");
// This is what buffered el_wgets() does, functionally important;
// perhaps it could be bound somewhere more appropriate
CALL_ (input, bind_control, 'g', "ed-start-over");
// We need to hide the prompt and input first
CALL_ (input, bind, "\r", "send-line");