From 932548ef4b440d1537b097d1317e7723c5534f51 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?P=C5=99emysl=20Janouch?= 
Date: Sat, 18 Apr 2015 16:03:50 +0200
Subject: [PATCH] degesch: make readline work better
By randomly poking at it until it stops being a little shit.
Still no Meta keys.
---
 degesch.c | 69 ++++++++++++++++++++++++++++++++++++++++++++-----------
 1 file changed, 56 insertions(+), 13 deletions(-)
diff --git a/degesch.c b/degesch.c
index e09f4cb..4c5afbb 100644
--- a/degesch.c
+++ b/degesch.c
@@ -446,7 +446,7 @@ static void
 app_readline_hide (struct app_readline_state *state)
 {
 	state->saved_point = rl_point;
-	state->saved_point = rl_mark;
+	state->saved_mark = rl_mark;
 	state->saved_line = rl_copy_text (0, rl_end);
 	rl_set_prompt ("");
 	rl_replace_line ("", 0);
@@ -464,6 +464,16 @@ app_readline_restore (struct app_readline_state *state, const char *prompt)
 	free (state->saved_line);
 }
 
+static void
+app_readline_erase_to_bol (const char *prompt)
+{
+	rl_set_prompt ("");
+	rl_replace_line ("", 0);
+	rl_point = rl_mark = 0;
+	rl_redisplay ();
+	rl_set_prompt (prompt);
+}
+
 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
 typedef int (*terminal_printer_fn) (int);
@@ -1045,10 +1055,10 @@ initiate_quit (struct app_context *ctx)
 {
 	// First get rid of readline
 	if (ctx->readline_prompt_shown)
-		rl_crlf ();
-
-	rl_callback_handler_remove ();
-	ctx->readline_prompt_shown = false;
+	{
+		app_readline_erase_to_bol (ctx->readline_prompt);
+		ctx->readline_prompt_shown = false;
+	}
 
 	// Initiate a connection close
 	buffer_send_status (ctx, ctx->global_buffer, "shutting down");
@@ -1441,6 +1451,37 @@ on_readline_next_buffer (int count, int key)
 	return 0;
 }
 
+static int
+on_readline_return (int count, int key)
+{
+	(void) count;
+	(void) key;
+
+	struct app_context *ctx = g_ctx;
+
+	// Let readline pass the line to our input handler
+	rl_done = 1;
+
+	// Save readline state
+	int saved_point = rl_point;
+	int saved_mark = rl_mark;
+	char *saved_line = rl_copy_text (0, rl_end);
+
+	// Erase the entire line from screen
+	rl_set_prompt ("");
+	rl_replace_line ("", 0);
+	rl_redisplay ();
+	ctx->readline_prompt_shown = false;
+
+	// Restore readline state
+	rl_set_prompt (ctx->readline_prompt);
+	rl_replace_line (saved_line, 0);
+	rl_point = saved_point;
+	rl_mark = saved_mark;
+	free (saved_line);
+	return 0;
+}
+
 static int
 init_readline (void)
 {
@@ -1464,6 +1505,8 @@ init_readline (void)
 	rl_bind_keyseq ("\\M-p", rl_named_function ("previous-history"));
 	rl_bind_keyseq ("\\M-n", rl_named_function ("next-history"));
 
+	rl_bind_key (RETURN, on_readline_return);
+
 	return 0;
 }
 
@@ -2233,9 +2276,6 @@ on_tty_readable (const struct pollfd *fd, struct app_context *ctx)
 static void
 on_readline_input (char *line)
 {
-	// Otherwise the prompt is shown at all times
-	g_ctx->readline_prompt_shown = false;
-
 	if (line)
 	{
 		if (*line)
@@ -2245,11 +2285,15 @@ on_readline_input (char *line)
 		free (line);
 	}
 	else
-		// Anything better to do?
-		rl_crlf ();
+	{
+		app_readline_erase_to_bol (g_ctx->readline_prompt);
+		rl_ding ();
+	}
 
-	// initiate_quit() disables readline; we just wait then
-	if (!g_ctx->quitting)
+	if (g_ctx->quitting)
+		rl_callback_handler_remove ();
+	else
+		// initiate_quit() disables readline; we just wait then
 		g_ctx->readline_prompt_shown = true;
 }
 
@@ -2584,7 +2628,6 @@ main (int argc, char *argv[])
 
 	if (ctx.readline_prompt_shown)
 		rl_callback_handler_remove ();
-	putchar ('\n');
 
 	app_context_free (&ctx);
 	free_terminal ();