From 1bf9555e4f1ad19e1e6f97ede6fb19808ff1c267 Mon Sep 17 00:00:00 2001 From: nicm Date: Tue, 16 Jun 2020 08:18:34 +0000 Subject: d and D keys to reset to default in customize mode. --- cmd-set-option.c | 11 +--- input.c | 8 +-- key-bindings.c | 49 ++++++++++++++++ mode-tree.c | 15 ++++- options.c | 21 ++++++- tmux.1 | 2 + tmux.h | 6 +- window-customize.c | 164 +++++++++++++++++++++++++++++++++++++++++------------ 8 files changed, 222 insertions(+), 54 deletions(-) diff --git a/cmd-set-option.c b/cmd-set-option.c index 36579f29..0df12aa0 100644 --- a/cmd-set-option.c +++ b/cmd-set-option.c @@ -151,16 +151,7 @@ cmd_set_option_exec(struct cmd *self, struct cmdq_item *item) if (args_has(args, 'u')) { if (o == NULL) goto out; - if (idx == -1) { - if (*name == '@') - options_remove(o); - else if (oo == global_options || - oo == global_s_options || - oo == global_w_options) - options_default(oo, options_table_entry(o)); - else - options_remove(o); - } else if (options_array_set(o, idx, NULL, 0, &cause) != 0) { + if (options_remove_or_default(o, idx, &cause) != 0) { cmdq_error(item, "%s", cause); free(cause); goto fail; diff --git a/input.c b/input.c index 46d8734d..a3850371 100644 --- a/input.c +++ b/input.c @@ -2347,7 +2347,7 @@ static void input_exit_rename(struct input_ctx *ictx) { struct window_pane *wp = ictx->wp; - struct options_entry *oe; + struct options_entry *o; if (wp == NULL) return; @@ -2361,9 +2361,9 @@ input_exit_rename(struct input_ctx *ictx) return; if (ictx->input_len == 0) { - oe = options_get_only(wp->window->options, "automatic-rename"); - if (oe != NULL) - options_remove(oe); + o = options_get_only(wp->window->options, "automatic-rename"); + if (o != NULL) + options_remove_or_default(o, -1, NULL); return; } window_set_name(wp->window, ictx->input_buf); diff --git a/key-bindings.c b/key-bindings.c index 9e198123..f11bb430 100644 --- a/key-bindings.c +++ b/key-bindings.c @@ -231,6 +231,38 @@ key_bindings_remove(const char *name, key_code key) } } +void +key_bindings_reset(const char *name, key_code key) +{ + struct key_table *table; + struct key_binding *bd, *dd; + + table = key_bindings_get_table(name, 0); + if (table == NULL) + return; + + bd = key_bindings_get(table, key & ~KEYC_MASK_FLAGS); + if (bd == NULL) + return; + + dd = key_bindings_get_default(table, bd->key); + if (dd == NULL) { + key_bindings_remove(name, bd->key); + return; + } + + cmd_list_free(bd->cmdlist); + bd->cmdlist = dd->cmdlist; + bd->cmdlist->references++; + + free((void *)bd->note); + if (dd->note != NULL) + bd->note = xstrdup(dd->note); + else + bd->note = NULL; + bd->flags = dd->flags; +} + void key_bindings_remove_table(const char *name) { @@ -248,6 +280,23 @@ key_bindings_remove_table(const char *name) } } +void +key_bindings_reset_table(const char *name) +{ + struct key_table *table; + struct key_binding *bd, *bd1; + + table = key_bindings_get_table(name, 0); + if (table == NULL) + return; + if (RB_EMPTY(&table->default_key_bindings)) { + key_bindings_remove_table(name); + return; + } + RB_FOREACH_SAFE(bd, key_bindings, &table->key_bindings, bd1) + key_bindings_reset(name, bd->key); +} + static enum cmd_retval key_bindings_init_done(__unused struct cmdq_item *item, __unused void *data) { diff --git a/mode-tree.c b/mode-tree.c index 993070ec..c4b776f9 100644 --- a/mode-tree.c +++ b/mode-tree.c @@ -80,7 +80,9 @@ struct mode_tree_item { int expanded; int tagged; + int draw_as_parent; + int no_tag; struct mode_tree_list children; TAILQ_ENTRY(mode_tree_item) entry; @@ -565,6 +567,12 @@ mode_tree_draw_as_parent(struct mode_tree_item *mti) mti->draw_as_parent = 1; } +void +mode_tree_no_tag(struct mode_tree_item *mti) +{ + mti->no_tag = 1; +} + void mode_tree_remove(struct mode_tree_data *mtd, struct mode_tree_item *mti) { @@ -1053,6 +1061,8 @@ mode_tree_key(struct mode_tree_data *mtd, struct client *c, key_code *key, * Do not allow parents and children to both be tagged: untag * all parents and children of current. */ + if (current->no_tag) + break; if (!current->tagged) { parent = current->parent; while (parent != NULL) { @@ -1072,7 +1082,10 @@ mode_tree_key(struct mode_tree_data *mtd, struct client *c, key_code *key, break; case '\024': /* C-t */ for (i = 0; i < mtd->line_size; i++) { - if (mtd->line_list[i].item->parent == NULL) + if ((mtd->line_list[i].item->parent == NULL && + !mtd->line_list[i].item->no_tag) || + (mtd->line_list[i].item->parent != NULL && + mtd->line_list[i].item->parent->no_tag)) mtd->line_list[i].item->tagged = 1; else mtd->line_list[i].item->tagged = 0; diff --git a/options.c b/options.c index 6ed38bcd..336eb732 100644 --- a/options.c +++ b/options.c @@ -66,6 +66,7 @@ struct options { }; static struct options_entry *options_add(struct options *, const char *); +static void options_remove(struct options_entry *); #define OPTIONS_IS_STRING(o) \ ((o)->tableentry == NULL || \ @@ -315,7 +316,7 @@ options_add(struct options *oo, const char *name) return (o); } -void +static void options_remove(struct options_entry *o) { struct options *oo = o->owner; @@ -1106,3 +1107,21 @@ options_push_changes(const char *name) server_redraw_client(loop); } } + +int +options_remove_or_default(struct options_entry *o, int idx, char **cause) +{ + struct options *oo = o->owner; + + if (idx == -1) { + if (o->tableentry != NULL && + (oo == global_options || + oo == global_s_options || + oo == global_w_options)) + options_default(oo, o->tableentry); + else + options_remove(o); + } else if (options_array_set(o, idx, NULL, 0, cause) != 0) + return (-1); + return (0); +} diff --git a/tmux.1 b/tmux.1 index d6fd1c85..3c017e64 100644 --- a/tmux.1 +++ b/tmux.1 @@ -2031,6 +2031,8 @@ The following keys may be used in customize mode: .It Li "s" Ta "Set option value or key attribute" .It Li "S" Ta "Set global option value" .It Li "w" Ta "Set window option value, if option is for pane and window" +.It Li "d" Ta "Set an option or key to the default" +.It Li "D" Ta "Set tagged options and tagged keys to the default" .It Li "u" Ta "Unset an option (set to default value if global) or unbind a key" .It Li "U" Ta "Unset tagged options and unbind tagged keys" .It Li "C-s" Ta "Search by name" diff --git a/tmux.h b/tmux.h index 9bc89628..837566ca 100644 --- a/tmux.h +++ b/tmux.h @@ -1988,7 +1988,6 @@ struct options *options_owner(struct options_entry *); const struct options_table_entry *options_table_entry(struct options_entry *); struct options_entry *options_get_only(struct options *, const char *); struct options_entry *options_get(struct options *, const char *); -void options_remove(struct options_entry *); void options_array_clear(struct options_entry *); union options_value *options_array_get(struct options_entry *, u_int); int options_array_set(struct options_entry *, u_int, const char *, @@ -2025,6 +2024,8 @@ int options_from_string(struct options *, const struct options_table_entry *, const char *, const char *, int, char **); void options_push_changes(const char *); +int options_remove_or_default(struct options_entry *, int, + char **); /* options-table.c */ extern const struct options_table_entry options_table[]; @@ -2325,7 +2326,9 @@ struct key_binding *key_bindings_next(struct key_table *, struct key_binding *); void key_bindings_add(const char *, key_code, const char *, int, struct cmd_list *); void key_bindings_remove(const char *, key_code); +void key_bindings_reset(const char *, key_code); void key_bindings_remove_table(const char *); +void key_bindings_reset_table(const char *); void key_bindings_init(void); struct cmdq_item *key_bindings_dispatch(struct key_binding *, struct cmdq_item *, struct client *, struct key_event *, @@ -2802,6 +2805,7 @@ struct mode_tree_item *mode_tree_add(struct mode_tree_data *, struct mode_tree_item *, void *, uint64_t, const char *, const char *, int); void mode_tree_draw_as_parent(struct mode_tree_item *); +void mode_tree_no_tag(struct mode_tree_item *); void mode_tree_remove(struct mode_tree_data *, struct mode_tree_item *); void mode_tree_draw(struct mode_tree_data *); int mode_tree_key(struct mode_tree_data *, struct client *, key_code *, diff --git a/window-customize.c b/window-customize.c index 093ebbe4..f60d2e6e 100644 --- a/window-customize.c +++ b/window-customize.c @@ -76,6 +76,11 @@ enum window_customize_scope { WINDOW_CUSTOMIZE_PANE }; +enum window_customize_change { + WINDOW_CUSTOMIZE_UNSET, + WINDOW_CUSTOMIZE_RESET, +}; + struct window_customize_itemdata { struct window_customize_modedata *data; enum window_customize_scope scope; @@ -101,6 +106,7 @@ struct window_customize_modedata { u_int item_size; struct cmd_find_state fs; + enum window_customize_change change; }; static uint64_t @@ -380,6 +386,7 @@ window_customize_build_options(struct window_customize_modedata *data, enum window_customize_scope scope; top = mode_tree_add(data->data, NULL, NULL, tag, title, NULL, 0); + mode_tree_no_tag(top); /* * We get the options from the first tree, but build it using the @@ -452,6 +459,7 @@ window_customize_build_keys(struct window_customize_modedata *data, xasprintf(&title, "Key Table - %s", kt->name); top = mode_tree_add(data->data, NULL, NULL, tag, title, NULL, 0); + mode_tree_no_tag(top); free(title); ft = format_create_from_state(NULL, NULL, fs); @@ -476,6 +484,8 @@ window_customize_build_keys(struct window_customize_modedata *data, item->scope = WINDOW_CUSTOMIZE_KEY; item->table = xstrdup(kt->name); item->key = bd->key; + item->name = xstrdup(key_string_lookup_key(item->key, 0)); + item->idx = -1; expanded = format_expand(ft, data->format); child = mode_tree_add(data->data, top, item, (uint64_t)bd, @@ -488,6 +498,7 @@ window_customize_build_keys(struct window_customize_modedata *data, mti = mode_tree_add(data->data, child, item, tag|(bd->key << 3)|(0 << 1)|1, "Command", text, -1); mode_tree_draw_as_parent(mti); + mode_tree_no_tag(mti); free(text); if (bd->note != NULL) @@ -497,6 +508,7 @@ window_customize_build_keys(struct window_customize_modedata *data, mti = mode_tree_add(data->data, child, item, tag|(bd->key << 3)|(1 << 1)|1, "Note", text, -1); mode_tree_draw_as_parent(mti); + mode_tree_no_tag(mti); free(text); if (bd->flags & KEY_BINDING_REPEAT) @@ -506,6 +518,7 @@ window_customize_build_keys(struct window_customize_modedata *data, mti = mode_tree_add(data->data, child, item, tag|(bd->key << 3)|(2 << 1)|1, "Repeat", flag, -1); mode_tree_draw_as_parent(mti); + mode_tree_no_tag(mti); bd = key_bindings_next(kt, bd); } @@ -1125,8 +1138,7 @@ static void window_customize_unset_option(struct window_customize_modedata *data, struct window_customize_itemdata *item) { - struct options_entry *o; - const struct options_table_entry *oe; + struct options_entry *o; if (item == NULL || !window_customize_check_item(data, item, NULL)) return; @@ -1134,20 +1146,30 @@ window_customize_unset_option(struct window_customize_modedata *data, o = options_get(item->oo, item->name); if (o == NULL) return; - if (item->idx != -1) { - if (item == mode_tree_get_current(data->data)) - mode_tree_up(data->data, 0); - options_array_set(o, item->idx, NULL, 0, NULL); + if (item->idx != -1 && item == mode_tree_get_current(data->data)) + mode_tree_up(data->data, 0); + options_remove_or_default(o, item->idx, NULL); +} + +static void +window_customize_reset_option(struct window_customize_modedata *data, + struct window_customize_itemdata *item) +{ + struct options *oo; + struct options_entry *o; + + if (item == NULL || !window_customize_check_item(data, item, NULL)) + return; + if (item->idx != -1) return; + + oo = item->oo; + while (oo != NULL) { + o = options_get_only(item->oo, item->name); + if (o != NULL) + options_remove_or_default(o, -1, NULL); + oo = options_get_parent(oo); } - oe = options_table_entry(o); - if (oe != NULL && - options_owner(o) != global_options && - options_owner(o) != global_s_options && - options_owner(o) != global_w_options) - options_remove(o); - else - options_default(options_owner(o), oe); } static int @@ -1286,21 +1308,52 @@ window_customize_unset_key(struct window_customize_modedata *data, } static void -window_customize_unset_each(void *modedata, void *itemdata, +window_customize_reset_key(struct window_customize_modedata *data, + struct window_customize_itemdata *item) +{ + struct key_table *kt; + struct key_binding *dd, *bd; + + if (item == NULL || !window_customize_get_key(item, &kt, &bd)) + return; + + dd = key_bindings_get_default(kt, bd->key); + if (dd != NULL && bd->cmdlist == dd->cmdlist) + return; + if (dd == NULL && item == mode_tree_get_current(data->data)) { + mode_tree_collapse_current(data->data); + mode_tree_up(data->data, 0); + } + key_bindings_reset(kt->name, bd->key); +} + +static void +window_customize_change_each(void *modedata, void *itemdata, __unused struct client *c, __unused key_code key) { + struct window_customize_modedata *data = modedata; struct window_customize_itemdata *item = itemdata; - if (item->scope == WINDOW_CUSTOMIZE_KEY) - window_customize_unset_key(modedata, item); - else { - window_customize_unset_option(modedata, item); - options_push_changes(item->name); + switch (data->change) { + case WINDOW_CUSTOMIZE_UNSET: + if (item->scope == WINDOW_CUSTOMIZE_KEY) + window_customize_unset_key(data, item); + else + window_customize_unset_option(data, item); + break; + case WINDOW_CUSTOMIZE_RESET: + if (item->scope == WINDOW_CUSTOMIZE_KEY) + window_customize_reset_key(data, item); + else + window_customize_reset_option(data, item); + break; } + if (item->scope != WINDOW_CUSTOMIZE_KEY) + options_push_changes(item->name); } static int -window_customize_unset_current_callback(__unused struct client *c, +window_customize_change_current_callback(__unused struct client *c, void *modedata, const char *s, __unused int done) { struct window_customize_modedata *data = modedata; @@ -1312,12 +1365,22 @@ window_customize_unset_current_callback(__unused struct client *c, return (0); item = mode_tree_get_current(data->data); - if (item->scope == WINDOW_CUSTOMIZE_KEY) - window_customize_unset_key(data, item); - else { - window_customize_unset_option(data, item); - options_push_changes(item->name); + switch (data->change) { + case WINDOW_CUSTOMIZE_UNSET: + if (item->scope == WINDOW_CUSTOMIZE_KEY) + window_customize_unset_key(data, item); + else + window_customize_unset_option(data, item); + break; + case WINDOW_CUSTOMIZE_RESET: + if (item->scope == WINDOW_CUSTOMIZE_KEY) + window_customize_reset_key(data, item); + else + window_customize_reset_option(data, item); + break; } + if (item->scope != WINDOW_CUSTOMIZE_KEY) + options_push_changes(item->name); mode_tree_build(data->data); mode_tree_draw(data->data); data->wp->flags |= PANE_REDRAW; @@ -1326,7 +1389,7 @@ window_customize_unset_current_callback(__unused struct client *c, } static int -window_customize_unset_tagged_callback(struct client *c, void *modedata, +window_customize_change_tagged_callback(struct client *c, void *modedata, const char *s, __unused int done) { struct window_customize_modedata *data = modedata; @@ -1336,7 +1399,7 @@ window_customize_unset_tagged_callback(struct client *c, void *modedata, if (tolower((u_char) s[0]) != 'y' || s[1] != '\0') return (0); - mode_tree_each_tagged(data->data, window_customize_unset_each, c, + mode_tree_each_tagged(data->data, window_customize_change_each, c, KEYC_NONE, 0); mode_tree_build(data->data); mode_tree_draw(data->data); @@ -1353,7 +1416,7 @@ window_customize_key(struct window_mode_entry *wme, struct client *c, struct window_pane *wp = wme->wp; struct window_customize_modedata *data = wme->data; struct window_customize_itemdata *item, *new_item; - int finished; + int finished, idx; char *prompt; u_int tagged; @@ -1390,17 +1453,43 @@ window_customize_key(struct window_mode_entry *wme, struct client *c, options_push_changes(item->name); mode_tree_build(data->data); break; + case 'd': + if (item == NULL || item->idx != -1) + break; + xasprintf(&prompt, "Reset %s to default? ", item->name); + data->references++; + data->change = WINDOW_CUSTOMIZE_RESET; + status_prompt_set(c, NULL, prompt, "", + window_customize_change_current_callback, + window_customize_free_callback, data, + PROMPT_SINGLE|PROMPT_NOFORMAT); + free(prompt); + break; + case 'D': + tagged = mode_tree_count_tagged(data->data); + if (tagged == 0) + break; + xasprintf(&prompt, "Reset %u tagged to default? ", tagged); + data->references++; + data->change = WINDOW_CUSTOMIZE_RESET; + status_prompt_set(c, NULL, prompt, "", + window_customize_change_tagged_callback, + window_customize_free_callback, data, + PROMPT_SINGLE|PROMPT_NOFORMAT); + free(prompt); + break; case 'u': if (item == NULL) break; - if (item->scope == WINDOW_CUSTOMIZE_KEY) { - xasprintf(&prompt, "Unbind key %s? ", - key_string_lookup_key(item->key, 0)); - } else - xasprintf(&prompt, "Unset option %s? ", item->name); + idx = item->idx; + if (idx != -1) + xasprintf(&prompt, "Unset %s[%d]? ", item->name, idx); + else + xasprintf(&prompt, "Unset %s? ", item->name); data->references++; + data->change = WINDOW_CUSTOMIZE_UNSET; status_prompt_set(c, NULL, prompt, "", - window_customize_unset_current_callback, + window_customize_change_current_callback, window_customize_free_callback, data, PROMPT_SINGLE|PROMPT_NOFORMAT); free(prompt); @@ -1409,10 +1498,11 @@ window_customize_key(struct window_mode_entry *wme, struct client *c, tagged = mode_tree_count_tagged(data->data); if (tagged == 0) break; - xasprintf(&prompt, "Unset or unbind %u tagged? ", tagged); + xasprintf(&prompt, "Unset %u tagged? ", tagged); data->references++; + data->change = WINDOW_CUSTOMIZE_UNSET; status_prompt_set(c, NULL, prompt, "", - window_customize_unset_tagged_callback, + window_customize_change_tagged_callback, window_customize_free_callback, data, PROMPT_SINGLE|PROMPT_NOFORMAT); free(prompt); -- cgit v1.2.3