From 869781c33a0269ab6038fd5d2fdc89e8b317feb3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?P=C5=99emysl=20Janouch?= Date: Sat, 18 Apr 2015 03:25:10 +0200 Subject: [PATCH] degesch: make it work to some extent GNU Readline still ignores our Meta keyseqs. --- degesch.c | 101 +++++++++++++++++++++++++++++++++++------------------- 1 file changed, 66 insertions(+), 35 deletions(-) diff --git a/degesch.c b/degesch.c index 839b9e8..e09f4cb 100644 --- a/degesch.c +++ b/degesch.c @@ -788,9 +788,9 @@ buffer_send (struct app_context *ctx, struct buffer *buffer, line->type = type; line->flags = flags; line->when = time (NULL); - line->who = origin ? xstrdup (origin) : NULL; + line->who = xstrdup (origin ? origin : ""); line->object = str_steal (&text); - line->reason = reason ? xstrdup (reason) : NULL; + line->reason = xstrdup (reason ? reason : ""); LIST_APPEND_WITH_TAIL (buffer->lines, buffer->lines_tail, line); buffer->lines_count++; @@ -910,9 +910,6 @@ buffer_activate (struct app_context *ctx, struct buffer *buffer) clear_history (); #endif // RL_READLINE_VERSION < 0x0603 - // Now at last we can switch the pointers - ctx->current_buffer = buffer; - // Restore the target buffer's history if (buffer->history) { @@ -946,6 +943,9 @@ buffer_activate (struct app_context *ctx, struct buffer *buffer) rl_redisplay (); } + // Now at last we can switch the pointers + ctx->current_buffer = buffer; + refresh_prompt (ctx); } @@ -1043,7 +1043,15 @@ try_finish_quit (struct app_context *ctx) static void initiate_quit (struct app_context *ctx) { - print_status ("shutting down"); + // First get rid of readline + if (ctx->readline_prompt_shown) + rl_crlf (); + + rl_callback_handler_remove (); + ctx->readline_prompt_shown = false; + + // Initiate a connection close + buffer_send_status (ctx, ctx->global_buffer, "shutting down"); if (ctx->irc_fd != -1) irc_shutdown (ctx); @@ -1273,8 +1281,8 @@ irc_establish_connection (struct app_context *ctx, real_host = buf; char *address = format_host_port_pair (real_host, port); - // FIXME: print to the server buffer - print_status ("connecting to %s...", address); + buffer_send_status (ctx, ctx->server_buffer, + "connecting to %s...", address); free (address); if (!connect (sockfd, gai_iter->ai_addr, gai_iter->ai_addrlen)) @@ -1386,7 +1394,11 @@ refresh_prompt (struct app_context *ctx) } str_free (&prompt); - // We need to be somehow able to initialize it + // First reset the prompt to work around a bug in readline + rl_set_prompt (""); + if (ctx->readline_prompt_shown) + rl_redisplay (); + rl_set_prompt (ctx->readline_prompt); if (ctx->readline_prompt_shown) rl_redisplay (); @@ -1397,9 +1409,6 @@ on_readline_goto_buffer (int count, int key) { (void) count; - if (!(key & 0x80)) - return 0; - int n = (key & 0x7F) - '0'; if (n < 0 || n > 9) return 0; @@ -1443,14 +1452,17 @@ init_readline (void) rl_add_defun ("next-buffer", on_readline_next_buffer, -1); // Redefine M-0 through M-9 to switch buffers + char keyseq[] = "\\M-0"; for (int i = 0; i <= 9; i++) - rl_bind_key (0x80 /* this is the Meta modifier for Readline */ - | ('0' + i), on_readline_goto_buffer); + { + keyseq[3] = '0' + i; + rl_bind_keyseq (keyseq, on_readline_goto_buffer); + } - rl_bind_keyseq ("C-p", rl_named_function ("previous-buffer")); - rl_bind_keyseq ("C-n", rl_named_function ("next-buffer")); - rl_bind_keyseq ("M-p", rl_named_function ("previous-history")); - rl_bind_keyseq ("M-n", rl_named_function ("next-history")); + rl_bind_keyseq ("\\C-p", rl_named_function ("previous-buffer")); + rl_bind_keyseq ("\\C-n", rl_named_function ("next-buffer")); + rl_bind_keyseq ("\\M-p", rl_named_function ("previous-history")); + rl_bind_keyseq ("\\M-n", rl_named_function ("next-history")); return 0; } @@ -1594,6 +1606,7 @@ irc_process_message (const struct irc_message *msg, // XXX: should we really print this? buffer_send_status (ctx, ctx->server_buffer, "successfully connected"); ctx->irc_ready = true; + refresh_prompt (ctx); const char *autojoin = str_map_find (&ctx->config, "autojoin"); if (autojoin) @@ -1613,7 +1626,11 @@ irc_process_message (const struct irc_message *msg, unsigned long dummy; if (xstrtoul (&dummy, msg->command, 10)) { - char *reconstructed = join_str_vector (&msg->params, ' '); + struct str_vector copy; + str_vector_init (©); + str_vector_add_vector (©, msg->params.vector + !!msg->params.len); + char *reconstructed = join_str_vector (©, ' '); + str_vector_free (©); char *utf8 = irc_to_utf8 (ctx, reconstructed); free (reconstructed); buffer_send_status (ctx, ctx->server_buffer, "%s", utf8); @@ -1834,7 +1851,7 @@ static void process_user_command (struct app_context *ctx, char *command) { static bool initialized = false; - struct str_map partial; + static struct str_map partial; if (!initialized) { init_partial_matching_user_command_map (&partial); @@ -2127,12 +2144,6 @@ irc_connect (struct app_context *ctx, struct error **e) // TODO: again, get rid of `struct error' in here. The question is: how // do we tell our caller that he should not try to reconnect? - if (!irc_host) - { - error_set (e, "no hostname specified in configuration"); - return false; - } - bool use_ssl; if (!irc_get_boolean_from_config (ctx, "ssl", &use_ssl, e)) return false; @@ -2233,8 +2244,13 @@ on_readline_input (char *line) process_input (g_ctx, line); free (line); } + else + // Anything better to do? + rl_crlf (); - g_ctx->readline_prompt_shown = true; + // initiate_quit() disables readline; we just wait then + if (!g_ctx->quitting) + g_ctx->readline_prompt_shown = true; } // --- Configuration loading --------------------------------------------------- @@ -2372,7 +2388,7 @@ autofill_user_info (struct app_context *ctx, struct error **e) if (comma) *comma = '\0'; - str_map_set (&ctx->config, "username", xstrdup (gecos)); + str_map_set (&ctx->config, "realname", xstrdup (gecos)); } return true; @@ -2418,6 +2434,13 @@ load_config (struct app_context *ctx, struct error **e) if (!success) return false; + const char *irc_host = str_map_find (&ctx->config, "irc_host"); + if (!irc_host) + { + error_set (e, "no hostname specified in configuration"); + return false; + } + if (!irc_get_boolean_from_config (ctx, "reconnect", &ctx->reconnect, e) || !irc_get_boolean_from_config (ctx, @@ -2454,7 +2477,7 @@ init_poller_events (struct app_context *ctx) poller_fd_init (&ctx->signal_event, &ctx->poller, g_signal_pipe[0]); ctx->signal_event.dispatcher = (poller_fd_fn) on_signal_pipe_readable; - ctx->signal_event.user_data = &ctx; + ctx->signal_event.user_data = ctx; poller_fd_set (&ctx->signal_event, POLLIN); poller_fd_init (&ctx->tty_event, &ctx->poller, STDIN_FILENO); @@ -2523,6 +2546,14 @@ main (int argc, char *argv[]) setup_signal_handlers (); + struct error *e = NULL; + if (!load_config (&ctx, &e)) + { + print_error ("%s", e->message); + error_free (e); + exit (EXIT_FAILURE); + } + init_colors (&ctx); init_poller_events (&ctx); init_buffers (&ctx); @@ -2530,17 +2561,17 @@ main (int argc, char *argv[]) refresh_prompt (&ctx); // TODO: connect asynchronously (first step towards multiple servers) - // TODO: print load_config() errors to the global buffer, - // switch buffers and print irc_connect() errors to the server buffer? - struct error *e = NULL; - if (!load_config (&ctx, &e) - || !irc_connect (&ctx, &e)) + if (!irc_connect (&ctx, &e)) { - buffer_send_error (&ctx, ctx.global_buffer, "%s", e->message); + buffer_send_error (&ctx, ctx.server_buffer, "%s", e->message); error_free (e); exit (EXIT_FAILURE); } + // TODO + ctx.irc_nickname = xstrdup ("TODO"); + ctx.irc_user_mode = xstrdup (""); + rl_startup_hook = init_readline; rl_catch_sigwinch = false; rl_callback_handler_install (ctx.readline_prompt, on_readline_input);