Improve #? conditional expression in formats:

1) add support for else if, so
   #{?cond1,value1,#{?cond2,value2,else-value}} can be changed to
   #{?cond1,value1,cond2,value2,else-value};

2) add default empty string if there's no else value, so
   #{?cond1,value1,} can be changed to #{?cond1,value1}.

From David Mandelberg in GitHub issue 4451.
This commit is contained in:
nicm
2025-04-22 12:23:26 +00:00
parent 68ffe65499
commit b905039ed2
4 changed files with 86 additions and 71 deletions

113
format.c
View File

@ -4514,7 +4514,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;
@ -4777,53 +4778,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)

View File

@ -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[] = {

View File

@ -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[] = {

View File

@ -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[] = {