.. zsh-module-meta::
   :name: zsh/zutil
   :summary: Some utility builtins, e.g. the one for supporting configuration via styles.

.. index:: single: builtins, utility; Command

The ``zsh/zutil`` module only adds some builtins:

.. index:: single: zstyle; Function

``zstyle`` [ ``-L`` [ :var:`metapattern` [ :var:`style` ] ] ]

``zstyle`` [ ``-e`` | ``-`` | ``--`` ] :var:`pattern` :var:`style` :var:`string` ...

``zstyle -d`` [ :var:`pattern` [ :var:`style` ... ] ]

``zstyle -g`` :var:`name` [ :var:`pattern` [ :var:`style` ] ]

``zstyle -q`` :var:`context` :var:`style`

``zstyle -{a|b|s``} :var:`context` :var:`style` :var:`name` [ :var:`sep` ]

``zstyle -{T|t``} :var:`context` :var:`style` [ :var:`string` ... ]

``zstyle -m`` :var:`context` :var:`style` :var:`pattern`
    
    This builtin command is used to define and lookup styles.  Styles are
    pairs of names and values, where the values consist of any number of
    strings.  They are stored together with patterns and lookup is done by
    giving a string, called the :emphasis:`context`, which is matched against the
    patterns.  The definition stored for the most specific pattern that matches
    will be returned.
    
    A pattern is considered to be more specific
    than another if it contains more components (substrings separated by
    colons) or if the patterns for the components are more specific, where 
    simple strings are considered to be more specific than patterns and
    complex patterns are considered to be more specific than the pattern
    ``*``.  A ``*`` in the pattern will match zero or more characters
    in the context; colons are not treated specially in this regard.
    If two patterns are equally specific, the tie is broken in favour of
    the pattern that was defined first.
    
    :emphasis:`Example`
    .. index:: single: preferred-precipitation, example style; Keystroke
    
    
    .. index:: single: weather, example function; Function
    
    
    
    For example, a fictional ``weather`` plugin might state in its documentation
    that it looks up the ``preferred-precipitation`` style under the
    ``:weather:``:var:`continent`\ ``:``:var:`day-of-the-week`\ ``:``:var:`phase-of-the-moon` context.
    According to this, you might set the following in your ``zshrc``:
    
    
    .. code-block:: zsh
       :class: 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
    
    
    .. code-block:: zsh
       :class: example

        zstyle -s \ 
          ":weather:${continent}:${day_of_week}:${moon_phase}" \ 
          preferred-precipitation REPLY
    
    
    in order to retrieve your preference into the scalar variable ``$REPLY``.
    On Sundays ``$REPLY`` would be set to ``snow``; in Europe it would be set
    to ``rain``; and on Sundays in Europe it would be set to ``snow`` again,
    because the patterns ``:weather:europe:*`` and ``:weather:*:Sunday:*`` both
    match the :var:`context` argument to ``zstyle -s``, are equally specific, and the
    latter is more specific (because it has more colon-separated components).
    
    :emphasis:`Usage`
    
    The forms that operate on patterns are the following.
    
    
    ``zstyle`` [ ``-L`` [ :var:`metapattern` [ :var:`style` ] ] ]
        
        Without arguments, lists style definitions.  Styles
        are shown in alphabetic order and patterns are shown in the order
        ``zstyle`` will test them.
        
        If the ``-L`` option is given, listing is done in the form of calls to
        ``zstyle``.  The optional first argument, :var:`metapattern`, is a pattern which
        will be matched against the string supplied as :var:`pattern` when the style was
        defined.  Note:
        this means, for example, ``zstyle -L ":completion:*"`` will
        match any supplied pattern beginning ``:completion:``, not
        just ``":completion:*"``:  use ``':completion:\*'`` to match that.
        The optional second argument limits the output to a specific :var:`style` (not a
        pattern).  ``-L`` is not compatible with any other options.
        
    
    ``zstyle`` [ ``-`` | ``--`` | ``-e`` ] :var:`pattern` :var:`style` :var:`string` ...
        
        .. index:: single: reply, use of; Variable
        
        
        Defines the given :var:`style` for the :var:`pattern` with the :var:`string`\s as
        the value.  If the ``-e`` option is given, the :var:`string`\s will be
        concatenated (separated by spaces) and the resulting string will be
        evaluated (in the same way as it is done by the ``eval`` builtin
        command) when the style is looked up.  In this case the parameter
        ``reply`` must be assigned to set the strings returned after the
        evaluation.  Before evaluating the value, ``reply`` is unset, and
        if it is still unset after the evaluation, the style is treated as if
        it were not set.
        
    
    ``zstyle -d`` [ :var:`pattern` [ :var:`style` ... ] ]
        
        Delete style definitions. Without arguments all definitions are deleted,
        with a :var:`pattern` all definitions for that pattern are deleted and if
        any :var:`style`\s are given, then only those styles are deleted for the
        :var:`pattern`.
        
    
    ``zstyle -g`` :var:`name` [ :var:`pattern` [ :var:`style` ] ]
        
        Retrieve a style definition. The :var:`name` is
        used as the name of an array in which the results are stored. Without
        any further arguments, all patterns defined are returned. With a
        :var:`pattern` the styles defined for that pattern are returned and with 
        both a :var:`pattern` and a :var:`style`, the value strings of that
        combination is returned.
        
    
    
    
    The other forms can be used to look up or test styles for a given context.
    
    
    ``zstyle -q`` :var:`context` :var:`style`
        
        Return ``0`` if :var:`style` is defined in :var:`context`.  This does not
        evaluate expressions defined by ``zstyle -e`` and does not examine any
        values set by :var:`style`.  The expected use is to test whether a style
        has been defined for :var:`context` before asserting a new style.
        
    
    ``zstyle -s`` :var:`context` :var:`style` :var:`name` [ :var:`sep` ]
        
        The parameter :var:`name` is set to the value of the style interpreted as a
        string.  If the value contains several strings they are concatenated with
        spaces (or with the :var:`sep` string if that is given) between them.
        
        Return ``0`` if the style is set, ``1`` otherwise.
        
    
    ``zstyle -b`` :var:`context` :var:`style` :var:`name`
        
        The value is stored in :var:`name` as a boolean, i.e. as the string
        ``yes`` if the value has only one string and that string is equal to one
        of ``yes``, ``true``, ``on``, or ``1``. If the value is any other
        string or has more than one string, the parameter is set to ``no``.
        
        Return ``0`` if :var:`name` is set to ``yes``, ``1`` otherwise.
        
    
    ``zstyle -a`` :var:`context` :var:`style` :var:`name`
        
        The value is stored in :var:`name` as an array. If :var:`name` is declared 
        as an associative array,  the first, third, etc. strings are used as the
        keys and the other strings are used as the values.
        
        Return ``0`` if the style is set, ``1`` otherwise.
        
    
    ``zstyle -t`` :var:`context` :var:`style` [ :var:`string` ... ]
    
    ``zstyle -T`` :var:`context` :var:`style` [ :var:`string` ... ]
        
        Test the value of a style, i.e. the ``-t`` option only returns a status
        (sets ``$?``).  Without any :var:`string` the return status is zero if the
        style is defined for at least one matching pattern, has only one string in
        its value, and that is equal to one of ``true``, ``yes``, ``on`` or
        ``1``. If any :var:`string`\s are given the status is zero if and only if
        at least one of the :var:`string`\s is equal to at least one of the strings
        in the value. If the style is defined but doesn't match, the return status
        is ``1``. If the style is not defined, the status is ``2``.
        
        The ``-T`` option tests the values of the style like ``-t``, but it
        returns status zero (rather than ``2``) if the style is not defined for any
        matching pattern.
        
    
    ``zstyle -m`` :var:`context` :var:`style` :var:`pattern`
        
        Match a value. Returns status zero if the 
        :var:`pattern` matches at least one of the strings in the value.
        
    
    
    

