I don't understand why they are both needed since they seem that zstyle
does the same as setopt
and even more?
2 Answers
setopt
sets shell options
Shell options are a boolean variables that change the behavior of the shell itself. setopt
toggles them on or off. Run setopt
without arguments to see which shell options have been toggled from their default value. Some of these are not possible to change at runtime; instead, they are to provide info about the shell’s internal state.
What shell options are available is determined by the shell; it’s not possible to create your own. However, any piece of shell code can decide to read the value of a shell option and change its own behavior accordingly. Additionally, a shell function or executable shell script (but not one that is source
d) can change shell options locally, without affecting the rest of the shell around it.
zstyle
provides namespaced properties
zstyle [<flag>] ( <namespace> | <selector> ) <property> <value>
is Zsh’s alternative to global variables. It allows shell code to provide a way for users to configure settings, as well as store its own internal state, without polluting your shell with actual global variables.
Unlike a shell option, a zstyle
property cannot be made local. Instead, zstyle
uses a system of namespaces and selectors. When reading a zstyle
property, you pass a namespace and the name of the property from which you want to read. However, when setting a zstyle
property, you pass a glob pattern that functions similar to a CSS selector, letting you set the same property for multiple namespaces at once. (This similarity to CSS appears to be the reason for the use of the word "style" here.)
Note that zstyle
does not care what syntax you use for your namespaces. Using :
as a hierarchical separator (as is done in Zsh’s completion system) is merely a convention.
Each zstyle
property stores an array of strings. However:
- If you pass the
-e
flag when setting a property, the strings are evaluated as code when the property is read, enabling the creation of computed properties – something which is not possible with global variables. zstyle
offers several convenience methods for getting and testing values, to let you more easily convert these string arrays to other types.
Looking at history helps.
zsh
was first released in 1990. It took the best from both the Bourne shell and csh.
The Bourne shell tuning was done with single-letter options to sh
, which could also be tweaked with the set
special built-in. For instance, sh -f
starts sh
with globbing disabled, or set -f
disables globbing at runtime.
csh was tuned with plain variables which you'd set or unset, some of which were mapped to start-up options. For instance, csh -x
starts csh in a mode where it prints everything it's doing. Or you can do set verbose
to enter that mode at runtime (unset verbose
to leave it).
A lot of zsh was based on csh as csh was the popular shell at the time. Here, it mimicked csh, but recognising that using plain variables to store option settings was a bad idea, it did use a different namespace for options and separate builtins to set/unset them: setopt
and unsetopt
, and those options were mapped to single-letter options.
ksh
in the 80s gave names to some of the Bourne options so you could set them alternatively with set -o optionName
(unset with set +o
).
In zsh 2.0.02 in 1991, setopt
/ unsetopt
were aliased to set -o
/ set +o
for compatibility with ksh
.
For comparison, bash
at the time had options as plain variables like in csh, some mapped to start-up / set
options, while some of the start-up / set
options were not all mapped to corresponding variables.
set -o option
was added to bash at some point between 1.06 and 1.08 circa 1990.
In bash 2.0 (1996), those variables were removed and shopt
introduced as replacement so you had two sets of options, some set with set -o
/ set +o
some with shopt -s
/ shopt -u
. It's not clear to me why.
AFAIK, set -o
was already in the POSIX.2 specification for sh
when it was first released in 1992. And is supported by all modern Bourne-like shells to set options, though the list of options varies from shell to shell outside of the ones specified by POSIX (and see bash
's second set of option as mentioned above), so I tend to use set -o
instead of setopt
myself.
zstyle
itself was added much later in 1999 in an optional module as a generalisation and reimplementation in C of an earlier compstyle
approach written as a zsh function. Its primary use case was and still is to allow fine tuning of the new completion system (though it can be and has been used since for other things)
It's a separate namespace from shell options or variables or functions. While shell options or variables can be made local to a function, zstyle
s AFAIK are always global, so if only for that, options or variables could not be reimplemented using zstyle
s, not that there would be much value in that. The set -o
/ setopt
would still have to be kept around anyway for backward compatibility.
zsh
shell? I find it bit difficult to see this.setopt
sets options for the zsh shell,zstyle
sets options for how a module would behave. But also my view of zsh was that the modules are mostly responsible for functionalities so most options could be set viazstyle
withoutsetopt
.