degesch: clean up key binding initialization

This commit is contained in:
Přemysl Eric Janouch 2015-05-08 06:23:38 +02:00
parent cc505090d4
commit 0bdf76edc5
1 changed files with 107 additions and 76 deletions

183
degesch.c
View File

@ -216,6 +216,34 @@ input_erase (struct input *self)
rl_redisplay ();
}
static void
input_bind (struct input *self, const char *seq, const char *function_name)
{
(void) self;
rl_bind_keyseq (seq, rl_named_function (function_name));
}
static void
input_bind_meta (struct input *self, char key, const char *function_name)
{
// This one seems to actually work
char keyseq[] = { '\\', 'e', key, 0 };
input_bind (self, keyseq, function_name);
#if 0
// While this one only fucks up UTF-8
// Tested with urxvt and xterm, on Debian Jessie/Arch, default settings
// \M-<key> behaves exactly the same
rl_bind_key (META (key), rl_named_function (function_name));
#endif
}
static void
input_bind_control (struct input *self, char key, const char *function_name)
{
char keyseq[] = { '\\', 'C', '-', key, 0 };
input_bind (self, keyseq, function_name);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
static int app_readline_init (void);
@ -437,6 +465,26 @@ input_on_terminal_resized (struct input *self)
el_resize (self->editline);
}
static void
input_bind (struct input *self, const char *seq, const char *function_name)
{
el_set (self->editline, EL_BIND, seq, function_name, NULL);
}
static void
input_bind_meta (struct input *self, char key, const char *function_name)
{
char keyseq[] = { 'M', '-', key, 0 };
input_bind (self, keyseq, function_name);
}
static void
input_bind_control (struct input *self, char key, const char *function_name)
{
char keyseq[] = { '^', key, 0 };
input_bind (self, keyseq, function_name);
}
static void
input_redisplay (struct input *self)
{
@ -506,12 +554,8 @@ input_start (struct input *self, const char *program_name)
el_set (self->editline, EL_UNBUFFERED, true);
el_set (self->editline, EL_EDITOR, "emacs");
// No, editline, it's not supposed to kill the entire line
el_set (self->editline, EL_BIND, "^W", "ed-delete-prev-word", NULL);
// Just what are you doing?
el_set (self->editline, EL_BIND, "^U", "vi-kill-line-prev", NULL);
app_editline_init (self);
self->prompt_shown = 1;
self->active = true;
}
@ -5391,6 +5435,26 @@ redraw_screen (struct app_context *ctx)
return true;
}
static void
bind_common_keys (struct app_context *ctx)
{
struct input *self = &ctx->input;
input_bind_control (self, 'p', "previous-buffer");
input_bind_control (self, 'n', "next-buffer");
// Redefine M-0 through M-9 to switch buffers
for (int i = 0; i <= 9; i++)
input_bind_meta (self, '0' + i, "goto-buffer");
if (key_f5)
input_bind (self, key_f5, "previous-buffer");
if (key_f6)
input_bind (self, key_f6, "next-buffer");
if (clear_screen)
input_bind_control (self, 'l', "redraw-screen");
}
// --- GNU Readline user actions -----------------------------------------------
#ifdef HAVE_READLINE
@ -5491,20 +5555,6 @@ on_readline_input (char *line)
ctx->input.prompt_shown = 1;
}
static void
app_readline_bind_meta (char key, rl_command_func_t cb)
{
// This one seems to actually work
char keyseq[] = { '\\', 'e', key, 0 };
rl_bind_keyseq (keyseq, cb);
#if 0
// While this one only fucks up UTF-8
// Tested with urxvt and xterm, on Debian Jessie/Arch, default settings
// \M-<key> behaves exactly the same
rl_bind_key (META (key), cb);
#endif
}
static char **
app_readline_completion (const char *text, int start, int end)
{
@ -5520,41 +5570,32 @@ app_readline_completion (const char *text, int start, int end)
static int
app_readline_init (void)
{
struct app_context *ctx = g_ctx;
struct input *self = &ctx->input;
// XXX: maybe use rl_make_bare_keymap() and start from there;
// our dear user could potentionally rig things up in a way that might
// result in some funny unspecified behaviour
rl_add_defun ("previous-buffer", on_readline_previous_buffer, -1);
rl_add_defun ("next-buffer", on_readline_next_buffer, -1);
// Redefine M-0 through M-9 to switch buffers
for (int i = 0; i <= 9; i++)
app_readline_bind_meta ('0' + i, on_readline_goto_buffer);
rl_bind_keyseq ("\\C-p", rl_named_function ("previous-buffer"));
rl_bind_keyseq ("\\C-n", rl_named_function ("next-buffer"));
app_readline_bind_meta ('p', rl_named_function ("previous-history"));
app_readline_bind_meta ('n', rl_named_function ("next-history"));
if (key_f5)
rl_bind_keyseq (key_f5, rl_named_function ("previous-buffer"));
if (key_f6)
rl_bind_keyseq (key_f6, rl_named_function ("next-buffer"));
if (clear_screen)
{
rl_add_defun ("goto-buffer", on_readline_goto_buffer, -1);
rl_add_defun ("redraw-screen", on_readline_redraw_screen, -1);
rl_bind_keyseq ("\\C-l", rl_named_function ("redraw-screen"));
}
rl_add_defun ("send-line", on_readline_return, -1);
// We need to hide the prompt first
rl_bind_key (RETURN, on_readline_return);
bind_common_keys (ctx);
// Move native history commands
input_bind_meta (self, 'p', "previous-history");
input_bind_meta (self, 'n', "next-history");
// We need to hide the prompt and input first
rl_bind_key (RETURN, rl_named_function ("send-line"));
// Completion
rl_variable_bind ("completion-ignore-case", "on");
rl_bind_key (TAB, rl_named_function ("menu-complete"));
if (key_btab)
rl_bind_keyseq (key_btab, rl_named_function ("menu-complete-backward"));
input_bind (self, key_btab, "menu-complete-backward");
return 0;
}
@ -5707,47 +5748,37 @@ on_editline_return (EditLine *editline, int key)
static void
app_editline_init (struct input *self)
{
el_set (self->editline, EL_ADDFN, "goto-buffer",
"Go to buffer", on_editline_goto_buffer);
el_set (self->editline, EL_ADDFN, "previous-buffer",
"Previous buffer", on_editline_previous_buffer);
el_set (self->editline, EL_ADDFN, "next-buffer",
"Next buffer", on_editline_next_buffer);
// Redefine M-0 through M-9 to switch buffers
for (size_t i = 0; i < 10; i++)
static const struct { const char *name; const char *help;
unsigned char (*func) (EditLine *, int); } x[] =
{
char keyseq[] = { 'M', '-', '0' + i, 0 };
el_set (self->editline, EL_BIND, keyseq, "goto-buffer", NULL);
}
{ "goto-buffer", "Go to buffer", on_editline_goto_buffer },
{ "previous-buffer", "Previous buffer", on_editline_previous_buffer },
{ "next-buffer", "Next buffer", on_editline_next_buffer },
{ "redraw-screen", "Redraw screen", on_editline_redraw_screen },
{ "send-line", "Send line", on_editline_return },
{ "complete", "Complete word", on_editline_complete },
};
for (size_t i = 0; i < N_ELEMENTS (x); i++)
el_set (self->editline, EL_ADDFN, x[i].name, x[i].help, x[i].func);
el_set (self->editline, EL_BIND, "M-p", "ed-prev-history", NULL);
el_set (self->editline, EL_BIND, "M-n", "ed-next-history", NULL);
el_set (self->editline, EL_BIND, "^P", "previous-buffer", NULL);
el_set (self->editline, EL_BIND, "^N", "next-buffer", NULL);
bind_common_keys (g_ctx);
if (key_f5)
el_set (self->editline, EL_BIND, key_f5, "previous-buffer", NULL);
if (key_f6)
el_set (self->editline, EL_BIND, key_f6, "next-buffer", NULL);
// Move native history commands
input_bind_meta (self, 'p', "ed-prev-history");
input_bind_meta (self, 'n', "ed-next-history");
if (clear_screen)
{
el_set (self->editline, EL_ADDFN, "redraw-screen",
"Redraw screen", on_editline_redraw_screen);
el_set (self->editline, EL_BIND, "^L", "redraw-screen", NULL);
}
// No, editline, it's not supposed to kill the entire line
input_bind_control (self, 'w', "ed-delete-prev-word");
// Just what are you doing?
input_bind_control (self, 'u', "vi-kill-line-prev");
// We need to hide the prompt and input first
input_bind (self, "\n", "send-line");
input_bind_control (self, 'i', "complete");
// Source the user's defaults file
el_source (self->editline, NULL);
el_set (self->editline, EL_ADDFN, "send-line",
"Send line", on_editline_return);
el_set (self->editline, EL_BIND, "\n", "send-line", NULL);
el_set (self->editline, EL_ADDFN, "complete",
"Complete word", on_editline_complete);
el_set (self->editline, EL_BIND, "^I", "complete", NULL);
}
#endif // HAVE_EDITLINE