aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile1
-rw-r--r--cmd-choose-tree.c17
-rw-r--r--cmd-list-keys.c8
-rw-r--r--cmd-run-shell.c3
-rw-r--r--cmd-set-option.c216
-rw-r--r--cmd-show-messages.c4
-rw-r--r--cmd-show-options.c8
-rw-r--r--cmd.c2
-rw-r--r--format-draw.c2
-rw-r--r--format.c2
-rw-r--r--key-bindings.c60
-rw-r--r--mode-tree.c97
-rw-r--r--options-table.c358
-rw-r--r--options.c252
-rw-r--r--screen-write.c92
-rw-r--r--style.c7
-rw-r--r--tmux.147
-rw-r--r--tmux.h33
-rw-r--r--window-buffer.c4
-rw-r--r--window-client.c2
-rw-r--r--window-customize.c1430
-rw-r--r--window-tree.c2
22 files changed, 2284 insertions, 363 deletions
diff --git a/Makefile b/Makefile
index 0f1c94c4..7fb664ad 100644
--- a/Makefile
+++ b/Makefile
@@ -120,6 +120,7 @@ SRCS= alerts.c \
window-client.c \
window-clock.c \
window-copy.c \
+ window-customize.c \
window-tree.c \
window.c \
xmalloc.c \
diff --git a/cmd-choose-tree.c b/cmd-choose-tree.c
index 0ada8fd4..a58469ac 100644
--- a/cmd-choose-tree.c
+++ b/cmd-choose-tree.c
@@ -68,6 +68,19 @@ const struct cmd_entry cmd_choose_buffer_entry = {
.exec = cmd_choose_tree_exec
};
+const struct cmd_entry cmd_customize_mode_entry = {
+ .name = "customize-mode",
+ .alias = NULL,
+
+ .args = { "F:f:Nt:Z", 0, 0 },
+ .usage = "[-NZ] [-F format] [-f filter] " CMD_TARGET_PANE_USAGE,
+
+ .target = { 't', CMD_FIND_PANE, 0 },
+
+ .flags = 0,
+ .exec = cmd_choose_tree_exec
+};
+
static enum cmd_retval
cmd_choose_tree_exec(struct cmd *self, struct cmdq_item *item)
{
@@ -84,7 +97,9 @@ cmd_choose_tree_exec(struct cmd *self, struct cmdq_item *item)
if (server_client_how_many() == 0)
return (CMD_RETURN_NORMAL);
mode = &window_client_mode;
- } else
+ } else if (cmd_get_entry(self) == &cmd_customize_mode_entry)
+ mode = &window_customize_mode;
+ else
mode = &window_tree_mode;
window_pane_set_mode(wp, NULL, mode, target, args);
diff --git a/cmd-list-keys.c b/cmd-list-keys.c
index 4e7ba39c..60ef73af 100644
--- a/cmd-list-keys.c
+++ b/cmd-list-keys.c
@@ -68,7 +68,8 @@ cmd_list_keys_get_width(const char *tablename, key_code only)
while (bd != NULL) {
if ((only != KEYC_UNKNOWN && bd->key != only) ||
KEYC_IS_MOUSE(bd->key) ||
- bd->note == NULL) {
+ bd->note == NULL ||
+ *bd->note == '\0') {
bd = key_bindings_next(table, bd);
continue;
}
@@ -99,14 +100,15 @@ cmd_list_keys_print_notes(struct cmdq_item *item, struct args *args,
while (bd != NULL) {
if ((only != KEYC_UNKNOWN && bd->key != only) ||
KEYC_IS_MOUSE(bd->key) ||
- (bd->note == NULL && !args_has(args, 'a'))) {
+ ((bd->note == NULL || *bd->note == '\0') &&
+ !args_has(args, 'a'))) {
bd = key_bindings_next(table, bd);
continue;
}
found = 1;
key = key_string_lookup_key(bd->key);
- if (bd->note == NULL)
+ if (bd->note == NULL || *bd->note == '\0')
note = cmd_list_print(bd->cmdlist, 1);
else
note = xstrdup(bd->note);
diff --git a/cmd-run-shell.c b/cmd-run-shell.c
index 82d4a1a2..3792aaae 100644
--- a/cmd-run-shell.c
+++ b/cmd-run-shell.c
@@ -190,7 +190,8 @@ cmd_run_shell_callback(struct job *job)
retcode = WTERMSIG(status);
xasprintf(&msg, "'%s' terminated by signal %d", cmd, retcode);
retcode += 128;
- }
+ } else
+ retcode = 0;
if (msg != NULL)
cmd_run_shell_print(job, msg);
free(msg);
diff --git a/cmd-set-option.c b/cmd-set-option.c
index e04aa7ff..c6f83796 100644
--- a/cmd-set-option.c
+++ b/cmd-set-option.c
@@ -30,15 +30,6 @@
static enum cmd_retval cmd_set_option_exec(struct cmd *, struct cmdq_item *);
-static int cmd_set_option_set(struct cmd *, struct cmdq_item *,
- struct options *, struct options_entry *, const char *);
-static int cmd_set_option_flag(struct cmdq_item *,
- const struct options_table_entry *, struct options *,
- const char *);
-static int cmd_set_option_choice(struct cmdq_item *,
- const struct options_table_entry *, struct options *,
- const char *);
-
const struct cmd_entry cmd_set_option_entry = {
.name = "set-option",
.alias = "set",
@@ -84,10 +75,6 @@ cmd_set_option_exec(struct cmd *self, struct cmdq_item *item)
struct args *args = cmd_get_args(self);
int append = args_has(args, 'a');
struct cmd_find_state *target = cmdq_get_target(item);
- struct client *loop;
- struct session *s = target->s;
- struct window *w;
- struct window_pane *wp;
struct options *oo;
struct options_entry *parent, *o;
char *name, *argument, *value = NULL, *cause;
@@ -138,7 +125,7 @@ cmd_set_option_exec(struct cmd *self, struct cmdq_item *item)
parent = options_get(oo, name);
/* Check that array options and indexes match up. */
- if (idx != -1 && (*name == '@' || !options_isarray(parent))) {
+ if (idx != -1 && (*name == '@' || !options_is_array(parent))) {
cmdq_error(item, "not an array: %s", argument);
goto fail;
}
@@ -185,10 +172,15 @@ cmd_set_option_exec(struct cmd *self, struct cmdq_item *item)
goto fail;
}
options_set_string(oo, name, append, "%s", value);
- } else if (idx == -1 && !options_isarray(parent)) {
- error = cmd_set_option_set(self, item, oo, parent, value);
- if (error != 0)
+ } else if (idx == -1 && !options_is_array(parent)) {
+ error = options_from_string(oo, options_table_entry(parent),
+ options_table_entry(parent)->name, value,
+ args_has(args, 'a'), &cause);
+ if (error != 0) {
+ cmdq_error(item, "%s", cause);
+ free(cause);
goto fail;
+ }
} else {
if (value == NULL) {
cmdq_error(item, "empty value");
@@ -212,51 +204,7 @@ cmd_set_option_exec(struct cmd *self, struct cmdq_item *item)
}
}
- /* Update timers and so on for various options. */
- if (strcmp(name, "automatic-rename") == 0) {
- RB_FOREACH(w, windows, &windows) {
- if (w->active == NULL)
- continue;
- if (options_get_number(w->options, "automatic-rename"))
- w->active->flags |= PANE_CHANGED;
- }
- }
- if (strcmp(name, "key-table") == 0) {
- TAILQ_FOREACH(loop, &clients, entry)
- server_client_set_key_table(loop, NULL);
- }
- if (strcmp(name, "user-keys") == 0) {
- TAILQ_FOREACH(loop, &clients, entry) {
- if (loop->tty.flags & TTY_OPENED)
- tty_keys_build(&loop->tty);
- }
- }
- if (strcmp(name, "status") == 0 ||
- strcmp(name, "status-interval") == 0)
- status_timer_start_all();
- if (strcmp(name, "monitor-silence") == 0)
- alerts_reset_all();
- if (strcmp(name, "window-style") == 0 ||
- strcmp(name, "window-active-style") == 0) {
- RB_FOREACH(wp, window_pane_tree, &all_window_panes)
- wp->flags |= PANE_STYLECHANGED;
- }
- if (strcmp(name, "pane-border-status") == 0) {
- RB_FOREACH(w, windows, &windows)
- layout_fix_panes(w);
- }
- RB_FOREACH(s, sessions, &sessions)
- status_update_cache(s);
-
- /*
- * Update sizes and redraw. May not always be necessary but do it
- * anyway.
- */
- recalculate_sizes();
- TAILQ_FOREACH(loop, &clients, entry) {
- if (loop->session != NULL)
- server_redraw_client(loop);
- }
+ options_push_changes(name);
out:
free(argument);
@@ -270,147 +218,3 @@ fail:
free(name);
return (CMD_RETURN_ERROR);
}
-
-static int
-cmd_set_option_check_string(const struct options_table_entry *oe,
- const char *value, char **cause)
-{
- struct style sy;
-
- if (strcmp(oe->name, "default-shell") == 0 && !checkshell(value)) {
- xasprintf(cause, "not a suitable shell: %s", value);
- return (-1);
- }
- if (oe->pattern != NULL && fnmatch(oe->pattern, value, 0) != 0) {
- xasprintf(cause, "value is invalid: %s", value);
- return (-1);
- }
- if ((oe->flags & OPTIONS_TABLE_IS_STYLE) &&
- strstr(value, "#{") == NULL &&
- style_parse(&sy, &grid_default_cell, value) != 0) {
- xasprintf(cause, "invalid style: %s", value);
- return (-1);
- }
- return (0);
-}
-
-static int
-cmd_set_option_set(struct cmd *self, struct cmdq_item *item, struct options *oo,
- struct options_entry *parent, const char *value)
-{
- const struct options_table_entry *oe;
- struct args *args = cmd_get_args(self);
- int append = args_has(args, 'a');
- long long number;
- const char *errstr, *new;
- char *old, *cause;
- key_code key;
-
- oe = options_table_entry(parent);
- if (value == NULL &&
- oe->type != OPTIONS_TABLE_FLAG &&
- oe->type != OPTIONS_TABLE_CHOICE) {
- cmdq_error(item, "empty value");
- return (-1);
- }
-
- switch (oe->type) {
- case OPTIONS_TABLE_STRING:
- old = xstrdup(options_get_string(oo, oe->name));
- options_set_string(oo, oe->name, append, "%s", value);
- new = options_get_string(oo, oe->name);
- if (cmd_set_option_check_string(oe, new, &cause) != 0) {
- cmdq_error(item, "%s", cause);
- free(cause);
-
- options_set_string(oo, oe->name, 0, "%s", old);
- free(old);
- return (-1);
- }
- free(old);
- return (0);
- case OPTIONS_TABLE_NUMBER:
- number = strtonum(value, oe->minimum, oe->maximum, &errstr);
- if (errstr != NULL) {
- cmdq_error(item, "value is %s: %s", errstr, value);
- return (-1);
- }
- options_set_number(oo, oe->name, number);
- return (0);
- case OPTIONS_TABLE_KEY:
- key = key_string_lookup_string(value);
- if (key == KEYC_UNKNOWN) {
- cmdq_error(item, "bad key: %s", value);
- return (-1);
- }
- options_set_number(oo, oe->name, key);
- return (0);
- case OPTIONS_TABLE_COLOUR:
- if ((number = colour_fromstring(value)) == -1) {
- cmdq_error(item, "bad colour: %s", value);
- return (-1);
- }
- options_set_number(oo, oe->name, number);
- return (0);
- case OPTIONS_TABLE_FLAG:
- return (cmd_set_option_flag(item, oe, oo, value));
- case OPTIONS_TABLE_CHOICE:
- return (cmd_set_option_choice(item, oe, oo, value));
- case OPTIONS_TABLE_COMMAND:
- break;
- }
- return (-1);
-}
-
-static int
-cmd_set_option_flag(struct cmdq_item *item,
- const struct options_table_entry *oe, struct options *oo,
- const char *value)
-{
- int flag;
-
- if (value == NULL || *value == '\0')
- flag = !options_get_number(oo, oe->name);
- else if (strcmp(value, "1") == 0 ||
- strcasecmp(value, "on") == 0 ||
- strcasecmp(value, "yes") == 0)
- flag = 1;
- else if (strcmp(value, "0") == 0 ||
- strcasecmp(value, "off") == 0 ||
- strcasecmp(value, "no") == 0)
- flag = 0;
- else {
- cmdq_error(item, "bad value: %s", value);
- return (-1);
- }
- options_set_number(oo, oe->name, flag);
- return (0);
-}
-
-static int
-cmd_set_option_choice(struct cmdq_item *item,
- const struct options_table_entry *oe, struct options *oo,
- const char *value)
-{
- const char **cp;
- int n, choice = -1;
-
- if (value == NULL) {
- choice = options_get_number(oo, oe->name);
- if (choice < 2)
- choice = !choice;
- } else {
- n = 0;
- for (cp = oe->choices; *cp != NULL; cp++) {
- if (strcmp(*cp, value) == 0)
- choice = n;
- n++;
- }
- if (choice == -1) {
- cmdq_error(item, "unknown value: %s", value);
- return (-1);
- }
- }
- options_set_number(oo, oe->name, choice);
- return (0);
-}
diff --git a/cmd-show-messages.c b/cmd-show-messages.c
index 2fa68f2a..deb0487c 100644
--- a/cmd-show-messages.c
+++ b/cmd-show-messages.c
@@ -18,6 +18,7 @@
#include <sys/types.h>
+#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <unistd.h>
@@ -29,6 +30,9 @@
* Show client message log.
*/
+#define SHOW_MESSAGES_TEMPLATE \
+ "#{t/p:message_time}: #{message_text}"
+
static enum cmd_retval cmd_show_messages_exec(struct cmd *,
struct cmdq_item *);
diff --git a/cmd-show-options.c b/cmd-show-options.c
index e2aec930..8e70eaa9 100644
--- a/cmd-show-options.c
+++ b/cmd-show-options.c
@@ -151,7 +151,7 @@ cmd_show_options_print(struct cmd *self, struct cmdq_item *item,
xasprintf(&tmp, "%s[%d]", name, idx);
name = tmp;
} else {
- if (options_isarray(o)) {
+ if (options_is_array(o)) {
a = options_array_first(o);
if (a == NULL) {
if (!args_has(args, 'v'))
@@ -168,10 +168,10 @@ cmd_show_options_print(struct cmd *self, struct cmdq_item *item,
}
}
- value = options_tostring(o, idx, 0);
+ value = options_to_string(o, idx, 0);
if (args_has(args, 'v'))
cmdq_print(item, "%s", value);
- else if (options_isstring(o)) {
+ else if (options_is_string(o)) {
escaped = args_escape(value);
if (parent)
cmdq_print(item, "%s* %s", name, escaped);
@@ -229,7 +229,7 @@ cmd_show_options_all(struct cmd *self, struct cmdq_item *item, int scope,
} else
parent = 0;
- if (!options_isarray(o))
+ if (!options_is_array(o))
cmd_show_options_print(self, item, o, -1, parent);
else if ((a = options_array_first(o)) == NULL) {
if (!args_has(args, 'v')) {
diff --git a/cmd.c b/cmd.c
index bc807cbe..8a977023 100644
--- a/cmd.c
+++ b/cmd.c
@@ -40,6 +40,7 @@ extern const struct cmd_entry cmd_clock_mode_entry;
extern const struct cmd_entry cmd_command_prompt_entry;
extern const struct cmd_entry cmd_confirm_before_entry;
extern const struct cmd_entry cmd_copy_mode_entry;
+extern const struct cmd_entry cmd_customize_mode_entry;
extern const struct cmd_entry cmd_delete_buffer_entry;
extern const struct cmd_entry cmd_detach_client_entry;
extern const struct cmd_entry cmd_display_menu_entry;
@@ -130,6 +131,7 @@ const struct cmd_entry *cmd_table[] = {
&cmd_command_prompt_entry,
&cmd_confirm_before_entry,
&cmd_copy_mode_entry,
+ &cmd_customize_mode_entry,
&cmd_delete_buffer_entry,
&cmd_detach_client_entry,
&cmd_display_menu_entry,
diff --git a/format-draw.c b/format-draw.c
index 3751082e..bd32b2a8 100644
--- a/format-draw.c
+++ b/format-draw.c
@@ -547,7 +547,7 @@ format_draw(struct screen_write_ctx *octx, const struct grid_cell *base,
*/
cp = expanded;
while (*cp != '\0') {
- if (cp[0] != '#' || cp[1] != '[') {
+ if (cp[0] != '#' || cp[1] != '[' || sy.ignore) {
/* See if this is a UTF-8 character. */
if ((more = utf8_open(ud, *cp)) == UTF8_MORE) {
while (*++cp != '\0' && more == UTF8_MORE)
diff --git a/format.c b/format.c
index 9cc8195c..c7f7b90a 100644
--- a/format.c
+++ b/format.c
@@ -1392,7 +1392,7 @@ format_find(struct format_tree *ft, const char *key, int modifiers,
if (o == NULL)
o = options_parse_get(global_s_options, key, &idx, 0);
if (o != NULL) {
- found = options_tostring(o, idx, 1);
+ found = options_to_string(o, idx, 1);
goto found;
}
diff --git a/key-bindings.c b/key-bindings.c
index 85bfb788..ecd2f7dc 100644
--- a/key-bindings.c
+++ b/key-bindings.c
@@ -89,9 +89,8 @@ key_bindings_cmp(struct key_binding *bd1, struct key_binding *bd2)
}
static void
-key_bindings_free(struct key_table *table, struct key_binding *bd)
+key_bindings_free(struct key_binding *bd)
{
- RB_REMOVE(key_bindings, &table->key_bindings, bd);
cmd_list_free(bd->cmdlist);
free((void *)bd->note);
free(bd);
@@ -110,6 +109,7 @@ key_bindings_get_table(const char *name, int create)
table = xmalloc(sizeof *table);
table->name = xstrdup(name);
RB_INIT(&table->key_bindings);
+ RB_INIT(&table->default_key_bindings);
table->references = 1; /* one reference in key_tables */
RB_INSERT(key_tables, &key_tables, table);
@@ -138,8 +138,14 @@ key_bindings_unref_table(struct key_table *table)
if (--table->references != 0)
return;
- RB_FOREACH_SAFE(bd, key_bindings, &table->key_bindings, bd1)
- key_bindings_free(table, bd);
+ RB_FOREACH_SAFE(bd, key_bindings, &table->key_bindings, bd1) {
+ RB_REMOVE(key_bindings, &table->key_bindings, bd);
+ key_bindings_free(bd);
+ }
+ RB_FOREACH_SAFE(bd, key_bindings, &table->default_key_bindings, bd1) {
+ RB_REMOVE(key_bindings, &table->default_key_bindings, bd);
+ key_bindings_free(bd);
+ }
free((void *)table->name);
free(table);
@@ -155,6 +161,15 @@ key_bindings_get(struct key_table *table, key_code key)
}
struct key_binding *
+key_bindings_get_default(struct key_table *table, key_code key)
+{
+ struct key_binding bd;
+
+ bd.key = key;
+ return (RB_FIND(key_bindings, &table->default_key_bindings, &bd));
+}
+
+struct key_binding *
key_bindings_first(struct key_table *table)
{
return (RB_MIN(key_bindings, &table->key_bindings));
@@ -176,8 +191,10 @@ key_bindings_add(const char *name, key_code key, const char *note, int repeat,
table = key_bindings_get_table(name, 1);
bd = key_bindings_get(table, key & ~KEYC_XTERM);
- if (bd != NULL)
- key_bindings_free(table, bd);
+ if (bd != NULL) {
+ RB_REMOVE(key_bindings, &table->key_bindings, bd);
+ key_bindings_free(bd);
+ }
bd = xcalloc(1, sizeof *bd);
bd->key = key;
@@ -203,9 +220,12 @@ key_bindings_remove(const char *name, key_code key)
bd = key_bindings_get(table, key & ~KEYC_XTERM);
if (bd == NULL)
return;
- key_bindings_free(table, bd);
- if (RB_EMPTY(&table->key_bindings)) {
+ RB_REMOVE(key_bindings, &table->key_bindings, bd);
+ key_bindings_free(bd);
+
+ if (RB_EMPTY(&table->key_bindings) &&
+ RB_EMPTY(&table->default_key_bindings)) {
RB_REMOVE(key_tables, &key_tables, table);
key_bindings_unref_table(table);
}
@@ -228,6 +248,28 @@ key_bindings_remove_table(const char *name)
}
}
+static enum cmd_retval
+key_bindings_init_done(__unused struct cmdq_item *item, __unused void *data)
+{
+ struct key_table *table;
+ struct key_binding *bd, *new_bd;
+
+ RB_FOREACH(table, key_tables, &key_tables) {
+ RB_FOREACH(bd, key_bindings, &table->key_bindings) {
+ new_bd = xcalloc(1, sizeof *bd);
+ new_bd->key = bd->key;
+ if (bd->note != NULL)
+ new_bd->note = xstrdup(bd->note);
+ new_bd->flags = bd->flags;
+ new_bd->cmdlist = bd->cmdlist;
+ new_bd->cmdlist->references++;
+ RB_INSERT(key_bindings, &table->default_key_bindings,
+ new_bd);
+ }
+ }
+ return (CMD_RETURN_NORMAL);
+}
+
void
key_bindings_init(void)
{
@@ -278,6 +320,7 @@ key_bindings_init(void)
"bind -N 'Toggle the marked pane' m select-pane -m",
"bind -N 'Select the next window' n next-window",
"bind -N 'Select the next pane' o select-pane -t:.+",
+ "bind -N 'Customize options' C customize-mode -Z",
"bind -N 'Select the previous pane' p previous-window",
"bind -N 'Display pane numbers' q display-panes",
"bind -N 'Redraw the current client' r refresh-client",
@@ -524,6 +567,7 @@ key_bindings_init(void)
cmdq_append(NULL, cmdq_get_command(pr->cmdlist, NULL));
cmd_list_free(pr->cmdlist);
}
+ cmdq_append(NULL, cmdq_get_callback(key_bindings_init_done, NULL));
}
static enum cmd_retval
diff --git a/mode-tree.c b/mode-tree.c
index b3b3f335..131830d6 100644
--- a/mode-tree.c
+++ b/mode-tree.c
@@ -45,6 +45,7 @@ struct mode_tree_data {
mode_tree_draw_cb drawcb;
mode_tree_search_cb searchcb;
mode_tree_menu_cb menucb;
+ mode_tree_height_cb heightcb;
struct mode_tree_list children;
struct mode_tree_list saved;
@@ -79,6 +80,7 @@ struct mode_tree_item {
int expanded;
int tagged;
+ int draw_as_parent;
struct mode_tree_list children;
TAILQ_ENTRY(mode_tree_item) entry;
@@ -210,7 +212,7 @@ mode_tree_clear_tagged(struct mode_tree_list *mtl)
}
}
-static void
+void
mode_tree_up(struct mode_tree_data *mtd, int wrap)
{
if (mtd->current == 0) {
@@ -247,6 +249,12 @@ mode_tree_get_current(struct mode_tree_data *mtd)
return (mtd->line_list[mtd->current].item->itemdata);
}
+const char *
+mode_tree_get_current_name(struct mode_tree_data *mtd)
+{
+ return (mtd->line_list[mtd->current].item->name);
+}
+
void
mode_tree_expand_current(struct mode_tree_data *mtd)
{
@@ -256,6 +264,15 @@ mode_tree_expand_current(struct mode_tree_data *mtd)
}
}
+void
+mode_tree_collapse_current(struct mode_tree_data *mtd)
+{
+ if (mtd->line_list[mtd->current].item->expanded) {
+ mtd->line_list[mtd->current].item->expanded = 0;
+ mode_tree_build(mtd);
+ }
+}
+
static int
mode_tree_get_tag(struct mode_tree_data *mtd, uint64_t tag, u_int *found)
{
@@ -343,7 +360,8 @@ mode_tree_each_tagged(struct mode_tree_data *mtd, mode_tree_each_cb cb,
struct mode_tree_data *
mode_tree_start(struct window_pane *wp, struct args *args,
mode_tree_build_cb buildcb, mode_tree_draw_cb drawcb,
- mode_tree_search_cb searchcb, mode_tree_menu_cb menucb, void *modedata,
+ mode_tree_search_cb searchcb, mode_tree_menu_cb menucb,
+ mode_tree_height_cb heightcb, void *modedata,
const struct menu_item *menu, const char **sort_list, u_int sort_size,
struct screen **s)
{
@@ -381,6 +399,7 @@ mode_tree_start(struct window_pane *wp, struct args *args,
mtd->drawcb = drawcb;
mtd->searchcb = searchcb;
mtd->menucb = menucb;
+ mtd->heightcb = heightcb;
TAILQ_INIT(&mtd->children);
@@ -404,6 +423,27 @@ mode_tree_zoom(struct mode_tree_data *mtd, struct args *args)
mtd->zoomed = -1;
}
+static void
+mode_tree_set_height(struct mode_tree_data *mtd)
+{
+ struct screen *s = &mtd->screen;
+ u_int height;
+
+ if (mtd->heightcb != NULL) {
+ height = mtd->heightcb(mtd, screen_size_y(s));
+ if (height < screen_size_y(s))
+ mtd->height = screen_size_y(s) - height;
+ } else {
+ mtd->height = (screen_size_y(s) / 3) * 2;
+ if (mtd->height > mtd->line_size)
+ mtd->height = screen_size_y(s) / 2;
+ }
+ if (mtd->height < 10)
+ mtd->height = screen_size_y(s);
+ if (screen_size_y(s) - mtd->height < 2)
+ mtd->height = screen_size_y(s);
+}
+
void
mode_tree_build(struct mode_tree_data *mtd)
{
@@ -434,15 +474,9 @@ mode_tree_build(struct mode_tree_data *mtd)
mode_tree_set_current(mtd, tag);
mtd->width = screen_size_x(s);
- if (mtd->preview) {
- mtd->height = (screen_size_y(s) / 3) * 2;
- if (mtd->height > mtd->line_size)
- mtd->height = screen_size_y(s) / 2;
- if (mtd->height < 10)
- mtd->height = screen_size_y(s);
- if (screen_size_y(s) - mtd->height < 2)
- mtd->height = screen_size_y(s);
- } else
+ if (mtd->preview)
+ mode_tree_set_height(mtd);
+ else
mtd->height = screen_size_y(s);
mode_tree_check_selected(mtd);
}
@@ -494,7 +528,7 @@ mode_tree_add(struct mode_tree_data *mtd, struct mode_tree_item *parent,
struct mode_tree_item *mti, *saved;
log_debug("%s: %llu, %s %s", __func__, (unsigned long long)tag,
- name, text);
+ name, (text == NULL ? "" : text));
mti = xcalloc(1, sizeof *mti);
mti->parent = parent;
@@ -502,7 +536,8 @@ mode_tree_add(struct mode_tree_data *mtd, struct mode_tree_item *parent,
mti->tag = tag;
mti->name = xstrdup(name);
- mti->text = xstrdup(text);
+ if (text != NULL)
+ mti->text = xstrdup(text);
saved = mode_tree_find_item(&mtd->saved, tag);
if (saved != NULL) {
@@ -525,6 +560,12 @@ mode_tree_add(struct mode_tree_data *mtd, struct mode_tree_item *parent,
}
void
+mode_tree_draw_as_parent(struct mode_tree_item *mti)
+{
+ mti->draw_as_parent = 1;
+}
+
+void
mode_tree_remove(struct mode_tree_data *mtd, struct mode_tree_item *mti)
{
struct mode_tree_item *parent = mti->parent;
@@ -621,8 +662,8 @@ mode_tree_draw(struct mode_tree_data *mtd)
tag = "*";
else
tag = "";
- xasprintf(&text, "%-*s%s%s%s: ", keylen, key, start, mti->name,
- tag);
+ xasprintf(&text, "%-*s%s%s%s%s", keylen, key, start, mti->name,
+ tag, (mti->text != NULL) ? ": " : "" );
width = utf8_cstrwidth(text);
if (width > w)
width = w;
@@ -636,11 +677,17 @@ mode_tree_draw(struct mode_tree_data *mtd)
if (i != mtd->current) {
screen_write_clearendofline(&ctx, 8);
screen_write_nputs(&ctx, w, &gc0, "%s", text);
- format_draw(&ctx, &gc0, w - width, mti->text, NULL);
+ if (mti->text != NULL) {
+ format_draw(&ctx, &gc0, w - width, mti->text,
+ NULL);
+ }
} else {
screen_write_clearendofline(&ctx, gc.bg);
screen_write_nputs(&ctx, w, &gc, "%s", text);
- format_draw(&ctx, &gc, w - width, mti->text, NULL);
+ if (mti->text != NULL) {
+ format_draw(&ctx, &gc, w - width, mti->text,
+ NULL);
+ }
}
free(text);
@@ -658,13 +705,18 @@ mode_tree_draw(struct mode_tree_data *mtd)
line = &mtd->line_list[mtd->current];
mti = line->item;
+ if (mti->draw_as_parent)
+ mti = mti->parent;
screen_write_cursormove(&ctx, 0, h, 0);
screen_write_box(&ctx, w, sy - h);
- xasprintf(&text, " %s (sort: %s%s)", mti->name,
- mtd->sort_list[mtd->sort_crit.field],
- mtd->sort_crit.reversed ? ", reversed" : "");
+ if (mtd->sort_list != NULL) {
+ xasprintf(&text, " %s (sort: %s%s)", mti->name,
+ mtd->sort_list[mtd->sort_crit.field],
+ mtd->sort_crit.reversed ? ", reversed" : "");
+ } else
+ xasprintf(&text, " %s", mti->name);
if (w - 2 >= strlen(text)) {
screen_write_cursormove(&ctx, 1, h, 0);
screen_write_puts(&ctx, &gc0, "%s", text);
@@ -680,7 +732,8 @@ mode_tree_draw(struct mode_tree_data *mtd)
else
screen_write_puts(&ctx, &gc0, "active");
screen_write_puts(&ctx, &gc0, ") ");
- }
+ } else
+ screen_write_puts(&ctx, &gc0, " ");
}
free(text);
@@ -1027,7 +1080,7 @@ mode_tree_key(struct mode_tree_data *mtd, struct client *c, key_code *key,
break;
case 'O':
mtd->sort_crit.field++;
- if (mtd->sort_crit.field == mtd->sort_size)
+ if (mtd->sort_crit.field >= mtd->sort_size)
mtd->sort_crit.field = 0;
mode_tree_build(mtd);
break;
diff --git a/options-table.c b/options-table.c
index 320a380f..55eb5b9f 100644
--- a/options-table.c
+++ b/options-table.c
@@ -103,9 +103,9 @@ static const char *options_table_window_size_list[] = {
"," \
"#[range=window|#{window_index} list=focus " \
"#{?#{!=:#{window-status-current-style},default}," \
- "#{window-status-current-style}," \
- "#{window-status-style}" \
- "}" \
+ "#{window-status-current-style}," \
+ "#{window-status-style}" \
+ "}" \
"#{?#{&&:#{window_last_flag}," \
"#{!=:#{window-status-last-style},default}}, " \
"#{window-status-last-style}," \
@@ -175,6 +175,7 @@ const struct options_table_entry options_table[] = {
.type = OPTIONS_TABLE_KEY,
.scope = OPTIONS_TABLE_SERVER,
.default_num = '\177',
+ .text = "The key to send for backspace."
},
{ .name = "buffer-limit",
@@ -182,7 +183,9 @@ const struct options_table_entry options_table[] = {
.scope = OPTIONS_TABLE_SERVER,
.minimum = 1,
.maximum = INT_MAX,
- .default_num = 50
+ .default_num = 50,
+ .text = "The maximum number of automatic buffers. "
+ "When this is reached, the oldest buffer is deleted."
},
{ .name = "command-alias",
@@ -195,25 +198,31 @@ const struct options_table_entry options_table[] = {
"info=show-messages -JT,"
"choose-window=choose-tree -w,"
"choose-session=choose-tree -s",
- .separator = ","
+ .separator = ",",
+ .text = "Array of command aliases. "
+ "Each entry is an alias and a command separated by '='."
},
{ .name = "copy-command",
.type = OPTIONS_TABLE_STRING,
.scope = OPTIONS_TABLE_SERVER,
- .default_str = ""
+ .default_str = "",
+ .text = "Shell command run when text is copied. "
+ "If empty, no command is run."
},
{ .name = "default-terminal",
.type = OPTIONS_TABLE_STRING,
.scope = OPTIONS_TABLE_SERVER,
- .default_str = "screen"
+ .default_str = "screen",
+ .text = "Default for the 'TERM' environment variable."
},
{ .name = "editor",
.type = OPTIONS_TABLE_STRING,
.scope = OPTIONS_TABLE_SERVER,
- .default_str = _PATH_VI
+ .default_str = _PATH_VI,
+ .text = "Editor run to edit files."
},
{ .name = "escape-time",
@@ -221,31 +230,38 @@ const struct options_table_entry options_table[] = {
.scope = OPTIONS_TABLE_SERVER,
.minimum = 0,
.maximum = INT_MAX,
- .default_num = 500
+ .default_num = 500,
+ .text = "Time to wait before assuming a key is Escape."
},
{ .name = "exit-empty",
.type = OPTIONS_TABLE_FLAG,
.scope = OPTIONS_TABLE_SERVER,
- .default_num = 1
+ .default_num = 1,
+ .text = "Whether the server should exit if there are no sessions."
},
{ .name = "exit-unattached",
.type = OPTIONS_TABLE_FLAG,
.scope = OPTIONS_TABLE_SERVER,
- .default_num = 0
+ .default_num = 0,
+ .text = "Whether the server should exit if there are no attached "
+ "clients."
},
{ .name = "focus-events",
.type = OPTIONS_TABLE_FLAG,
.scope = OPTIONS_TABLE_SERVER,
- .default_num = 0
+ .default_num = 0,
+ .text = "Whether to send focus events to applications."
},
{ .name = "history-file",
.type = OPTIONS_TABLE_STRING,
.scope = OPTIONS_TABLE_SERVER,
- .default_str = ""
+ .default_str = "",
+ .text = "Location of the command prompt history file. "
+ "Empty does not write a history file."
},
{ .name = "message-limit",
@@ -253,14 +269,18 @@ const struct options_table_entry options_table[] = {
.scope = OPTIONS_TABLE_SERVER,
.minimum = 0,
.maximum = INT_MAX,
- .default_num = 1000
+ .default_num = 1000,
+ .text = "Maximum number of server messages to keep."
},
{ .name = "set-clipboard",
.type = OPTIONS_TABLE_CHOICE,
.scope = OPTIONS_TABLE_SERVER,
.choices = options_table_set_clipboard_list,
- .default_num = 1
+ .default_num = 1,
+ .text = "Whether to attempt to set the system clipboard ('on' or "
+ "'external') and whether to allow applications to create "
+ "paste buffers with an escape sequence ('on' only)."
},
{ .name = "terminal-overrides",
@@ -268,7 +288,8 @@ const struct options_table_entry options_table[] = {
.scope = OPTIONS_TABLE_SERVER,
.flags = OPTIONS_TABLE_IS_ARRAY,
.default_str = "",
- .separator = ","
+ .separator = ",",
+ .text = "List of terminal capabilities overrides."
},
{ .name = "terminal-features",
@@ -276,8 +297,10 @@ const struct options_table_entry options_table[] = {
.scope = OPTIONS_TABLE_SERVER,
.flags = OPTIONS_TABLE_IS_ARRAY,
.default_str = "xterm*:clipboard:ccolour:cstyle:title,"