diff --git a/degesch.c b/degesch.c index c5debdb..1f960ba 100644 --- a/degesch.c +++ b/degesch.c @@ -282,6 +282,7 @@ struct app_context struct buffer *buffers; ///< All our buffers in order struct buffer *buffers_tail; ///< The tail of our buffers + // XXX: when we go multiserver, there will be collisions struct str_map buffers_by_name; ///< Excludes GLOBAL and SERVER struct buffer *global_buffer; ///< The global buffer struct buffer *server_buffer; ///< The server buffer @@ -822,6 +823,8 @@ buffer_remove (struct app_context *ctx, struct buffer *buffer) { hard_assert (buffer != ctx->current_buffer); + // TODO: part from the channel if needed + // rl_clear_history, being the only way I know of to get rid of the complete // history including attached data, is a pretty recent addition. *sigh* #if RL_READLINE_VERSION >= 0x0603 @@ -1524,16 +1527,107 @@ irc_process_message (const struct irc_message *msg, // --- User input handling ----------------------------------------------------- -static void handle_command_help (struct app_context *, const char *); +static void handle_command_help (struct app_context *, char *); -static void -handle_command_buffer (struct app_context *ctx, const char *arguments) +/// Cuts the longest non-whitespace portion of text and advances the pointer +static char * +cut_word (char **s) { - // TODO: parse the arguments + char *start = *s; + size_t word_len = strcspn (*s, " \t"); + char *end = start + word_len; + *s = end + strspn (end, " \t"); + *end = '\0'; + return start; +} + +static bool +try_handle_buffer_goto (struct app_context *ctx, const char *word) +{ + unsigned long n; + if (!xstrtoul (&n, word, 10)) + return false; + + if (n > INT_MAX || !buffer_goto (ctx, n)) + { + // TODO: print a "no such buffer" error message + } + return true; +} + +static struct buffer * +try_decode_buffer (struct app_context *ctx, const char *word) +{ + unsigned long n; + struct buffer *buffer = NULL; + if (xstrtoul (&n, word, 10) && n <= INT_MAX) + buffer = buffer_at_index (ctx, n); + if (!buffer) + buffer = str_map_find (&ctx->buffers_by_name, word); + // TODO: decode the global and server buffers, partial matches + return buffer; } static void -handle_command_quit (struct app_context *ctx, const char *arguments) +handle_command_buffer (struct app_context *ctx, char *arguments) +{ + char *action = cut_word (&arguments); + if (try_handle_buffer_goto (ctx, action)) + return; + + struct buffer *buffer = NULL; + + // XXX: also build a prefix map? + // TODO: some subcommand to print N last lines from the buffer + if (!strcasecmp_ascii (action, "list")) + { + // TODO: print a list of "%d: %s", index, name + } + else if (!strcasecmp_ascii (action, "clear")) + { + // TODO + } + else if (!strcasecmp_ascii (action, "move")) + { + // TODO: unlink the buffer and link it back at index; + // we will probably need to extend liberty for this + } + else if (!strcasecmp_ascii (action, "close")) + { + const char *which = NULL; + if (!*arguments) + buffer = ctx->current_buffer; + else + buffer = try_decode_buffer (ctx, (which = cut_word (&arguments))); + + if (!buffer) + { + // TODO: print a "no such buffer: %s" message + return; + } + if (buffer == ctx->global_buffer) + { + // TODO: print a "can't close the global buffer" message + return; + } + if (buffer == ctx->server_buffer) + { + // TODO: print a "can't close the server buffer" message + return; + } + + if (buffer == ctx->current_buffer) + buffer_activate (ctx, buffer_next (ctx, 1)); + buffer_remove (ctx, buffer); + } + else + { + // TODO: show usage (or do something else?) + } +} + +static void +handle_command_quit (struct app_context *ctx, char *arguments) { if (ctx->irc_fd != -1) { @@ -1548,7 +1642,7 @@ handle_command_quit (struct app_context *ctx, const char *arguments) static struct command_handler { char *name; - void (*handler) (struct app_context *ctx, const char *arguments); + void (*handler) (struct app_context *ctx, char *arguments); // TODO: probably also a usage string } g_command_handlers[] = @@ -1586,7 +1680,7 @@ g_command_handlers[] = }; static void -handle_command_help (struct app_context *ctx, const char *arguments) +handle_command_help (struct app_context *ctx, char *arguments) { // TODO: show a list of all user commands } @@ -1637,13 +1731,17 @@ process_user_command (struct app_context *ctx, char *command) initialized = true; } - // TODO: cut a single word (strtok_r()?) - // TODO: if it's a number, switch to the given buffer + char *name = cut_word (&command); + if (try_handle_buffer_goto (ctx, name)) + return; - struct command_handler *handler = str_map_find (&partial, command); + struct command_handler *handler = str_map_find (&partial, name); if (handler) - // FIXME: pass arguments correctly - handler->handler (ctx, ""); + handler->handler (ctx, command); + else + { + // TODO: print a "no such command" error message + } } static void