.. index:: single: zformat; Function

``zformat -f`` [ ``-qQ`` ] ] :var:`param` :var:`format` :var:`spec` ...

``zformat -F`` [ ``-qQ`` ] ] :var:`param` :var:`format` :var:`spec` ...

``zformat -a`` :var:`array` :var:`sep` :var:`spec` ...
    
    This builtin provides different forms of formatting.
    
    The first form is selected with the ``-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
    of the form :var:`char`\ ``:``:var:`string` which will cause every
    appearance of the sequence ``%``:var:`char` in :var:`format` to be replaced 
    by the :var:`string`.  The ``%`` sequence may also contain optional
    minimum and maximum field width specifications between the ``%`` and 
    the :var:`char` in the form ``%``:var:`min`\ ``.``:var:`max`\ ``c``,
    i.e. the minimum field width is given first and if the maximum field
    width is used, it has to be preceded by a dot.  Specifying a minimum field
    width makes the result be padded with spaces to the right if the
    :var:`string` is shorter than the requested width.  Padding to the left
    can be achieved by giving a negative minimum field width.  If a maximum 
    field width is specified, the :var:`string` will be truncated after that
    many characters.
    
    The :var:`char` in each :var:`spec` may optionally be preceded by an
    escaping indicator, either ``%`` to explicitly enable the
    :var:`spec`-escaping behaviour of ``-q`` described below, or ``%%`` to
    explicitly disable it.  The default behaviour is to :emphasis:`not` escape specs.
    
    Any ``%`` sequence in ``format`` that does not match a given :var:`spec`
    (or one of the special sequences described below) is output as-is.  If
    desired, these sequences may be processed by a second round of
    formatting, by prompt expansion, etc. -- see also ``-q``.
    
    The sequence ``%%`` can be used to produce a literal ``%``.
    After all ``%`` sequences have been processed, the resulting string is
    stored in the parameter :var:`param`.
    
    The ``%``-escapes also understand ternary expressions in the form used by
    prompts.  The ``%`` is followed by a ``(`` and then an ordinary
    format specifier character as described above.  There may be a set of
    digits either before or after the ``(``; these specify a test
    number, which defaults to zero.  Negative numbers are also allowed.  An
    arbitrary delimiter character follows the format specifier, which is
    followed by a piece of \`true' text, the delimiter character again, a piece
    of \`false' text, and a closing parenthesis.  The complete expression
    (without the digits) thus looks like
    ``%(``:var:`X`\ ``.``:var:`text1`\ ``.``:var:`text2`\ ``)``, except that
    the ``.`` character is arbitrary.  The value given for the format
    specifier in the :var:`char`\ ``:``:var:`string` expressions is evaluated as a
    mathematical expression, and compared with the test number.  If they are
    the same, :var:`text1` is output, else :var:`text2` is output.  A parenthesis
    may be escaped in :var:`text2` as ``%)``.  Either of :var:`text1` or
    :var:`text2` may contain nested ``%``-escapes.
    
    For example:
    
    
    .. code-block:: zsh
       :class: example

        zformat -f REPLY "The answer is '%3(c.yes.no)'." c:3
    
    
    outputs "The answer is 'yes'." to ``REPLY`` since the value for the format
    specifier ``c`` is 3, agreeing with the digit argument to the ternary
    expression.
    
    With ``-F`` instead of ``-f``, ternary expressions choose between the
    \`true' or \`false' text on the basis of whether the format specifier is
    present and non-empty.  If a test number is provided, it tests the width
    of the value given in the format specifier -- with a positive
    number the condition is true when the width is :emphasis:`greater than` that
    number, and with a negative number the condition is true when the width
    is :emphasis:`less than or equal to` the absolute value of that number.
    
    With ``-q``, ``%`` characters in the :var:`spec`\s are escaped by default
    as they are inserted into the formatted string, and pre-escaped ``%`` and
    ```)``\` characters in the format string are left as they are.  For
    example:
    
    
    .. code-block:: zsh
       :class: example

        zformat -qF REPLY '%%foo%% %B%d%b' d:%bar%
    
    
    outputs ``%%foo%% %B%%bar%%%b`` to ``REPLY``.  This is useful when the
    formatted string will undergo further expansion -- in this example
    the ``%B...%b`` sequences could be used with prompt expansion to
    produce bold text.  One notable use case is formatting a description to
    be passed to ``compadd -x`` in a completion function.
    
    Since the output with ``-q`` is expected to be subject to further
    processing, width specifiers don't count the extra escape characters,
    ensuring that the widths are correct :emphasis:`after` that processing.
    Additionally, with ``-F``, ternary-expression test numbers are compared
    against the :emphasis:`pre-escaped` spec lengths.
    
    ``-Q`` is like ``-q`` except that it interprets pre-escaped ``%`` and
    ```)`` characters in the format string as normal.
    
    The optional escaping indicator can be used to exempt individual
    :var:`spec`\s from escaping as described above.  For example:
    
    
    .. code-block:: zsh
       :class: example

        zformat -qF REPLY %d %D' d:%foo% %%D:%bar%
    
    
    outputs ``%%foo%% %bar%`` to ``REPLY``.
    
    The form using the ``-a`` option can be used for aligning
    strings.  Here, the :var:`spec`\s are of the form
    :var:`left`\ ``:``:var:`right` where :var:`left` and :var:`right` are
    arbitrary strings.  These strings are modified by replacing the colons
    by the :var:`sep` string and padding the :var:`left` strings with spaces 
    to the right so that the :var:`sep` strings in the result (and hence the 
    :var:`right` strings after them) are all aligned if the strings are
    printed below each other.  All strings without a colon are left
    unchanged and all strings with an empty :var:`right` string have the
    trailing colon removed.  In both cases the lengths of the strings
    are not used to determine how the other strings are to be aligned.
    A colon in the :var:`left` string can be escaped with a backslash.
    The resulting strings are stored in the :var:`array`.
    

