diff --git a/cmd-swap-pane.c b/cmd-swap-pane.c index 4680f598..7271e50e 100644 --- a/cmd-swap-pane.c +++ b/cmd-swap-pane.c @@ -132,9 +132,12 @@ cmd_swap_pane_exec(struct cmd *self, struct cmdq_item *item) window_pane_stack_remove(&dst_w->last_panes, dst_wp); colour_palette_from_option(&src_wp->palette, src_wp->options); colour_palette_from_option(&dst_wp->palette, dst_wp->options); + layout_fix_panes(src_w, NULL); + server_redraw_window(src_w); } - server_redraw_window(src_w); + layout_fix_panes(dst_w, NULL); server_redraw_window(dst_w); + notify_window("window-layout-changed", src_w); if (src_w != dst_w) notify_window("window-layout-changed", dst_w); diff --git a/format.c b/format.c index 010e8462..93128d92 100644 --- a/format.c +++ b/format.c @@ -4518,7 +4518,8 @@ format_replace(struct format_expand_state *es, const char *key, size_t keylen, { struct format_tree *ft = es->ft; struct window_pane *wp = ft->wp; - const char *errstr, *copy, *cp, *marker = NULL; + const char *errstr, *copy, *cp, *cp2; + const char *marker = NULL; const char *time_format = NULL; char *copy0, *condition, *found, *new; char *value, *left, *right; @@ -4781,53 +4782,81 @@ format_replace(struct format_expand_state *es, const char *key, size_t keylen, free(right); free(left); } else if (*copy == '?') { - /* Conditional: check first and choose second or third. */ - cp = format_skip(copy + 1, ","); - if (cp == NULL) { - format_log(es, "condition syntax error: %s", copy + 1); - goto fail; - } - condition = xstrndup(copy + 1, cp - (copy + 1)); - format_log(es, "condition is: %s", condition); - - found = format_find(ft, condition, modifiers, time_format); - if (found == NULL) { - /* - * If the condition not found, try to expand it. If - * the expansion doesn't have any effect, then assume - * false. - */ - found = format_expand1(es, condition); - if (strcmp(found, condition) == 0) { - free(found); - found = xstrdup(""); + /* + * Conditional: For each pair of (condition, value), check the + * condition and return the value if true. If no condition + * matches, return the last unpaired arg if there is one, or the + * empty string if not. + */ + cp = copy + 1; + while (1) { + cp2 = format_skip(cp, ","); + if (cp2 == NULL) { format_log(es, - "condition '%s' not found; assuming false", + "no condition matched in '%s'; using last " + "arg", copy + 1); + value = format_expand1(es, cp); + break; + } + + condition = xstrndup(cp, cp2 - cp); + format_log(es, "condition is: %s", condition); + + found = format_find(ft, condition, modifiers, + time_format); + if (found == NULL) { + /* + * If the condition not found, try to expand it. + * If the expansion doesn't have any effect, + * then assume false. + */ + found = format_expand1(es, condition); + if (strcmp(found, condition) == 0) { + free(found); + found = xstrdup(""); + format_log(es, + "condition '%s' not found; " + "assuming false", + condition); + } + } else { + format_log(es, "condition '%s' found: %s", + condition, found); + } + + cp = cp2 + 1; + cp2 = format_skip(cp, ","); + if (format_true(found)) { + format_log(es, "condition '%s' is true", + condition); + if (cp2 == NULL) + value = format_expand1(es, cp); + else { + right = xstrndup(cp, cp2 - cp); + value = format_expand1(es, right); + free(right); + } + free(condition); + free(found); + break; + } else { + format_log(es, "condition '%s' is false", condition); } - } else { - format_log(es, "condition '%s' found: %s", condition, - found); - } - if (format_choose(es, cp + 1, &left, &right, 0) != 0) { - format_log(es, "condition '%s' syntax error: %s", - condition, cp + 1); + free(condition); free(found); - goto fail; - } - if (format_true(found)) { - format_log(es, "condition '%s' is true", condition); - value = format_expand1(es, left); - } else { - format_log(es, "condition '%s' is false", condition); - value = format_expand1(es, right); - } - free(right); - free(left); - free(condition); - free(found); + if (cp2 == NULL) { + format_log(es, + "no condition matched in '%s'; using empty " + "string", copy + 1); + value = xstrdup(""); + break; + } + + cp = cp2 + 1; + } } else if (mexp != NULL) { value = format_replace_expression(mexp, es, copy); if (value == NULL) diff --git a/key-bindings.c b/key-bindings.c index 8761a9d7..d334fe70 100644 --- a/key-bindings.c +++ b/key-bindings.c @@ -197,11 +197,12 @@ key_bindings_add(const char *name, key_code key, const char *note, int repeat, bd = key_bindings_get(table, key & ~KEYC_MASK_FLAGS); if (cmdlist == NULL) { if (bd != NULL) { - free((void *)bd->note); - if (note != NULL) + if (note != NULL) { + free((void *)bd->note); bd->note = xstrdup(note); - else - bd->note = NULL; + } + if (repeat) + bd->flags |= KEY_BINDING_REPEAT; } return; } @@ -433,8 +434,9 @@ key_bindings_init(void) "bind -N 'Resize the pane right' -r C-Right { resize-pane -R }", /* Menu keys */ - "bind < { display-menu -xW -yW -T '#[align=centre]#{window_index}:#{window_name}' " DEFAULT_WINDOW_MENU " }", - "bind > { display-menu -xP -yP -T '#[align=centre]#{pane_index} (#{pane_id})' " DEFAULT_PANE_MENU " }", + "bind -N 'Display window menu' < { display-menu -xW -yW -T '#[align=centre]#{window_index}:#{window_name}' " DEFAULT_WINDOW_MENU " }", + "bind -N 'Display pane menu' > { display-menu -xP -yP -T '#[align=centre]#{pane_index} (#{pane_id})' " DEFAULT_PANE_MENU " }", + /* Mouse button 1 down on pane. */ "bind -n MouseDown1Pane { select-pane -t=; send -M }", diff --git a/tmux.1 b/tmux.1 index 1d43b76f..f3764da0 100644 --- a/tmux.1 +++ b/tmux.1 @@ -3730,7 +3730,15 @@ options. .Fl N attaches a note to the key (shown with .Ic list-keys -.Fl N ) . +.Fl N ) , +which can be cleared by passing an empty string. +The +.Fl r +and +.Fl N +flags can be used without +.Ar command +to alter an existing binding. .Pp To view the default bindings and possible commands, see the .Ic list-keys @@ -5633,10 +5641,12 @@ by a .Ql } . .Pp Conditionals are available by prefixing with -.Ql \&? -and separating two alternatives with a comma; -if the specified variable exists and is not zero, the first alternative -is chosen, otherwise the second is used. +.Ql \&? . +For each pair of two arguments, if the variable in the first of the pair exists +and is not zero, the second of the pair is chosen, otherwise it continues. +If no condition from paired arguments matches, the default value is chosen. +If there's an unpaired final argument, that is the default. +If not, the default is the empty string. For example .Ql #{?session_attached,attached,not attached} will include the string @@ -5652,6 +5662,12 @@ if is enabled, or .Ql no if not. +.Ql #{?#{n:window_name},#{window_name} - } +will include the window name with a dash separator if there is a window name, or +the empty string if the window name is empty. +.Ql #{?session_format,format1,window_format,format2,format3} +will include format1 for a session format, format2 for a window format, or +format3 for neither a session nor a window format. Conditionals can be nested arbitrarily. Inside a conditional, .Ql \&, @@ -6054,7 +6070,7 @@ The following variables are available, where appropriate: .It Li "pane_format" Ta "" Ta "1 if format is for a pane" .It Li "pane_height" Ta "" Ta "Height of pane" .It Li "pane_id" Ta "#D" Ta "Unique pane ID" -.It Li "pane_in_mode" Ta "" Ta "1 if pane is in a mode" +.It Li "pane_in_mode" Ta "" Ta "Number of modes pane is in" .It Li "pane_index" Ta "#P" Ta "Index of pane" .It Li "pane_input_off" Ta "" Ta "1 if input to pane is disabled" .It Li "pane_key_mode" Ta "" Ta "Extended key reporting mode in this pane" diff --git a/window-buffer.c b/window-buffer.c index 16cab7eb..dfc65109 100644 --- a/window-buffer.c +++ b/window-buffer.c @@ -44,12 +44,8 @@ static void window_buffer_key(struct window_mode_entry *, #define WINDOW_BUFFER_DEFAULT_KEY_FORMAT \ "#{?#{e|<:#{line},10}," \ "#{line}" \ - "," \ - "#{?#{e|<:#{line},36}," \ - "M-#{a:#{e|+:97,#{e|-:#{line},10}}}" \ - "," \ - "" \ - "}" \ + ",#{e|<:#{line},36}," \ + "M-#{a:#{e|+:97,#{e|-:#{line},10}}}" \ "}" static const struct menu_item window_buffer_menu_items[] = { diff --git a/window-client.c b/window-client.c index c1b962f1..a7735250 100644 --- a/window-client.c +++ b/window-client.c @@ -43,12 +43,8 @@ static void window_client_key(struct window_mode_entry *, #define WINDOW_CLIENT_DEFAULT_KEY_FORMAT \ "#{?#{e|<:#{line},10}," \ "#{line}" \ - "," \ - "#{?#{e|<:#{line},36}," \ - "M-#{a:#{e|+:97,#{e|-:#{line},10}}}" \ - "," \ - "" \ - "}" \ + ",#{e|<:#{line},36}," \ + "M-#{a:#{e|+:97,#{e|-:#{line},10}}}" \ "}" static const struct menu_item window_client_menu_items[] = { diff --git a/window-tree.c b/window-tree.c index f53f16c9..0aca9b4f 100644 --- a/window-tree.c +++ b/window-tree.c @@ -41,30 +41,24 @@ static void window_tree_key(struct window_mode_entry *, "#{?pane_marked,#[reverse],}" \ "#{pane_current_command}#{?pane_active,*,}#{?pane_marked,M,}" \ "#{?#{&&:#{pane_title},#{!=:#{pane_title},#{host_short}}},: \"#{pane_title}\",}" \ + ",window_format," \ + "#{?window_marked_flag,#[reverse],}" \ + "#{window_name}#{window_flags}" \ + "#{?#{&&:#{==:#{window_panes},1},#{&&:#{pane_title},#{!=:#{pane_title},#{host_short}}}},: \"#{pane_title}\",}" \ "," \ - "#{?window_format," \ - "#{?window_marked_flag,#[reverse],}" \ - "#{window_name}#{window_flags}" \ - "#{?#{&&:#{==:#{window_panes},1},#{&&:#{pane_title},#{!=:#{pane_title},#{host_short}}}},: \"#{pane_title}\",}" \ - "," \ - "#{session_windows} windows" \ - "#{?session_grouped, " \ - "(group #{session_group}: " \ - "#{session_group_list})," \ - "}" \ - "#{?session_attached, (attached),}" \ + "#{session_windows} windows" \ + "#{?session_grouped, " \ + "(group #{session_group}: " \ + "#{session_group_list})," \ "}" \ + "#{?session_attached, (attached),}" \ "}" #define WINDOW_TREE_DEFAULT_KEY_FORMAT \ "#{?#{e|<:#{line},10}," \ "#{line}" \ - "," \ - "#{?#{e|<:#{line},36}," \ - "M-#{a:#{e|+:97,#{e|-:#{line},10}}}" \ - "," \ - "" \ - "}" \ + ",#{e|<:#{line},36}," \ + "M-#{a:#{e|+:97,#{e|-:#{line},10}}}" \ "}" static const struct menu_item window_tree_menu_items[] = {