diff --git a/CHANGES b/CHANGES index ebb8877a..628265bb 100644 --- a/CHANGES +++ b/CHANGES @@ -93,6 +93,13 @@ * tmux 0.5 released. +07 January 2009 + +* New flag to set and setw, -u, to unset a option (allowing it to inherit from) + the global options again. +* Added more info messages for options changes. +* A bit of tidying and reorganisation of options code. + 16 November 2008 * New window option: "utf8"; this must be on (it is off by default) for UTF-8 @@ -802,7 +809,7 @@ (including mutt, emacs). No status bar yet and no key remapping or other customisation. -$Id: CHANGES,v 1.180 2009-01-06 18:24:37 nicm Exp $ +$Id: CHANGES,v 1.181 2009-01-07 19:53:17 nicm Exp $ LocalWords: showw utf UTF fulvio ciriaco joshe OSC APC gettime abc DEF OA clr LocalWords: rivo nurges lscm Erdely eol smysession mysession ek dstname RB diff --git a/cmd-generic.c b/cmd-generic.c index 5b4d74c6..d6d5cd96 100644 --- a/cmd-generic.c +++ b/cmd-generic.c @@ -1,4 +1,4 @@ -/* $Id: cmd-generic.c,v 1.15 2008-12-10 20:25:41 nicm Exp $ */ +/* $Id: cmd-generic.c,v 1.16 2009-01-07 19:53:17 nicm Exp $ */ /* * Copyright (c) 2008 Nicholas Marriott <nicm@users.sourceforge.net> @@ -22,6 +22,86 @@ #include "tmux.h" +#define CMD_FLAGS "dgku" + +int cmd_do_flags(int, int, int *); +size_t cmd_print_flags(char *, size_t, size_t, int); +int cmd_fill_argument(int, char **, int, char **); + +int +cmd_do_flags(int opt, int iflags, int *oflags) +{ + switch (opt) { + case 'd': + if (iflags & CMD_DFLAG) { + (*oflags) |= CMD_DFLAG; + return (0); + } + return (-1); + case 'g': + if (iflags & CMD_GFLAG) { + (*oflags) |= CMD_GFLAG; + return (0); + } + return (-1); + case 'k': + if (iflags & CMD_KFLAG) { + (*oflags) |= CMD_KFLAG; + return (0); + } + return (-1); + case 'u': + if (iflags & CMD_UFLAG) { + (*oflags) |= CMD_UFLAG; + return (0); + } + return (-1); + } + return (1); +} + +size_t +cmd_print_flags(char *buf, size_t len, size_t off, int flags) +{ + if ((flags & (CMD_DFLAG|CMD_GFLAG|CMD_KFLAG|CMD_UFLAG)) == 0) + return (0); + off += xsnprintf(buf + off, len - off, " -"); + if (off < len && flags & CMD_DFLAG) + off += xsnprintf(buf + off, len - off, "d"); + if (off < len && flags & CMD_GFLAG) + off += xsnprintf(buf + off, len - off, "g"); + if (off < len && flags & CMD_KFLAG) + off += xsnprintf(buf + off, len - off, "k"); + if (off < len && flags & CMD_UFLAG) + off += xsnprintf(buf + off, len - off, "u"); + return (off); +} + +int +cmd_fill_argument(int flags, char **arg, int argc, char **argv) +{ + *arg = NULL; + + if (flags & CMD_ONEARG) { + if (argc != 1) + return (-1); + *arg = xstrdup(argv[0]); + return (0); + } + + if (flags & CMD_ZEROONEARG) { + if (argc != 0 && argc != 1) + return (-1); + if (argc == 1) + *arg = xstrdup(argv[0]); + return (0); + } + + if (argc != 0) + return (-1); + return (0); +} + void cmd_target_init(struct cmd *self, unused int key) { @@ -43,26 +123,14 @@ cmd_target_parse(struct cmd *self, int argc, char **argv, char **cause) cmd_target_init(self, 0); data = self->data; - while ((opt = getopt(argc, argv, "dgkt:")) != -1) { + while ((opt = getopt(argc, argv, CMD_FLAGS "t:")) != -1) { + switch (cmd_do_flags(opt, self->entry->flags, &data->flags)) { + case -1: + goto usage; + case 0: + continue; + } switch (opt) { - case 'd': - if (self->entry->flags & CMD_DFLAG) { - data->flags |= CMD_DFLAG; - break; - } - goto usage; - case 'g': - if (self->entry->flags & CMD_GFLAG) { - data->flags |= CMD_GFLAG; - break; - } - goto usage; - case 'k': - if (self->entry->flags & CMD_KFLAG) { - data->flags |= CMD_KFLAG; - break; - } - goto usage; case 't': if (data->target == NULL) data->target = xstrdup(optarg); @@ -74,21 +142,8 @@ cmd_target_parse(struct cmd *self, int argc, char **argv, char **cause) argc -= optind; argv += optind; - if (self->entry->flags & CMD_ONEARG) { - if (argc != 1) - goto usage; - data->arg = xstrdup(argv[0]); - } else if (self->entry->flags & CMD_ZEROONEARG) { - if (argc == 0) - data->arg = NULL; - else if (argc == 1) - data->arg = xstrdup(argv[0]); - else - goto usage; - } else { - if (argc != 0) - goto usage; - } + if (cmd_fill_argument(self->entry->flags, &data->arg, argc, argv) != 0) + goto usage; return (0); usage: @@ -140,12 +195,7 @@ cmd_target_print(struct cmd *self, char *buf, size_t len) off += xsnprintf(buf, len, "%s", self->entry->name); if (data == NULL) return; - if (off < len && data->flags & CMD_DFLAG) - off += xsnprintf(buf + off, len - off, " -d"); - if (off < len && data->flags & CMD_GFLAG) - off += xsnprintf(buf + off, len - off, " -g"); - if (off < len && data->flags & CMD_KFLAG) - off += xsnprintf(buf + off, len - off, " -k"); + off += cmd_print_flags(buf, len, off, data->flags); if (off < len && data->target != NULL) off += xsnprintf(buf + off, len - off, " -t %s", data->target); if (off < len && data->arg != NULL) @@ -173,26 +223,14 @@ cmd_srcdst_parse(struct cmd *self, int argc, char **argv, char **cause) cmd_srcdst_init(self, 0); data = self->data; - while ((opt = getopt(argc, argv, "dgks:t:")) != -1) { + while ((opt = getopt(argc, argv, CMD_FLAGS "s:t:")) != -1) { + switch (cmd_do_flags(opt, self->entry->flags, &data->flags)) { + case -1: + goto usage; + case 0: + continue; + } switch (opt) { - case 'd': - if (self->entry->flags & CMD_DFLAG) { - data->flags |= CMD_DFLAG; - break; - } - goto usage; - case 'g': - if (self->entry->flags & CMD_GFLAG) { - data->flags |= CMD_GFLAG; - break; - } - goto usage; - case 'k': - if (self->entry->flags & CMD_KFLAG) { - data->flags |= CMD_KFLAG; - break; - } - goto usage; case 's': if (data->src == NULL) data->src = xstrdup(optarg); @@ -208,21 +246,8 @@ cmd_srcdst_parse(struct cmd *self, int argc, char **argv, char **cause) argc -= optind; argv += optind; - if (self->entry->flags & CMD_ONEARG) { - if (argc != 1) - goto usage; - data->arg = xstrdup(argv[0]); - } else if (self->entry->flags & CMD_ZEROONEARG) { - if (argc == 0) - data->arg = NULL; - else if (argc == 1) - data->arg = xstrdup(argv[0]); - else - goto usage; - } else { - if (argc != 0) - goto usage; - } + if (cmd_fill_argument(self->entry->flags, &data->arg, argc, argv) != 0) + goto usage; return (0); usage: @@ -278,12 +303,7 @@ cmd_srcdst_print(struct cmd *self, char *buf, size_t len) off += xsnprintf(buf, len, "%s", self->entry->name); if (data == NULL) return; - if (off < len && data->flags & CMD_DFLAG) - off += xsnprintf(buf + off, len - off, " -d"); - if (off < len && data->flags & CMD_GFLAG) - off += xsnprintf(buf + off, len - off, " -g"); - if (off < len && data->flags & CMD_KFLAG) - off += xsnprintf(buf + off, len - off, " -k"); + off += cmd_print_flags(buf, len, off, data->flags); if (off < len && data->src != NULL) off += xsnprintf(buf + off, len - off, " -s %s", data->src); if (off < len && data->dst != NULL) @@ -314,37 +334,24 @@ cmd_buffer_parse(struct cmd *self, int argc, char **argv, char **cause) cmd_buffer_init(self, 0); data = self->data; - while ((opt = getopt(argc, argv, "b:dgkt:")) != -1) { + while ((opt = getopt(argc, argv, CMD_FLAGS "b:t:")) != -1) { + switch (cmd_do_flags(opt, self->entry->flags, &data->flags)) { + case -1: + goto usage; + case 0: + continue; + } switch (opt) { case 'b': if (data->buffer == -1) { n = strtonum(optarg, 0, INT_MAX, &errstr); if (errstr != NULL) { - xasprintf( - cause, "buffer index %s", errstr); + xasprintf(cause, "buffer %s", errstr); goto error; } data->buffer = n; } break; - case 'd': - if (self->entry->flags & CMD_DFLAG) { - data->flags |= CMD_DFLAG; - break; - } - goto usage; - case 'g': - if (self->entry->flags & CMD_GFLAG) { - data->flags |= CMD_GFLAG; - break; - } - goto usage; - case 'k': - if (self->entry->flags & CMD_KFLAG) { - data->flags |= CMD_KFLAG; - break; - } - goto usage; case 't': if (data->target == NULL) data->target = xstrdup(optarg); @@ -356,21 +363,8 @@ cmd_buffer_parse(struct cmd *self, int argc, char **argv, char **cause) argc -= optind; argv += optind; - if (self->entry->flags & CMD_ONEARG) { - if (argc != 1) - goto usage; - data->arg = xstrdup(argv[0]); - } else if (self->entry->flags & CMD_ZEROONEARG) { - if (argc == 0) - data->arg = NULL; - else if (argc == 1) - data->arg = xstrdup(argv[0]); - else - goto usage; - } else { - if (argc != 0) - goto usage; - } + if (cmd_fill_argument(self->entry->flags, &data->arg, argc, argv) != 0) + goto usage; return (0); usage: @@ -423,12 +417,7 @@ cmd_buffer_print(struct cmd *self, char *buf, size_t len) off += xsnprintf(buf, len, "%s", self->entry->name); if (data == NULL) return; - if (off < len && data->flags & CMD_DFLAG) - off += xsnprintf(buf + off, len - off, " -d"); - if (off < len && data->flags & CMD_GFLAG) - off += xsnprintf(buf + off, len - off, " -g"); - if (off < len && data->flags & CMD_KFLAG) - off += xsnprintf(buf + off, len - off, " -k"); + off += cmd_print_flags(buf, len, off, data->flags); if (off < len && data->buffer != -1) off += xsnprintf(buf + off, len - off, " -b %d", data->buffer); if (off < len && data->target != NULL) @@ -459,26 +448,14 @@ cmd_option_parse(struct cmd *self, int argc, char **argv, char **cause) cmd_option_init(self, 0); data = self->data; - while ((opt = getopt(argc, argv, "dgkt:")) != -1) { + while ((opt = getopt(argc, argv, CMD_FLAGS "t:")) != -1) { + switch (cmd_do_flags(opt, self->entry->flags, &data->flags)) { + case -1: + goto usage; + case 0: + continue; + } switch (opt) { - case 'd': - if (self->entry->flags & CMD_DFLAG) { - data->flags |= CMD_DFLAG; - break; - } - goto usage; - case 'g': - if (self->entry->flags & CMD_GFLAG) { - data->flags |= CMD_GFLAG; - break; - } - goto usage; - case 'k': - if (self->entry->flags & CMD_KFLAG) { - data->flags |= CMD_KFLAG; - break; - } - goto usage; case 't': if (data->target == NULL) data->target = xstrdup(optarg); @@ -552,12 +529,7 @@ cmd_option_print(struct cmd *self, char *buf, size_t len) off += xsnprintf(buf, len, "%s", self->entry->name); if (data == NULL) return; - if (off < len && data->flags & CMD_DFLAG) - off += xsnprintf(buf + off, len - off, " -d"); - if (off < len && data->flags & CMD_GFLAG) - off += xsnprintf(buf + off, len - off, " -g"); - if (off < len && data->flags & CMD_KFLAG) - off += xsnprintf(buf + off, len - off, " -k"); + off += cmd_print_flags(buf, len, off, data->flags); if (off < len && data->target != NULL) off += xsnprintf(buf + off, len - off, " -t %s", data->target); if (off < len && data->option != NULL) diff --git a/cmd-set-option.c b/cmd-set-option.c index a2d11f82..2f0a2f72 100644 --- a/cmd-set-option.c +++ b/cmd-set-option.c @@ -1,4 +1,4 @@ -/* $Id: cmd-set-option.c,v 1.47 2008-12-10 20:25:41 nicm Exp $ */ +/* $Id: cmd-set-option.c,v 1.48 2009-01-07 19:53:17 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> @@ -31,8 +31,8 @@ void cmd_set_option_exec(struct cmd *, struct cmd_ctx *); const struct cmd_entry cmd_set_option_entry = { "set-option", "set", - "[-t target-session] option value", - CMD_GFLAG, + CMD_OPTION_SESSION_USAGE, + CMD_GFLAG|CMD_UFLAG, NULL, cmd_option_parse, cmd_set_option_exec, @@ -108,27 +108,47 @@ cmd_set_option_exec(struct cmd *self, struct cmd_ctx *ctx) return; } - switch (entry->type) { - case SET_OPTION_STRING: - set_option_string(ctx, oo, entry, data->value); - break; - case SET_OPTION_NUMBER: - set_option_number(ctx, oo, entry, data->value); - break; - case SET_OPTION_KEY: - set_option_key(ctx, oo, entry, data->value); - break; - case SET_OPTION_COLOUR: - set_option_colour(ctx, oo, entry, data->value); - break; - case SET_OPTION_FLAG: - set_option_flag(ctx, oo, entry, data->value); - break; - case SET_OPTION_CHOICE: - set_option_choice(ctx, oo, entry, data->value); - break; - } + if (data->flags & CMD_UFLAG) { + if (data->flags & CMD_GFLAG) { + ctx->error(ctx, + "can't unset global option: %s", entry->name); + return; + } + if (data->value != NULL) { + ctx->error(ctx, + "value passed to unset option: %s", entry->name); + return; + } + if (options_remove(oo, entry->name) != 0) { + ctx->error(ctx, + "can't unset option, not set: %s", entry->name); + return; + } + ctx->info(ctx, "unset option: %s", entry->name); + } else { + switch (entry->type) { + case SET_OPTION_STRING: + set_option_string(ctx, oo, entry, data->value); + break; + case SET_OPTION_NUMBER: + set_option_number(ctx, oo, entry, data->value); + break; + case SET_OPTION_KEY: + set_option_key(ctx, oo, entry, data->value); + break; + case SET_OPTION_COLOUR: + set_option_colour(ctx, oo, entry, data->value); + break; + case SET_OPTION_FLAG: + set_option_flag(ctx, oo, entry, data->value); + break; + case SET_OPTION_CHOICE: + set_option_choice(ctx, oo, entry, data->value); + break; + } + } + recalculate_sizes(); for (i = 0; i < ARRAY_LENGTH(&clients); i++) { c = ARRAY_ITEM(&clients, i); diff --git a/cmd-set-window-option.c b/cmd-set-window-option.c index 36bd3e81..c0684d18 100644 --- a/cmd-set-window-option.c +++ b/cmd-set-window-option.c @@ -1,4 +1,4 @@ -/* $Id: cmd-set-window-option.c,v 1.15 2008-12-10 20:25:41 nicm Exp $ */ +/* $Id: cmd-set-window-option.c,v 1.16 2009-01-07 19:53:17 nicm Exp $ */ /* * Copyright (c) 2008 Nicholas Marriott <nicm@users.sourceforge.net> @@ -36,8 +36,8 @@ void cmd_set_window_option_print(struct cmd *, char *, size_t); const struct cmd_entry cmd_set_window_option_entry = { "set-window-option", "setw", - "[-g] [-t target-window] option value", - CMD_GFLAG, + CMD_OPTION_WINDOW_USAGE, + CMD_GFLAG|CMD_UFLAG, NULL, cmd_option_parse, cmd_set_window_option_exec, @@ -105,27 +105,47 @@ cmd_set_window_option_exec(struct cmd *self, struct cmd_ctx *ctx) return; } - switch (entry->type) { - case SET_OPTION_STRING: - set_option_string(ctx, oo, entry, data->value); - break; - case SET_OPTION_NUMBER: - set_option_number(ctx, oo, entry, data->value); - break; - case SET_OPTION_KEY: - set_option_key(ctx, oo, entry, data->value); - break; - case SET_OPTION_COLOUR: - set_option_colour(ctx, oo, entry, data->value); - break; - case SET_OPTION_FLAG: - set_option_flag(ctx, oo, entry, data->value); - break; - case SET_OPTION_CHOICE: - set_option_choice(ctx, oo, entry, data->value); - break; - } + if (data->flags & CMD_UFLAG) { + if (data->flags & CMD_GFLAG) { + ctx->error(ctx, + "can't unset global option: %s", entry->name); + return; + } + if (data->value != NULL) { + ctx->error(ctx, + "value passed to unset option: %s", entry->name); + return; + } + if (options_remove(oo, entry->name) != 0) { + ctx->error(ctx, + "can't unset option, not set: %s", entry->name); + return; + } + ctx->info(ctx, "unset option: %s", entry->name); + } else { + switch (entry->type) { + case SET_OPTION_STRING: + set_option_string(ctx, oo, entry, data->value); + break; + case SET_OPTION_NUMBER: + set_option_number(ctx, oo, entry, data->value); + break; + case SET_OPTION_KEY: + set_option_key(ctx, oo, entry, data->value); + break; + case SET_OPTION_COLOUR: + set_option_colour(ctx, oo, entry, data->value); + break; + case SET_OPTION_FLAG: + set_option_flag(ctx, oo, entry, data->value); + break; + case SET_OPTION_CHOICE: + set_option_choice(ctx, oo, entry, data->value); + break; + } + } + recalculate_sizes(); for (i = 0; i < ARRAY_LENGTH(&clients); i++) { c = ARRAY_ITEM(&clients, i); diff --git a/options-cmd.c b/options-cmd.c index 6a2e9e58..106def0b 100644 --- a/options-cmd.c +++ b/options-cmd.c @@ -1,4 +1,4 @@ -/* $Id: options-cmd.c,v 1.1 2008-12-08 16:19:51 nicm Exp $ */ +/* $Id: options-cmd.c,v 1.2 2009-01-07 19:53:17 nicm Exp $ */ /* * Copyright (c) 2008 Nicholas Marriott <nicm@users.sourceforge.net> @@ -33,6 +33,7 @@ set_option_string(struct cmd_ctx *ctx, struct options *oo, } options_set_string(oo, entry->name, "%s", value); + ctx->info(ctx, "set option: %s -> %s", entry->name, value); } void @@ -53,6 +54,7 @@ set_option_number(struct cmd_ctx *ctx, struct options *oo, return; } options_set_number(oo, entry->name, number); + ctx->info(ctx, "set option: %s -> %lld", entry->name, number); } void @@ -71,7 +73,8 @@ set_option_key(struct cmd_ctx *ctx, struct options *oo, return; } options_set_number(oo, entry->name, key); - + ctx->info(ctx, + "set option: %s -> %s", entry->name, key_string_lookup_key(key)); } void @@ -91,6 +94,8 @@ set_option_colour(struct cmd_ctx *ctx, struct options *oo, } options_set_number(oo, entry->name, colour); + ctx->info(ctx, + "set option: %s -> %s", entry->name, colour_tostring(colour)); } void @@ -117,6 +122,8 @@ set_option_flag(struct cmd_ctx *ctx, struct options *oo, } options_set_number(oo, entry->name, flag); + ctx->info(ctx, + "set option: %s -> %s", entry->name, flag ? "on" : "off"); } void @@ -149,4 +156,6 @@ set_option_choice(struct cmd_ctx *ctx, struct options *oo, } options_set_number(oo, entry->name, choice); + ctx->info(ctx, + "set option: %s -> %s", entry->name, entry->choices[choice]); } diff --git a/options.c b/options.c index 63ff6e4f..140135ea 100644 --- a/options.c +++ b/options.c @@ -1,4 +1,4 @@ -/* $Id: options.c,v 1.3 2008-06-23 07:41:21 nicm Exp $ */ +/* $Id: options.c,v 1.4 2009-01-07 19:53:17 nicm Exp $ */ /* * Copyright (c) 2008 Nicholas Marriott <nicm@users.sourceforge.net> @@ -83,6 +83,22 @@ options_find(struct options *oo, const char *name) return (o); } +int +options_remove(struct options *oo, const char *name) +{ + struct options_entry *o; + + if ((o = options_find1(oo, name)) == NULL) + return (-1); + + SPLAY_REMOVE(options_tree, &oo->tree, o); + xfree(o->name); + if (o->type == OPTIONS_STRING) + xfree(o->value.string); + xfree(o); + return (0); +} + void printflike3 options_set_string(struct options *oo, const char *name, const char *fmt, ...) { diff --git a/tmux.h b/tmux.h index d709c18d..11294f38 100644 --- a/tmux.h +++ b/tmux.h @@ -1,4 +1,4 @@ -/* $Id: tmux.h,v 1.207 2009-01-06 17:04:56 nicm Exp $ */ +/* $Id: tmux.h,v 1.208 2009-01-07 19:53:17 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> @@ -796,6 +796,7 @@ struct cmd_entry { #define CMD_ONEARG 0x10 #define CMD_ZEROONEARG 0x20 #define CMD_GFLAG 0x40 +#define CMD_UFLAG 0x80 int flags; void (*init)(struct cmd *, int); @@ -948,6 +949,7 @@ void options_init(struct options *, struct options *); void options_free(struct options *); struct options_entry *options_find1(struct options *, const char *); struct options_entry *options_find(struct options *, const char *); +int options_remove(struct options *, const char *); void printflike3 options_set_string( struct options *, const char *, const char *, ...); char *options_get_string(struct options *, const char *); @@ -1102,9 +1104,9 @@ void cmd_buffer_send(struct cmd *, struct buffer *); void cmd_buffer_recv(struct cmd *, struct buffer *); void cmd_buffer_free(struct cmd *); void cmd_buffer_print(struct cmd *, char *, size_t); -#define CMD_OPTION_WINDOW_USAGE "[-t target-window] option value" -#define CMD_OPTION_SESSION_USAGE "[-t target-session] option value" -#define CMD_OPTION_CLIENT_USAGE "[-t target-client] option value" +#define CMD_OPTION_WINDOW_USAGE "[-gu] [-t target-window] option [value]" +#define CMD_OPTION_SESSION_USAGE "[-gu] [-t target-session] option [value]" +#define CMD_OPTION_CLIENT_USAGE "[-gu] [-t target-client] option [value]" void cmd_option_init(struct cmd *, int); int cmd_option_parse(struct cmd *, int, char **, char **); void cmd_option_exec(struct cmd *, struct cmd_ctx *);