diff options
author | Nicholas Marriott <nicholas.marriott@gmail.com> | 2007-10-03 21:31:07 +0000 |
---|---|---|
committer | Nicholas Marriott <nicholas.marriott@gmail.com> | 2007-10-03 21:31:07 +0000 |
commit | df716ecc8fadc9ffd6b8c9ee33d062b58895a47b (patch) | |
tree | d9ba914e38d207a7ed1ee330cdc48bc681b220fe /cmd.c | |
parent | a5a17b40ee9cd25eae3c3d177abf4e4faa2dc4d8 (diff) | |
download | rtmux-df716ecc8fadc9ffd6b8c9ee33d062b58895a47b.tar.gz rtmux-df716ecc8fadc9ffd6b8c9ee33d062b58895a47b.tar.bz2 rtmux-df716ecc8fadc9ffd6b8c9ee33d062b58895a47b.zip |
Rewrite command handling to be more generic. Not finished!
Diffstat (limited to 'cmd.c')
-rw-r--r-- | cmd.c | 306 |
1 files changed, 113 insertions, 193 deletions
@@ -1,4 +1,4 @@ -/* $Id: cmd.c,v 1.4 2007-10-03 12:43:47 nicm Exp $ */ +/* $Id: cmd.c,v 1.5 2007-10-03 21:31:07 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> @@ -18,243 +18,163 @@ #include <sys/types.h> -#include <stdlib.h> +#include <getopt.h> #include <string.h> #include "tmux.h" -int cmd_prefix = META; - -void cmd_fn_detach(struct client *, struct cmd *); -void cmd_fn_last(struct client *, struct cmd *); -void cmd_fn_meta(struct client *, struct cmd *); -void cmd_fn_new(struct client *, struct cmd *); -void cmd_fn_next(struct client *, struct cmd *); -void cmd_fn_previous(struct client *, struct cmd *); -void cmd_fn_refresh(struct client *, struct cmd *); -void cmd_fn_select(struct client *, struct cmd *); -void cmd_fn_info(struct client *, struct cmd *); - -const struct cmd cmd_default[] = { - { '0', cmd_fn_select, 0, NULL }, - { '1', cmd_fn_select, 1, NULL }, - { '2', cmd_fn_select, 2, NULL }, - { '3', cmd_fn_select, 3, NULL }, - { '4', cmd_fn_select, 4, NULL }, - { '5', cmd_fn_select, 5, NULL }, - { '6', cmd_fn_select, 6, NULL }, - { '7', cmd_fn_select, 7, NULL }, - { '8', cmd_fn_select, 8, NULL }, - { '9', cmd_fn_select, 9, NULL }, - { 'C', cmd_fn_new, 0, NULL }, - { 'c', cmd_fn_new, 0, NULL }, - { 'D', cmd_fn_detach, 0, NULL }, - { 'd', cmd_fn_detach, 0, NULL }, - { 'N', cmd_fn_next, 0, NULL }, - { 'n', cmd_fn_next, 0, NULL }, - { 'P', cmd_fn_previous, 0, NULL }, - { 'p', cmd_fn_previous, 0, NULL }, - { 'R', cmd_fn_refresh, 0, NULL }, - { 'r', cmd_fn_refresh, 0, NULL }, - { 'L', cmd_fn_last, 0, NULL }, - { 'l', cmd_fn_last, 0, NULL }, - { 'I', cmd_fn_info, 0, NULL }, - { 'i', cmd_fn_info, 0, NULL }, - { META, cmd_fn_meta, 0, NULL }, -}; -u_int cmd_count = (sizeof cmd_default / sizeof cmd_default[0]); -struct cmd *cmd_table; - -const struct bind cmd_bind_table[] = { - { "detach", cmd_fn_detach, 0 }, - { "info", cmd_fn_info, 0 }, - { "last", cmd_fn_last, 0 }, - { "meta", cmd_fn_meta, 0 }, - { "new", cmd_fn_new, BIND_STRING|BIND_USER }, - { "next", cmd_fn_next, 0 }, - { "previous", cmd_fn_previous, 0 }, - { "refresh", cmd_fn_refresh, 0 }, - { "select", cmd_fn_select, BIND_NUMBER|BIND_USER }, +const struct cmd_entry *cmd_table[] = { + &cmd_detach_session_entry, + &cmd_list_sessions_entry, + &cmd_new_session_entry, + NULL }; -#define NCMDBIND (sizeof cmd_bind_table / sizeof cmd_bind_table[0]) - -const struct bind * -cmd_lookup_bind(const char *name) -{ - const struct bind *bind; - u_int i; - - for (i = 0; i < NCMDBIND; i++) { - bind = cmd_bind_table + i; - if (strcmp(bind->name, name) == 0) - return (bind); - } - return (NULL); -} -void -cmd_add_bind(int key, u_int num, char *str, const struct bind *bind) +struct cmd * +cmd_parse(int argc, char **argv, char **cause) { - struct cmd *cmd = NULL; - u_int i; - - for (i = 0; i < cmd_count; i++) { - cmd = cmd_table + i; - if (cmd->key == key) + const struct cmd_entry **this, *entry; + struct cmd *cmd; + int opt; + + *cause = NULL; + if (argc == 0) + return (NULL); + + entry = NULL; + for (this = cmd_table; *this != NULL; this++) { + if (strcmp((*this)->alias, argv[0]) == 0) { + entry = *this; break; - } - if (i == cmd_count) { - for (i = 0; i < cmd_count; i++) { - cmd = cmd_table + i; - if (cmd->key == KEYC_NONE) - break; } - if (i == cmd_count) { - cmd_count++; - cmd_table = xrealloc(cmd_table, - cmd_count, sizeof cmd_table[0]); - cmd = cmd_table + cmd_count - 1; + + if (strncmp((*this)->name, argv[0], strlen(argv[0])) != 0) + continue; + if (entry != NULL) { + xasprintf(cause, "ambiguous command: %s", argv[0]); + return (NULL); } + entry = *this; } - - cmd->key = key; - cmd->fn = bind->fn; - if (bind->flags & BIND_USER) { - if (bind->flags & BIND_STRING) - cmd->str = xstrdup(str); - if (bind->flags & BIND_NUMBER) - cmd->num = num; + if (entry == NULL) { + xasprintf(cause, "unknown command: %s", argv[0]); + return (NULL); } -} -void -cmd_remove_bind(int key) -{ - struct cmd *cmd; - u_int i; - - for (i = 0; i < cmd_count; i++) { - cmd = cmd_table + i; - if (cmd->key == key) { - cmd->key = KEYC_NONE; - break; + optind = 1; + if (entry->parse == NULL) { + while ((opt = getopt(argc, argv, "")) != EOF) { + switch (opt) { + default: + goto usage; + } } + argc -= optind; + argv += optind; + if (argc != 0) + goto usage; } -} -void -cmd_init(void) -{ - cmd_table = xmalloc(sizeof cmd_default); - memcpy(cmd_table, cmd_default, sizeof cmd_default); -} + cmd = xmalloc(sizeof *cmd); + cmd->entry = entry; + if (entry->parse != NULL) { + if (entry->parse(&cmd->data, argc, argv, cause) != 0) { + xfree(cmd); + return (NULL); + } + } + return (cmd); -void -cmd_free(void) -{ - /* XXX free strings */ - xfree(cmd_table); +usage: + if (entry->usage == NULL) + usage(cause, "%s", entry->name); + else + usage(cause, "%s", entry->usage()); + return (NULL); } void -cmd_dispatch(struct client *c, int key) +cmd_exec(struct cmd *cmd, struct cmd_ctx *ctx) { - struct cmd *cmd; - u_int i; - - for (i = 0; i < cmd_count; i++) { - cmd = cmd_table + i; - if (cmd->key != KEYC_NONE && cmd->key == key) - cmd->fn(c, cmd); - } + return (cmd->entry->exec(cmd->data, ctx)); } void -cmd_fn_new(struct client *c, struct cmd *cmd) +cmd_send(struct cmd *cmd, struct buffer *b) { - char *s; + buffer_write(b, &cmd->entry->type, sizeof cmd->entry->type); - s = cmd->str; - if (s == NULL) - s = default_command; - if (session_new(c->session, s, c->sx, c->sy) != 0) - server_write_message(c, "%s failed", s); /* XXX */ - else - server_draw_client(c, 0, c->sy - 1); + if (cmd->entry->send == NULL) + return; + return (cmd->entry->send(cmd->data, b)); } -void -cmd_fn_detach(struct client *c, unused struct cmd *cmd) +struct cmd * +cmd_recv(struct buffer *b) { - server_write_client(c, MSG_DETACH, NULL, 0); -} + const struct cmd_entry **this, *entry; + struct cmd *cmd; + enum cmd_type type; + + buffer_read(b, &type, sizeof type); + + entry = NULL; + for (this = cmd_table; *this != NULL; this++) { + if ((*this)->type == type) { + entry = *this; + break; + } + } + if (*this == NULL) + return (NULL); -void -cmd_fn_last(struct client *c, unused struct cmd *cmd) -{ - if (session_last(c->session) == 0) - server_window_changed(c); - else - server_write_message(c, "No last window"); -} + cmd = xmalloc(sizeof *cmd); + cmd->entry = entry; -void -cmd_fn_meta(struct client *c, unused struct cmd *cmd) -{ - window_key(c->session->window, cmd_prefix); + if (cmd->entry->recv != NULL) + cmd->entry->recv(&cmd->data, b); + return (cmd); } void -cmd_fn_next(struct client *c, unused struct cmd *cmd) +cmd_free(struct cmd *cmd) { - if (session_next(c->session) == 0) - server_window_changed(c); - else - server_write_message(c, "No next window"); + if (cmd->entry->free != NULL) + cmd->entry->free(cmd->data); + xfree(cmd); } void -cmd_fn_previous(struct client *c, unused struct cmd *cmd) +cmd_send_string(struct buffer *b, const char *s) { - if (session_previous(c->session) == 0) - server_window_changed(c); - else - server_write_message(c, "No previous window"); -} + size_t n; + + if (s == NULL) { + n = 0; + buffer_write(b, &n, sizeof n); + return; + } -void -cmd_fn_refresh(struct client *c, unused struct cmd *cmd) -{ - server_draw_client(c, 0, c->sy - 1); -} + n = strlen(s) + 1; + buffer_write(b, &n, sizeof n); -void -cmd_fn_select(struct client *c, struct cmd *cmd) -{ - if (session_select(c->session, cmd->num) == 0) - server_window_changed(c); - else - server_write_message(c, "Window %u not present", cmd->num); + buffer_write(b, s, n); } -void -cmd_fn_info(struct client *c, unused struct cmd *cmd) +char * +cmd_recv_string(struct buffer *b) { - struct window *w; - char *buf; - size_t len; - u_int i; + char *s; + size_t n; - len = c->sx + 1; - buf = xmalloc(len); + buffer_read(b, &n, sizeof n); - w = c->session->window; - window_index(&c->session->windows, w, &i); - xsnprintf(buf, len, "%u:%s \"%s\" (size %u,%u) (cursor %u,%u) " - "(region %u,%u)", i, w->name, w->screen.title, w->screen.sx, - w->screen.sy, w->screen.cx, w->screen.cy, w->screen.ry_upper, - w->screen.ry_lower); + if (n == 0) + return (NULL); + + s = xmalloc(n); + buffer_read(b, s, n); + s[n - 1] = '\0'; - server_write_message(c, "%s", buf); - xfree(buf); + return (s); } |