From ff50d96b19373baaceeb49ccce5d9db218f2c4db Mon Sep 17 00:00:00 2001 From: Benjamin Esham Date: Sun, 26 Apr 2020 19:36:34 -0700 Subject: github #56: typo: Add a single quote that had been missing --- Doc/Zsh/mod_zutil.yo | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Doc/Zsh/mod_zutil.yo') diff --git a/Doc/Zsh/mod_zutil.yo b/Doc/Zsh/mod_zutil.yo index 24aebdfaf..812a1fd38 100644 --- a/Doc/Zsh/mod_zutil.yo +++ b/Doc/Zsh/mod_zutil.yo @@ -37,7 +37,7 @@ For example, to define your preferred form of precipitation depending on which city you're in, you might set the following in your tt(zshrc): example(zstyle ':weather:europe:*' preferred-precipitation rain -zstyle ':weather:europe:germany:* preferred-precipitation none +zstyle ':weather:europe:germany:*' preferred-precipitation none zstyle ':weather:europe:germany:*:munich' preferred-precipitation snow) Then, the fictional `tt(weather)' plugin might run under the hood a command -- cgit v1.2.3 From 5d9f7975a97a368ab16e1cd96a361a7594acdbbf Mon Sep 17 00:00:00 2001 From: Daniel Shahaf Date: Mon, 27 Apr 2020 10:06:57 +0000 Subject: 45722: docs: Change zstyle example to a non-hierarchical one --- ChangeLog | 3 + Doc/Zsh/mod_zutil.yo | 23 ++++--- Test/V05styles.ztst | 153 ----------------------------------------------- V05styles.ztst | 166 +++++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 184 insertions(+), 161 deletions(-) delete mode 100644 Test/V05styles.ztst create mode 100644 V05styles.ztst (limited to 'Doc/Zsh/mod_zutil.yo') diff --git a/ChangeLog b/ChangeLog index aba434c8c..e980c9187 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,8 @@ 2020-05-02 Daniel Shahaf + * 45722: Doc/Zsh/mod_zutil.yo, V05styles.ztst: docs: Change + zstyle example to a non-hierarchical one + * 45752/0002: Completion/Unix/Command/_gcc: Complete --output like -o. diff --git a/Doc/Zsh/mod_zutil.yo b/Doc/Zsh/mod_zutil.yo index 812a1fd38..c69233f9d 100644 --- a/Doc/Zsh/mod_zutil.yo +++ b/Doc/Zsh/mod_zutil.yo @@ -32,20 +32,27 @@ If two patterns are equally specific, the tie is broken in favour of the pattern that was defined first. em(Example) +kindex(preferred-precipitation, example style) +findex(weather, example function) -For example, to define your preferred form of precipitation depending on which -city you're in, you might set the following in your tt(zshrc): +For example, a fictional `tt(weather)' plugin might state in its documentation +that it looks up the tt(preferred-precipitation) style under the +`tt(:weather:)var(continent)tt(:)var(day-of-the-week)tt(:)var(phase-of-the-moon))' context. +According to this, you might set the following in your tt(zshrc): -example(zstyle ':weather:europe:*' preferred-precipitation rain -zstyle ':weather:europe:germany:*' preferred-precipitation none -zstyle ':weather:europe:germany:*:munich' preferred-precipitation snow) +example(zstyle ':weather:*:Sunday:*' preferred-precipitation snow +zstyle ':weather:europe:*' preferred-precipitation rain) -Then, the fictional `tt(weather)' plugin might run under the hood a command -such as +Then the plugin would run under the hood a command such as -example(zstyle -s ":weather:${continent}:${country}:${county}:${city}" preferred-precipitation REPLY) +example(zstyle -s ":weather:${continent}:${day_of_week}:${moon_phase}" preferred-precipitation REPLY) in order to retrieve your preference into the scalar variable tt($REPLY). +On Sundays tt($REPLY) would be set to `tt(snow)'; in Europe it would be set +to `tt(rain)'; and on Sundays in Europe it would be set to `tt(snow)' again, +because the patterns `tt(:weather:europe:*)' and `tt(:weather:*:Sunday:*)' both +match the var(context) argument to tt(zstyle -s), are equally specific, and the +latter was defined first. em(Usage) diff --git a/Test/V05styles.ztst b/Test/V05styles.ztst deleted file mode 100644 index c221d9db8..000000000 --- a/Test/V05styles.ztst +++ /dev/null @@ -1,153 +0,0 @@ -%prep - -# Test the use of styles, if the zsh/zutil module is available. - - if ! zmodload zsh/zutil 2>/dev/null; then - ZTST_unimplemented="can't load the zsh/zutil module for testing" - fi - -%test - zstyle :random:stuff any-old-style with any old value - zstyle :randomly:chosen some-other-style I can go on and on - zstyle -d - zstyle -0:zstyle -d restores a pristine state - -# patterns should be ordered by weight, so add in reverse order to check - zstyle ':ztst:context*' scalar-style other-scalar-value - zstyle ':ztst:context:*' scalar-style second-scalar-value - zstyle ':ztst:context:sub1' scalar-style scalar-value - zstyle ':ztst:context:sub1' array-style array value elements 'with spaces' - zstyle ':ztst:context*' boolean-style false - zstyle ':ztst:context:sub1' boolean-style true -0:defining styles - -# styles are now sorted, but patterns are in order of definition - zstyle -0:listing styles in default format ->array-style -> :ztst:context:sub1 array value elements 'with spaces' ->boolean-style -> :ztst:context:sub1 true -> :ztst:context* false ->scalar-style -> :ztst:context:sub1 scalar-value -> :ztst:context:* second-scalar-value -> :ztst:context* other-scalar-value - - zstyle -L -0:listing styles in zstyle format ->zstyle :ztst:context:sub1 array-style array value elements 'with spaces' ->zstyle :ztst:context:sub1 boolean-style true ->zstyle ':ztst:context*' boolean-style false ->zstyle :ztst:context:sub1 scalar-style scalar-value ->zstyle ':ztst:context:*' scalar-style second-scalar-value ->zstyle ':ztst:context*' scalar-style other-scalar-value - - zstyle -b :ztst:context:sub1 boolean-style bool; print $bool - zstyle -t :ztst:context:sub1 boolean-style -0:boolean test -b/-t + true ->yes - - zstyle -b :ztst:context:sub2 boolean-style bool; print $bool - zstyle -t :ztst:context:sub2 boolean-style -1:boolean test -b/-t + false ->no - - zstyle -b :ztst:context:sub1 boolean-unset-style bool; print $bool - zstyle -t :ztst:context:sub1 boolean-unset-style -2:boolean test -b/-t + unset ->no - - zstyle -T :ztst:context:sub1 boolean-style -0:boolean test -T + true - - zstyle -T :ztst:context:sub2 boolean-style -1:boolean test -T + false - - zstyle -T :ztst:context:sub1 boolean-unset-style -0:boolean test -T + unset - - zstyle -s :ztst:context:sub1 scalar-style scalar && print $scalar - zstyle -s :ztst:context:sub2 scalar-style scalar && print $scalar - zstyle -s :ztst:contextual-psychedelia scalar-style scalar && print $scalar - zstyle -s :ztst:contemplative scalar-style scalar || print no match -0:pattern matching rules ->scalar-value ->second-scalar-value ->other-scalar-value ->no match - - zstyle -s :ztst:context:sub1 array-style scalar + && print $scalar -0:scalar with separator ->array+value+elements+with spaces - - zstyle -e :ztst:\* eval-style 'reply=($something)' - something=(one two three) - zstyle -a :ztst:eval eval-style array && print -l $array -0:zstyle -e evaluations ->one ->two ->three - -# pattern ordering on output is not specified, so although in the -# current implementation it's deterministic we shouldn't -# assume it's always the same. Thus we sort the array. -# (It might be a nice touch to order patterns by weight, which is -# the way they are stored for each separate style.) - zstyle -g array && print -l ${(o)array} -0:retrieving patterns ->:ztst:* ->:ztst:context* ->:ztst:context:* ->:ztst:context:sub1 - - zstyle -m :ztst:context:sub1 array-style 'w* *s' -0:positive pattern match - - zstyle -m :ztst:context:sub1 array-style 'v' -1:negative pattern match - - zstyle -g array ':ztst:context*' && print -l $array -0:retrieving styles by pattern ->boolean-style ->scalar-style - - zstyle -g array ':ztst:context:sub1' array-style && print -l $array -0:retrieving values by pattern and name ->array ->value ->elements ->with spaces - - zstyle -d :ztst:context:sub1 - zstyle -0:deleting styles by pattern only ->boolean-style -> :ztst:context* false ->eval-style ->(eval) :ztst:* 'reply=($something)' ->scalar-style -> :ztst:context:* second-scalar-value -> :ztst:context* other-scalar-value - - zstyle -d :ztst:context\* scalar-style - zstyle -0:deleting styles by pattern and style name ->boolean-style -> :ztst:context* false ->eval-style ->(eval) :ztst:* 'reply=($something)' ->scalar-style -> :ztst:context:* second-scalar-value - - (zstyle 'ctx?' foo one - zstyle 'ctx*' foo two - zstyle -s 'ctx1' foo bar && print $bar) - (zstyle 'ctx*' foo two - zstyle 'ctx?' foo one - zstyle -s 'ctx1' foo bar && print $bar) -0:patterns of equal weight are used in order of definition ->one ->two - diff --git a/V05styles.ztst b/V05styles.ztst new file mode 100644 index 000000000..9b5fc4517 --- /dev/null +++ b/V05styles.ztst @@ -0,0 +1,166 @@ +%prep + +# Test the use of styles, if the zsh/zutil module is available. + + if ! zmodload zsh/zutil 2>/dev/null; then + ZTST_unimplemented="can't load the zsh/zutil module for testing" + fi + +%test + zstyle :random:stuff any-old-style with any old value + zstyle :randomly:chosen some-other-style I can go on and on + zstyle -d + zstyle +0:zstyle -d restores a pristine state + +# patterns should be ordered by weight, so add in reverse order to check + zstyle ':ztst:context*' scalar-style other-scalar-value + zstyle ':ztst:context:*' scalar-style second-scalar-value + zstyle ':ztst:context:sub1' scalar-style scalar-value + zstyle ':ztst:context:sub1' array-style array value elements 'with spaces' + zstyle ':ztst:context*' boolean-style false + zstyle ':ztst:context:sub1' boolean-style true +0:defining styles + +# styles are now sorted, but patterns are in order of definition + zstyle +0:listing styles in default format +>array-style +> :ztst:context:sub1 array value elements 'with spaces' +>boolean-style +> :ztst:context:sub1 true +> :ztst:context* false +>scalar-style +> :ztst:context:sub1 scalar-value +> :ztst:context:* second-scalar-value +> :ztst:context* other-scalar-value + + zstyle -L +0:listing styles in zstyle format +>zstyle :ztst:context:sub1 array-style array value elements 'with spaces' +>zstyle :ztst:context:sub1 boolean-style true +>zstyle ':ztst:context*' boolean-style false +>zstyle :ztst:context:sub1 scalar-style scalar-value +>zstyle ':ztst:context:*' scalar-style second-scalar-value +>zstyle ':ztst:context*' scalar-style other-scalar-value + + zstyle -b :ztst:context:sub1 boolean-style bool; print $bool + zstyle -t :ztst:context:sub1 boolean-style +0:boolean test -b/-t + true +>yes + + zstyle -b :ztst:context:sub2 boolean-style bool; print $bool + zstyle -t :ztst:context:sub2 boolean-style +1:boolean test -b/-t + false +>no + + zstyle -b :ztst:context:sub1 boolean-unset-style bool; print $bool + zstyle -t :ztst:context:sub1 boolean-unset-style +2:boolean test -b/-t + unset +>no + + zstyle -T :ztst:context:sub1 boolean-style +0:boolean test -T + true + + zstyle -T :ztst:context:sub2 boolean-style +1:boolean test -T + false + + zstyle -T :ztst:context:sub1 boolean-unset-style +0:boolean test -T + unset + + zstyle -s :ztst:context:sub1 scalar-style scalar && print $scalar + zstyle -s :ztst:context:sub2 scalar-style scalar && print $scalar + zstyle -s :ztst:contextual-psychedelia scalar-style scalar && print $scalar + zstyle -s :ztst:contemplative scalar-style scalar || print no match +0:pattern matching rules +>scalar-value +>second-scalar-value +>other-scalar-value +>no match + + zstyle -s :ztst:context:sub1 array-style scalar + && print $scalar +0:scalar with separator +>array+value+elements+with spaces + + zstyle -e :ztst:\* eval-style 'reply=($something)' + something=(one two three) + zstyle -a :ztst:eval eval-style array && print -l $array +0:zstyle -e evaluations +>one +>two +>three + +# pattern ordering on output is not specified, so although in the +# current implementation it's deterministic we shouldn't +# assume it's always the same. Thus we sort the array. +# (It might be a nice touch to order patterns by weight, which is +# the way they are stored for each separate style.) + zstyle -g array && print -l ${(o)array} +0:retrieving patterns +>:ztst:* +>:ztst:context* +>:ztst:context:* +>:ztst:context:sub1 + + zstyle -m :ztst:context:sub1 array-style 'w* *s' +0:positive pattern match + + zstyle -m :ztst:context:sub1 array-style 'v' +1:negative pattern match + + zstyle -g array ':ztst:context*' && print -l $array +0:retrieving styles by pattern +>boolean-style +>scalar-style + + zstyle -g array ':ztst:context:sub1' array-style && print -l $array +0:retrieving values by pattern and name +>array +>value +>elements +>with spaces + + zstyle -d :ztst:context:sub1 + zstyle +0:deleting styles by pattern only +>boolean-style +> :ztst:context* false +>eval-style +>(eval) :ztst:* 'reply=($something)' +>scalar-style +> :ztst:context:* second-scalar-value +> :ztst:context* other-scalar-value + + zstyle -d :ztst:context\* scalar-style + zstyle +0:deleting styles by pattern and style name +>boolean-style +> :ztst:context* false +>eval-style +>(eval) :ztst:* 'reply=($something)' +>scalar-style +> :ztst:context:* second-scalar-value + + (zstyle 'ctx?' foo one + zstyle 'ctx*' foo two + zstyle -s 'ctx1' foo bar && print $bar) + (zstyle 'ctx*' foo two + zstyle 'ctx?' foo one + zstyle -s 'ctx1' foo bar && print $bar) +0:patterns of equal weight are used in order of definition +>one +>two + + ( + zstyle ':weather:*:Sunday:*' preferred-precipitation snow + zstyle ':weather:europe:*' preferred-precipitation rain + zstyle -s ':weather:europe:Sunday:foo' preferred-precipitation REPLY && print $REPLY + ) + ( + zstyle ':weather:europe:*' preferred-precipitation rain + zstyle ':weather:*:Sunday:*' preferred-precipitation snow + zstyle -s ':weather:europe:Sunday:foo' preferred-precipitation REPLY && print $REPLY + ) +0:the example in the documentation remains correct +>snow +>rain -- cgit v1.2.3 From 34d69acbef44f654ea51d762ffdb02f5b1e8b9e1 Mon Sep 17 00:00:00 2001 From: Daniel Shahaf Date: Wed, 29 Apr 2020 00:30:17 +0000 Subject: 45737 (+ docs, and update the test from 45722): zstyle: When determining the weight (specificity) of a pattern, consider the number of components before anything else, as documented. --- ChangeLog | 6 ++++++ Doc/Zsh/mod_zutil.yo | 6 +++--- README | 19 +++++++++++++++++++ Src/Modules/zutil.c | 13 +++++++++++-- Test/V05styles.ztst | 2 +- 5 files changed, 40 insertions(+), 6 deletions(-) (limited to 'Doc/Zsh/mod_zutil.yo') diff --git a/ChangeLog b/ChangeLog index ec1e413c7..1fd8b9944 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,11 @@ 2020-05-02 Daniel Shahaf + * 45737 (+ docs, and update the test from 45722): + Doc/Zsh/mod_zutil.yo, README, Src/Modules/zutil.c, + Test/V05styles.ztst: zstyle: When determining the weight + (specificity) of a pattern, consider the number of components + before anything else, as documented. + * unposted: Test/V05styles.ztst: Revert unintentional move from 45722. diff --git a/Doc/Zsh/mod_zutil.yo b/Doc/Zsh/mod_zutil.yo index c69233f9d..9c50e6122 100644 --- a/Doc/Zsh/mod_zutil.yo +++ b/Doc/Zsh/mod_zutil.yo @@ -40,8 +40,8 @@ that it looks up the tt(preferred-precipitation) style under the `tt(:weather:)var(continent)tt(:)var(day-of-the-week)tt(:)var(phase-of-the-moon))' context. According to this, you might set the following in your tt(zshrc): -example(zstyle ':weather:*:Sunday:*' preferred-precipitation snow -zstyle ':weather:europe:*' preferred-precipitation rain) +example(zstyle ':weather:europe:*' preferred-precipitation rain +zstyle ':weather:*:Sunday:*' preferred-precipitation snow) Then the plugin would run under the hood a command such as @@ -52,7 +52,7 @@ On Sundays tt($REPLY) would be set to `tt(snow)'; in Europe it would be set to `tt(rain)'; and on Sundays in Europe it would be set to `tt(snow)' again, because the patterns `tt(:weather:europe:*)' and `tt(:weather:*:Sunday:*)' both match the var(context) argument to tt(zstyle -s), are equally specific, and the -latter was defined first. +latter is more specific (because it has more colon-separated components). em(Usage) diff --git a/README b/README index b87f660bf..8ae615153 100644 --- a/README +++ b/README @@ -64,6 +64,25 @@ The sh-compatible function definition syntax, "f() { ... }", is unchanged. The time-out (-t) value given to zsh/system's `zsystem flock` command is now limited to 2^30-1 seconds (= a little over 34 years). +zstyle: For background, recall that the zstyle builtin associates styles with +values for particular contexts, and when a context (such as ':foo:bar:baz') is +matched by multiple patterns (such as ':foo:*' and ':foo:bar:*'), the style's +value for the more specific of the patterns is used. In zsh 5.8 and earlier +the determination of which pattern is "more specific" used semantics slightly +different to those the documentation promised. The implementation was changed +to match the documentation. The upshot of this is that if you set a single +style in multiple contexts, zsh 5.9 may use the values set for a pattern other +than the one zsh 5.8 used. For example, if you do + zstyle ':foo:bar:*' style value1 + zstyle ':foo:*:baz:*' style value2 +and the style is looked up under a context that both patterns match (e.g., +:foo:bar:baz:qux), zsh 5.9 will use value2 -- which is consistent with the +documentation of both 5.8 and 5.9 -- but zsh 5.8 will use value1. If this +affects you, make the implied colons in the first pattern explicit, as in: + zstyle ':foo:bar:*:*' style value1 + zstyle ':foo:*:baz:*' style value2 +This will use value1 in both 5.8 and 5.9. + Incompatibilities between 5.7.1 and 5.8 --------------------------------------- diff --git a/Src/Modules/zutil.c b/Src/Modules/zutil.c index 7d9bf05d6..5c96d06c1 100644 --- a/Src/Modules/zutil.c +++ b/Src/Modules/zutil.c @@ -96,7 +96,7 @@ struct stypat { Stypat next; char *pat; /* pattern string */ Patprog prog; /* compiled pattern */ - int weight; /* how specific is the pattern? */ + zulong weight; /* how specific is the pattern? */ Eprog eval; /* eval-on-retrieve? */ char **vals; }; @@ -293,7 +293,9 @@ newzstyletable(int size, char const *name) static int setstypat(Style s, char *pat, Patprog prog, char **vals, int eval) { - int weight, tmp, first; + zulong weight; + int tmp; + int first; char *str; Stypat p, q, qq; Eprog eprog = NULL; @@ -348,6 +350,12 @@ setstypat(Style s, char *pat, Patprog prog, char **vals, int eval) * - A component that's a literal string scores 2 points. * - The score of a pattern is the sum of the score of its components. * + * The result of this calculation is stored in the low bits of 'weight'. + * The high bits of 'weight' are used to store the number of ':'-separated + * components. This provides a lexicographic comparison: first compare + * the number of components, and if that's equal, compare the specificity + * of the components. + * * This corresponds to the notion of 'more specific' in the zshmodules(1) * documentation of zstyle. */ @@ -367,6 +375,7 @@ setstypat(Style s, char *pat, Patprog prog, char **vals, int eval) if (*str == ':') { /* Yet another component. */ + weight += ZLONG_CONST(1) << (CHAR_BIT * sizeof(weight) / 2); first = 1; weight += tmp; diff --git a/Test/V05styles.ztst b/Test/V05styles.ztst index 9b5fc4517..048751941 100644 --- a/Test/V05styles.ztst +++ b/Test/V05styles.ztst @@ -163,4 +163,4 @@ ) 0:the example in the documentation remains correct >snow ->rain +>snow -- cgit v1.2.3 From c5f12fb732cc9ee9f151dd3357cf5f3f4bb55a48 Mon Sep 17 00:00:00 2001 From: Daniel Shahaf Date: Wed, 10 Jun 2020 13:07:52 +0000 Subject: unposted: zstyle docs: Fix typo. This manifested as a trailing non-underlined ".RE" in the rendered man page. (I guess that was a man page directive, but I'm not sure how the extraneous closing parenthesis caused it to be rendered in the output.) --- ChangeLog | 4 ++++ Doc/Zsh/mod_zutil.yo | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) (limited to 'Doc/Zsh/mod_zutil.yo') diff --git a/ChangeLog b/ChangeLog index 3addf253f..2e02cb123 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2020-06-10 Daniel Shahaf + + * unposted: Doc/Zsh/mod_zutil.yo: zstyle docs: Fix typo. + 2020-06-09 Peter Stephenson * 46026: Doc/Zsh/options.yo, Src/exec.c, Src/options.c, diff --git a/Doc/Zsh/mod_zutil.yo b/Doc/Zsh/mod_zutil.yo index 9c50e6122..41d3dfdb0 100644 --- a/Doc/Zsh/mod_zutil.yo +++ b/Doc/Zsh/mod_zutil.yo @@ -37,7 +37,7 @@ findex(weather, example function) For example, a fictional `tt(weather)' plugin might state in its documentation that it looks up the tt(preferred-precipitation) style under the -`tt(:weather:)var(continent)tt(:)var(day-of-the-week)tt(:)var(phase-of-the-moon))' context. +`tt(:weather:)var(continent)tt(:)var(day-of-the-week)tt(:)var(phase-of-the-moon)' context. According to this, you might set the following in your tt(zshrc): example(zstyle ':weather:europe:*' preferred-precipitation rain -- cgit v1.2.3 From dfb7ac94bb4c28472d759a61ea3c2dab30cf9cd3 Mon Sep 17 00:00:00 2001 From: Oliver Kiddle Date: Fri, 12 Nov 2021 20:33:52 +0100 Subject: 49561: add zformat -F option, similar to -f but ternary expressions check for existence instead of doing math evaluation --- ChangeLog | 8 +++++++ Completion/Base/Core/_description | 2 +- Completion/Base/Core/_message | 2 +- Doc/Zsh/mod_zutil.yo | 11 +++++++-- Src/Modules/zutil.c | 48 ++++++++++++++++++++++++++------------- Test/V13zformat.ztst | 24 ++++++++++++++++++++ 6 files changed, 75 insertions(+), 20 deletions(-) (limited to 'Doc/Zsh/mod_zutil.yo') diff --git a/ChangeLog b/ChangeLog index 5865cb727..65c0dfa8f 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,11 @@ +2021-11-12 Oliver Kiddle + + * 49561: Src/Modules/zutil.c, Doc/Zsh/mod_zutil.yo, + Completion/Base/Core/_description, Completion/Base/Core/_message, + Test/V13zformat.ztst: Add zformat -F option, similar to -f but + ternary expressions check for existence instead of doing math + evaluation. Make use it with the format style. + 2021-11-07 Oliver Kiddle * 49544: Src/Modules/watch.c: only tie watch/WATCH if both come diff --git a/Completion/Base/Core/_description b/Completion/Base/Core/_description index bdb4007a6..5b54484c7 100644 --- a/Completion/Base/Core/_description +++ b/Completion/Base/Core/_description @@ -78,7 +78,7 @@ shift 2 if [[ -z "$1" && $# -eq 1 ]]; then format= elif [[ -n "$format" ]]; then - zformat -f format "$format" "d:$1" "${(@)argv[2,-1]}" + zformat -F format "$format" "d:$1" "${(@)argv[2,-1]}" fi if [[ -n "$gname" ]]; then diff --git a/Completion/Base/Core/_message b/Completion/Base/Core/_message index 4d5645eaf..dbeed4a88 100644 --- a/Completion/Base/Core/_message +++ b/Completion/Base/Core/_message @@ -39,7 +39,7 @@ else fi if [[ -n "$format$raw" ]]; then - [[ -z "$raw" ]] && zformat -f format "$format" "d:$1" "${(@)argv[2,-1]}" + [[ -z "$raw" ]] && zformat -F format "$format" "d:$1" "${(@)argv[2,-1]}" builtin compadd "$gopt[@]" -x "$format" _comp_mesg=yes fi diff --git a/Doc/Zsh/mod_zutil.yo b/Doc/Zsh/mod_zutil.yo index 41d3dfdb0..3cf9e5028 100644 --- a/Doc/Zsh/mod_zutil.yo +++ b/Doc/Zsh/mod_zutil.yo @@ -150,8 +150,9 @@ enditem() ) findex(zformat) xitem(tt(zformat -f) var(param) var(format) var(spec) ...) +xitem(tt(zformat -F) var(param) var(format) var(spec) ...) item(tt(zformat -a) var(array) var(sep) var(spec) ...)( -This builtin provides two different forms of formatting. The first form +This builtin provides different forms of formatting. The first form is selected with the tt(-f) option. In this case the var(format) string will be modified by replacing sequences starting with a percent sign in it with strings from the var(spec)s. Each var(spec) should be @@ -195,7 +196,13 @@ outputs "The answer is 'yes'." to tt(REPLY) since the value for the format specifier tt(c) is 3, agreeing with the digit argument to the ternary expression. -The second form, using the tt(-a) option, can be used for aligning +With tt(-F) instead of tt(-f), ternary expressions choose between the +`true' or `false' text on the basis of whether the format specifier is +present and non-empty. A test number indicates a minimum width for the +value given in the format specifier. Negative numbers reverse this, +so the test is for whether the value exceeds a maximum width. + +The form, using the tt(-a) option, can be used for aligning strings. Here, the var(spec)s are of the form `var(left)tt(:)var(right)' where `var(left)' and `var(right)' are arbitrary strings. These strings are modified by replacing the colons diff --git a/Src/Modules/zutil.c b/Src/Modules/zutil.c index 691ba6c2f..2f17c03f1 100644 --- a/Src/Modules/zutil.c +++ b/Src/Modules/zutil.c @@ -776,10 +776,12 @@ bin_zstyle(char *nam, char **args, UNUSED(Options ops), UNUSED(int func)) * ousedp (*outp)[*ousedp] is where to write next * olenp *olenp is the size allocated for *outp * endchar Terminator character in addition to `\0' (may be '\0') + * presence -F: Ternary expressions test emptyness instead * skip If 1, don't output, just parse. */ static char *zformat_substring(char* instr, char **specs, char **outp, - int *ousedp, int *olenp, int endchar, int skip) + int *ousedp, int *olenp, int endchar, + int presence, int skip) { char *s; @@ -813,20 +815,29 @@ static char *zformat_substring(char* instr, char **specs, char **outp, if (testit && STOUC(*s)) { int actval, testval, endcharl; - /* - * One one number is useful for ternary expressions. - * Remember to put the sign back. - */ + /* Only one number is useful for ternary expressions. */ testval = (min >= 0) ? min : (max >= 0) ? max : 0; - if (right) - testval *= -1; - if (specs[STOUC(*s)]) - actval = (int)mathevali(specs[STOUC(*s)]); - else - actval = 0; - /* zero means values are equal, i.e. true */ - actval -= testval; + if (specs[STOUC(*s)] && *specs[STOUC(*s)]) { + if (presence) { + if (testval) +#ifdef MULTIBYTE_SUPPORT + if (isset(MULTIBYTE)) + actval = MB_METASTRWIDTH(specs[STOUC(*s)]); + else +#endif + actval = strlen(specs[STOUC(*s)]); + else + actval = 1; + actval = right ? (testval < actval) : (testval >= actval); + } else { + if (right) /* put the sign back */ + testval *= -1; + /* zero means values are equal, i.e. true */ + actval = (int)mathevali(specs[STOUC(*s)]) - testval; + } + } else + actval = presence ? !right : testval; /* careful about premature end of string */ if (!(endcharl = *++s)) @@ -837,10 +848,10 @@ static char *zformat_substring(char* instr, char **specs, char **outp, * vice versa... unless we are already skipping. */ if (!(s = zformat_substring(s+1, specs, outp, ousedp, - olenp, endcharl, skip || actval))) + olenp, endcharl, presence, skip || actval))) return NULL; if (!(s = zformat_substring(s+1, specs, outp, ousedp, - olenp, ')', skip || !actval))) + olenp, ')', presence, skip || !actval))) return NULL; } else if (skip) { continue; @@ -912,6 +923,7 @@ static int bin_zformat(char *nam, char **args, UNUSED(Options ops), UNUSED(int func)) { char opt; + int presence = 0; if (args[0][0] != '-' || !(opt = args[0][1]) || args[0][2]) { zwarnnam(nam, "invalid argument: %s", args[0]); @@ -920,6 +932,9 @@ bin_zformat(char *nam, char **args, UNUSED(Options ops), UNUSED(int func)) args++; switch (opt) { + case 'F': + presence = 1; + /* fall-through */ case 'f': { char **ap, *specs[256] = {0}, *out; @@ -939,7 +954,8 @@ bin_zformat(char *nam, char **args, UNUSED(Options ops), UNUSED(int func)) } out = (char *) zhalloc(olen = 128); - zformat_substring(args[1], specs, &out, &oused, &olen, '\0', 0); + zformat_substring(args[1], specs, &out, &oused, &olen, '\0', + presence, 0); out[oused] = '\0'; setsparam(args[0], ztrdup(out)); diff --git a/Test/V13zformat.ztst b/Test/V13zformat.ztst index 982866e13..035a0a495 100644 --- a/Test/V13zformat.ztst +++ b/Test/V13zformat.ztst @@ -58,6 +58,30 @@ 0:nested conditionals test >yes + () { + zformat -f 1 '%(w.zero.fail) %(x.fail.present) %(y.empty.fail) %(z.missing.fail)' w:0 x:1 y: + zformat -F 2 '%(w.zero.fail) %(x.present.fail) %(y.fail.empty) %(z.fail.missing)' w:0 x:1 y: + echo $1 + echo $2 + } +0:conditionals with empty and missing values +>zero present empty missing +>zero present empty missing + + () { + local l + for l in 0 1 2 3; do + zformat -F 1 "%$l(a.a.A)%$l(b.b.B)%$l(c.c.C)%$l(d.d.D)" a: b:1 c:12 d:123 + zformat -F 2 "%-$l(a.a.A)%-$l(b.b.B)%-$l(c.c.C)%-$l(d.d.D)" a: b:1 c:12 d:123 + print - $1 $2 + done + } +0:minimum and maximum widths +>Abcd aBCD +>ABcd abCD +>ABCd abcD +>ABCD abcd + zformat -a argv . foo:lorem ipsum:bar bazbaz '\\esc\:ape' print -rl -- "$@" 0:basic -a test -- cgit v1.2.3