From 0bdf76edc591524ec133a728e37b05a25d00c9d9 Mon Sep 17 00:00:00 2001
From: Přemysl Janouch 
Date: Fri, 8 May 2015 06:23:38 +0200
Subject: 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);
-
-	// 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_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);
 
-	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"));
+	bind_common_keys (ctx);
 
-	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 ("redraw-screen", on_readline_redraw_screen, -1);
-		rl_bind_keyseq ("\\C-l", rl_named_function ("redraw-screen"));
-	}
+	// Move native history commands
+	input_bind_meta (self, 'p', "previous-history");
+	input_bind_meta (self, 'n', "next-history");
 
-	// We need to hide the prompt first
-	rl_bind_key (RETURN, on_readline_return);
+	// 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");
 
-	// Source the user's defaults file
-	el_source (self->editline, NULL);
+	// We need to hide the prompt and input first
+	input_bind (self, "\n", "send-line");
 
-	el_set (self->editline, EL_ADDFN, "send-line",
-		"Send line", on_editline_return);
-	el_set (self->editline, EL_BIND, "\n", "send-line", NULL);
+	input_bind_control (self, 'i', "complete");
 
-	el_set (self->editline, EL_ADDFN, "complete",
-		"Complete word", on_editline_complete);
-	el_set (self->editline, EL_BIND, "^I", "complete", NULL);
+	// Source the user's defaults file
+	el_source (self->editline, NULL);
 }
 
 #endif // HAVE_EDITLINE
-- 
cgit v1.2.3-70-g09d2