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: 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
|
* xC: made it show WALLOPS messages, as PRIVMSG for the server buffer
|
||||||
|
|
||||||
* xD: implemented WALLOPS, choosing to make it target even non-operators
|
* 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),
|
Additionally for 'xC': curses, libffi, lua >= 5.3 (optional),
|
||||||
readline >= 6.0 or libedit >= 2013-07-12
|
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
|
$ git clone --recursive https://git.janouch.name/p/xK.git
|
||||||
$ mkdir xK/build
|
$ mkdir xK/build
|
||||||
$ cd xK/build
|
$ cd xK/build
|
||||||
|
|
3
xC.adoc
3
xC.adoc
|
@ -114,8 +114,7 @@ _/usr/share/xC/plugins/_::
|
||||||
|
|
||||||
Bugs
|
Bugs
|
||||||
----
|
----
|
||||||
The editline (libedit) frontend is more of a proof of concept that mostly seems
|
The editline (libedit) frontend may exhibit some unexpected behaviour.
|
||||||
to work but exhibits bugs that are not our fault.
|
|
||||||
|
|
||||||
Reporting bugs
|
Reporting bugs
|
||||||
--------------
|
--------------
|
||||||
|
|
53
xC.c
53
xC.c
|
@ -761,6 +761,7 @@ struct input_el
|
||||||
{
|
{
|
||||||
struct input super; ///< Parent class
|
struct input super; ///< Parent class
|
||||||
EditLine *editline; ///< The EditLine object
|
EditLine *editline; ///< The EditLine object
|
||||||
|
FILE *null; ///< Output redirect
|
||||||
|
|
||||||
bool active; ///< Are we a thing?
|
bool active; ///< Are we a thing?
|
||||||
char *prompt; ///< The prompt we use
|
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
|
// See rl_redisplay(), however NetBSD editline's map.c v1.54 breaks VREPRINT
|
||||||
// so we bind redisplay somewhere else in app_editline_init()
|
// so we bind redisplay somewhere else in app_editline_init()
|
||||||
struct input_el *self = input;
|
struct input_el *self = input;
|
||||||
char x[] = { 'q' & 31, 0 };
|
wchar_t x[] = { L'q' & 31, 0 };
|
||||||
el_push (self->editline, x);
|
el_wpush (self->editline, x);
|
||||||
|
|
||||||
// We have to do this or it gets stuck and nothing is done
|
// We have to do this or it gets stuck and nothing is done
|
||||||
int count = 0;
|
int dummy_count = 0;
|
||||||
(void) el_wgets (self->editline, &count);
|
(void) el_wgets (self->editline, &dummy_count);
|
||||||
}
|
}
|
||||||
|
|
||||||
static char *
|
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
|
static void
|
||||||
input_el_buffer_switch (void *input, input_buffer_t input_buffer)
|
input_el_buffer_switch (void *input, input_buffer_t input_buffer)
|
||||||
{
|
{
|
||||||
struct input_el *self = input;
|
struct input_el *self = input;
|
||||||
struct input_el_buffer *buffer = input_buffer;
|
struct input_el_buffer *buffer = input_buffer;
|
||||||
|
if (!self->active)
|
||||||
|
return;
|
||||||
|
|
||||||
if (self->current)
|
if (self->current)
|
||||||
input_el__save_buffer (self, 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;
|
self->current = buffer;
|
||||||
|
el_wset (self->editline, EL_HIST, history, buffer->history);
|
||||||
|
input_el__bottom (self);
|
||||||
|
input_el__restore_buffer (self, buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -1111,7 +1144,7 @@ input_el_on_tty_readable (void *input)
|
||||||
if (!buf || count-- <= 0)
|
if (!buf || count-- <= 0)
|
||||||
return;
|
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);
|
el_deletestr (self->editline, 1);
|
||||||
input_el__redisplay (self);
|
input_el__redisplay (self);
|
||||||
|
@ -1131,6 +1164,7 @@ input_el_destroy (void *input)
|
||||||
free (iter->help);
|
free (iter->help);
|
||||||
ffi_closure_free (iter);
|
ffi_closure_free (iter);
|
||||||
}
|
}
|
||||||
|
fclose (self->null);
|
||||||
free (self->prompt);
|
free (self->prompt);
|
||||||
free (self);
|
free (self);
|
||||||
}
|
}
|
||||||
|
@ -1144,6 +1178,7 @@ input_el_new (void)
|
||||||
{
|
{
|
||||||
struct input_el *self = xcalloc (1, sizeof *self);
|
struct input_el *self = xcalloc (1, sizeof *self);
|
||||||
self->super.vtable = &input_el_vtable;
|
self->super.vtable = &input_el_vtable;
|
||||||
|
self->null = fopen ("/dev/null", "w");
|
||||||
return &self->super;
|
return &self->super;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -13908,13 +13943,10 @@ on_editline_return (EditLine *editline, int key)
|
||||||
wchar_t *line = calloc (sizeof *info->buffer, len + 1);
|
wchar_t *line = calloc (sizeof *info->buffer, len + 1);
|
||||||
memcpy (line, info->buffer, sizeof *info->buffer * len);
|
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)
|
if (*line)
|
||||||
{
|
{
|
||||||
HistEventW ev;
|
HistEventW ev;
|
||||||
history_w (self->current->history, &ev, H_ENTER, line);
|
history_w (self->current->history, &ev, H_ENTER, line);
|
||||||
print_debug ("history: %d %ls", ev.num, ev.str);
|
|
||||||
}
|
}
|
||||||
free (line);
|
free (line);
|
||||||
|
|
||||||
|
@ -13926,6 +13958,7 @@ on_editline_return (EditLine *editline, int key)
|
||||||
|
|
||||||
el_cursor (editline, len - point);
|
el_cursor (editline, len - point);
|
||||||
el_wdeletestr (editline, len);
|
el_wdeletestr (editline, len);
|
||||||
|
input_el__bottom (self);
|
||||||
return CC_REFRESH;
|
return CC_REFRESH;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue