summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog6
-rw-r--r--Doc/Zsh/mod_zutil.yo6
-rw-r--r--README19
-rw-r--r--Src/Modules/zutil.c13
-rw-r--r--Test/V05styles.ztst2
5 files changed, 40 insertions, 6 deletions
diff --git a/ChangeLog b/ChangeLog
index ec1e413c7..1fd8b9944 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,11 @@
2020-05-02 Daniel Shahaf <d.s@daniel.shahaf.name>
+ * 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