.. index:: single: zregexparse; Function

``zregexparse``
    
    This implements some internals of the ``_regex_arguments`` function.
    

.. index:: single: zparseopts; Function

``zparseopts`` [ ``-DEFGKM`` ] [ ``-a`` :var:`array` ] [ ``-A`` :var:`assoc` ] [ ``-n`` :var:`name` ] [ ``-v`` :var:`argv` ] [ ``-`` ] :var:`spec` ...
    
    This builtin simplifies the parsing of options in positional parameters,
    i.e. the set of arguments given by ``$*``.  Each :var:`spec` describes one
    option and must be of the form :var:`opt`\[``=``:var:`array`].  If an option
    described by :var:`opt` is found in the positional parameters it is copied
    into the :var:`array` specified with the ``-a`` option; if the optional
    ``=``:var:`array` is given, it is instead copied into that array, which
    should be declared as a normal array and never as an associative array.
    
    At least one :var:`spec` must be given.  If a single spec is given which
    is either an empty string or a single hyphen (as in
    ``zparseopts -DF ''``), it signifies that no options are recognised.
    (This is useful for future-proofing functions that might gain options
    later.)  Otherwise, it is an error to give any :var:`spec` without an
    ``=``:var:`array` unless one of the ``-a`` or ``-A`` options is used.
    
    Unless the ``-E`` option is given, parsing stops at the first string
    that isn't described by one of the :var:`spec`\s.  Even with ``-E``,
    parsing always stops at a positional parameter equal to ``--`` or
    (without ``-G``) ``-``. See also ``-F``.
    
    The :var:`opt` description must be one of the following.  Any of the special
    characters can appear in the option name provided it is preceded by a
    backslash.
    
    
    :var:`name`
    
    :var:`name`\ ``+``
        
        The :var:`name` is the name of the option without the leading ``-``.  To
        specify a GNU-style long option, one of the usual two leading ``-`` must
        be included in :var:`name`; for example, a ``--file`` option is
        represented by a :var:`name` of ``-file``.
        
        If a ``+`` appears after :var:`name`, the option is appended to :var:`array`
        each time it is found in the positional parameters; without the ``+``
        only the :emphasis:`last` occurrence of the option is preserved.
        
        If one of these forms is used, the option takes no argument, so parsing
        stops if the next positional parameter does not also begin with ``-``
        (unless the ``-E`` option is used).
        
    
    :var:`name`\ ``:``
    
    :var:`name`\ ``:-``
    
    :var:`name`\ ``::``
        
        If one or two colons are given, the option takes an argument; with one
        colon, the argument is mandatory and with two colons it is optional.  The
        argument is appended to the :var:`array` after the option itself.
        
        An optional argument is put into the same array element as the option name
        (note that this makes empty strings as arguments indistinguishable).  A
        mandatory argument is added as a separate element unless the ``:-`` form
        is used, in which case the argument is put into the same element.
        
        A ``+`` as described above may appear between the :var:`name` and the
        first colon.
        
    
    
    
    By default, option-arguments may appear either immediately following the
    option in the same positional parameter or in the next one. Even an optional
    argument may appear in the next parameter, unless it begins with a ``-``.
    Additionally, there is no special consideration given to an ``=``
    between an option and its argument. To make parsing use the more common
    GNU-style conventions, use the ``-G`` option.
    
    When the names of two options that take no arguments overlap, the longest one
    wins, so that parsing for the :var:`spec`\s ``-foo -foobar`` (for example) is
    unambiguous. However, due to the aforementioned handling of option-arguments,
    ambiguities may arise when at least one overlapping :var:`spec` takes an
    argument, as in ``-foo: -foobar``. In that case, the last matching
    :var:`spec` wins. (This is not an issue with GNU-style parsing.)
    
    In order to distinguish GNU-style long option :var:`spec`\s from
    ``zparseopts``'s own options, they :emphasis:`must` be preceded by a ``-``,
    ``--``, or short option ``spec``, as in ``zparseopts -Ga opts - -foo``.
    
    The options of ``zparseopts`` itself are:
    
    
    ``-a`` :var:`array`
        
        As described above, this names the default array in which to store the
        recognised options.
        
    
    ``-A`` :var:`assoc`
        
        If this is given, the options and their values are also put into an
        associative array with the option names as keys and the arguments (if any)
        as the values.
        
    
    ``-D``
        
        If this option is given, all options found are removed from the positional
        parameters of the calling shell or shell function, up to but not including
        any not described by the :var:`spec`\s.  If the first such parameter is
        ``--`` or (without ``-G``) ``-``, it is removed as well.  This is
        similar to using the ``shift`` builtin.
        
    
    ``-E``
        
        This changes the parsing rules to :emphasis:`not` stop at the first string
        that isn't described by one of the :var:`spec`\s.  It can be used to test
        for or (if used together with ``-D``) extract options and their
        arguments, ignoring all other options and arguments that may be in the
        positional parameters.  As indicated above, parsing still stops at the
        first ``-`` or ``--`` not described by a :var:`spec`, but it is not
        removed when used with ``-D``.
        
    
    ``-F``
        
        If this option is given, ``zparseopts`` immediately stops at the first
        option-like parameter not described by one of the :var:`spec`\s, prints an
        error message, and returns status 1.  Removal (``-D``) and extraction
        (``-E``) are not performed, and option arrays are not updated.  This
        provides basic validation for the given options.
        
        Note that the appearance in the positional parameters of an option without
        its required argument always aborts parsing and returns an error as described
        above regardless of whether this option is used.
        
    
    ``-G``
        
        This option specifies that options are parsed in the GNU style,
        similar to ``getopt_long(3)``. In particular:
        
        Given the :var:`spec` ``-foo:``, the positional parameter
        ``--foo=bar`` is interpreted as option ``--foo`` with
        argument ``bar``, rather than argument ``=bar`` as is the default,
        whilst the positional parameter ``--foobar`` is considered an
        unknown option (unless another :var:`spec` describes it). This applies
        to both singly and doubly hyphenated long options.
        
        An empty option-argument can be given to its long option in the same
        parameter using a trailing ``=``.
        
        An optional argument to a long option must be given with the
        equals syntax, and an optional argument to a short option must
        follow it immediately in the same parameter; in both cases the
        following parameter is considered unrelated.
        
        Whenever a long option and its argument are stored in the same array
        element, an ``=`` is used to separate them.
        
        A mandatory option-argument given in a separate parameter from its
        option (as in ``--foo`` ``bar``), or any option-argument given to
        a short option in the same parameter, is always treated the same
        regardless of whether this option is in effect.
        
        Lastly, when this option is active, only ``--`` is treated as an
        explicit option-parsing terminator in the parsed arguments; a single
        ``-`` is considered a normal operand.
        
        Note: Unlike most ``getopt_long(3)`` implementations,
        ``zparseopts`` does not support abbreviating long options.
        
    
    ``-K``
        
        With this option, the arrays specified with the ``-a`` option and with the
        ``=``:var:`array` forms are kept unchanged when none of the :var:`spec`\s for
        them is used.  Otherwise the entire array is replaced when any of the
        :var:`spec`\s is used.  Individual elements of associative arrays specified
        with the ``-A`` option are preserved by ``-K``.  This allows assignment of
        default values to arrays before calling ``zparseopts``.
        
    
    ``-M``
        
        This changes the assignment rules to implement a map among equivalent
        option names.  If any :var:`spec` uses the ``=``:var:`array` form, the
        string :var:`array` is interpreted as the name of another :var:`spec`,
        which is used to choose where to store the values.
        Values stored in an associative array (``-A``) use the name of the
        mapped-to option, whereas values stored in an array use the last
        as-given option name.  If no other :var:`spec`
        is found, the values are stored as usual.  This changes only the way the
        values are stored, not the way ``$*`` is parsed, so results may be
        unpredictable if the :var:`name`\ ``+`` specifier is used inconsistently.
        
    
    ``-n`` :var:`name`
        
        If this option is given, :var:`name` is used when printing usage errors
        intended for the end user.  Otherwise, the name of the calling function
        or script is used.  Error messages arising from misusage of ``zparseopts``
        itself are not affected by this option.
        
    
    ``-v`` :var:`argv`
        
        With this option, the elements of the named array :var:`argv` are used as the
        positional parameters to parse, rather than those given by ``$*``.  The
        array may be modified according to the ``-D`` option.
        
    
    
    
    For example,
    
    
    .. code-block:: zsh
       :class: example

        set -- -a -bx -c y -cz baz -cend
        zparseopts a=foo b:=bar c+:=bar
    
    
    will have the effect of
    
    
    .. code-block:: zsh
       :class: example

        foo=(-a)
        bar=(-b x -c y -c z)
    
    
    The arguments from ``baz`` on will not be used.
    
    As an example for the ``-E`` option, consider:
    
    
    .. code-block:: zsh
       :class: example

        set -- -a x -b y -c z arg1 arg2
        zparseopts -E -D b:=bar
    
    
    will have the effect of
    
    
    .. code-block:: zsh
       :class: example

        bar=(-b y)
        set -- -a x -c z arg1 arg2
    
    
    I.e., the option ``-b`` and its arguments are taken from the
    positional parameters and put into the array ``bar``.
    
    The ``-M`` option can be used like this:
    
    
    .. code-block:: zsh
       :class: example

        set -- -a -bx -c y -cz baz -cend
        zparseopts -A bar -M a=foo b+: c:=b
    
    
    to have the effect of
    
    
    .. code-block:: zsh
       :class: example

        foo=(-a)
        bar=(-a '' -b xyz)
    
    

The following is a useful general-purpose pattern:

.. code-block:: zsh
   :class: example

    local -A opts
    zparseopts -DFGA opts - x -long: || return
    (( $+opts[-x] )) && ... # handle -x
    (( $+opts[--long] )) && ... # handle --long, optarg in $opts[--long]

