diff --git a/CHANGES b/CHANGES index b3768f18..a9bf027b 100644 --- a/CHANGES +++ b/CHANGES @@ -1,3 +1,37 @@ +06 December 2008 + +* Bring set/setw/show/showw into line with other commands. This means that by + default they now affect the current window (if any); the new -g flag must be + passed to set the global options. This changes the behaviour of set/show and + WILL BREAK CURRENT CONFIGURATIONS. + + In summary, whether in the configuration file, the command prompt, or a key + binding, use -g to set a global option, use -t to specify a particular window + or session, or omit both to try and use the current window or session. + + This makes set/show a bit of a pain but is the correct behaviour for + setw/showw and is the same as every other command, so we can put up with a + bit of pain for consistency. +* Redo window options. They now work in the same way to session options with a + global options set. showw/setw commands now have similar syntax to show/set + (including the ability to use abbreviations). + + PLEASE NOTE this includes the following configuration-breaking changes: + + - remain-by-default is now GONE, use "setw -g remain-on-exit" to apply the + global window option instead; + - mode-keys is now a window option rather than session - use "setw [-g] + mode-keys" instead of set. + + There are also some additions: + + - message-fg and message-bg session options to control status line message + colours; + - mode-fg and mode-bg window options to set colours in window modes such as + copy mode. + + The options code still a mess and now there is twice as much of it :-(. + 02 December 2008 * Add support for including the window title in status-left or status-right @@ -272,7 +306,7 @@ 07 June 2008 -* Make status-interval actually changable. +* Make status-interval actually changeable. 06 June 2008 @@ -355,7 +389,7 @@ * -s to specify session name now supports fnmatch(3) wildcards; if multiple sessions are found, or if no -s is specified, the most newly created is used. * If no command is specified, assume new-session. As a byproduct, clean up - command default values into seperate init functions. + command default values into separate init functions. * kill-server command. 02 June 2008 @@ -669,7 +703,7 @@ a serious problem when it comes to things like scrolling. This change consolidates all the range checking and limiting together which should make it easier. -* (mxey) Added window remaming, like "tmux rename [-s session] [-i index] name" +* (mxey) Added window renaming, like "tmux rename [-s session] [-i index] name" 27 September 2007 @@ -728,4 +762,8 @@ (including mutt, emacs). No status bar yet and no key remapping or other customisation. -$Id: CHANGES,v 1.169 2008-12-05 20:04:06 nicm Exp $ +$Id: CHANGES,v 1.170 2008-12-08 16:19:51 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 + LocalWords: dstidx srcname srcidx winlink lsw nabc sabc Exp diff --git a/GNUmakefile b/GNUmakefile index ee69a306..eaf27ff8 100644 --- a/GNUmakefile +++ b/GNUmakefile @@ -1,13 +1,13 @@ -# $Id: GNUmakefile,v 1.42 2008-09-26 06:45:25 nicm Exp $ +# $Id: GNUmakefile,v 1.43 2008-12-08 16:19:51 nicm Exp $ .PHONY: clean PROG= tmux -VERSION= 0.5 +VERSION= 0.6 DATE= $(shell date +%Y%m%d-%H%M) -#DEBUG= 1 +DEBUG= 1 META?= \002 @@ -33,7 +33,7 @@ SRCS= tmux.c server.c server-msg.c server-fn.c buffer.c buffer-poll.c status.c \ cmd-list-commands.c cmd-move-window.c cmd-select-prompt.c \ cmd-respawn-window.c \ window-scroll.c window-more.c window-copy.c options.c paste.c \ - tty.c tty-keys.c tty-write.c colour.c utf8.c + tty.c tty-keys.c tty-write.c colour.c utf8.c options-cmd.c CC?= gcc INCDIRS+= -I. -I- diff --git a/Makefile b/Makefile index ada7be6a..b331580e 100644 --- a/Makefile +++ b/Makefile @@ -1,10 +1,10 @@ -# $Id: Makefile,v 1.78 2008-12-05 20:04:06 nicm Exp $ +# $Id: Makefile,v 1.79 2008-12-08 16:19:51 nicm Exp $ .SUFFIXES: .c .o .y .h .PHONY: clean update-index.html upload-index.html PROG= tmux -VERSION= 0.5 +VERSION= 0.6 OS!= uname REL!= uname -r @@ -37,7 +37,7 @@ SRCS= tmux.c server.c server-msg.c server-fn.c buffer.c buffer-poll.c status.c \ cmd-list-commands.c cmd-move-window.c cmd-select-prompt.c \ cmd-respawn-window.c \ window-scroll.c window-more.c window-copy.c options.c paste.c \ - tty.c tty-keys.c tty-write.c colour.c utf8.c + tty.c tty-keys.c tty-write.c colour.c utf8.c options-cmd.c CC?= cc INCDIRS+= -I. -I- -I/usr/local/include diff --git a/TODO b/TODO index 34dd15c4..be612baf 100644 --- a/TODO +++ b/TODO @@ -52,3 +52,5 @@ - vi half page scroll - why do home/end work in emacs outside tmux but not inside? - document status line options, title bits +- document mode-fg/mode-bg/message-fg/message-bg +- document window options changes diff --git a/cmd-generic.c b/cmd-generic.c index f1322d1c..c3632055 100644 --- a/cmd-generic.c +++ b/cmd-generic.c @@ -1,4 +1,4 @@ -/* $Id: cmd-generic.c,v 1.13 2008-09-25 23:28:12 nicm Exp $ */ +/* $Id: cmd-generic.c,v 1.14 2008-12-08 16:19:51 nicm Exp $ */ /* * Copyright (c) 2008 Nicholas Marriott @@ -44,7 +44,7 @@ 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, GETOPT_PREFIX "dkt:")) != EOF) { + while ((opt = getopt(argc, argv, GETOPT_PREFIX "dgkt:")) != EOF) { switch (opt) { case 'd': if (self->entry->flags & CMD_DFLAG) { @@ -52,6 +52,12 @@ cmd_target_parse(struct cmd *self, int argc, char **argv, char **cause) 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; @@ -137,6 +143,8 @@ cmd_target_print(struct cmd *self, char *buf, size_t len) 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"); if (off < len && data->target != NULL) @@ -166,7 +174,7 @@ 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, GETOPT_PREFIX "dks:t:")) != EOF) { + while ((opt = getopt(argc, argv, GETOPT_PREFIX "dgks:t:")) != EOF) { switch (opt) { case 'd': if (self->entry->flags & CMD_DFLAG) { @@ -174,6 +182,12 @@ cmd_srcdst_parse(struct cmd *self, int argc, char **argv, char **cause) 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; @@ -267,6 +281,8 @@ cmd_srcdst_print(struct cmd *self, char *buf, size_t len) 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"); if (off < len && data->src != NULL) @@ -299,7 +315,7 @@ 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, GETOPT_PREFIX "b:dkt:")) != EOF) { + while ((opt = getopt(argc, argv, GETOPT_PREFIX "b:dgkt:")) != EOF) { switch (opt) { case 'b': if (data->buffer == -1) { @@ -318,6 +334,12 @@ cmd_buffer_parse(struct cmd *self, int argc, char **argv, char **cause) 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; @@ -404,6 +426,8 @@ cmd_buffer_print(struct cmd *self, char *buf, size_t len) 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"); if (off < len && data->buffer != -1) @@ -413,3 +437,132 @@ cmd_buffer_print(struct cmd *self, char *buf, size_t len) if (off < len && data->arg != NULL) off += xsnprintf(buf + off, len - off, " %s", data->arg); } + +void +cmd_option_init(struct cmd *self, unused int key) +{ + struct cmd_option_data *data; + + self->data = data = xmalloc(sizeof *data); + data->flags = 0; + data->target = NULL; + data->option = NULL; + data->value = NULL; +} + +int +cmd_option_parse(struct cmd *self, int argc, char **argv, char **cause) +{ + struct cmd_option_data *data; + int opt; + + /* Don't use the entry version since it may be dependent on key. */ + cmd_option_init(self, 0); + data = self->data; + + while ((opt = getopt(argc, argv, GETOPT_PREFIX "dgkt:")) != EOF) { + 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); + break; + default: + goto usage; + } + } + argc -= optind; + argv += optind; + + if (argc == 2) { + data->option = xstrdup(argv[0]); + data->value = xstrdup(argv[1]); + } else if (argc == 1) + data->option = xstrdup(argv[0]); + else + goto usage; + return (0); + +usage: + xasprintf(cause, "usage: %s %s", self->entry->name, self->entry->usage); + + self->entry->free(self); + return (-1); +} + +void +cmd_option_send(struct cmd *self, struct buffer *b) +{ + struct cmd_option_data *data = self->data; + + buffer_write(b, data, sizeof *data); + cmd_send_string(b, data->target); + cmd_send_string(b, data->option); + cmd_send_string(b, data->value); +} + +void +cmd_option_recv(struct cmd *self, struct buffer *b) +{ + struct cmd_option_data *data; + + self->data = data = xmalloc(sizeof *data); + buffer_read(b, data, sizeof *data); + data->target = cmd_recv_string(b); + data->option = cmd_recv_string(b); + data->value = cmd_recv_string(b); +} + +void +cmd_option_free(struct cmd *self) +{ + struct cmd_option_data *data = self->data; + + if (data->target != NULL) + xfree(data->target); + if (data->option != NULL) + xfree(data->option); + if (data->value != NULL) + xfree(data->value); + xfree(data); +} + +void +cmd_option_print(struct cmd *self, char *buf, size_t len) +{ + struct cmd_option_data *data = self->data; + size_t off = 0; + + 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"); + if (off < len && data->target != NULL) + off += xsnprintf(buf + off, len - off, " -t %s", data->target); + if (off < len && data->option != NULL) + off += xsnprintf(buf + off, len - off, " %s", data->option); + if (off < len && data->value != NULL) + off += xsnprintf(buf + off, len - off, " %s", data->value); +} diff --git a/cmd-set-option.c b/cmd-set-option.c index 93896835..72f6c0a2 100644 --- a/cmd-set-option.c +++ b/cmd-set-option.c @@ -1,4 +1,4 @@ -/* $Id: cmd-set-option.c,v 1.45 2008-12-05 20:04:06 nicm Exp $ */ +/* $Id: cmd-set-option.c,v 1.46 2008-12-08 16:19:51 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott @@ -28,132 +28,61 @@ * Set an option. */ -int cmd_set_option_parse(struct cmd *, int, char **, char **); void cmd_set_option_exec(struct cmd *, struct cmd_ctx *); -void cmd_set_option_send(struct cmd *, struct buffer *); -void cmd_set_option_recv(struct cmd *, struct buffer *); -void cmd_set_option_free(struct cmd *); -void cmd_set_option_print(struct cmd *, char *, size_t); - -struct cmd_set_option_data { - char *target; - int flag_global; - char *option; - char *value; -}; const struct cmd_entry cmd_set_option_entry = { "set-option", "set", "[-t target-session] option value", - 0, + CMD_GFLAG, NULL, - cmd_set_option_parse, + cmd_option_parse, cmd_set_option_exec, - cmd_set_option_send, - cmd_set_option_recv, - cmd_set_option_free, - cmd_set_option_print + cmd_option_send, + cmd_option_recv, + cmd_option_free, + cmd_option_print }; const char *set_option_bell_action_list[] = { "none", "any", "current", NULL }; -const char *set_option_mode_keys_list[] = { - "emacs", "vi", NULL -}; const struct set_option_entry set_option_table[NSETOPTION] = { { "bell-action", SET_OPTION_CHOICE, 0, 0, set_option_bell_action_list }, { "buffer-limit", SET_OPTION_NUMBER, 1, INT_MAX, NULL }, { "default-command", SET_OPTION_STRING, 0, 0, NULL }, { "display-time", SET_OPTION_NUMBER, 1, INT_MAX, NULL }, { "history-limit", SET_OPTION_NUMBER, 0, SHRT_MAX, NULL }, - { "mode-keys", SET_OPTION_CHOICE, 0, 0, set_option_mode_keys_list }, + { "message-bg", SET_OPTION_COLOUR, 0, 0, NULL }, + { "message-fg", SET_OPTION_COLOUR, 0, 0, NULL }, { "prefix", SET_OPTION_KEY, 0, 0, NULL }, - { "remain-by-default", SET_OPTION_FLAG, 0, 0, NULL }, { "set-titles", SET_OPTION_FLAG, 0, 0, NULL }, { "status", SET_OPTION_FLAG, 0, 0, NULL }, { "status-bg", SET_OPTION_COLOUR, 0, 0, NULL }, { "status-fg", SET_OPTION_COLOUR, 0, 0, NULL }, { "status-interval", SET_OPTION_NUMBER, 0, INT_MAX, NULL }, { "status-left", SET_OPTION_STRING, 0, 0, NULL }, - { "status-right", SET_OPTION_STRING, 0, 0, NULL }, { "status-left-length", SET_OPTION_NUMBER, 0, SHRT_MAX, NULL }, + { "status-right", SET_OPTION_STRING, 0, 0, NULL }, { "status-right-length", SET_OPTION_NUMBER, 0, SHRT_MAX, NULL }, - { "utf8", SET_OPTION_FLAG, 0, 0, NULL }, }; -void set_option_string(struct cmd_ctx *, - struct options *, const struct set_option_entry *, char *); -void set_option_number(struct cmd_ctx *, - struct options *, const struct set_option_entry *, char *); -void set_option_key(struct cmd_ctx *, - struct options *, const struct set_option_entry *, char *); -void set_option_colour(struct cmd_ctx *, - struct options *, const struct set_option_entry *, char *); -void set_option_flag(struct cmd_ctx *, - struct options *, const struct set_option_entry *, char *); -void set_option_choice(struct cmd_ctx *, - struct options *, const struct set_option_entry *, char *); - -int -cmd_set_option_parse(struct cmd *self, int argc, char **argv, char **cause) -{ - struct cmd_set_option_data *data; - int opt; - - self->data = data = xmalloc(sizeof *data); - data->target = NULL; - data->flag_global = 1; - data->option = NULL; - data->value = NULL; - - while ((opt = getopt(argc, argv, GETOPT_PREFIX "t:s:")) != EOF) { - switch (opt) { - case 't': - if (data->target == NULL) - data->target = xstrdup(optarg); - data->flag_global = 0; - break; - default: - goto usage; - } - } - argc -= optind; - argv += optind; - if (argc != 1 && argc != 2) - goto usage; - - data->option = xstrdup(argv[0]); - if (argc == 2) - data->value = xstrdup(argv[1]); - - return (0); - -usage: - xasprintf(cause, "usage: %s %s", self->entry->name, self->entry->usage); - - self->entry->free(self); - return (-1); -} - void cmd_set_option_exec(struct cmd *self, struct cmd_ctx *ctx) { - struct cmd_set_option_data *data = self->data; + struct cmd_option_data *data = self->data; struct session *s; struct client *c; struct options *oo; const struct set_option_entry *entry; u_int i; - if (data == NULL) - return; - - if (data->flag_global || - ((s = cmd_find_session(ctx, data->target))) == NULL) + if (data->flags & CMD_GFLAG) oo = &global_options; - else + else { + if ((s = cmd_find_session(ctx, data->target)) == NULL) + return; oo = &s->options; + } if (*data->option == '\0') { ctx->error(ctx, "invalid option"); @@ -211,183 +140,3 @@ cmd_set_option_exec(struct cmd *self, struct cmd_ctx *ctx) if (ctx->cmdclient != NULL) server_write_client(ctx->cmdclient, MSG_EXIT, NULL, 0); } - -void -set_option_string(struct cmd_ctx *ctx, struct options *oo, - const struct set_option_entry *entry, char *value) -{ - if (value == NULL) { - ctx->error(ctx, "empty value"); - return; - } - - options_set_string(oo, entry->name, "%s", value); -} - -void -set_option_number(struct cmd_ctx *ctx, struct options *oo, - const struct set_option_entry *entry, char *value) -{ - long long number; - const char *errstr; - - if (value == NULL) { - ctx->error(ctx, "empty value"); - return; - } - - number = strtonum(value, entry->minimum, entry->maximum, &errstr); - if (errstr != NULL) { - ctx->error(ctx, "value is %s: %s", errstr, value); - return; - } - options_set_number(oo, entry->name, number); -} - -void -set_option_key(struct cmd_ctx *ctx, struct options *oo, - const struct set_option_entry *entry, char *value) -{ - int key; - - if (value == NULL) { - ctx->error(ctx, "empty value"); - return; - } - - if ((key = key_string_lookup_string(value)) == KEYC_NONE) { - ctx->error(ctx, "unknown key: %s", value); - return; - } - options_set_number(oo, entry->name, key); - -} - -void -set_option_colour(struct cmd_ctx *ctx, struct options *oo, - const struct set_option_entry *entry, char *value) -{ - u_char colour; - - if (value == NULL) { - ctx->error(ctx, "empty value"); - return; - } - - if ((colour = colour_fromstring(value)) > 8) { - ctx->error(ctx, "bad colour: %s", value); - return; - } - - options_set_number(oo, entry->name, colour); -} - -void -set_option_flag(struct cmd_ctx *ctx, struct options *oo, - const struct set_option_entry *entry, char *value) -{ - int flag; - - if (value == NULL || *value == '\0') - flag = !options_get_number(oo, entry->name); - else { - if ((value[0] == '1' && value[1] == '\0') || - strcasecmp(value, "on") == 0 || - strcasecmp(value, "yes") == 0) - flag = 1; - else if ((value[0] == '0' && value[1] == '\0') || - strcasecmp(value, "off") == 0 || - strcasecmp(value, "no") == 0) - flag = 0; - else { - ctx->error(ctx, "bad value: %s", value); - return; - } - } - - options_set_number(oo, entry->name, flag); -} - -void -set_option_choice(struct cmd_ctx *ctx, struct options *oo, - const struct set_option_entry *entry, char *value) -{ - const char **choicep; - int n, choice = -1; - - if (value == NULL) { - ctx->error(ctx, "empty value"); - return; - } - - n = 0; - for (choicep = entry->choices; *choicep != NULL; choicep++) { - n++; - if (strncmp(*choicep, value, strlen(value)) != 0) - continue; - - if (choice != -1) { - ctx->error(ctx, "ambiguous option: %s", value); - return; - } - choice = n - 1; - } - if (choice == -1) { - ctx->error(ctx, "unknown option: %s", value); - return; - } - - options_set_number(oo, entry->name, choice); -} - -void -cmd_set_option_send(struct cmd *self, struct buffer *b) -{ - struct cmd_set_option_data *data = self->data; - - buffer_write(b, data, sizeof *data); - cmd_send_string(b, data->target); - cmd_send_string(b, data->option); - cmd_send_string(b, data->value); -} - -void -cmd_set_option_recv(struct cmd *self, struct buffer *b) -{ - struct cmd_set_option_data *data; - - self->data = data = xmalloc(sizeof *data); - buffer_read(b, data, sizeof *data); - data->target = cmd_recv_string(b); - data->option = cmd_recv_string(b); - data->value = cmd_recv_string(b); -} - -void -cmd_set_option_free(struct cmd *self) -{ - struct cmd_set_option_data *data = self->data; - - if (data->target != NULL) - xfree(data->target); - if (data->option != NULL) - xfree(data->option); - if (data->value != NULL) - xfree(data->value); - xfree(data); -} - -void -cmd_set_option_print(struct cmd *self, char *buf, size_t len) -{ - struct cmd_set_option_data *data = self->data; - size_t off = 0; - - off += xsnprintf(buf, len, "%s", self->entry->name); - if (data == NULL) - return; - if (off < len && data->option != NULL) - off += xsnprintf(buf + off, len - off, " %s", data->option); - if (off < len && data->value != NULL) - off += xsnprintf(buf + off, len - off, " %s", data->value); -} diff --git a/cmd-set-window-option.c b/cmd-set-window-option.c index cafce6bb..c628da8d 100644 --- a/cmd-set-window-option.c +++ b/cmd-set-window-option.c @@ -1,7 +1,7 @@ -/* $Id: cmd-set-window-option.c,v 1.13 2008-11-16 13:28:59 nicm Exp $ */ +/* $Id: cmd-set-window-option.c,v 1.14 2008-12-08 16:19:51 nicm Exp $ */ /* - * Copyright (c) 2007 Nicholas Marriott + * Copyright (c) 2008 Nicholas Marriott * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -35,286 +35,105 @@ void cmd_set_window_option_recv(struct cmd *, struct buffer *); void cmd_set_window_option_free(struct cmd *); void cmd_set_window_option_print(struct cmd *, char *, size_t); -struct cmd_set_window_option_data { - char *target; - char *option; - char *value; -}; - const struct cmd_entry cmd_set_window_option_entry = { "set-window-option", "setw", - "[-t target-window] option value", - 0, + "[-g] [-t target-window] option value", + CMD_GFLAG, NULL, - cmd_set_window_option_parse, + cmd_option_parse, cmd_set_window_option_exec, - cmd_set_window_option_send, - cmd_set_window_option_recv, - cmd_set_window_option_free, - cmd_set_window_option_print + cmd_option_send, + cmd_option_recv, + cmd_option_free, + cmd_option_print }; -int -cmd_set_window_option_parse( - struct cmd *self, int argc, char **argv, char **cause) -{ - struct cmd_set_window_option_data *data; - int opt; - - self->data = data = xmalloc(sizeof *data); - data->target = NULL; - data->option = NULL; - data->value = NULL; - - while ((opt = getopt(argc, argv, GETOPT_PREFIX "t:")) != EOF) { - switch (opt) { - case 't': - if (data->target == NULL) - data->target = xstrdup(optarg); - break; - default: - goto usage; - } - } - argc -= optind; - argv += optind; - if (argc != 1 && argc != 2) - goto usage; - - data->option = xstrdup(argv[0]); - if (argc == 2) - data->value = xstrdup(argv[1]); - - return (0); - -usage: - xasprintf(cause, "usage: %s %s", self->entry->name, self->entry->usage); - - self->entry->free(self); - return (-1); -} +const char *set_option_mode_keys_list[] = { + "emacs", "vi", NULL +}; +const struct set_option_entry set_window_option_table[NSETWINDOWOPTION] = { + { "aggressive-resize", SET_OPTION_FLAG, 0, 0, NULL }, + { "force-height", SET_OPTION_NUMBER, 0, INT_MAX, NULL }, + { "force-width", SET_OPTION_NUMBER, 0, INT_MAX, NULL }, + { "mode-bg", SET_OPTION_COLOUR, 0, 0, NULL }, + { "mode-fg", SET_OPTION_COLOUR, 0, 0, NULL }, + { "mode-keys", SET_OPTION_CHOICE, 0, 0, set_option_mode_keys_list }, + { "monitor-activity", SET_OPTION_FLAG, 0, 0, NULL }, + { "remain-on-exit", SET_OPTION_FLAG, 0, 0, NULL }, + { "utf8", SET_OPTION_FLAG, 0, 0, NULL }, +}; void cmd_set_window_option_exec(struct cmd *self, struct cmd_ctx *ctx) { - struct cmd_set_window_option_data *data = self->data; - struct winlink *wl; - struct session *s; - const char *errstr; - int number, flag; - u_int i; + struct cmd_option_data *data = self->data; + struct winlink *wl; + struct client *c; + struct options *oo; + const struct set_option_entry *entry; + u_int i; - if (data == NULL) - return; - - wl = cmd_find_window(ctx, data->target, &s); - if (wl == NULL) - return; + if (data->flags & CMD_GFLAG) + oo = &global_window_options; + else { + if ((wl = cmd_find_window(ctx, data->target, NULL)) == NULL) + return; + oo = &wl->window->options; + } if (*data->option == '\0') { ctx->error(ctx, "invalid option"); return; } - number = -1; - if (data->value != NULL) { - number = strtonum(data->value, 0, INT_MAX, &errstr); - - flag = -1; - if (number == 1 || strcasecmp(data->value, "on") == 0 || - strcasecmp(data->value, "yes") == 0) - flag = 1; - else if (number == 0 || strcasecmp(data->value, "off") == 0 || - strcasecmp(data->value, "no") == 0) - flag = 0; - } else - flag = -2; - - if (strcmp(data->option, "monitor-activity") == 0) { - if (flag == -1) { - ctx->error(ctx, "bad value: %s", data->value); + entry = NULL; + for (i = 0; i < NSETWINDOWOPTION; i++) { + if (strncmp(set_window_option_table[i].name, + data->option, strlen(data->option)) != 0) + continue; + if (entry != NULL) { + ctx->error(ctx, "ambiguous option: %s", data->option); return; } + entry = &set_window_option_table[i]; - if (flag == -2) - wl->window->flags ^= WINDOW_MONITOR; - else { - if (flag) - wl->window->flags |= WINDOW_MONITOR; - else - wl->window->flags &= ~WINDOW_MONITOR; - } - - if (wl->window->flags & WINDOW_MONITOR) { - ctx->info(ctx, "window %s:%d: set %s", - s->name, wl->idx, data->option); - } else { - ctx->info(ctx, "window %s:%d: cleared %s", - s->name, wl->idx, data->option); - } - - for (i = 0; i < ARRAY_LENGTH(&sessions); i++) { - s = ARRAY_ITEM(&sessions, i); - if (s != NULL) - session_alert_cancel(s, wl); - } - } else if (strcmp(data->option, "aggressive-resize") == 0) { - if (flag == -1) { - ctx->error(ctx, "bad value: %s", data->value); - return; - } - - if (flag == -2) - wl->window->flags ^= WINDOW_AGGRESSIVE; - else { - if (flag) - wl->window->flags |= WINDOW_AGGRESSIVE; - else - wl->window->flags &= ~WINDOW_AGGRESSIVE; - } - - if (wl->window->flags & WINDOW_AGGRESSIVE) { - ctx->info(ctx, "window %s:%d: set %s", - s->name, wl->idx, data->option); - } else { - ctx->info(ctx, "window %s:%d: cleared %s", - s->name, wl->idx, data->option); - } - - recalculate_sizes(); - } else if (strcmp(data->option, "utf8") == 0) { - if (flag == -1) { - ctx->error(ctx, "bad value: %s", data->value); - return; - } - - if (flag == -2) - wl->window->flags ^= WINDOW_UTF8; - else { - if (flag) - wl->window->flags |= WINDOW_UTF8; - else - wl->window->flags &= ~WINDOW_UTF8; - } - - if (wl->window->flags & WINDOW_UTF8) { - ctx->info(ctx, "window %s:%d: set %s", - s->name, wl->idx, data->option); - } else { - ctx->info(ctx, "window %s:%d: cleared %s", - s->name, wl->idx, data->option); - } - - recalculate_sizes(); - } else if (strcmp(data->option, "force-width") == 0) { - if (data->value == NULL || number == -1) { - ctx->error(ctx, "invalid value"); - return; - } - if (errstr != NULL) { - ctx->error(ctx, "force-width %s", errstr); - return; - } - if (number == 0) - wl->window->limitx = UINT_MAX; - else - wl->window->limitx = number; - - ctx->info(ctx, "window %s:%d: set force-width %u", - s->name, wl->idx, number); - - recalculate_sizes(); - } else if (strcmp(data->option, "force-height") == 0) { - if (data->value == NULL || number == -1) { - ctx->error(ctx, "invalid value"); - return; - } - if (errstr != NULL) { - ctx->error(ctx, "force-height %s", errstr); - return; - } - if (number == 0) - wl->window->limity = UINT_MAX; - else - wl->window->limity = number; - - ctx->info(ctx, "window %s:%d: set force-height %u", - s->name, wl->idx, number); - - recalculate_sizes(); - } else if (strcmp(data->option, "remain-on-exit") == 0) { - if (flag == -1) { - ctx->error(ctx, "bad value: %s", data->value); - return; - } - - if (flag == -2) - wl->window->flags ^= WINDOW_ZOMBIFY; - else { - if (flag) - wl->window->flags |= WINDOW_ZOMBIFY; - else - wl->window->flags &= ~WINDOW_ZOMBIFY; - } - } else { + /* Bail now if an exact match. */ + if (strcmp(entry->name, data->option) == 0) + break; + } + if (entry == NULL) { ctx->error(ctx, "unknown option: %s", data->option); 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; + } + + recalculate_sizes(); + for (i = 0; i < ARRAY_LENGTH(&clients); i++) { + c = ARRAY_ITEM(&clients, i); + if (c != NULL && c->session != NULL) + server_redraw_client(c); + } + if (ctx->cmdclient != NULL) server_write_client(ctx->cmdclient, MSG_EXIT, NULL, 0); } - -void -cmd_set_window_option_send(struct cmd *self, struct buffer *b) -{ - struct cmd_set_window_option_data *data = self->data; - - buffer_write(b, data, sizeof *data); - cmd_send_string(b, data->target); - cmd_send_string(b, data->option); - cmd_send_string(b, data->value); -} - -void -cmd_set_window_option_recv(struct cmd *self, struct buffer *b) -{ - struct cmd_set_window_option_data *data; - - self->data = data = xmalloc(sizeof *data); - buffer_read(b, data, sizeof *data); - data->target = cmd_recv_string(b); - data->option = cmd_recv_string(b); - data->value = cmd_recv_string(b); -} - -void -cmd_set_window_option_free(struct cmd *self) -{ - struct cmd_set_window_option_data *data = self->data; - - if (data->target != NULL) - xfree(data->target); - if (data->option != NULL) - xfree(data->option); - if (data->value != NULL) - xfree(data->value); - xfree(data); -} - -void -cmd_set_window_option_print(struct cmd *self, char *buf, size_t len) -{ - struct cmd_set_window_option_data *data = self->data; - size_t off = 0; - - off += xsnprintf(buf, len, "%s", self->entry->name); - if (data == NULL) - return; - if (off < len && data->target != NULL) - off += xsnprintf(buf + off, len - off, " -t %s", data->target); - if (off < len && data->option != NULL) - off += xsnprintf(buf + off, len - off, " %s", data->option); - if (off < len && data->value != NULL) - off += xsnprintf(buf + off, len - off, " %s", data->value); -} diff --git a/cmd-show-options.c b/cmd-show-options.c index c7ed643d..de1e728e 100644 --- a/cmd-show-options.c +++ b/cmd-show-options.c @@ -1,4 +1,4 @@ -/* $Id: cmd-show-options.c,v 1.7 2008-09-25 23:28:15 nicm Exp $ */ +/* $Id: cmd-show-options.c,v 1.8 2008-12-08 16:19:51 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott @@ -28,74 +28,25 @@ * Show options. */ -int cmd_show_options_parse(struct cmd *, int, char **, char **); void cmd_show_options_exec(struct cmd *, struct cmd_ctx *); -void cmd_show_options_send(struct cmd *, struct buffer *); -void cmd_show_options_recv(struct cmd *, struct buffer *); -void cmd_show_options_free(struct cmd *); -void cmd_show_options_print(struct cmd *, char *, size_t); -struct cmd_show_options_data { - char *target; - int flag_global; -}; - -/* - * XXX Can't use cmd_target because we want -t not to use current if missing - * (this could be a flag??). - */ const struct cmd_entry cmd_show_options_entry = { "show-options", "show", - "[-t target-session]", - 0, - NULL, - cmd_show_options_parse, + "[-g] " CMD_TARGET_SESSION_USAGE, + CMD_GFLAG, + cmd_target_init, + cmd_target_parse, cmd_show_options_exec, - cmd_show_options_send, - cmd_show_options_recv, - cmd_show_options_free, - cmd_show_options_print + cmd_target_send, + cmd_target_recv, + cmd_target_free, + cmd_target_print }; -int -cmd_show_options_parse(struct cmd *self, int argc, char **argv, char **cause) -{ - struct cmd_show_options_data *data; - int opt; - - self->data = data = xmalloc(sizeof *data); - data->target = NULL; - data->flag_global = 1; - - while ((opt = getopt(argc, argv, GETOPT_PREFIX "t:s:")) != EOF) { - switch (opt) { - case 't': - if (data->target == NULL) - data->target = xstrdup(optarg); - data->flag_global = 0; - break; - default: - goto usage; - } - } - argc -= optind; - argv += optind; - if (argc != 0) - goto usage; - - return (0); - -usage: - xasprintf(cause, "usage: %s %s", self->entry->name, self->entry->usage); - - self->entry->free(self); - return (-1); -} - void cmd_show_options_exec(struct cmd *self, struct cmd_ctx *ctx) { - struct cmd_show_options_data *data = self->data; + struct cmd_target_data *data = self->data; struct session *s; struct options *oo; const struct set_option_entry *entry; @@ -103,14 +54,13 @@ cmd_show_options_exec(struct cmd *self, struct cmd_ctx *ctx) char *vs; long long vn; - if (data == NULL) - return; - - if (data->flag_global || - ((s = cmd_find_session(ctx, data->target))) == NULL) + if (data->flags & CMD_GFLAG) oo = &global_options; - else + else { + if ((s = cmd_find_session(ctx, data->target)) == NULL) + return; oo = &s->options; + } for (i = 0; i < NSETOPTION; i++) { entry = &set_option_table[i]; @@ -155,38 +105,3 @@ cmd_show_options_exec(struct cmd *self, struct cmd_ctx *ctx) if (ctx->cmdclient != NULL) server_write_client(ctx->cmdclient, MSG_EXIT, NULL, 0); } - -void -cmd_show_options_send(struct cmd *self, struct buffer *b) -{ - struct cmd_show_options_data *data = self->data; - - buffer_write(b, data, sizeof *data); - cmd_send_string(b, data->target); -} - -void -cmd_show_options_recv(struct cmd *self, struct buffer *b) -{ - struct cmd_show_options_data *data; - - self->data = data = xmalloc(sizeof *data); - buffer_read(b, data, sizeof *data); - data->target = cmd_recv_string(b); -} - -void -cmd_show_options_free(struct cmd *self) -{ - struct cmd_show_options_data *data = self->data; - - if (data->target != NULL) - xfree(data->target); - xfree(data); -} - -void -cmd_show_options_print(struct cmd *self, char *buf, size_t len) -{ - xsnprintf(buf, len, "%s", self->entry->name); -} diff --git a/cmd-show-window-options.c b/cmd-show-window-options.c index bc8054dd..1336a2c6 100644 --- a/cmd-show-window-options.c +++ b/cmd-show-window-options.c @@ -1,7 +1,7 @@ -/* $Id: cmd-show-window-options.c,v 1.3 2008-11-16 13:28:59 nicm Exp $ */ +/* $Id: cmd-show-window-options.c,v 1.4 2008-12-08 16:19:51 nicm Exp $ */ /* - * Copyright (c) 2007 Nicholas Marriott + * Copyright (c) 2008 Nicholas Marriott * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -20,6 +20,7 @@ #include #include +#include #include "tmux.h" @@ -31,8 +32,8 @@ void cmd_show_window_options_exec(struct cmd *, struct cmd_ctx *); const struct cmd_entry cmd_show_window_options_entry = { "show-window-options", "showw", - CMD_TARGET_WINDOW_USAGE, - 0, + "[-g] " CMD_TARGET_WINDOW_USAGE, + CMD_GFLAG, cmd_target_init, cmd_target_parse, cmd_show_window_options_exec, @@ -45,25 +46,61 @@ const struct cmd_entry cmd_show_window_options_entry = { void cmd_show_window_options_exec(struct cmd *self, struct cmd_ctx *ctx) { - struct cmd_target_data *data = self->data; - struct winlink *wl; - struct session *s; + struct cmd_target_data *data = self->data; + struct winlink *wl; + struct options *oo; + const struct set_option_entry *entry; + u_int i; + char *vs; + long long vn; - if ((wl = cmd_find_window(ctx, data->target, &s)) == NULL) - return; + if (data->flags & CMD_GFLAG) + oo = &global_window_options; + else { + if ((wl = cmd_find_window(ctx, data->target, NULL)) == NULL) + return; + oo = &wl->window->options; + } - if (wl->window->flags & WINDOW_AGGRESSIVE) - ctx->print(ctx, "aggressive-resize"); - if (wl->window->limitx != UINT_MAX) - ctx->print(ctx, "force-width %u", wl->window->limitx); - if (wl->window->limity != UINT_MAX) - ctx->print(ctx, "force-height %u", wl->window->limity); - if (wl->window->flags & WINDOW_MONITOR) - ctx->print(ctx, "monitor-activity"); - if (wl->window->flags & WINDOW_ZOMBIFY) - ctx->print(ctx, "remain-on-exit"); - if (wl->window->flags & WINDOW_UTF8) - ctx->print(ctx, "utf8"); + for (i = 0; i < NSETWINDOWOPTION; i++) { + entry = &set_window_option_table[i]; + + if (options_find1(oo, entry->name) == NULL) + continue; + + switch (entry->type) { + case SET_OPTION_STRING: + vs = options_get_string(oo, entry->name); + ctx->print(ctx, "%s \"%s\"", entry->name, vs); + break; + case SET_OPTION_NUMBER: + vn = options_get_number(oo, entry->name); + ctx->print(ctx, "%s %lld", entry->name, vn); + break; + case SET_OPTION_KEY: + vn = options_get_number(oo, entry->name); + ctx->print(ctx, "%s %s", + entry->name, key_string_lookup_key(vn)); + break; + case SET_OPTION_COLOUR: + vn = options_get_number(oo, entry->name); + ctx->print(ctx, "%s %s", + entry->name, colour_tostring(vn)); + break; + case SET_OPTION_FLAG: + vn = options_get_number(oo, entry->name); + if (vn) + ctx->print(ctx, "%s on", entry->name); + else + ctx->print(ctx, "%s off", entry->name); + break; + case SET_OPTION_CHOICE: + vn = options_get_number(oo, entry->name); + ctx->print(ctx, "%s %s", + entry->name, entry->choices[vn]); + break; + } + } if (ctx->cmdclient != NULL) server_write_client(ctx->cmdclient, MSG_EXIT, NULL, 0); diff --git a/cmd-string.c b/cmd-string.c index b896701e..45677310 100644 --- a/cmd-string.c +++ b/cmd-string.c @@ -1,4 +1,4 @@ -/* $Id: cmd-string.c,v 1.7 2008-09-26 06:45:26 nicm Exp $ */ +/* $Id: cmd-string.c,v 1.8 2008-12-08 16:19:51 nicm Exp $ */ /* * Copyright (c) 2008 Nicholas Marriott @@ -131,7 +131,8 @@ cmd_string_parse(const char *s, struct cmd **cmd, char **cause) if (argc == 0) goto out; - *cmd = cmd_parse(argc, argv, cause); + if ((*cmd = cmd_parse(argc, argv, cause)) == NULL) + goto error; rval = 0; goto out; default: @@ -145,7 +146,7 @@ cmd_string_parse(const char *s, struct cmd **cmd, char **cause) } error: - xasprintf(cause, "bad command: %s", s); + xasprintf(cause, "invalid or unknown command: %s", s); out: if (buf != NULL) diff --git a/examples/n-marriott.conf b/examples/n-marriott.conf index 5650f004..c3695fbc 100644 --- a/examples/n-marriott.conf +++ b/examples/n-marriott.conf @@ -1,32 +1,29 @@ # Default global options. -set status-bg green -set default-command "exec /bin/ksh -l" -set bell-action none +set -g status-bg green +set -g status-right-length 60 +set -g default-command "exec /bin/ksh -l" +set -g bell-action none + +# Default global window options. +setw -g remain-on-exit on # Prefix key. -set prefix ^A +set -g prefix ^A unbind ^B bind ^A send-prefix # Keys to switch session. bind q switch -t0 -bind Q switch -t0 bind w switch -t1 -bind W switch -t1 bind e switch -t2 -bind E switch -t2 # Other key bindings. bind i list-windows -bind I list-windows bind m setw monitor-activity -bind M setw monitor-activity bind y setw force-width 81 -bind Y setw force-width 81 bind u setw force-width 0 -bind U setw force-width 0 # First session. new -d -s0 -nirssi 'screen -DRS irssi irssi' # safe from pkill tmux ;-) @@ -35,7 +32,7 @@ setw -t0:0 aggressive-resize on set -t0 status-bg green set -t0 status-left '[0]' neww -d -ntodo 'exec emacs ~/TODO' -neww -d -nncmpc +neww -d -nncmpc 'exec ncmpc -f ~/.ncmpc.conf' neww -d neww -d neww -d diff --git a/input.c b/input.c index 2ff1ec5e..9f5cb6b0 100644 --- a/input.c +++ b/input.c @@ -1,4 +1,4 @@ -/* $Id: input.c,v 1.68 2008-12-05 20:04:06 nicm Exp $ */ +/* $Id: input.c,v 1.69 2008-12-08 16:19:51 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott @@ -512,7 +512,7 @@ input_state_utf8(u_char ch, struct input_ctx *ictx) void input_handle_character(u_char ch, struct input_ctx *ictx) { - if (ictx->w->flags & WINDOW_UTF8 && ch > 0x7f) { + if (ch > 0x7f && options_get_number(&ictx->w->options, "utf8")) { /* * UTF-8 sequence. * diff --git a/log.c b/log.c index 631ec5b9..a97f5eb8 100644 --- a/log.c +++ b/log.c @@ -1,4 +1,4 @@ -/* $Id: log.c,v 1.9 2008-10-09 05:31:04 nicm Exp $ */ +/* $Id: log.c,v 1.10 2008-12-08 16:19:51 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott @@ -225,9 +225,6 @@ log_vfatal(const char *msg, va_list ap) } free(fmt); -#ifdef DEBUG - abort(); -#endif exit(1); } diff --git a/options-cmd.c b/options-cmd.c new file mode 100644 index 00000000..6a2e9e58 --- /dev/null +++ b/options-cmd.c @@ -0,0 +1,152 @@ +/* $Id: options-cmd.c,v 1.1 2008-12-08 16:19:51 nicm Exp $ */ + +/* + * Copyright (c) 2008 Nicholas Marriott + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER + * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include + +#include +#include + +#include "tmux.h" + +void +set_option_string(struct cmd_ctx *ctx, struct options *oo, + const struct set_option_entry *entry, char *value) +{ + if (value == NULL) { + ctx->error(ctx, "empty value"); + return; + } + + options_set_string(oo, entry->name, "%s", value); +} + +void +set_option_number(struct cmd_ctx *ctx, struct options *oo, + const struct set_option_entry *entry, char *value) +{ + long long number; + const char *errstr; + + if (value == NULL) { + ctx->error(ctx, "empty value"); + return; + } + + number = strtonum(value, entry->minimum, entry->maximum, &errstr); + if (errstr != NULL) { + ctx->error(ctx, "value is %s: %s", errstr, value); + return; + } + options_set_number(oo, entry->name, number); +} + +void +set_option_key(struct cmd_ctx *ctx, struct options *oo, + const struct set_option_entry *entry, char *value) +{ + int key; + + if (value == NULL) { + ctx->error(ctx, "empty value"); + return; + } + + if ((key = key_string_lookup_string(value)) == KEYC_NONE) { + ctx->error(ctx, "unknown key: %s", value); + return; + } + options_set_number(oo, entry->name, key); + +} + +void +set_option_colour(struct cmd_ctx *ctx, struct options *oo, + const struct set_option_entry *entry, char *value) +{ + u_char colour; + + if (value == NULL) { + ctx->error(ctx, "empty value"); + return; + } + + if ((colour = colour_fromstring(value)) > 8) { + ctx->error(ctx, "bad colour: %s", value); + return; + } + + options_set_number(oo, entry->name, colour); +} + +void +set_option_flag(struct cmd_ctx *ctx, struct options *oo, + const struct set_option_entry *entry, char *value) +{ + int flag; + + if (value == NULL || *value == '\0') + flag = !options_get_number(oo, entry->name); + else { + if ((value[0] == '1' && value[1] == '\0') || + strcasecmp(value, "on") == 0 || + strcasecmp(value, "yes") == 0) + flag = 1; + else if ((value[0] == '0' && value[1] == '\0') || + strcasecmp(value, "off") == 0 || + strcasecmp(value, "no") == 0) + flag = 0; + else { + ctx->error(ctx, "bad value: %s", value); + return; + } + } + + options_set_number(oo, entry->name, flag); +} + +void +set_option_choice(struct cmd_ctx *ctx, struct options *oo, + const struct set_option_entry *entry, char *value) +{ + const char **choicep; + int n, choice = -1; + + if (value == NULL) { + ctx->error(ctx, "empty value"); + return; + } + + n = 0; + for (choicep = entry->choices; *choicep != NULL; choicep++) { + n++; + if (strncmp(*choicep, value, strlen(value)) != 0) + continue; + + if (choice != -1) { + ctx->error(ctx, "ambiguous option: %s", value); + return; + } + choice = n - 1; + } + if (choice == -1) { + ctx->error(ctx, "unknown option: %s", value); + return; + } + + options_set_number(oo, entry->name, choice); +} diff --git a/resize.c b/resize.c index ca9059de..4068e471 100644 --- a/resize.c +++ b/resize.c @@ -1,4 +1,4 @@ -/* $Id: resize.c,v 1.16 2008-06-19 22:04:02 nicm Exp $ */ +/* $Id: resize.c,v 1.17 2008-12-08 16:19:51 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott @@ -48,7 +48,8 @@ recalculate_sizes(void) struct session *s; struct client *c; struct window *w; - u_int i, j, ssx, ssy, has; + u_int i, j, ssx, ssy, has, limit; + int flag; for (i = 0; i < ARRAY_LENGTH(&sessions); i++) { s = ARRAY_ITEM(&sessions, i); @@ -93,13 +94,14 @@ recalculate_sizes(void) w = ARRAY_ITEM(&windows, i); if (w == NULL) continue; + flag = options_get_number(&w->options, "aggressive-resize"); ssx = ssy = UINT_MAX; for (j = 0; j < ARRAY_LENGTH(&sessions); j++) { s = ARRAY_ITEM(&sessions, j); if (s == NULL || s->flags & SESSION_UNATTACHED) continue; - if (w->flags & WINDOW_AGGRESSIVE) + if (flag) has = s->curw->window == w; else has = session_has(s, w); @@ -116,10 +118,12 @@ recalculate_sizes(void) } w->flags &= ~WINDOW_HIDDEN; - if (ssx > w->limitx) - ssx = w->limitx; - if (ssy > w->limity) - ssy = w->limity; + limit = options_get_number(&w->options, "force-width"); + if (limit != 0 && ssx > limit) + ssx = limit; + limit = options_get_number(&w->options, "force-height"); + if (limit != 0 && ssy > limit) + ssy = limit; if (screen_size_x(&w->base) == ssx && screen_size_y(&w->base) == ssy) diff --git a/screen-redraw.c b/screen-redraw.c index 1b6b5b47..4f6286f5 100644 --- a/screen-redraw.c +++ b/screen-redraw.c @@ -1,4 +1,4 @@ -/* $Id: screen-redraw.c,v 1.13 2008-09-26 06:45:26 nicm Exp $ */ +/* $Id: screen-redraw.c,v 1.14 2008-12-08 16:19:51 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott @@ -124,7 +124,7 @@ void screen_redraw_cell(struct screen_redraw_ctx *ctx, u_int px, u_int py) { const struct grid_cell *gc; - struct grid_cell hc; + struct grid_cell tc; if (px != ctx->s->cx || py != ctx->s->cy) { ctx->s->cx = px; @@ -134,9 +134,9 @@ screen_redraw_cell(struct screen_redraw_ctx *ctx, u_int px, u_int py) gc = grid_view_peek_cell(ctx->s->grid, px, py); if (screen_check_selection(ctx->s, px, py)) { - memcpy(&hc, gc, sizeof hc); - hc.attr |= GRID_ATTR_REVERSE; - ctx->write(ctx->data, TTY_CELL, &hc); + memcpy(&tc, &ctx->s->sel.cell, sizeof tc); + tc.data = gc->data; + ctx->write(ctx->data, TTY_CELL, &tc); } else ctx->write(ctx->data, TTY_CELL, gc); ctx->s->cx++; diff --git a/screen-write.c b/screen-write.c index 19f5b9ae..633f02a9 100644 --- a/screen-write.c +++ b/screen-write.c @@ -1,4 +1,4 @@ -/* $Id: screen-write.c,v 1.16 2008-11-12 23:38:40 nicm Exp $ */ +/* $Id: screen-write.c,v 1.17 2008-12-08 16:19:51 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott @@ -608,8 +608,8 @@ screen_write_cell(struct screen_write_ctx *ctx, const struct grid_cell *gc) if (ctx->write != NULL) { if (screen_check_selection(ctx->s, s->cx, s->cy)) { - memcpy(&tc, gc, sizeof tc); - tc.attr |= GRID_ATTR_REVERSE; + memcpy(&tc, &ctx->s->sel.cell, sizeof tc); + tc.data = gc->data; ctx->write(ctx->data, TTY_CELL, &tc); } else ctx->write(ctx->data, TTY_CELL, gc); diff --git a/screen.c b/screen.c index 550eb58a..6a30f3a7 100644 --- a/screen.c +++ b/screen.c @@ -1,4 +1,4 @@ -/* $Id: screen.c,v 1.76 2008-10-09 05:31:04 nicm Exp $ */ +/* $Id: screen.c,v 1.77 2008-12-08 16:19:51 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott @@ -183,10 +183,13 @@ screen_resize_y(struct screen *s, u_int sy) /* Set selection. */ void -screen_set_selection(struct screen *s, u_int sx, u_int sy, u_int ex, u_int ey) +screen_set_selection(struct screen *s, + u_int sx, u_int sy, u_int ex, u_int ey, struct grid_cell *gc) { struct screen_sel *sel = &s->sel; + memcpy(&sel->cell, gc, sizeof sel->cell); + sel->flag = 1; if (ey < sy || (sy == ey && ex < sx)) { sel->sx = ex; sel->sy = ey; diff --git a/server.c b/server.c index 33dffa91..8ee3efb8 100644 --- a/server.c +++ b/server.c @@ -1,4 +1,4 @@ -/* $Id: server.c,v 1.85 2008-12-05 20:04:06 nicm Exp $ */ +/* $Id: server.c,v 1.86 2008-12-08 16:19:51 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott @@ -612,7 +612,7 @@ server_handle_window(struct window *w) update = 1; } - if ((w->flags & WINDOW_MONITOR) && + if (options_get_number(&w->options, "monitor-activity") && (w->flags & WINDOW_ACTIVITY) && !session_alert_has_window(s, w, WINDOW_ACTIVITY)) { session_alert_add(s, w, WINDOW_ACTIVITY); @@ -637,7 +637,7 @@ server_lost_window(struct window *w) log_debug("lost window %d", w->fd); - if (w->flags & WINDOW_ZOMBIFY) { + if (options_get_number(&w->options, "remain-on-exit")) { w->fd = -1; return; } diff --git a/session.c b/session.c index d3af7388..ee83f445 100644 --- a/session.c +++ b/session.c @@ -1,4 +1,4 @@ -/* $Id: session.c,v 1.46 2008-11-16 13:28:59 nicm Exp $ */ +/* $Id: session.c,v 1.47 2008-12-08 16:19:51 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott @@ -207,11 +207,6 @@ session_new(struct session *s, const char *name, const char *cmd, int idx) if ((w = window_create(name, cmd, env, s->sx, s->sy, hlimit)) == NULL) return (NULL); - if (options_get_number(&s->options, "remain-by-default")) - w->flags |= WINDOW_ZOMBIFY; - if (options_get_number(&s->options, "utf8-default")) - w->flags |= WINDOW_UTF8; - return (session_attach(s, w, idx)); } diff --git a/status.c b/status.c index 16a558e7..d4e9cf5e 100644 --- a/status.c +++ b/status.c @@ -1,4 +1,4 @@ -/* $Id: status.c,v 1.51 2008-12-05 20:04:06 nicm Exp $ */ +/* $Id: status.c,v 1.52 2008-12-08 16:19:51 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott @@ -369,6 +369,7 @@ void status_message_redraw(struct client *c) { struct screen_redraw_ctx ctx; + struct session *s = c->session; size_t xx, yy; struct grid_cell gc; @@ -381,7 +382,8 @@ status_message_redraw(struct client *c) yy = c->sy - 1; memcpy(&gc, &grid_default_cell, sizeof gc); - gc.attr |= GRID_ATTR_REVERSE; + gc.fg = options_get_number(&s->options, "message-fg"); + gc.bg = options_get_number(&s->options, "message-bg"); screen_redraw_start_client(&ctx, c); @@ -400,6 +402,7 @@ void status_prompt_redraw(struct client *c) { struct screen_redraw_ctx ctx; + struct session *s = c->session; size_t i, xx, yy, left, size, offset; char ch; struct grid_cell gc; @@ -414,7 +417,8 @@ status_prompt_redraw(struct client *c) yy = c->sy - 1; memcpy(&gc, &grid_default_cell, sizeof gc); - gc.attr |= GRID_ATTR_REVERSE; + gc.fg = options_get_number(&s->options, "message-fg"); + gc.bg = options_get_number(&s->options, "message-bg"); screen_redraw_start_client(&ctx, c); @@ -448,7 +452,8 @@ status_prompt_redraw(struct client *c) ch = c->prompt_buffer[c->prompt_index]; if (ch == '\0') ch = ' '; - gc.attr &= ~GRID_ATTR_REVERSE; + gc.bg = gc.fg; + gc.fg = options_get_number(&s->options, "message-bg"); screen_redraw_putc(&ctx, &gc, ch); screen_redraw_stop(&ctx); diff --git a/tmux.c b/tmux.c index 36983f76..ed2c7acf 100644 --- a/tmux.c +++ b/tmux.c @@ -1,4 +1,4 @@ -/* $Id: tmux.c,v 1.82 2008-12-05 20:04:06 nicm Exp $ */ +/* $Id: tmux.c,v 1.83 2008-12-08 16:19:51 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott @@ -48,6 +48,7 @@ volatile sig_atomic_t sigterm; char *cfg_file; struct options global_options; +struct options global_window_options; int debug_level; int be_quiet; @@ -232,9 +233,18 @@ main(int argc, char **argv) options_set_number(&global_options, "status-interval", 15); options_set_number(&global_options, "set-titles", 1); options_set_number(&global_options, "buffer-limit", 9); - options_set_number(&global_options, "remain-by-default", 0); - options_set_number(&global_options, "mode-keys", MODEKEY_EMACS); - options_set_number(&global_options, "utf8-default", 0); + options_set_number(&global_options, "message-fg", 0); + options_set_number(&global_options, "message-bg", 3); + options_init(&global_window_options, NULL); + options_set_number(&global_window_options, "monitor-activity", 0); + options_set_number(&global_window_options, "aggressive-resize", 0); + options_set_number(&global_window_options, "remain-on-exit", 0); + options_set_number(&global_window_options, "utf8", 0); + options_set_number(&global_window_options, "mode-fg", 0); + options_set_number(&global_window_options, "mode-bg", 3); + options_set_number(&global_window_options, "mode-keys", MODEKEY_EMACS); + options_set_number(&global_window_options, "force-width", 0); + options_set_number(&global_window_options, "force-height", 0); if (cfg_file == NULL) { home = getenv("HOME"); @@ -363,6 +373,7 @@ main(int argc, char **argv) out: options_free(&global_options); + options_free(&global_window_options); close(cctx.srv_fd); buffer_destroy(cctx.srv_in); diff --git a/tmux.h b/tmux.h index 4975e5fb..575d0283 100644 --- a/tmux.h +++ b/tmux.h @@ -1,4 +1,4 @@ -/* $Id: tmux.h,v 1.200 2008-12-05 20:04:06 nicm Exp $ */ +/* $Id: tmux.h,v 1.201 2008-12-08 16:19:51 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott @@ -450,6 +450,31 @@ struct grid_data { struct grid_cell **data; }; +/* Option data structures. */ +struct options_entry { + char *name; + + enum { + OPTIONS_STRING, + OPTIONS_NUMBER, + OPTIONS_KEY, + OPTIONS_COLOURS + } type; + union { + char *string; + long long number; + int key; + u_char colours; + } value; + + SPLAY_ENTRY(options_entry) entry; +}; + +struct options { + SPLAY_HEAD(options_tree, options_entry) tree; + struct options *parent; +}; + /* Screen selection. */ struct screen_sel { int flag; @@ -459,6 +484,8 @@ struct screen_sel { u_int ex; u_int ey; + + struct grid_cell cell; }; /* Virtual screen. */ @@ -566,17 +593,12 @@ struct window { struct input_ctx ictx; + struct options options; + int flags; #define WINDOW_BELL 0x1 #define WINDOW_HIDDEN 0x2 #define WINDOW_ACTIVITY 0x4 -#define WINDOW_MONITOR 0x8 -#define WINDOW_AGGRESSIVE 0x10 -#define WINDOW_ZOMBIFY 0x20 -#define WINDOW_UTF8 0x40 - - u_int limitx; - u_int limity; struct screen *screen; struct screen base; @@ -599,31 +621,6 @@ struct winlink { RB_HEAD(winlinks, winlink); SLIST_HEAD(winlink_stack, winlink); -/* Option data structures. */ -struct options_entry { - char *name; - - enum { - OPTIONS_STRING, - OPTIONS_NUMBER, - OPTIONS_KEY, - OPTIONS_COLOURS - } type; - union { - char *string; - long long number; - int key; - u_char colours; - } value; - - SPLAY_ENTRY(options_entry) entry; -}; - -struct options { - SPLAY_HEAD(options_tree, options_entry) tree; - struct options *parent; -}; - /* Paste buffer. */ struct paste_buffer { char *data; @@ -787,6 +784,7 @@ struct cmd_entry { #define CMD_DFLAG 0x8 #define CMD_ONEARG 0x10 #define CMD_ZEROONEARG 0x20 +#define CMD_GFLAG 0x40 int flags; void (*init)(struct cmd *, int); @@ -819,6 +817,13 @@ struct cmd_buffer_data { char *arg; }; +struct cmd_option_data { + int flags; + char *target; + char *option; + char *value; +}; + /* Key binding. */ struct binding { int key; @@ -844,7 +849,9 @@ struct set_option_entry { const char **choices; }; extern const struct set_option_entry set_option_table[]; -#define NSETOPTION 18 +extern const struct set_option_entry set_window_option_table[]; +#define NSETOPTION 17 +#define NSETWINDOWOPTION 9 /* Edit keys. */ enum mode_key { @@ -907,6 +914,7 @@ char *fgetln(FILE *, size_t *); extern volatile sig_atomic_t sigwinch; extern volatile sig_atomic_t sigterm; extern struct options global_options; +extern struct options global_window_options; extern char *cfg_file; extern int debug_level; extern int be_quiet; @@ -956,6 +964,20 @@ void tty_vwrite_window(void *, int, va_list); void tty_write_session(void *, int, ...); void tty_vwrite_session(void *, int, va_list); +/* options-cmd.c */ +void set_option_string(struct cmd_ctx *, + struct options *, const struct set_option_entry *, char *); +void set_option_number(struct cmd_ctx *, + struct options *, const struct set_option_entry *, char *); +void set_option_key(struct cmd_ctx *, + struct options *, const struct set_option_entry *, char *); +void set_option_colour(struct cmd_ctx *, + struct options *, const struct set_option_entry *, char *); +void set_option_flag(struct cmd_ctx *, + struct options *, const struct set_option_entry *, char *); +void set_option_choice(struct cmd_ctx *, + struct options *, const struct set_option_entry *, char *); + /* paste.c */ void paste_init_stack(struct paste_stack *); void paste_free_stack(struct paste_stack *); @@ -1066,6 +1088,16 @@ 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" +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 *); +void cmd_option_send(struct cmd *, struct buffer *); +void cmd_option_recv(struct cmd *, struct buffer *); +void cmd_option_free(struct cmd *); +void cmd_option_print(struct cmd *, char *, size_t); /* client.c */ int client_init(const char *, struct client_ctx *, int, int); @@ -1248,7 +1280,8 @@ void screen_reinit(struct screen *); void screen_free(struct screen *); void screen_set_title(struct screen *, const char *); void screen_resize(struct screen *, u_int, u_int); -void screen_set_selection(struct screen *, u_int, u_int, u_int, u_int); +void screen_set_selection( + struct screen *, u_int, u_int, u_int, u_int, struct grid_cell *); void screen_clear_selection(struct screen *); int screen_check_selection(struct screen *, u_int, u_int); void screen_display_copy_area(struct screen *, struct screen *, diff --git a/window-copy.c b/window-copy.c index 3cfb750f..e9162b40 100644 --- a/window-copy.c +++ b/window-copy.c @@ -1,4 +1,4 @@ -/* $Id: window-copy.c,v 1.33 2008-11-12 23:39:25 nicm Exp $ */ +/* $Id: window-copy.c,v 1.34 2008-12-08 16:19:51 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott @@ -137,7 +137,7 @@ window_copy_key(struct window *w, struct client *c, int key) struct screen *s = &data->screen; int table; - table = options_get_number(&c->session->options, "mode-keys"); + table = options_get_number(&w->options, "mode-keys"); switch (mode_key_lookup(table, key)) { case MODEKEY_QUIT: window_reset_mode(w); @@ -213,10 +213,11 @@ window_copy_write_line(struct window *w, struct screen_write_ctx *ctx, u_int py) memcpy(&gc, &grid_default_cell, sizeof gc); size = xsnprintf(hdr, sizeof hdr, "[%u,%u/%u]", data->ox, data->oy, screen_hsize(&w->base)); - gc.attr |= GRID_ATTR_BRIGHT|GRID_ATTR_REVERSE; + gc.fg = options_get_number(&w->options, "mode-fg"); + gc.bg = options_get_number(&w->options, "mode-bg"); screen_write_cursormove(ctx, screen_size_x(s) - size, 0); screen_write_puts(ctx, &gc, "%s", hdr); - gc.attr &= ~(GRID_ATTR_BRIGHT|GRID_ATTR_REVERSE); + screen_write_puts(ctx, &gc, "%s", hdr); } else size = 0; @@ -308,11 +309,17 @@ window_copy_update_selection(struct window *w) { struct window_copy_mode_data *data = w->modedata; struct screen *s = &data->screen; + struct grid_cell gc; u_int sx, sy, tx, ty; if (!s->sel.flag) return (0); + /* Set colours. */ + memcpy(&gc, &grid_default_cell, sizeof gc); + gc.fg = options_get_number(&w->options, "mode-fg"); + gc.bg = options_get_number(&w->options, "mode-bg"); + /* Find top-left of screen. */ tx = data->ox; ty = screen_hsize(&w->base) - data->oy; @@ -343,7 +350,8 @@ window_copy_update_selection(struct window *w) } sy = screen_hsize(s) + sy; - screen_set_selection(s, sx, sy, data->cx, screen_hsize(s) + data->cy); + screen_set_selection( + s, sx, sy, data->cx, screen_hsize(s) + data->cy, &gc); return (1); } diff --git a/window-more.c b/window-more.c index 75821ed5..4f59d1c8 100644 --- a/window-more.c +++ b/window-more.c @@ -1,4 +1,4 @@ -/* $Id: window-more.c,v 1.20 2008-09-26 06:45:28 nicm Exp $ */ +/* $Id: window-more.c,v 1.21 2008-12-08 16:19:51 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott @@ -123,13 +123,13 @@ window_more_resize(struct window *w, u_int sx, u_int sy) } void -window_more_key(struct window *w, struct client *c, int key) +window_more_key(struct window *w, unused struct client *c, int key) { struct window_more_mode_data *data = w->modedata; struct screen *s = &data->screen; int table; - table = options_get_number(&c->session->options, "mode-keys"); + table = options_get_number(&w->options, "mode-keys"); switch (mode_key_lookup(table, key)) { case MODEKEY_QUIT: window_reset_mode(w); @@ -174,9 +174,10 @@ window_more_write_line(struct window *w, struct screen_write_ctx *ctx, u_int py) size = xsnprintf(hdr, sizeof hdr, "[%u/%u]", data->top, ARRAY_LENGTH(&data->list)); screen_write_cursormove(ctx, screen_size_x(s) - size, 0); - gc.attr |= GRID_ATTR_BRIGHT|GRID_ATTR_REVERSE; + gc.fg = options_get_number(&w->options, "mode-fg"); + gc.bg = options_get_number(&w->options, "mode-bg"); screen_write_puts(ctx, &gc, "%s", hdr); - gc.attr &= ~(GRID_ATTR_BRIGHT|GRID_ATTR_REVERSE); + memcpy(&gc, &grid_default_cell, sizeof gc); } else size = 0; diff --git a/window-scroll.c b/window-scroll.c index 210f66f2..a529a82a 100644 --- a/window-scroll.c +++ b/window-scroll.c @@ -1,4 +1,4 @@ -/* $Id: window-scroll.c,v 1.24 2008-09-25 20:08:57 nicm Exp $ */ +/* $Id: window-scroll.c,v 1.25 2008-12-08 16:19:51 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott @@ -101,13 +101,13 @@ window_scroll_resize(struct window *w, u_int sx, u_int sy) } void -window_scroll_key(struct window *w, struct client *c, int key) +window_scroll_key(struct window *w, unused struct client *c, int key) { struct window_scroll_mode_data *data = w->modedata; struct screen *s = &data->screen; int table; - table = options_get_number(&c->session->options, "mode-keys"); + table = options_get_number(&w->options, "mode-keys"); switch (mode_key_lookup(table, key)) { case MODEKEY_QUIT: window_reset_mode(w); @@ -157,10 +157,11 @@ window_scroll_write_line( memcpy(&gc, &grid_default_cell, sizeof gc); size = xsnprintf(hdr, sizeof hdr, "[%u,%u/%u]", data->ox, data->oy, screen_hsize(&w->base)); - gc.attr |= GRID_ATTR_BRIGHT|GRID_ATTR_REVERSE; + gc.fg = options_get_number(&w->options, "mode-fg"); + gc.bg = options_get_number(&w->options, "mode-bg"); screen_write_cursormove(ctx, screen_size_x(s) - size, 0); screen_write_puts(ctx, &gc, "%s", hdr); - gc.attr &= ~(GRID_ATTR_BRIGHT|GRID_ATTR_REVERSE); + memcpy(&gc, &grid_default_cell, sizeof gc); } else size = 0; diff --git a/window.c b/window.c index 92d955c0..2e33f192 100644 --- a/window.c +++ b/window.c @@ -1,4 +1,4 @@ -/* $Id: window.c,v 1.51 2008-11-16 10:10:26 nicm Exp $ */ +/* $Id: window.c,v 1.52 2008-12-08 16:19:51 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott @@ -207,11 +207,11 @@ window_create(const char *name, w->mode = NULL; w->flags = 0; - w->limitx = w->limity = UINT_MAX; screen_init(&w->base, sx, sy, hlimit); w->screen = &w->base; input_init(w); + options_init(&w->options, &global_window_options); if (name == NULL) { /* XXX */ @@ -308,6 +308,7 @@ window_destroy(struct window *w) input_free(w); window_reset_mode(w); + options_free(&w->options); screen_free(&w->base); buffer_destroy(w->in);