degesch: make it work to some extent

GNU Readline still ignores our Meta keyseqs.
This commit is contained in:
Přemysl Eric Janouch 2015-04-18 03:25:10 +02:00
parent 583262ae67
commit 869781c33a
1 changed files with 66 additions and 35 deletions

101
degesch.c
View File

@ -788,9 +788,9 @@ buffer_send (struct app_context *ctx, struct buffer *buffer,
line->type = type; line->type = type;
line->flags = flags; line->flags = flags;
line->when = time (NULL); line->when = time (NULL);
line->who = origin ? xstrdup (origin) : NULL; line->who = xstrdup (origin ? origin : "");
line->object = str_steal (&text); 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); LIST_APPEND_WITH_TAIL (buffer->lines, buffer->lines_tail, line);
buffer->lines_count++; buffer->lines_count++;
@ -910,9 +910,6 @@ buffer_activate (struct app_context *ctx, struct buffer *buffer)
clear_history (); clear_history ();
#endif // RL_READLINE_VERSION < 0x0603 #endif // RL_READLINE_VERSION < 0x0603
// Now at last we can switch the pointers
ctx->current_buffer = buffer;
// Restore the target buffer's history // Restore the target buffer's history
if (buffer->history) if (buffer->history)
{ {
@ -946,6 +943,9 @@ buffer_activate (struct app_context *ctx, struct buffer *buffer)
rl_redisplay (); rl_redisplay ();
} }
// Now at last we can switch the pointers
ctx->current_buffer = buffer;
refresh_prompt (ctx); refresh_prompt (ctx);
} }
@ -1043,7 +1043,15 @@ try_finish_quit (struct app_context *ctx)
static void static void
initiate_quit (struct app_context *ctx) 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) if (ctx->irc_fd != -1)
irc_shutdown (ctx); irc_shutdown (ctx);
@ -1273,8 +1281,8 @@ irc_establish_connection (struct app_context *ctx,
real_host = buf; real_host = buf;
char *address = format_host_port_pair (real_host, port); char *address = format_host_port_pair (real_host, port);
// FIXME: print to the server buffer buffer_send_status (ctx, ctx->server_buffer,
print_status ("connecting to %s...", address); "connecting to %s...", address);
free (address); free (address);
if (!connect (sockfd, gai_iter->ai_addr, gai_iter->ai_addrlen)) if (!connect (sockfd, gai_iter->ai_addr, gai_iter->ai_addrlen))
@ -1386,7 +1394,11 @@ refresh_prompt (struct app_context *ctx)
} }
str_free (&prompt); 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); rl_set_prompt (ctx->readline_prompt);
if (ctx->readline_prompt_shown) if (ctx->readline_prompt_shown)
rl_redisplay (); rl_redisplay ();
@ -1397,9 +1409,6 @@ on_readline_goto_buffer (int count, int key)
{ {
(void) count; (void) count;
if (!(key & 0x80))
return 0;
int n = (key & 0x7F) - '0'; int n = (key & 0x7F) - '0';
if (n < 0 || n > 9) if (n < 0 || n > 9)
return 0; return 0;
@ -1443,14 +1452,17 @@ init_readline (void)
rl_add_defun ("next-buffer", on_readline_next_buffer, -1); rl_add_defun ("next-buffer", on_readline_next_buffer, -1);
// Redefine M-0 through M-9 to switch buffers // Redefine M-0 through M-9 to switch buffers
char keyseq[] = "\\M-0";
for (int i = 0; i <= 9; i++) 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-p", rl_named_function ("previous-buffer"));
rl_bind_keyseq ("C-n", rl_named_function ("next-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-p", rl_named_function ("previous-history"));
rl_bind_keyseq ("M-n", rl_named_function ("next-history")); rl_bind_keyseq ("\\M-n", rl_named_function ("next-history"));
return 0; return 0;
} }
@ -1594,6 +1606,7 @@ irc_process_message (const struct irc_message *msg,
// XXX: should we really print this? // XXX: should we really print this?
buffer_send_status (ctx, ctx->server_buffer, "successfully connected"); buffer_send_status (ctx, ctx->server_buffer, "successfully connected");
ctx->irc_ready = true; ctx->irc_ready = true;
refresh_prompt (ctx);
const char *autojoin = str_map_find (&ctx->config, "autojoin"); const char *autojoin = str_map_find (&ctx->config, "autojoin");
if (autojoin) if (autojoin)
@ -1613,7 +1626,11 @@ irc_process_message (const struct irc_message *msg,
unsigned long dummy; unsigned long dummy;
if (xstrtoul (&dummy, msg->command, 10)) if (xstrtoul (&dummy, msg->command, 10))
{ {
char *reconstructed = join_str_vector (&msg->params, ' '); struct str_vector copy;
str_vector_init (&copy);
str_vector_add_vector (&copy, msg->params.vector + !!msg->params.len);
char *reconstructed = join_str_vector (&copy, ' ');
str_vector_free (&copy);
char *utf8 = irc_to_utf8 (ctx, reconstructed); char *utf8 = irc_to_utf8 (ctx, reconstructed);
free (reconstructed); free (reconstructed);
buffer_send_status (ctx, ctx->server_buffer, "%s", utf8); buffer_send_status (ctx, ctx->server_buffer, "%s", utf8);
@ -1834,7 +1851,7 @@ static void
process_user_command (struct app_context *ctx, char *command) process_user_command (struct app_context *ctx, char *command)
{ {
static bool initialized = false; static bool initialized = false;
struct str_map partial; static struct str_map partial;
if (!initialized) if (!initialized)
{ {
init_partial_matching_user_command_map (&partial); 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 // 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? // 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; bool use_ssl;
if (!irc_get_boolean_from_config (ctx, "ssl", &use_ssl, e)) if (!irc_get_boolean_from_config (ctx, "ssl", &use_ssl, e))
return false; return false;
@ -2233,8 +2244,13 @@ on_readline_input (char *line)
process_input (g_ctx, line); process_input (g_ctx, line);
free (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 --------------------------------------------------- // --- Configuration loading ---------------------------------------------------
@ -2372,7 +2388,7 @@ autofill_user_info (struct app_context *ctx, struct error **e)
if (comma) if (comma)
*comma = '\0'; *comma = '\0';
str_map_set (&ctx->config, "username", xstrdup (gecos)); str_map_set (&ctx->config, "realname", xstrdup (gecos));
} }
return true; return true;
@ -2418,6 +2434,13 @@ load_config (struct app_context *ctx, struct error **e)
if (!success) if (!success)
return false; 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, if (!irc_get_boolean_from_config (ctx,
"reconnect", &ctx->reconnect, e) "reconnect", &ctx->reconnect, e)
|| !irc_get_boolean_from_config (ctx, || !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]); 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.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_set (&ctx->signal_event, POLLIN);
poller_fd_init (&ctx->tty_event, &ctx->poller, STDIN_FILENO); poller_fd_init (&ctx->tty_event, &ctx->poller, STDIN_FILENO);
@ -2523,6 +2546,14 @@ main (int argc, char *argv[])
setup_signal_handlers (); 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_colors (&ctx);
init_poller_events (&ctx); init_poller_events (&ctx);
init_buffers (&ctx); init_buffers (&ctx);
@ -2530,17 +2561,17 @@ main (int argc, char *argv[])
refresh_prompt (&ctx); refresh_prompt (&ctx);
// TODO: connect asynchronously (first step towards multiple servers) // TODO: connect asynchronously (first step towards multiple servers)
// TODO: print load_config() errors to the global buffer, if (!irc_connect (&ctx, &e))
// switch buffers and print irc_connect() errors to the server buffer?
struct error *e = NULL;
if (!load_config (&ctx, &e)
|| !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); error_free (e);
exit (EXIT_FAILURE); exit (EXIT_FAILURE);
} }
// TODO
ctx.irc_nickname = xstrdup ("TODO");
ctx.irc_user_mode = xstrdup ("");
rl_startup_hook = init_readline; rl_startup_hook = init_readline;
rl_catch_sigwinch = false; rl_catch_sigwinch = false;
rl_callback_handler_install (ctx.readline_prompt, on_readline_input); rl_callback_handler_install (ctx.readline_prompt, on_readline_input);