xC: normalize BSD Editline's history behaviour
Now it's a realistically useful frontend.
This commit is contained in:
parent
03d8ea4c5a
commit
c0996fcbe7
2
NEWS
2
NEWS
@ -8,6 +8,8 @@ Unreleased
|
||||
|
||||
* xC: improved pager integration capabilities
|
||||
|
||||
* xC: normalized editline's history behaviour, making it a viable frontend
|
||||
|
||||
* xC: made it show WALLOPS messages, as PRIVMSG for the server buffer
|
||||
|
||||
* xD: implemented WALLOPS, choosing to make it target even non-operators
|
||||
|
@ -77,9 +77,6 @@ Runtime dependencies: openssl +
|
||||
Additionally for 'xC': curses, libffi, lua >= 5.3 (optional),
|
||||
readline >= 6.0 or libedit >= 2013-07-12
|
||||
|
||||
Avoid libedit if you can, in general it works but at the moment history is
|
||||
acting up and I have no clue about fixing it.
|
||||
|
||||
$ git clone --recursive https://git.janouch.name/p/xK.git
|
||||
$ mkdir xK/build
|
||||
$ cd xK/build
|
||||
|
3
xC.adoc
3
xC.adoc
@ -114,8 +114,7 @@ _/usr/share/xC/plugins/_::
|
||||
|
||||
Bugs
|
||||
----
|
||||
The editline (libedit) frontend is more of a proof of concept that mostly seems
|
||||
to work but exhibits bugs that are not our fault.
|
||||
The editline (libedit) frontend may exhibit some unexpected behaviour.
|
||||
|
||||
Reporting bugs
|
||||
--------------
|
||||
|
53
xC.c
53
xC.c
@ -761,6 +761,7 @@ 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
|
||||
@ -778,12 +779,12 @@ input_el__redisplay (void *input)
|
||||
// See rl_redisplay(), however NetBSD editline's map.c v1.54 breaks VREPRINT
|
||||
// so we bind redisplay somewhere else in app_editline_init()
|
||||
struct input_el *self = input;
|
||||
char x[] = { 'q' & 31, 0 };
|
||||
el_push (self->editline, x);
|
||||
wchar_t x[] = { L'q' & 31, 0 };
|
||||
el_wpush (self->editline, x);
|
||||
|
||||
// We have to do this or it gets stuck and nothing is done
|
||||
int count = 0;
|
||||
(void) el_wgets (self->editline, &count);
|
||||
int dummy_count = 0;
|
||||
(void) el_wgets (self->editline, &dummy_count);
|
||||
}
|
||||
|
||||
static char *
|
||||
@ -1026,18 +1027,50 @@ 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.
|
||||
static void
|
||||
input_el__bottom (struct input_el *self)
|
||||
{
|
||||
// First, we need to redirect output to avoid ringing the terminal bell.
|
||||
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");
|
||||
(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);
|
||||
}
|
||||
|
||||
el_wset (self->editline, EL_SETFP, 1, out);
|
||||
}
|
||||
|
||||
static void
|
||||
input_el_buffer_switch (void *input, input_buffer_t input_buffer)
|
||||
{
|
||||
struct input_el *self = input;
|
||||
struct input_el_buffer *buffer = input_buffer;
|
||||
if (!self->active)
|
||||
return;
|
||||
|
||||
if (self->current)
|
||||
input_el__save_buffer (self, self->current);
|
||||
|
||||
input_el__restore_buffer (self, buffer);
|
||||
el_wset (self->editline, EL_HIST, history, buffer->history);
|
||||
self->current = buffer;
|
||||
el_wset (self->editline, EL_HIST, history, buffer->history);
|
||||
input_el__bottom (self);
|
||||
input_el__restore_buffer (self, buffer);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -1111,7 +1144,7 @@ input_el_on_tty_readable (void *input)
|
||||
if (!buf || count-- <= 0)
|
||||
return;
|
||||
|
||||
if (count == 0 && buf[0] == ('D' - 0x40) /* hardcoded VEOF in editline */)
|
||||
if (count == 0 && buf[0] == ('D' - 0x40) /* hardcoded VEOF in el_wgets() */)
|
||||
{
|
||||
el_deletestr (self->editline, 1);
|
||||
input_el__redisplay (self);
|
||||
@ -1131,6 +1164,7 @@ input_el_destroy (void *input)
|
||||
free (iter->help);
|
||||
ffi_closure_free (iter);
|
||||
}
|
||||
fclose (self->null);
|
||||
free (self->prompt);
|
||||
free (self);
|
||||
}
|
||||
@ -1144,6 +1178,7 @@ 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;
|
||||
}
|
||||
|
||||
@ -13908,13 +13943,10 @@ on_editline_return (EditLine *editline, int key)
|
||||
wchar_t *line = calloc (sizeof *info->buffer, len + 1);
|
||||
memcpy (line, info->buffer, sizeof *info->buffer * len);
|
||||
|
||||
// XXX: Editline seems to remember its position in history,
|
||||
// so it's not going to work as you'd expect it to
|
||||
if (*line)
|
||||
{
|
||||
HistEventW ev;
|
||||
history_w (self->current->history, &ev, H_ENTER, line);
|
||||
print_debug ("history: %d %ls", ev.num, ev.str);
|
||||
}
|
||||
free (line);
|
||||
|
||||
@ -13926,6 +13958,7 @@ on_editline_return (EditLine *editline, int key)
|
||||
|
||||
el_cursor (editline, len - point);
|
||||
el_wdeletestr (editline, len);
|
||||
input_el__bottom (self);
|
||||
return CC_REFRESH;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user