diff --git a/Makefile b/Makefile index 532b19e1..86b28b60 100644 --- a/Makefile +++ b/Makefile @@ -32,7 +32,7 @@ SRCS= attributes.c cfg.c client.c clock.c \ colour.c environ.c grid-view.c grid-utf8.c grid.c input-keys.c \ input.c key-bindings.c key-string.c \ layout-custom.c layout-set.c layout-string.c layout.c log.c job.c \ - mode-key.c names.c options.c paste.c procname.c \ + mode-key.c names.c options.c options-table.c paste.c procname.c \ resize.c screen-redraw.c screen-write.c screen.c session.c status.c \ signal.c server-fn.c server.c server-client.c server-window.c \ tmux.c tty-acs.c tty-keys.c tty-term.c tty.c utf8.c \ diff --git a/cmd-set-option.c b/cmd-set-option.c index 81e3cffa..f15ce052 100644 --- a/cmd-set-option.c +++ b/cmd-set-option.c @@ -29,22 +29,25 @@ int cmd_set_option_exec(struct cmd *, struct cmd_ctx *); -const char *cmd_set_option_print( - const struct set_option_entry *, struct options_entry *); -void cmd_set_option_string(struct cmd_ctx *, - struct options *, const struct set_option_entry *, char *, int); -void cmd_set_option_number(struct cmd_ctx *, - struct options *, const struct set_option_entry *, char *); -void cmd_set_option_keys(struct cmd_ctx *, - struct options *, const struct set_option_entry *, char *); -void cmd_set_option_colour(struct cmd_ctx *, - struct options *, const struct set_option_entry *, char *); -void cmd_set_option_attributes(struct cmd_ctx *, - struct options *, const struct set_option_entry *, char *); -void cmd_set_option_flag(struct cmd_ctx *, - struct options *, const struct set_option_entry *, char *); -void cmd_set_option_choice(struct cmd_ctx *, - struct options *, const struct set_option_entry *, char *); +int cmd_set_option_unset(struct cmd *, struct cmd_ctx *, + const struct options_table_entry *, struct options *); +int cmd_set_option_set(struct cmd *, struct cmd_ctx *, + const struct options_table_entry *, struct options *); + +struct options_entry *cmd_set_option_string(struct cmd *, struct cmd_ctx *, + const struct options_table_entry *, struct options *); +struct options_entry *cmd_set_option_number(struct cmd *, struct cmd_ctx *, + const struct options_table_entry *, struct options *); +struct options_entry *cmd_set_option_keys(struct cmd *, struct cmd_ctx *, + const struct options_table_entry *, struct options *); +struct options_entry *cmd_set_option_colour(struct cmd *, struct cmd_ctx *, + const struct options_table_entry *, struct options *); +struct options_entry *cmd_set_option_attributes(struct cmd *, struct cmd_ctx *, + const struct options_table_entry *, struct options *); +struct options_entry *cmd_set_option_flag(struct cmd *, struct cmd_ctx *, + const struct options_table_entry *, struct options *); +struct options_entry *cmd_set_option_choice(struct cmd *, struct cmd_ctx *, + const struct options_table_entry *, struct options *); const struct cmd_entry cmd_set_option_entry = { "set-option", "set", @@ -57,149 +60,26 @@ const struct cmd_entry cmd_set_option_entry = { cmd_target_print }; -const char *set_option_mode_keys_list[] = { - "emacs", "vi", NULL -}; -const char *set_option_clock_mode_style_list[] = { - "12", "24", NULL -}; -const char *set_option_status_keys_list[] = { - "emacs", "vi", NULL -}; -const char *set_option_status_justify_list[] = { - "left", "centre", "right", NULL -}; -const char *set_option_bell_action_list[] = { - "none", "any", "current", NULL -}; - -const struct set_option_entry set_option_table[] = { - { "buffer-limit", SET_OPTION_NUMBER, 1, INT_MAX, NULL }, - { "escape-time", SET_OPTION_NUMBER, 0, INT_MAX, NULL }, - { "exit-unattached", SET_OPTION_FLAG, 0, 0, NULL }, - { "quiet", SET_OPTION_FLAG, 0, 0, NULL }, - { NULL, 0, 0, 0, NULL } -}; - -const struct set_option_entry set_session_option_table[] = { - { "base-index", SET_OPTION_NUMBER, 0, INT_MAX, NULL }, - { "bell-action", SET_OPTION_CHOICE, 0, 0, set_option_bell_action_list }, - { "default-command", SET_OPTION_STRING, 0, 0, NULL }, - { "default-path", SET_OPTION_STRING, 0, 0, NULL }, - { "default-shell", SET_OPTION_STRING, 0, 0, NULL }, - { "default-terminal", SET_OPTION_STRING, 0, 0, NULL }, - { "destroy-unattached", SET_OPTION_FLAG, 0, 0, NULL }, - { "detach-on-destroy", SET_OPTION_FLAG, 0, 0, NULL }, - { "display-panes-active-colour", SET_OPTION_COLOUR, 0, 0, NULL }, - { "display-panes-colour", SET_OPTION_COLOUR, 0, 0, NULL }, - { "display-panes-time", SET_OPTION_NUMBER, 1, INT_MAX, NULL }, - { "display-time", SET_OPTION_NUMBER, 1, INT_MAX, NULL }, - { "history-limit", SET_OPTION_NUMBER, 0, INT_MAX, NULL }, - { "lock-after-time", SET_OPTION_NUMBER, 0, INT_MAX, NULL }, - { "lock-command", SET_OPTION_STRING, 0, 0, NULL }, - { "lock-server", SET_OPTION_FLAG, 0, 0, NULL }, - { "message-attr", SET_OPTION_ATTRIBUTES, 0, 0, NULL }, - { "message-bg", SET_OPTION_COLOUR, 0, 0, NULL }, - { "message-fg", SET_OPTION_COLOUR, 0, 0, NULL }, - { "message-limit", SET_OPTION_NUMBER, 0, INT_MAX, NULL }, - { "mouse-select-pane", SET_OPTION_FLAG, 0, 0, NULL }, - { "pane-active-border-bg", SET_OPTION_COLOUR, 0, 0, NULL }, - { "pane-active-border-fg", SET_OPTION_COLOUR, 0, 0, NULL }, - { "pane-border-bg", SET_OPTION_COLOUR, 0, 0, NULL }, - { "pane-border-fg", SET_OPTION_COLOUR, 0, 0, NULL }, - { "prefix", SET_OPTION_KEYS, 0, 0, NULL }, - { "repeat-time", SET_OPTION_NUMBER, 0, SHRT_MAX, NULL }, - { "set-remain-on-exit", SET_OPTION_FLAG, 0, 0, NULL }, - { "set-titles", SET_OPTION_FLAG, 0, 0, NULL }, - { "set-titles-string", SET_OPTION_STRING, 0, 0, NULL }, - { "status", SET_OPTION_FLAG, 0, 0, NULL }, - { "status-attr", SET_OPTION_ATTRIBUTES, 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-justify", - SET_OPTION_CHOICE, 0, 0, set_option_status_justify_list }, - { "status-keys", SET_OPTION_CHOICE, 0, 0, set_option_status_keys_list }, - { "status-left", SET_OPTION_STRING, 0, 0, NULL }, - { "status-left-attr", SET_OPTION_ATTRIBUTES, 0, 0, NULL }, - { "status-left-bg", SET_OPTION_COLOUR, 0, 0, NULL }, - { "status-left-fg", SET_OPTION_COLOUR, 0, 0, NULL }, - { "status-left-length", SET_OPTION_NUMBER, 0, SHRT_MAX, NULL }, - { "status-right", SET_OPTION_STRING, 0, 0, NULL }, - { "status-right-attr", SET_OPTION_ATTRIBUTES, 0, 0, NULL }, - { "status-right-bg", SET_OPTION_COLOUR, 0, 0, NULL }, - { "status-right-fg", SET_OPTION_COLOUR, 0, 0, NULL }, - { "status-right-length", SET_OPTION_NUMBER, 0, SHRT_MAX, NULL }, - { "status-utf8", SET_OPTION_FLAG, 0, 0, NULL }, - { "terminal-overrides", SET_OPTION_STRING, 0, 0, NULL }, - { "update-environment", SET_OPTION_STRING, 0, 0, NULL }, - { "visual-activity", SET_OPTION_FLAG, 0, 0, NULL }, - { "visual-bell", SET_OPTION_FLAG, 0, 0, NULL }, - { "visual-content", SET_OPTION_FLAG, 0, 0, NULL }, - { "visual-silence", SET_OPTION_FLAG, 0, 0, NULL }, - { NULL, 0, 0, 0, NULL } -}; - -const struct set_option_entry set_window_option_table[] = { - { "aggressive-resize", SET_OPTION_FLAG, 0, 0, NULL }, - { "alternate-screen", SET_OPTION_FLAG, 0, 0, NULL }, - { "automatic-rename", SET_OPTION_FLAG, 0, 0, NULL }, - { "clock-mode-colour", SET_OPTION_COLOUR, 0, 0, NULL }, - { "clock-mode-style", - SET_OPTION_CHOICE, 0, 0, set_option_clock_mode_style_list }, - { "force-height", SET_OPTION_NUMBER, 0, INT_MAX, NULL }, - { "force-width", SET_OPTION_NUMBER, 0, INT_MAX, NULL }, - { "main-pane-height", SET_OPTION_NUMBER, 1, INT_MAX, NULL }, - { "main-pane-width", SET_OPTION_NUMBER, 1, INT_MAX, NULL }, - { "mode-attr", SET_OPTION_ATTRIBUTES, 0, 0, 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 }, - { "mode-mouse", SET_OPTION_FLAG, 0, 0, NULL }, - { "monitor-activity", SET_OPTION_FLAG, 0, 0, NULL }, - { "monitor-content", SET_OPTION_STRING, 0, 0, NULL }, - { "monitor-silence",SET_OPTION_NUMBER, 0, INT_MAX, NULL}, - { "other-pane-height", SET_OPTION_NUMBER, 0, INT_MAX, NULL }, - { "other-pane-width", SET_OPTION_NUMBER, 0, INT_MAX, NULL }, - { "remain-on-exit", SET_OPTION_FLAG, 0, 0, NULL }, - { "synchronize-panes", SET_OPTION_FLAG, 0, 0, NULL }, - { "utf8", SET_OPTION_FLAG, 0, 0, NULL }, - { "window-status-alert-attr", SET_OPTION_ATTRIBUTES, 0, 0, NULL }, - { "window-status-alert-bg", SET_OPTION_COLOUR, 0, 0, NULL }, - { "window-status-alert-fg", SET_OPTION_COLOUR, 0, 0, NULL }, - { "window-status-attr", SET_OPTION_ATTRIBUTES, 0, 0, NULL }, - { "window-status-bg", SET_OPTION_COLOUR, 0, 0, NULL }, - { "window-status-current-attr", SET_OPTION_ATTRIBUTES, 0, 0, NULL }, - { "window-status-current-bg", SET_OPTION_COLOUR, 0, 0, NULL }, - { "window-status-current-fg", SET_OPTION_COLOUR, 0, 0, NULL }, - { "window-status-current-format", SET_OPTION_STRING, 0, 0, NULL }, - { "window-status-fg", SET_OPTION_COLOUR, 0, 0, NULL }, - { "window-status-format", SET_OPTION_STRING, 0, 0, NULL }, - { "word-separators", SET_OPTION_STRING, 0, 0, NULL }, - { "xterm-keys", SET_OPTION_FLAG, 0, 0, NULL }, - { NULL, 0, 0, 0, NULL } -}; - int cmd_set_option_exec(struct cmd *self, struct cmd_ctx *ctx) { - struct cmd_target_data *data = self->data; - const struct set_option_entry *table; - struct session *s; - struct winlink *wl; - struct client *c; - struct options *oo; - const struct set_option_entry *entry, *opt; - struct jobs *jobs; - struct job *job, *nextjob; - u_int i; - int try_again; + struct cmd_target_data *data = self->data; + const struct options_table_entry *table, *oe, *oe_loop; + struct session *s; + struct winlink *wl; + struct client *c; + struct options *oo; + struct jobs *jobs; + struct job *job, *nextjob; + u_int i; + int try_again; + /* Work out the options tree and table to use. */ if (cmd_check_flag(data->chflags, 's')) { oo = &global_options; - table = set_option_table; + table = server_options_table; } else if (cmd_check_flag(data->chflags, 'w')) { - table = set_window_option_table; + table = window_options_table; if (cmd_check_flag(data->chflags, 'g')) oo = &global_w_options; else { @@ -209,7 +89,7 @@ cmd_set_option_exec(struct cmd *self, struct cmd_ctx *ctx) oo = &wl->window->options; } } else { - table = set_session_option_table; + table = session_options_table; if (cmd_check_flag(data->chflags, 'g')) oo = &global_s_options; else { @@ -220,71 +100,36 @@ cmd_set_option_exec(struct cmd *self, struct cmd_ctx *ctx) } } - if (*data->arg == '\0') { - ctx->error(ctx, "invalid option"); - return (-1); - } - - entry = NULL; - for (opt = table; opt->name != NULL; opt++) { - if (strncmp(opt->name, data->arg, strlen(data->arg)) != 0) + /* Find the option table entry. */ + oe = NULL; + for (oe_loop = table; oe_loop->name != NULL; oe_loop++) { + if (strncmp(oe_loop->name, data->arg, strlen(data->arg)) != 0) continue; - if (entry != NULL) { + if (oe != NULL) { ctx->error(ctx, "ambiguous option: %s", data->arg); return (-1); } - entry = opt; + oe = oe_loop; /* Bail now if an exact match. */ - if (strcmp(entry->name, data->arg) == 0) + if (strcmp(oe->name, data->arg) == 0) break; } - if (entry == NULL) { + if (oe == NULL) { ctx->error(ctx, "unknown option: %s", data->arg); return (-1); } + /* Unset or set the option. */ if (cmd_check_flag(data->chflags, 'u')) { - if (cmd_check_flag(data->chflags, 'g')) { - ctx->error(ctx, - "can't unset global option: %s", entry->name); + if (cmd_set_option_unset(self, ctx, oe, oo) != 0) return (-1); - } - if (data->arg2 != NULL) { - ctx->error(ctx, - "value passed to unset option: %s", entry->name); - return (-1); - } - - options_remove(oo, entry->name); - ctx->info(ctx, "unset option: %s", entry->name); } else { - switch (entry->type) { - case SET_OPTION_STRING: - cmd_set_option_string(ctx, oo, entry, - data->arg2, cmd_check_flag(data->chflags, 'a')); - break; - case SET_OPTION_NUMBER: - cmd_set_option_number(ctx, oo, entry, data->arg2); - break; - case SET_OPTION_KEYS: - cmd_set_option_keys(ctx, oo, entry, data->arg2); - break; - case SET_OPTION_COLOUR: - cmd_set_option_colour(ctx, oo, entry, data->arg2); - break; - case SET_OPTION_ATTRIBUTES: - cmd_set_option_attributes(ctx, oo, entry, data->arg2); - break; - case SET_OPTION_FLAG: - cmd_set_option_flag(ctx, oo, entry, data->arg2); - break; - case SET_OPTION_CHOICE: - cmd_set_option_choice(ctx, oo, entry, data->arg2); - break; - } + if (cmd_set_option_set(self, ctx, oe, oo) != 0) + return (-1); } + /* Update sizes and redraw. May not need it but meh. */ recalculate_sizes(); for (i = 0; i < ARRAY_LENGTH(&clients); i++) { c = ARRAY_ITEM(&clients, i); @@ -297,11 +142,11 @@ cmd_set_option_exec(struct cmd *self, struct cmd_ctx *ctx) * or set-titles-string have changed. Persistent jobs are only used by * the status line at the moment so this works XXX. */ - if (strcmp(entry->name, "status-left") == 0 || - strcmp(entry->name, "status-right") == 0 || - strcmp(entry->name, "status") == 0 || - strcmp(entry->name, "set-titles-string") == 0 || - strcmp(entry->name, "window-status-format") == 0) { + if (strcmp(oe->name, "status-left") == 0 || + strcmp(oe->name, "status-right") == 0 || + strcmp(oe->name, "status") == 0 || + strcmp(oe->name, "set-titles-string") == 0 || + strcmp(oe->name, "window-status-format") == 0) { for (i = 0; i < ARRAY_LENGTH(&clients); i++) { c = ARRAY_ITEM(&clients, i); if (c == NULL || c->session == NULL) @@ -328,242 +173,226 @@ cmd_set_option_exec(struct cmd *self, struct cmd_ctx *ctx) return (0); } -const char * -cmd_set_option_print( - const struct set_option_entry *entry, struct options_entry *o) +/* Unset an option. */ +int +cmd_set_option_unset(struct cmd *self, struct cmd_ctx *ctx, + const struct options_table_entry *oe, struct options *oo) { - static char out[BUFSIZ]; - const char *s; - struct keylist *keylist; - u_int i; + struct cmd_target_data *data = self->data; - *out = '\0'; - switch (entry->type) { - case SET_OPTION_STRING: - xsnprintf(out, sizeof out, "\"%s\"", o->str); - break; - case SET_OPTION_NUMBER: - xsnprintf(out, sizeof out, "%lld", o->num); - break; - case SET_OPTION_KEYS: - keylist = o->data; - for (i = 0; i < ARRAY_LENGTH(keylist); i++) { - strlcat(out, key_string_lookup_key( - ARRAY_ITEM(keylist, i)), sizeof out); - if (i != ARRAY_LENGTH(keylist) - 1) - strlcat(out, ",", sizeof out); - } - break; - case SET_OPTION_COLOUR: - s = colour_tostring(o->num); - xsnprintf(out, sizeof out, "%s", s); - break; - case SET_OPTION_ATTRIBUTES: - s = attributes_tostring(o->num); - xsnprintf(out, sizeof out, "%s", s); - break; - case SET_OPTION_FLAG: - if (o->num) - strlcpy(out, "on", sizeof out); - else - strlcpy(out, "off", sizeof out); - break; - case SET_OPTION_CHOICE: - s = entry->choices[o->num]; - xsnprintf(out, sizeof out, "%s", s); - break; + if (cmd_check_flag(data->chflags, 'g')) { + ctx->error(ctx, "can't unset global option: %s", oe->name); + return (-1); } - return (out); + if (data->arg2 != NULL) { + ctx->error(ctx, "value passed to unset option: %s", oe->name); + return (-1); + } + + options_remove(oo, oe->name); + ctx->info(ctx, "unset option: %s", oe->name); + return (0); } -void -cmd_set_option_string(struct cmd_ctx *ctx, struct options *oo, - const struct set_option_entry *entry, char *value, int append) +/* Set an option. */ +int +cmd_set_option_set(struct cmd *self, struct cmd_ctx *ctx, + const struct options_table_entry *oe, struct options *oo) { + struct cmd_target_data *data = self->data; struct options_entry *o; - char *oldvalue, *newvalue; + const char *s; - if (value == NULL) { - ctx->error(ctx, "empty value"); - return; + if (oe->type != OPTIONS_TABLE_FLAG && data->arg2 == NULL) { + ctx->error(ctx, "empty data->arg2"); + return (-1); } - if (append) { - oldvalue = options_get_string(oo, entry->name); - xasprintf(&newvalue, "%s%s", oldvalue, value); + o = NULL; + switch (oe->type) { + case OPTIONS_TABLE_STRING: + o = cmd_set_option_string(self, ctx, oe, oo); + break; + case OPTIONS_TABLE_NUMBER: + o = cmd_set_option_number(self, ctx, oe, oo); + break; + case OPTIONS_TABLE_KEYS: + o = cmd_set_option_keys(self, ctx, oe, oo); + break; + case OPTIONS_TABLE_COLOUR: + o = cmd_set_option_colour(self, ctx, oe, oo); + break; + case OPTIONS_TABLE_ATTRIBUTES: + o = cmd_set_option_attributes(self, ctx, oe, oo); + break; + case OPTIONS_TABLE_FLAG: + o = cmd_set_option_flag(self, ctx, oe, oo); + break; + case OPTIONS_TABLE_CHOICE: + o = cmd_set_option_choice(self, ctx, oe, oo); + break; + } + if (o == NULL) + return (-1); + + s = options_table_print_entry(oe, o); + ctx->info(ctx, "set option: %s -> %s", oe->name, s); + return (0); +} + +/* Set a string option. */ +struct options_entry * +cmd_set_option_string(struct cmd *self, unused struct cmd_ctx *ctx, + const struct options_table_entry *oe, struct options *oo) +{ + struct cmd_target_data *data = self->data; + struct options_entry *o; + char *oldval, *newval; + + if (cmd_check_flag(data->chflags, 'a')) { + oldval = options_get_string(oo, oe->name); + xasprintf(&newval, "%s%s", oldval, data->arg2); } else - newvalue = value; + newval = data->arg2; - o = options_set_string(oo, entry->name, "%s", newvalue); - ctx->info(ctx, - "set option: %s -> %s", o->name, cmd_set_option_print(entry, o)); + o = options_set_string(oo, oe->name, "%s", newval); - if (newvalue != value) - xfree(newvalue); + if (newval != data->arg2) + xfree(newval); + return (o); } -void -cmd_set_option_number(struct cmd_ctx *ctx, struct options *oo, - const struct set_option_entry *entry, char *value) +/* Set a number option. */ +struct options_entry * +cmd_set_option_number(struct cmd *self, struct cmd_ctx *ctx, + const struct options_table_entry *oe, struct options *oo) { - struct options_entry *o; - long long number; + struct cmd_target_data *data = self->data; + long long ll; const char *errstr; - if (value == NULL) { - ctx->error(ctx, "empty value"); - return; - } - - number = strtonum(value, entry->minimum, entry->maximum, &errstr); + ll = strtonum(data->arg2, oe->minimum, oe->maximum, &errstr); if (errstr != NULL) { - ctx->error(ctx, "value is %s: %s", errstr, value); - return; + ctx->error(ctx, "value is %s: %s", errstr, data->arg2); + return (NULL); } - o = options_set_number(oo, entry->name, number); - ctx->info(ctx, - "set option: %s -> %s", o->name, cmd_set_option_print(entry, o)); + return (options_set_number(oo, oe->name, ll)); } -void -cmd_set_option_keys(struct cmd_ctx *ctx, struct options *oo, - const struct set_option_entry *entry, char *value) +/* Set a keys option. */ +struct options_entry * +cmd_set_option_keys(struct cmd *self, struct cmd_ctx *ctx, + const struct options_table_entry *oe, struct options *oo) { - struct options_entry *o; + struct cmd_target_data *data = self->data; struct keylist *keylist; - char *copyvalue, *ptr, *str; + char *copy, *ptr, *s; int key; - if (value == NULL) { - ctx->error(ctx, "empty value"); - return; - } - keylist = xmalloc(sizeof *keylist); ARRAY_INIT(keylist); - ptr = copyvalue = xstrdup(value); - while ((str = strsep(&ptr, ",")) != NULL) { - if ((key = key_string_lookup_string(str)) == KEYC_NONE) { + ptr = copy = xstrdup(data->arg2); + while ((s = strsep(&ptr, ",")) != NULL) { + if ((key = key_string_lookup_string(s)) == KEYC_NONE) { + ctx->error(ctx, "unknown key: %s", s); + xfree(copy); xfree(keylist); - ctx->error(ctx, "unknown key: %s", str); - xfree(copyvalue); - return; + return (NULL); } ARRAY_ADD(keylist, key); } - xfree(copyvalue); + xfree(copy); - o = options_set_data(oo, entry->name, keylist, xfree); - ctx->info(ctx, - "set option: %s -> %s", o->name, cmd_set_option_print(entry, o)); + return (options_set_data(oo, oe->name, keylist, xfree)); } -void -cmd_set_option_colour(struct cmd_ctx *ctx, struct options *oo, - const struct set_option_entry *entry, char *value) +/* Set a colour option. */ +struct options_entry * +cmd_set_option_colour(struct cmd *self, struct cmd_ctx *ctx, + const struct options_table_entry *oe, struct options *oo) { - struct options_entry *o; + struct cmd_target_data *data = self->data; int colour; - if (value == NULL) { - ctx->error(ctx, "empty value"); - return; + if ((colour = colour_fromstring(data->arg2)) == -1) { + ctx->error(ctx, "bad colour: %s", data->arg2); + return (NULL); } - if ((colour = colour_fromstring(value)) == -1) { - ctx->error(ctx, "bad colour: %s", value); - return; - } - - o = options_set_number(oo, entry->name, colour); - ctx->info(ctx, - "set option: %s -> %s", o->name, cmd_set_option_print(entry, o)); + return (options_set_number(oo, oe->name, colour)); } -void -cmd_set_option_attributes(struct cmd_ctx *ctx, struct options *oo, - const struct set_option_entry *entry, char *value) +/* Set an attributes option. */ +struct options_entry * +cmd_set_option_attributes(struct cmd *self, struct cmd_ctx *ctx, + const struct options_table_entry *oe, struct options *oo) { - struct options_entry *o; + struct cmd_target_data *data = self->data; int attr; - if (value == NULL) { - ctx->error(ctx, "empty value"); - return; + if ((attr = attributes_fromstring(data->arg2)) == -1) { + ctx->error(ctx, "bad attributes: %s", data->arg2); + return (NULL); } - if ((attr = attributes_fromstring(value)) == -1) { - ctx->error(ctx, "bad attributes: %s", value); - return; - } - - o = options_set_number(oo, entry->name, attr); - ctx->info(ctx, - "set option: %s -> %s", o->name, cmd_set_option_print(entry, o)); + return (options_set_number(oo, oe->name, attr)); } -void -cmd_set_option_flag(struct cmd_ctx *ctx, struct options *oo, - const struct set_option_entry *entry, char *value) +/* Set a flag option. */ +struct options_entry * +cmd_set_option_flag(struct cmd *self, struct cmd_ctx *ctx, + const struct options_table_entry *oe, struct options *oo) { - struct options_entry *o; + struct cmd_target_data *data = self->data; int flag; - if (value == NULL || *value == '\0') - flag = !options_get_number(oo, entry->name); + if (data->arg2 == NULL || *data->arg2 == '\0') + flag = !options_get_number(oo, oe->name); else { - if ((value[0] == '1' && value[1] == '\0') || - strcasecmp(value, "on") == 0 || - strcasecmp(value, "yes") == 0) + if ((data->arg2[0] == '1' && data->arg2[1] == '\0') || + strcasecmp(data->arg2, "on") == 0 || + strcasecmp(data->arg2, "yes") == 0) flag = 1; - else if ((value[0] == '0' && value[1] == '\0') || - strcasecmp(value, "off") == 0 || - strcasecmp(value, "no") == 0) + else if ((data->arg2[0] == '0' && data->arg2[1] == '\0') || + strcasecmp(data->arg2, "off") == 0 || + strcasecmp(data->arg2, "no") == 0) flag = 0; else { - ctx->error(ctx, "bad value: %s", value); - return; + ctx->error(ctx, "bad value: %s", data->arg2); + return (NULL); } } - o = options_set_number(oo, entry->name, flag); - ctx->info(ctx, - "set option: %s -> %s", o->name, cmd_set_option_print(entry, o)); + return (options_set_number(oo, oe->name, flag)); } -void -cmd_set_option_choice(struct cmd_ctx *ctx, struct options *oo, - const struct set_option_entry *entry, char *value) +/* Set a choice option. */ +struct options_entry * +cmd_set_option_choice(struct cmd *self, struct cmd_ctx *ctx, + const struct options_table_entry *oe, struct options *oo) { - struct options_entry *o; + struct cmd_target_data *data = self->data; 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++) { + for (choicep = oe->choices; *choicep != NULL; choicep++) { n++; - if (strncmp(*choicep, value, strlen(value)) != 0) + if (strncmp(*choicep, data->arg2, strlen(data->arg2)) != 0) continue; if (choice != -1) { - ctx->error(ctx, "ambiguous option value: %s", value); - return; + ctx->error(ctx, "ambiguous value: %s", data->arg2); + return (NULL); } choice = n - 1; } if (choice == -1) { - ctx->error(ctx, "unknown option value: %s", value); - return; + ctx->error(ctx, "unknown value: %s", data->arg2); + return (NULL); } - o = options_set_number(oo, entry->name, choice); - ctx->info(ctx, - "set option: %s -> %s", o->name, cmd_set_option_print(entry, o)); + return (options_set_number(oo, oe->name, choice)); } diff --git a/cmd-show-options.c b/cmd-show-options.c index 23838e4c..02ca91e3 100644 --- a/cmd-show-options.c +++ b/cmd-show-options.c @@ -43,20 +43,19 @@ const struct cmd_entry cmd_show_options_entry = { int cmd_show_options_exec(struct cmd *self, struct cmd_ctx *ctx) { - struct cmd_target_data *data = self->data; - const struct set_option_entry *table; - struct session *s; - struct winlink *wl; - struct options *oo; - struct options_entry *o; - const struct set_option_entry *entry; - const char *optval; + struct cmd_target_data *data = self->data; + const struct options_table_entry *table, *oe; + struct session *s; + struct winlink *wl; + struct options *oo; + struct options_entry *o; + const char *optval; if (cmd_check_flag(data->chflags, 's')) { oo = &global_options; - table = set_option_table; + table = server_options_table; } else if (cmd_check_flag(data->chflags, 'w')) { - table = set_window_option_table; + table = window_options_table; if (cmd_check_flag(data->chflags, 'g')) oo = &global_w_options; else { @@ -66,7 +65,7 @@ cmd_show_options_exec(struct cmd *self, struct cmd_ctx *ctx) oo = &wl->window->options; } } else { - table = set_session_option_table; + table = session_options_table; if (cmd_check_flag(data->chflags, 'g')) oo = &global_s_options; else { @@ -77,11 +76,11 @@ cmd_show_options_exec(struct cmd *self, struct cmd_ctx *ctx) } } - for (entry = table; entry->name != NULL; entry++) { - if ((o = options_find1(oo, entry->name)) == NULL) + for (oe = table; oe->name != NULL; oe++) { + if ((o = options_find1(oo, oe->name)) == NULL) continue; - optval = cmd_set_option_print(entry, o); - ctx->print(ctx, "%s %s", entry->name, optval); + optval = options_table_print_entry(oe, o); + ctx->print(ctx, "%s %s", oe->name, optval); } return (0); diff --git a/options-table.c b/options-table.c new file mode 100644 index 00000000..56cb24e5 --- /dev/null +++ b/options-table.c @@ -0,0 +1,639 @@ +/* $OpenBSD$ */ + +/* + * Copyright (c) 2011 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" + +/* + * This file has a tables with all the server, session and window + * options. These tables are the master copy of the options with their real + * (user-visible) types, range limits and default values. At start these are + * copied into the runtime global options trees (which only has number and + * string types). These tables are then used to loop up the real type when + * the user sets an option or its value needs to be shown. + */ + +/* Choice option type lists. */ +const char *options_table_mode_keys_list[] = { + "emacs", "vi", NULL +}; +const char *options_table_clock_mode_style_list[] = { + "12", "24", NULL +}; +const char *options_table_status_keys_list[] = { + "emacs", "vi", NULL +}; +const char *options_table_status_justify_list[] = { + "left", "centre", "right", NULL +}; +const char *options_table_bell_action_list[] = { + "none", "any", "current", NULL +}; + +/* Server options. */ +const struct options_table_entry server_options_table[] = { + { .name = "buffer-limit", + .type = OPTIONS_TABLE_NUMBER, + .minimum = 1, + .maximum = INT_MAX, + .default_num = 9 + }, + + { .name = "escape-time", + .type = OPTIONS_TABLE_NUMBER, + .minimum = 0, + .maximum = INT_MAX, + .default_num = 500 + }, + + { .name = "exit-unattached", + .type = OPTIONS_TABLE_FLAG, + .default_num = 0 + }, + + { .name = "quiet", + .type = OPTIONS_TABLE_FLAG, + .default_num = 0 /* overridden in main() */ + }, + + { .name = NULL } +}; + +/* Session options. */ +const struct options_table_entry session_options_table[] = { + { .name = "base-index", + .type = OPTIONS_TABLE_NUMBER, + .minimum = 0, + .maximum = INT_MAX, + .default_num = 0 + }, + + { .name = "bell-action", + .type = OPTIONS_TABLE_CHOICE, + .choices = options_table_bell_action_list, + .default_num = BELL_ANY + }, + + { .name = "default-command", + .type = OPTIONS_TABLE_STRING, + .default_str = "" + }, + + { .name = "default-path", + .type = OPTIONS_TABLE_STRING, + .default_str = "" + }, + + { .name = "default-shell", + .type = OPTIONS_TABLE_STRING, + .default_str = _PATH_BSHELL + }, + + { .name = "default-terminal", + .type = OPTIONS_TABLE_STRING, + .default_str = "screen" + }, + + { .name = "destroy-unattached", + .type = OPTIONS_TABLE_FLAG, + .default_num = 0 + }, + + { .name = "detach-on-destroy", + .type = OPTIONS_TABLE_FLAG, + .default_num = 1 + }, + + { .name = "display-panes-active-colour", + .type = OPTIONS_TABLE_COLOUR, + .default_num = 1 + }, + + { .name = "display-panes-colour", + .type = OPTIONS_TABLE_COLOUR, + .default_num = 4 + }, + + { .name = "display-panes-time", + .type = OPTIONS_TABLE_NUMBER, + .minimum = 1, + .maximum = INT_MAX, + .default_num = 1000 + }, + + { .name = "display-time", + .type = OPTIONS_TABLE_NUMBER, + .minimum = 1, + .maximum = INT_MAX, + .default_num = 750 + }, + + { .name = "history-limit", + .type = OPTIONS_TABLE_NUMBER, + .minimum = 0, + .maximum = SHRT_MAX, + .default_num = 2000 + }, + + { .name = "lock-after-time", + .type = OPTIONS_TABLE_NUMBER, + .minimum = 0, + .maximum = INT_MAX, + .default_num = 0 + }, + + { .name = "lock-command", + .type = OPTIONS_TABLE_STRING, + .default_str = "lock -np" + }, + + { .name = "lock-server", + .type = OPTIONS_TABLE_FLAG, + .default_num = 1 + }, + + { .name = "message-attr", + .type = OPTIONS_TABLE_ATTRIBUTES, + .default_num = 0 + }, + + { .name = "message-bg", + .type = OPTIONS_TABLE_COLOUR, + .default_num = 3 + }, + + { .name = "message-fg", + .type = OPTIONS_TABLE_COLOUR, + .default_num = 0 + }, + + { .name = "message-limit", + .type = OPTIONS_TABLE_NUMBER, + .minimum = 0, + .maximum = INT_MAX, + .default_num = 20 + }, + + { .name = "mouse-select-pane", + .type = OPTIONS_TABLE_FLAG, + .default_num = 0 + }, + + { .name = "pane-active-border-bg", + .type = OPTIONS_TABLE_COLOUR, + .default_num = 8 + }, + + { .name = "pane-active-border-fg", + .type = OPTIONS_TABLE_COLOUR, + .default_num = 2 + }, + + { .name = "pane-border-bg", + .type = OPTIONS_TABLE_COLOUR, + .default_num = 8 + }, + + { .name = "pane-border-fg", + .type = OPTIONS_TABLE_COLOUR, + .default_num = 8 + }, + + { .name = "prefix", + .type = OPTIONS_TABLE_KEYS, + /* set in main() */ + }, + + { .name = "repeat-time", + .type = OPTIONS_TABLE_NUMBER, + .minimum = 0, + .maximum = SHRT_MAX, + .default_num = 500 + }, + + { .name = "set-remain-on-exit", + .type = OPTIONS_TABLE_FLAG, + .default_num = 0 + }, + + { .name = "set-titles", + .type = OPTIONS_TABLE_FLAG, + .default_num = 0 + }, + + { .name = "set-titles-string", + .type = OPTIONS_TABLE_STRING, + .default_str = "#S:#I:#W - \"#T\"" + }, + + { .name = "status", + .type = OPTIONS_TABLE_FLAG, + .default_num = 1 + }, + + { .name = "status-attr", + .type = OPTIONS_TABLE_ATTRIBUTES, + .default_num = 0 + }, + + { .name = "status-bg", + .type = OPTIONS_TABLE_COLOUR, + .default_num = 2 + }, + + { .name = "status-fg", + .type = OPTIONS_TABLE_COLOUR, + .default_num = 0 + }, + + { .name = "status-interval", + .type = OPTIONS_TABLE_NUMBER, + .minimum = 0, + .maximum = INT_MAX, + .default_num = 15 + }, + + { .name = "status-justify", + .type = OPTIONS_TABLE_CHOICE, + .choices = options_table_status_justify_list, + .default_num = 0 + }, + + { .name = "status-keys", + .type = OPTIONS_TABLE_CHOICE, + .choices = options_table_status_keys_list, + .default_num = MODEKEY_EMACS + }, + + { .name = "status-left", + .type = OPTIONS_TABLE_STRING, + .default_str = "[#S]" + }, + + { .name = "status-left-attr", + .type = OPTIONS_TABLE_ATTRIBUTES, + .default_num = 0 + }, + + { .name = "status-left-bg", + .type = OPTIONS_TABLE_COLOUR, + .default_num = 8 + }, + + { .name = "status-left-fg", + .type = OPTIONS_TABLE_COLOUR, + .default_num = 8 + }, + + { .name = "status-left-length", + .type = OPTIONS_TABLE_NUMBER, + .minimum = 0, + .maximum = SHRT_MAX, + .default_num = 10 + }, + + { .name = "status-right", + .type = OPTIONS_TABLE_STRING, + .default_str = "\"#22T\" %H:%M %d-%b-%y" + }, + + { .name = "status-right-attr", + .type = OPTIONS_TABLE_ATTRIBUTES, + .default_num = 0 + }, + + { .name = "status-right-bg", + .type = OPTIONS_TABLE_COLOUR, + .default_num = 8 + }, + + { .name = "status-right-fg", + .type = OPTIONS_TABLE_COLOUR, + .default_num = 8 + }, + + { .name = "status-right-length", + .type = OPTIONS_TABLE_NUMBER, + .minimum = 0, + .maximum = SHRT_MAX, + .default_num = 40 + }, + + { .name = "status-utf8", + .type = OPTIONS_TABLE_FLAG, + .default_num = 0 /* overridden in main() */ + }, + + { .name = "terminal-overrides", + .type = OPTIONS_TABLE_STRING, + .default_str = "*88col*:colors=88,*256col*:colors=256" + }, + + { .name = "update-environment", + .type = OPTIONS_TABLE_STRING, + .default_str = "DISPLAY SSH_ASKPASS SSH_AUTH_SOCK SSH_AGENT_PID " + "SSH_CONNECTION WINDOWID XAUTHORITY" + + }, + + { .name = "visual-activity", + .type = OPTIONS_TABLE_FLAG, + .default_num = 0 + }, + + { .name = "visual-bell", + .type = OPTIONS_TABLE_FLAG, + .default_num = 0 + }, + + { .name = "visual-content", + .type = OPTIONS_TABLE_FLAG, + .default_num = 0 + }, + + { .name = "visual-silence", + .type = OPTIONS_TABLE_FLAG, + .default_num = 0 + }, + + { .name = NULL } +}; + +/* Window options. */ +const struct options_table_entry window_options_table[] = { + { .name = "aggressive-resize", + .type = OPTIONS_TABLE_FLAG, + .default_num = 0 + }, + + { .name = "alternate-screen", + .type = OPTIONS_TABLE_FLAG, + .default_num = 1 + }, + + { .name = "automatic-rename", + .type = OPTIONS_TABLE_FLAG, + .default_num = 1 + }, + + { .name = "clock-mode-colour", + .type = OPTIONS_TABLE_COLOUR, + .default_num = 4 + }, + + { .name = "clock-mode-style", + .type = OPTIONS_TABLE_CHOICE, + .choices = options_table_clock_mode_style_list, + .default_num = 1 + }, + + { .name = "force-height", + .type = OPTIONS_TABLE_NUMBER, + .minimum = 0, + .maximum = INT_MAX, + .default_num = 0 + }, + + { .name = "force-width", + .type = OPTIONS_TABLE_NUMBER, + .minimum = 0, + .maximum = INT_MAX, + .default_num = 0 + }, + + { .name = "main-pane-height", + .type = OPTIONS_TABLE_NUMBER, + .minimum = 1, + .maximum = INT_MAX, + .default_num = 24 + }, + + { .name = "main-pane-width", + .type = OPTIONS_TABLE_NUMBER, + .minimum = 1, + .maximum = INT_MAX, + .default_num = 80 + }, + + { .name = "mode-attr", + .type = OPTIONS_TABLE_ATTRIBUTES, + .default_num = 0 + }, + + { .name = "mode-bg", + .type = OPTIONS_TABLE_COLOUR, + .default_num = 3 + }, + + { .name = "mode-fg", + .type = OPTIONS_TABLE_COLOUR, + .default_num = 0 + }, + + { .name = "mode-keys", + .type = OPTIONS_TABLE_CHOICE, + .choices = options_table_mode_keys_list, + .default_num = MODEKEY_EMACS + }, + + { .name = "mode-mouse", + .type = OPTIONS_TABLE_FLAG, + .default_num = 0 + }, + + { .name = "monitor-activity", + .type = OPTIONS_TABLE_FLAG, + .default_num = 0 + }, + + { .name = "monitor-content", + .type = OPTIONS_TABLE_STRING, + .default_str = "" + }, + + { .name = "monitor-silence", + .type = OPTIONS_TABLE_NUMBER, + .minimum = 0, + .maximum = INT_MAX, + .default_num = 0 + }, + + { .name = "other-pane-height", + .type = OPTIONS_TABLE_NUMBER, + .minimum = 0, + .maximum = INT_MAX, + .default_num = 0 + }, + + { .name = "other-pane-width", + .type = OPTIONS_TABLE_NUMBER, + .minimum = 0, + .maximum = INT_MAX, + .default_num = 0 + }, + + { .name = "remain-on-exit", + .type = OPTIONS_TABLE_FLAG, + .default_num = 0 + }, + + { .name = "synchronize-panes", + .type = OPTIONS_TABLE_FLAG, + .default_num = 0 + }, + + { .name = "utf8", + .type = OPTIONS_TABLE_FLAG, + .default_num = 0 /* overridden in main() */ + }, + + { .name = "window-status-alert-attr", + .type = OPTIONS_TABLE_ATTRIBUTES, + .default_num = GRID_ATTR_REVERSE + }, + + { .name = "window-status-alert-bg", + .type = OPTIONS_TABLE_COLOUR, + .default_num = 8 + }, + + { .name = "window-status-alert-fg", + .type = OPTIONS_TABLE_COLOUR, + .default_num = 8 + }, + + { .name = "window-status-attr", + .type = OPTIONS_TABLE_ATTRIBUTES, + .default_num = 0 + }, + + { .name = "window-status-bg", + .type = OPTIONS_TABLE_COLOUR, + .default_num = 8 + }, + + { .name = "window-status-current-attr", + .type = OPTIONS_TABLE_ATTRIBUTES, + .default_num = 0 + }, + + { .name = "window-status-current-bg", + .type = OPTIONS_TABLE_COLOUR, + .default_num = 8 + }, + + { .name = "window-status-current-fg", + .type = OPTIONS_TABLE_COLOUR, + .default_num = 8 + }, + + { .name = "window-status-current-format", + .type = OPTIONS_TABLE_STRING, + .default_str = "#I:#W#F" + }, + + { .name = "window-status-fg", + .type = OPTIONS_TABLE_COLOUR, + .default_num = 8 + }, + + { .name = "window-status-format", + .type = OPTIONS_TABLE_STRING, + .default_str = "#I:#W#F" + }, + + { .name = "word-separators", + .type = OPTIONS_TABLE_STRING, + .default_str = " -_@" + }, + + { .name = "xterm-keys", + .type = OPTIONS_TABLE_FLAG, + .default_num = 0 + }, + + { .name = NULL } +}; + +/* Populate an options tree from a table. */ +void +options_table_populate_tree( + const struct options_table_entry *table, struct options *oo) +{ + const struct options_table_entry *oe; + + for (oe = table; oe->name != NULL; oe++) { + if (oe->default_str != NULL) + options_set_string(oo, oe->name, "%s", oe->default_str); + else + options_set_number(oo, oe->name, oe->default_num); + } +} + +/* Print an option using its type from the table. */ +const char * +options_table_print_entry( + const struct options_table_entry *oe, struct options_entry *o) +{ + static char out[BUFSIZ]; + const char *s; + struct keylist *keylist; + u_int i; + + *out = '\0'; + switch (oe->type) { + case OPTIONS_TABLE_STRING: + xsnprintf(out, sizeof out, "\"%s\"", o->str); + break; + case OPTIONS_TABLE_NUMBER: + xsnprintf(out, sizeof out, "%lld", o->num); + break; + case OPTIONS_TABLE_KEYS: + keylist = o->data; + for (i = 0; i < ARRAY_LENGTH(keylist); i++) { + s = key_string_lookup_key(ARRAY_ITEM(keylist, i)); + strlcat(out, s, sizeof out); + if (i != ARRAY_LENGTH(keylist) - 1) + strlcat(out, ",", sizeof out); + } + break; + case OPTIONS_TABLE_COLOUR: + s = colour_tostring(o->num); + xsnprintf(out, sizeof out, "%s", s); + break; + case OPTIONS_TABLE_ATTRIBUTES: + s = attributes_tostring(o->num); + xsnprintf(out, sizeof out, "%s", s); + break; + case OPTIONS_TABLE_FLAG: + if (o->num) + strlcpy(out, "on", sizeof out); + else + strlcpy(out, "off", sizeof out); + break; + case OPTIONS_TABLE_CHOICE: + s = oe->choices[o->num]; + xsnprintf(out, sizeof out, "%s", s); + break; + } + return (out); +} diff --git a/status.c b/status.c index 75b0a830..073ccf12 100644 --- a/status.c +++ b/status.c @@ -1112,12 +1112,12 @@ status_prompt_add_history(const char *line) char * status_prompt_complete(const char *s) { - const struct cmd_entry **cmdent; - const struct set_option_entry *entry; - ARRAY_DECL(, const char *) list; - char *prefix, *s2; - u_int i; - size_t j; + const struct cmd_entry **cmdent; + const struct options_table_entry *oe; + ARRAY_DECL(, const char *) list; + char *prefix, *s2; + u_int i; + size_t j; if (*s == '\0') return (NULL); @@ -1128,17 +1128,17 @@ status_prompt_complete(const char *s) if (strncmp((*cmdent)->name, s, strlen(s)) == 0) ARRAY_ADD(&list, (*cmdent)->name); } - for (entry = set_option_table; entry->name != NULL; entry++) { - if (strncmp(entry->name, s, strlen(s)) == 0) - ARRAY_ADD(&list, entry->name); + for (oe = server_options_table; oe->name != NULL; oe++) { + if (strncmp(oe->name, s, strlen(s)) == 0) + ARRAY_ADD(&list, oe->name); } - for (entry = set_session_option_table; entry->name != NULL; entry++) { - if (strncmp(entry->name, s, strlen(s)) == 0) - ARRAY_ADD(&list, entry->name); + for (oe = session_options_table; oe->name != NULL; oe++) { + if (strncmp(oe->name, s, strlen(s)) == 0) + ARRAY_ADD(&list, oe->name); } - for (entry = set_window_option_table; entry->name != NULL; entry++) { - if (strncmp(entry->name, s, strlen(s)) == 0) - ARRAY_ADD(&list, entry->name); + for (oe = window_options_table; oe->name != NULL; oe++) { + if (strncmp(oe->name, s, strlen(s)) == 0) + ARRAY_ADD(&list, oe->name); } /* If none, bail now. */ diff --git a/tmux.c b/tmux.c index a8331a1f..54abf658 100644 --- a/tmux.c +++ b/tmux.c @@ -228,7 +228,6 @@ int main(int argc, char **argv) { struct passwd *pw; - struct options *oo, *so, *wo; struct keylist *keylist; char *s, *path, *label, *home, **var; int opt, flags, quiet, keys; @@ -316,129 +315,39 @@ main(int argc, char **argv) environ_put(&global_environ, *var); options_init(&global_options, NULL); - oo = &global_options; - options_set_number(oo, "quiet", quiet); - options_set_number(oo, "escape-time", 500); - options_set_number(oo, "exit-unattached", 0); - options_set_number(oo, "buffer-limit", 9); + options_table_populate_tree(server_options_table, &global_options); + options_set_number(&global_options, "quiet", quiet); options_init(&global_s_options, NULL); - so = &global_s_options; - options_set_number(so, "base-index", 0); - options_set_number(so, "bell-action", BELL_ANY); - options_set_string(so, "default-command", "%s", ""); - options_set_string(so, "default-path", "%s", ""); - options_set_string(so, "default-shell", "%s", getshell()); - options_set_string(so, "default-terminal", "screen"); - options_set_number(so, "destroy-unattached", 0); - options_set_number(so, "detach-on-destroy", 1); - options_set_number(so, "display-panes-active-colour", 1); - options_set_number(so, "display-panes-colour", 4); - options_set_number(so, "display-panes-time", 1000); - options_set_number(so, "display-time", 750); - options_set_number(so, "history-limit", 2000); - options_set_number(so, "lock-after-time", 0); - options_set_string(so, "lock-command", "lock -np"); - options_set_number(so, "lock-server", 1); - options_set_number(so, "message-attr", 0); - options_set_number(so, "message-bg", 3); - options_set_number(so, "message-fg", 0); - options_set_number(so, "message-limit", 20); - options_set_number(so, "mouse-select-pane", 0); - options_set_number(so, "pane-active-border-bg", 8); - options_set_number(so, "pane-active-border-fg", 2); - options_set_number(so, "pane-border-bg", 8); - options_set_number(so, "pane-border-fg", 8); - options_set_number(so, "repeat-time", 500); - options_set_number(so, "set-remain-on-exit", 0); - options_set_number(so, "set-titles", 0); - options_set_string(so, "set-titles-string", "#S:#I:#W - \"#T\""); - options_set_number(so, "status", 1); - options_set_number(so, "status-attr", 0); - options_set_number(so, "status-bg", 2); - options_set_number(so, "status-fg", 0); - options_set_number(so, "status-interval", 15); - options_set_number(so, "status-justify", 0); - options_set_string(so, "status-left", "[#S]"); - options_set_number(so, "status-left-attr", 0); - options_set_number(so, "status-left-bg", 8); - options_set_number(so, "status-left-fg", 8); - options_set_number(so, "status-left-length", 10); - options_set_string(so, "status-right", "\"#22T\" %%H:%%M %%d-%%b-%%y"); - options_set_number(so, "status-right-attr", 0); - options_set_number(so, "status-right-bg", 8); - options_set_number(so, "status-right-fg", 8); - options_set_number(so, "status-right-length", 40); - options_set_string(so, "terminal-overrides", - "*88col*:colors=88,*256col*:colors=256"); - options_set_string(so, "update-environment", - "DISPLAY " - "SSH_ASKPASS SSH_AUTH_SOCK SSH_AGENT_PID SSH_CONNECTION " - "WINDOWID " - "XAUTHORITY"); - options_set_number(so, "visual-activity", 0); - options_set_number(so, "visual-bell", 0); - options_set_number(so, "visual-content", 0); - options_set_number(so, "visual-silence", 0); + options_table_populate_tree(session_options_table, &global_s_options); + options_set_string(&global_s_options, "default-shell", "%s", getshell()); + options_init(&global_w_options, NULL); + options_table_populate_tree(window_options_table, &global_w_options); + + /* Set the prefix option (its a list, so not in the table). */ keylist = xmalloc(sizeof *keylist); ARRAY_INIT(keylist); ARRAY_ADD(keylist, '\002'); - options_set_data(so, "prefix", keylist, xfree); - - options_init(&global_w_options, NULL); - wo = &global_w_options; - options_set_number(wo, "aggressive-resize", 0); - options_set_number(wo, "alternate-screen", 1); - options_set_number(wo, "automatic-rename", 1); - options_set_number(wo, "clock-mode-colour", 4); - options_set_number(wo, "clock-mode-style", 1); - options_set_number(wo, "force-height", 0); - options_set_number(wo, "force-width", 0); - options_set_number(wo, "main-pane-height", 24); - options_set_number(wo, "main-pane-width", 80); - options_set_number(wo, "mode-attr", 0); - options_set_number(wo, "mode-bg", 3); - options_set_number(wo, "mode-fg", 0); - options_set_number(wo, "mode-mouse", 0); - options_set_number(wo, "monitor-activity", 0); - options_set_string(wo, "monitor-content", "%s", ""); - options_set_number(wo, "monitor-silence", 0); - options_set_number(wo, "other-pane-height", 0); - options_set_number(wo, "other-pane-width", 0); - options_set_number(wo, "window-status-attr", 0); - options_set_number(wo, "window-status-bg", 8); - options_set_number(wo, "window-status-current-attr", 0); - options_set_number(wo, "window-status-current-bg", 8); - options_set_number(wo, "window-status-current-fg", 8); - options_set_number(wo, "window-status-fg", 8); - options_set_number(wo, "window-status-alert-attr", GRID_ATTR_REVERSE); - options_set_number(wo, "window-status-alert-bg", 8); - options_set_number(wo, "window-status-alert-fg", 8); - options_set_string(wo, "window-status-format", "#I:#W#F"); - options_set_string(wo, "window-status-current-format", "#I:#W#F"); - options_set_string(wo, "word-separators", " -_@"); - options_set_number(wo, "xterm-keys", 0); - options_set_number(wo, "remain-on-exit", 0); - options_set_number(wo, "synchronize-panes", 0); + options_set_data(&global_s_options, "prefix", keylist, xfree); + /* Enable UTF-8 if the first client is on UTF-8 terminal. */ if (flags & IDENTIFY_UTF8) { - options_set_number(so, "status-utf8", 1); - options_set_number(wo, "utf8", 1); - } else { - options_set_number(so, "status-utf8", 0); - options_set_number(wo, "utf8", 0); + options_set_number(&global_s_options, "status-utf8", 1); + options_set_number(&global_w_options, "utf8", 1); } - keys = MODEKEY_EMACS; + /* Override keys to vi if VISUAL or EDITOR are set. */ if ((s = getenv("VISUAL")) != NULL || (s = getenv("EDITOR")) != NULL) { if (strrchr(s, '/') != NULL) s = strrchr(s, '/') + 1; if (strstr(s, "vi") != NULL) keys = MODEKEY_VI; + else + keys = MODEKEY_EMACS; + options_set_number(&global_s_options, "status-keys", keys); + options_set_number(&global_w_options, "mode-keys", keys); } - options_set_number(so, "status-keys", keys); - options_set_number(wo, "mode-keys", keys); /* Locate the configuration file. */ if (cfg_file == NULL) { diff --git a/tmux.h b/tmux.h index 116f8d78..45bb1a1b 100644 --- a/tmux.h +++ b/tmux.h @@ -1270,23 +1270,31 @@ struct key_binding { }; SPLAY_HEAD(key_bindings, key_binding); -/* Set/display option data. */ -struct set_option_entry { - const char *name; - enum { - SET_OPTION_STRING, - SET_OPTION_NUMBER, - SET_OPTION_KEYS, - SET_OPTION_COLOUR, - SET_OPTION_ATTRIBUTES, - SET_OPTION_FLAG, - SET_OPTION_CHOICE - } type; +/* + * Option table entries. The option table is the user-visible part of the + * option, as opposed to the internal options (struct option) which are just + * number or string. + */ +enum options_table_type { + OPTIONS_TABLE_STRING, + OPTIONS_TABLE_NUMBER, + OPTIONS_TABLE_KEYS, + OPTIONS_TABLE_COLOUR, + OPTIONS_TABLE_ATTRIBUTES, + OPTIONS_TABLE_FLAG, + OPTIONS_TABLE_CHOICE +}; - u_int minimum; - u_int maximum; +struct options_table_entry { + const char *name; + enum options_table_type type; - const char **choices; + u_int minimum; + u_int maximum; + const char **choices; + + const char *default_str; + long long default_num; }; /* List of configuration causes. */ @@ -1356,6 +1364,15 @@ struct options_entry *options_set_data( struct options *, const char *, void *, void (*)(void *)); void *options_get_data(struct options *, const char *); +/* options-table.c */ +extern const struct options_table_entry server_options_table[]; +extern const struct options_table_entry session_options_table[]; +extern const struct options_table_entry window_options_table[]; +void options_table_populate_tree( + const struct options_table_entry *, struct options *); +const char *options_table_print_entry( + const struct options_table_entry *, struct options_entry *); + /* job.c */ extern struct joblist all_jobs; int job_cmp(struct job *, struct job *); @@ -1461,13 +1478,6 @@ char *paste_print(struct paste_buffer *, size_t); extern const char clock_table[14][5][5]; void clock_draw(struct screen_write_ctx *, int, int); -/* cmd-set-option.c */ -extern const struct set_option_entry set_option_table[]; -extern const struct set_option_entry set_session_option_table[]; -extern const struct set_option_entry set_window_option_table[]; -const char *cmd_set_option_print( - const struct set_option_entry *, struct options_entry *); - /* cmd.c */ int cmd_pack_argv(int, char **, char *, size_t); int cmd_unpack_argv(char *, size_t, int, char ***);