degesch: make it work to some extent
GNU Readline still ignores our Meta keyseqs.
This commit is contained in:
parent
583262ae67
commit
869781c33a
99
degesch.c
99
degesch.c
|
@ -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 (©);
|
||||||
|
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);
|
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,7 +2244,12 @@ 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 ();
|
||||||
|
|
||||||
|
// initiate_quit() disables readline; we just wait then
|
||||||
|
if (!g_ctx->quitting)
|
||||||
g_ctx->readline_prompt_shown = true;
|
g_ctx->readline_prompt_shown = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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);
|
||||||
|
|
Loading…
Reference in New Issue