about summary refs log tree commit diff
path: root/Doc/Zsh/expn.yo
diff options
context:
space:
mode:
Diffstat (limited to 'Doc/Zsh/expn.yo')
-rw-r--r--Doc/Zsh/expn.yo306
1 files changed, 242 insertions, 64 deletions
diff --git a/Doc/Zsh/expn.yo b/Doc/Zsh/expn.yo
index 753e5a008..7eade4a11 100644
--- a/Doc/Zsh/expn.yo
+++ b/Doc/Zsh/expn.yo
@@ -312,7 +312,8 @@ zero) that are neither `tt(.)' nor `tt(/)' and that continue to the end
 of the string.  For example, the extension of
 `tt(foo.orig.c)' is `tt(.c)', and `tt(dir.c/foo)' has no extension.
 )
-item(tt(s/)var(l)tt(/)var(r)[tt(/)])(
+xitem(tt(s/)var(l)tt(/)var(r)[tt(/)])
+item(tt(S/)var(l)tt(/)var(r)[tt(/)])(
 Substitute var(r) for var(l) as described below.
 The substitution is done only for the
 first string that matches var(l).  For arrays and for filename
@@ -324,13 +325,17 @@ perform global substitution, i.e. substitute every occurrence of var(r)
 for var(l).  Note that the tt(g) or tt(:G) must appear in exactly the
 position shown.
 
+The use of tt(S) instead of tt(s) is identical except that
+the source is treated as a pattern, just as if the option
+tt(HIST_SUBST_PATTERN) were set.
+
 See further notes on this form of substitution below.
 )
 item(tt(&))(
-Repeat the previous tt(s) substitution.  Like tt(s), may be preceded
-immediately by a tt(g).  In parameter expansion the tt(&) must appear
-inside braces, and in filename generation it must be quoted with a
-backslash.
+Repeat the previous tt(s) or tt(S) substitution, whichever was most
+recent.  Like tt(s) and tt(S), may be preceded immediately by a tt(g).
+In parameter expansion the tt(&) must appear inside braces, and in
+filename generation it must be quoted with a backslash.
 )
 item(tt(t) [ var(digits) ])(
 Remove all leading pathname components, leaving the final component (tail).
@@ -377,7 +382,8 @@ substitutions or expansions are performed once at the time the qualifier
 is parsed, even before the `tt(:s)' expression itself is divided into
 var(l) and var(r) sides.
 
-If the option tt(HIST_SUBST_PATTERN) is set, var(l) is treated as
+If the option tt(HIST_SUBST_PATTERN) is set or the original substitution
+was started with a capital tt(S), var(l) is treated as
 a pattern of the usual form described in
 ifzman(the section FILENAME GENERATION below)\
 ifnzman(noderef(Filename Generation)).  This can be used in
@@ -604,6 +610,16 @@ and other operators, such as `tt(${PREFIX:-"/usr/local"})'.  Parameter
 expansions can also be nested.  These topics will be introduced below.
 The full rules are complicated and are noted at the end.
 
+cindex(namespace)
+Parameter expansions may optionally include a em(namespace) prefix in
+the format `tt(.)var(identifier)tt(.)' This currently has no special
+meaning to the shell, but provides a convenient means of grouping
+related parameters.  Expansions using a namespace em(must) include
+braces (tt({) and tt(})) as shown in the descriptions below, and
+only one namespace prefix is allowed.  Note that, for support of
+possible future features, the first `tt(.)' is optional, but omitting
+it is discouraged.
+
 In the expansions discussed below that require a pattern, the form of
 the pattern is the same as that used for filename generation;
 see noderef(Filename Generation).  Note that these patterns, along with
@@ -616,6 +632,8 @@ substitution on the expansion of parameter tt($i).
 
 In the following descriptions, `var(word)' refers to a single word
 substituted on the command line, not necessarily a space delimited word.
+The reference to `var(name)' in each description presumes any optional
+namespace prefix.
 
 startitem()
 item(tt(${)var(name)tt(}))(
@@ -665,7 +683,9 @@ item(tt(${)var(name)tt(:?)var(word)tt(}))(
 In the first form, if var(name) is set, or in the second form if var(name)
 is both set and non-null, then substitute its value; otherwise, print
 var(word) and exit from the shell.  Interactive shells instead return to
-the prompt.  If var(word) is omitted, then a standard message is printed.
+the prompt.  If var(word) is omitted, then a standard message is
+printed.  Note that var(word) is expanded even though its value
+is not substituted onto the command line.
 )
 enditem()
 
@@ -967,10 +987,16 @@ means the same thing as the more readable `(tt(%%qqq))'.  The
 following flags are supported:
 
 startitem()
+item(tt(!))(
+When the parameter being expanded is a named reference, the reference
+itself is examined and thus is em(not) resolved to its referent.  In
+ksh emulation, the parens around this flag are optional.
+)
 item(tt(#))(
-Evaluate the resulting words as numeric expressions and output the
-characters corresponding to the resulting integer.  Note that this form is
-entirely distinct from use of the tt(#) without parentheses.
+Evaluate the resulting words as numeric expressions and interpret
+these as character codes.  Output the corresponding characters.  Note
+that this form is entirely distinct from use of the tt(#) without
+parentheses.
 
 If the tt(MULTIBYTE) option is set and the number is greater than 127
 (i.e. not an ASCII character) it is treated as a Unicode character.
@@ -1092,7 +1118,7 @@ tt(KSH_ARRAYS) option a subscript `tt([*])' or `tt([@])' is needed
 to operate on the whole array, as usual.
 )
 item(tt(L))(
-Convert all letters in the result to lower case.
+Convert all letters in the result to lower case, like `tt(typeset -l)'.
 )
 item(tt(n))(
 Sort decimal integers numerically; if the first differing
@@ -1176,46 +1202,56 @@ of the parameter would usually appear. This string consists of keywords
 separated by hyphens (`tt(-)'). The first keyword in the string describes
 the main type, it can be one of `tt(scalar)', `tt(array)', `tt(integer)',
 `tt(float)' or `tt(association)'. The other keywords describe the type in
-more detail:
+more detail, in most cases corresponding to options of the `tt(typeset)'
+command:
 
 startitem()
 item(tt(local))(
 for local parameters
 )
 item(tt(left))(
-for left justified parameters
+for left justified parameters (tt(-L))
 )
 item(tt(right_blanks))(
-for right justified parameters with leading blanks
+for right justified parameters with leading blanks (tt(-R))
 )
 item(tt(right_zeros))(
-for right justified parameters with leading zeros
+for right justified parameters with leading zeros (tt(-Z))
 )
 item(tt(lower))(
 for parameters whose value is converted to all lower case when it is
-expanded
+expanded (tt(-l))
 )
 item(tt(upper))(
 for parameters whose value is converted to all upper case when it is
-expanded
+expanded (tt(-u))
 )
 item(tt(readonly))(
-for readonly parameters
+for readonly parameters (tt(-r))
 )
 item(tt(tag))(
-for tagged parameters
+for tagged parameters (tt(-t))
+)
+item(tt(tied))(
+for parameters tied to another parameter in the manner of tt(PATH)
+(colon-separated list) and tt(path) (array), whether these are
+special parameters or user-defined with `tt(typeset -T)'
 )
 item(tt(export))(
-for exported parameters
+for exported parameters (tt(-x) or `tt(export)')
 )
 item(tt(unique))(
-for arrays which keep only the first occurrence of duplicated values
+for arrays which keep only the first occurrence of duplicated values (tt(-U))
 )
 item(tt(hide))(
-for parameters with the `hide' flag
+for parameters with the `hide' flag (tt(-h))
 )
 item(tt(hideval))(
-for parameters with the `hideval' flag
+for parameters with the `hideval' flag (tt(-H))
+)
+item(tt(nameref))(
+for named references (tt(typeset -n)) either having an empty value or
+when combined with `tt(!)' as in `tt(${LPAR()!t)tt(RPAR()var(rname)})'
 )
 item(tt(special))(
 for special parameters defined by the shell
@@ -1223,10 +1259,10 @@ for special parameters defined by the shell
 enditem()
 )
 item(tt(u))(
-Expand only the first occurrence of each unique word.
+Expand only the first occurrence of each unique word, like `tt(typeset -U)'.
 )
 item(tt(U))(
-Convert all letters in the result to upper case.
+Convert all letters in the result to upper case, like `tt(typeset -u)'.
 )
 item(tt(v))(
 Used with tt(k), substitute (as two consecutive words) both the key
@@ -1492,8 +1528,9 @@ form using `tt(%%)' will remove the same matches as for `tt(##)' in reverse
 order.
 )
 item(tt(*))(
+pindex(EXTENDED_GLOB, enable)
 Enable tt(EXTENDED_GLOB) for substitution via tt(${)...tt(/)...tt(}) or
-tt(${)...tt(//)...tt(}).
+tt(${)...tt(//)...tt(}).  Note that `tt(**)' does not disable extendedglob.
 )
 item(tt(B))(
 Include the index of the beginning of the match in the result.
@@ -1513,6 +1550,103 @@ Include the unmatched portion in the result (the em(R)est).
 )
 enditem()
 
+subsect(Named References)
+cindex(named references)
+cindex(namerefs)
+cindex(reference variables)
+cindex(parameters, nameref)
+The command
+ifzman()
+indent(tt(typeset -n )var(pname)tt(=)var(rname))
+
+initializes a parameter var(pname) as a reference to a second
+parameter var(rname).  With the few exceptions described here, when
+var(pname) is used in any of the expansion forms described above, the
+parameter var(rname) is expanded instead.  This is similar to the
+action of the `tt((P))' expansion flag, but when var(rname) has itself
+been declared a named reference, that third parameter referenced by
+var(pname) is also expanded, and so on.  With `tt((P))' this must be
+done explicitly, so for example
+tt(${LPAR()P)tt(RPAR()${LPAR()P)tt(RPAR())var(name)tt(}}).
+
+Unlike `tt((P))', named references in substitutions that perform
+assignment, such as tt(${)var(pname)tt(::=)var(word)tt(}), do not
+create new arrays when var(rname) is in the form of an array element
+or slice and no such array (or associative array) is presently set.
+This includes arrays declared, but not initialized, when the option
+tt(TYPESET_TO_UNSET) is in effect.  The var(word) is substituted but
+no assignment occurs.
+
+Also unlike `tt((P))' named references always expand parameters at
+the scope in which var(rname) existed when `tt(typeset -n)' was
+called.  This can be used to expand or assign parameters from an
+earlier scope even if a local of the same name has been declared at
+a later scope.  Example:
+ifzman()
+example(tt(caller=OUTER)
+tt(func LPAR()RPAR() {)
+tt(  print before local: $caller)
+tt(  typeset -n outer=$1)
+tt(  local caller=INNER)
+tt(  print by reference: $outer)
+tt(  outer=RESULT)
+tt(})
+tt(func caller)
+tt(print after func: $caller))
+
+displays the output
+ifzman()
+example(tt(before local: OUTER)
+tt(by reference: OUTER)
+tt(after func: RESULT))
+
+To force a named reference to refer to the outer scope, even if a local
+has already been declared, add the tt(-u) option when declaring the
+named reference.  In this case var(rname) should already exist in the
+outer scope, otherwise the behavior of assignment through var(pname)
+is not defined and may change the scope of the reference or fail with
+a status of 1.  Example of correct usage:
+ifzman()
+example(tt(caller=OUTER)
+tt(func LPAR()RPAR() {)
+tt(  print before local: $caller)
+tt(  local caller=INNER)
+tt(  print after local: $caller)
+tt(  typeset -n -u outer=$1)
+tt(  print by reference: $outer)
+tt(  outer=RESULT)
+tt(})
+tt(func caller)
+tt(print after func: $caller))
+
+Note, however, that named references to em(special) parameters acquire
+the behavior of the special parameter, regardless of the scope where
+the reference is declared.
+
+When var(rname) includes an array subscript, the subscript expression
+is interpreted at the time tt(${)var(pname)tt(}) is expanded.  Any
+form of subscript is allowed, including those that select individual
+elements, substrings of scalar strings, or multiple elements as with
+array slices or the `tt((i))', `tt((I))', `tt((r))', `tt((R))' and
+`tt((w))' subscript flags.  However, the subscript is evaluated with
+the tt(NO_EXEC) option in effect, so command substitution and other
+similar constructs produce no output, although are not syntactically
+excluded.
+
+When var(rname) is an array (but not an array element or slice), the
+named reference may also be used in substitutions requiring an
+var(arrayname), so these are equivalent:
+ifzman()
+example(tt(${)var(name)tt(:|)var(rname)tt(})
+tt(${)var(name)tt(:|)var(pname)tt(}))
+
+Expansions of the form `tt(${LPAR()t)tt(RPAR())var(pname)tt(})' expand
+the type information of var(rname), unless var(rname) is empty, in which
+case the expansion is `tt(nameref)', or when no variable var(rname)
+exists, in which case the expansion is empty.
+
+See also ifzman(zmanref(zshparam))ifnzman(noderef(Parameters)).
+
 subsect(Rules)
 cindex(parameter expansion rules)
 cindex(rules, parameter expansion)
@@ -1535,12 +1669,16 @@ substitutions; the nested substitution will return either a scalar or an
 array as determined by the flags, possibly adjusted for quoting.  All the
 following steps take place where applicable at all levels of substitution.
 
-Note that, unless the `tt((P))' flag is present, the flags and any
+Note that, unless the `tt((P))' flag or a named reference is present,
+the flags and any
 subscripts apply directly to the value of the nested substitution; for
 example, the expansion tt(${${foo}}) behaves exactly the same as
-tt(${foo}).  When the `tt((P))' flag is present in a nested substitution,
+tt(${foo}).  When a named reference or the `tt((P))' flag is used in a
+nested substitution,
 the other substitution rules are applied to the value em(before) it is
 interpreted as a name, so tt(${${(P)foo}}) may differ from tt(${(P)foo}).
+When both a named reference and the `tt((P))' flag appear, the named
+reference is resolved before `tt((P))' is applied.
 
 At each nested level of substitution, the substituted words undergo all
 forms of single-word substitution (i.e. not filename generation), including
@@ -1766,23 +1904,65 @@ sect(Command Substitution)
 cindex(command substitution)
 cindex(substitution, command)
 A command enclosed in parentheses preceded by a dollar sign, like
-`tt($LPAR())...tt(RPAR())', or quoted with grave
-accents, like `tt(`)...tt(`)', is replaced with its standard output, with
-any trailing newlines deleted.
-If the substitution is not enclosed in double quotes, the
-output is broken into words using the tt(IFS) parameter.
+`tt($LPAR())...tt(RPAR())', or quoted with grave accents, like
+`tt(`)...tt(`)', is executed in a subshell and replaced by its
+standard output, with any trailing newlines deleted.  If the
+substitution is not enclosed in double quotes, the output is broken
+into words using the tt(IFS) parameter.
 vindex(IFS, use of)
 
 The substitution `tt($LPAR()cat) var(foo)tt(RPAR())' may be replaced
 by the faster `tt($LPAR()<)var(foo)tt(RPAR())'.  In this case var(foo)
 undergoes single word shell expansions (em(parameter expansion),
 em(command substitution) and em(arithmetic expansion)), but not
-filename generation.
+filename generation.  No subshell is created.
 
 If the option tt(GLOB_SUBST) is set, the result of any unquoted command
 substitution, including the special form just mentioned, is eligible for
 filename generation.
 
+A command with a leading pipe character, enclosed in braces prefixed by
+a dollar sign, as in `tt(${|)...tt(})', is executed in the current shell
+context, rather than in a subshell, and is replaced by the value of the
+parameter tt(REPLY) at the end of the command.  There em(must not) be
+any whitespace between the opening brace and the pipe character.  Any
+prior value of tt($REPLY) is saved and restored around this substitution,
+in the manner of a function local parameter.  Other parameters declared
+within the substitution also behave as locals, as if in a function,
+unless `tt(typeset -g)' is used.  Trailing newlines are em(not) deleted
+from the final replacement in this case, and it is subject to filename
+generation in the same way as `tt($LPAR())...tt(RPAR())' but is em(not)
+split on tt(IFS) unless the tt(SH_WORD_SPLIT) option is set.
+
+cindex(substitution, command, current shell)
+cindex(substitution, command, non forking)
+cindex(substitution, nofork)
+Substitutions of the form `tt(${{)var(param)tt(}) ...tt(})' are similar,
+except that the substitution is replaced by the value of the parameter
+named by var(param).  No implicit save or restore applies to var(param)
+and var(param) should em(not) be declared within the command.  No space
+is allowed within `tt(${{)' and space or newline is required after
+`tt({)var(param)tt(})'.  The var(param) may include a subscript, and if,
+after evaluating the expression, var(param) names an array, then array
+expansion rules apply to the final substitution.
+
+A command enclosed in braces preceded by a dollar sign, and set off from
+the braces by whitespace, like `tt(${ )...tt( })', is replaced by its
+standard output.  Like `tt(${|)...tt(})' and unlike
+`tt($LPAR())...tt(RPAR())', the command executes in the current shell
+context with function local behaviors and does not create a subshell.
+Word splitting does not apply unless tt(SH_WORD_SPLIT) is set, but a
+single trailing newline is stripped unless the substitution is enclosed
+in double quotes.
+
+Note that because `tt(${|)...tt(})' and the two related substitutions
+must be parsed at once as both string tokens and commands, all other
+braces (`tt({)' or `tt(})') within the command either must be quoted,
+or must appear in syntactically valid pairs, such as around complex
+commands, function bodies, or parameter references.  Furthermore,
+comments are always recognized, even when tt(NO_INTERACTIVE_COMMENTS)
+is in effect.
+
 texinode(Arithmetic Expansion)(Brace Expansion)(Command Substitution)(Expansion)
 sect(Arithmetic Expansion)
 cindex(arithmetic expansion)
@@ -1892,6 +2072,13 @@ The tt(PUSHD_MINUS)
 option exchanges the effects of `tt(~PLUS())' and `tt(~-)' where they are
 followed by a number.
 
+startmenu()
+menu(Dynamic named directories)
+menu(Static named directories)
+menu(`=' expansion)
+menu(Notes)
+endmenu()
+
 texinode(Dynamic named directories)(Static named directories)()(Filename Expansion)
 subsect(Dynamic named directories)
 cindex(directories, named, dynamic)
@@ -1956,34 +2143,24 @@ tt(/home/pws/perforce).  In this simple case a static name for the
 directory would be just as effective.
 
 example(zsh_directory_name+LPAR()RPAR() {
-  emulate -L zsh
-  setopt extendedglob
+  emulate -L zsh -o extendedglob
   local -a match mbegin mend
-  if [[ $1 = d ]]; then
-    # turn the directory into a name
-    if [[ $2 = (#b)(/home/pws/perforce/)([^/]##)* ]]; then
-      typeset -ga reply
-      reply=(p:$match[2] $(( ${#match[1]} + ${#match[2]} )) )
-    else
-      return 1
-    fi
-  elif [[ $1 = n ]]; then
-    # turn the name into a directory
-    [[ $2 != (#b)p:(?*) ]] && return 1
-    typeset -ga reply
-    reply=(/home/pws/perforce/$match[1])
-  elif [[ $1 = c ]]; then
-    # complete names
-    local expl
-    local -a dirs
-    dirs=(/home/pws/perforce/*(/:t))
-    dirs=(p:${^dirs})
-    _wanted dynamic-dirs expl 'dynamic directory' compadd -S\] -a dirs
-    return
-  else
-    return 1
-  fi
-  return 0
+  local base=/home/pws/perforce
+  case $1 in
+  ( d )  # Turn the directory into a name.
+    [[ $2 == (#b)($base/)([^/]##)* ]] &&
+        reply=( p:$match[2] $(( $#match[1] + $#match[2] )) )
+  ;;
+  ( n )  # Turn the name into a directory.
+    [[ $2 == (#b)p:(?*) ]] &&
+        reply=( $base/$match[1] )
+  ;;
+  ( c )  # Complete names.
+    local -a dirs=( $base/*(/:t) )
+    # Completion system populates $expl with flags for compadd.
+    compadd "$expl[@]" p:$^dirs
+  ;;
+  esac
 })
 
 texinode(Static named directories)(`=' expansion)(Dynamic named directories)(Filename Expansion)
@@ -2973,9 +3150,10 @@ so both can be used on the same glob expression; for example by writing
 )
 enditem()
 
-More than one of these lists can be combined, separated by commas. The
-whole list matches if at least one of the sublists matches (they are
-`or'ed, the qualifiers in the sublists are `and'ed).  Some qualifiers,
+Multiple consecutive qualifiers are joined into a list by implicit logical AND.
+More than one of these lists can be combined using comma `tt(,)' as logical OR.
+The whole list matches if at least one of the sublists matches.
+Some qualifiers,
 however, affect all matches generated, independent of the sublist in
 which they are given.  These are the qualifiers `tt(M)', `tt(T)',
 `tt(N)', `tt(D)', `tt(n)', `tt(o)', `tt(O)' and the subscripts given