d and D keys to reset to default in customize mode.

This commit is contained in:
nicm 2020-06-16 08:18:34 +00:00
parent afe4ea4250
commit 1bf9555e4f
8 changed files with 222 additions and 54 deletions

View File

@ -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;

View File

@ -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);

View File

@ -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)
{

View File

@ -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;

View File

@ -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);
}

2
tmux.1
View File

@ -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"

6
tmux.h
View File

@ -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 *,

View File

@ -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);