From 0bdf76edc591524ec133a728e37b05a25d00c9d9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?P=C5=99emysl=20Janouch?= Date: Fri, 8 May 2015 06:23:38 +0200 Subject: [PATCH] degesch: clean up key binding initialization --- degesch.c | 183 +++++++++++++++++++++++++++++++----------------------- 1 file changed, 107 insertions(+), 76 deletions(-) diff --git a/degesch.c b/degesch.c index e60f1ad..18ad689 100644 --- a/degesch.c +++ b/degesch.c @@ -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- 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- 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); + rl_add_defun ("next-buffer", on_readline_next_buffer, -1); + rl_add_defun ("goto-buffer", on_readline_goto_buffer, -1); + rl_add_defun ("redraw-screen", on_readline_redraw_screen, -1); + rl_add_defun ("send-line", on_readline_return, -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); + bind_common_keys (ctx); - 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")); + // Move native history commands + input_bind_meta (self, 'p', "previous-history"); + input_bind_meta (self, 'n', "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")); + // We need to hide the prompt and input first + rl_bind_key (RETURN, rl_named_function ("send-line")); - if (clear_screen) - { - rl_add_defun ("redraw-screen", on_readline_redraw_screen, -1); - rl_bind_keyseq ("\\C-l", rl_named_function ("redraw-screen")); - } - - // We need to hide the prompt first - rl_bind_key (RETURN, on_readline_return); - - // 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