Zsh Mailing List Archive
Messages sorted by: Reverse Date, Date, Thread, Author

[PATCH] coding practice in examples (-- with globs mostly)



Hello, I've spotted a few cases in the doc of things like "ls *"
instead of "ls -d -- *".

While that's something one could do interactively when they know
how the files are named and their nature, that's bad practice in
scripts. As a reference manual, IMO, the zsh documentation
should show "the right way".

- always use "--" when using globs or wherever the arguments are
  not known in advance and can't be guaranteed not to start with
  - or +
- never use ls without -d unless you want it to list the
  *contents* of directory arguments.

(I've not made a thorough scan, there might be more I missed).

I include some related changes spotted on the way:
- mention echo in the list of builtins that don't support --
- note print -C1 as the canonical way to print a list of
  arguments one per line as I've changed one example to use
  that.

diff --git a/Doc/Zsh/builtins.yo b/Doc/Zsh/builtins.yo
index 415bce613..6c1c4f41a 100644
--- a/Doc/Zsh/builtins.yo
+++ b/Doc/Zsh/builtins.yo
@@ -39,11 +39,11 @@ be familiar to most command line users.
 
 Typically, options are single letters preceded by a hyphen (tt(-)).
 Options that take an argument accept it either immediately following the
-option letter or after white space, for example `tt(print -C3 *)' or
-`tt(print -C 3 *)' are equivalent.  Arguments to options are not the
+option letter or after white space, for example `tt(print -C3 {1..9})' or
+`tt(print -C 3 {1..9})' are equivalent.  Arguments to options are not the
 same as arguments to the command; the documentation indicates which is
 which.  Options that do not take an argument may be combined in a single
-word, for example `tt(print -ca *)' and `tt(print -c -a *)' are
+word, for example `tt(print -rca -- *)' and `tt(print -r -c -a -- *)' are
 equivalent.
 
 Some shell builtin commands also take options that begin with `tt(+)'
@@ -54,14 +54,14 @@ Options (together with their individual arguments, if any) must appear
 in a group before any non-option arguments; once the first non-option
 argument has been found, option processing is terminated.
 
-All builtin commands other than precommand modifiers, even those that
-have no options, can be given the argument `tt(-)tt(-)' to terminate option
-processing.  This indicates that the following words are non-option
-arguments, but is otherwise ignored.  This is useful in cases where
-arguments to the command may begin with `tt(-)'.  For historical
-reasons, most builtin commands also recognize a single `tt(-)' in a
-separate word for this purpose; note that this is less standard and
-use of `tt(-)tt(-)' is recommended.
+All builtin commands other than `tt(echo)' and precommand modifiers,
+even those that have no options, can be given the argument `tt(-)tt(-)'
+to terminate option processing.  This indicates that the following words
+are non-option arguments, but is otherwise ignored.  This is useful in
+cases where arguments to the command may begin with `tt(-)'.  For
+historical reasons, most builtin commands (including `tt(echo)') also
+recognize a single `tt(-)' in a separate word for this purpose; note
+that this is less standard and use of `tt(-)tt(-)' is recommended.
 
 startitem()
 prefix(-)
@@ -114,9 +114,9 @@ var(text) is any non-empty string, it is replaced by the text
 a literal string, not a pattern.  A trailing space in var(value) is not
 special in this case.  For example,
 
-example(alias -s ps=gv)
+example(alias -s ps='gv --')
 
-will cause the command `tt(*.ps)' to be expanded to `tt(gv *.ps)'.  As
+will cause the command `tt(*.ps)' to be expanded to `tt(gv -- *.ps)'.  As
 alias expansion is carried out earlier than globbing, the `tt(*.ps)' will
 then be expanded.  Suffix aliases constitute a different name space from
 other aliases (so in the above example it is still possible
@@ -1258,7 +1258,11 @@ If given together with tt(-o) or tt(-O), sorting is performed
 case-independently.
 )
 item(tt(-l))(
-Print the arguments separated by newlines instead of spaces.
+Print the arguments separated by newlines instead of spaces. Note:
+if the list of arguments is empty, tt(print -l) as opposed to
+tt(print -C1), still outputs one empty line; tt(print -rC1 --
+"$list[@]") is a more canonical way to print an arbitrary list of
+arguments, one per line.
 )
 item(tt(-m))(
 Take the first argument as a pattern (should be quoted), and remove
@@ -1269,7 +1273,9 @@ item(tt(-n))(
 Do not add a newline to the output.
 )
 item(tt(-N))(
-Print the arguments separated and terminated by nulls.
+Print the arguments separated and terminated by nulls. Again,
+tt(print -rNC1 -- "$list[@]") is a canonical way to print an
+arbitrary list as null-delimited records.
 )
 item(tt(-o))(
 Print the arguments sorted in ascending order.
diff --git a/Doc/Zsh/contrib.yo b/Doc/Zsh/contrib.yo
index 558342711..743ac73dc 100644
--- a/Doc/Zsh/contrib.yo
+++ b/Doc/Zsh/contrib.yo
@@ -4422,10 +4422,11 @@ For example, to get a long tt(ls) listing of all plain files in the
 current directory or its subdirectories:
 
 example(autoload -U zargs
-zargs -- **/*(.) -- ls -l)
+zargs -- **/*(.) -- ls -ld --)
 
 Note that `tt(-)tt(-)' is used both to mark the end of the var(option)
-list and to mark the end of the var(input) list, so it must appear twice
+list and to mark the end of the var(input) list (and here also to mark
+the end of the option list for tt(ls)), so it must appear twice
 whenever the var(input) list may be empty.  If there is guaranteed to be
 at least one var(input) and the first var(input) does not begin with a
 `tt(-)', then the first `tt(-)tt(-)' may be omitted.
@@ -4435,7 +4436,7 @@ tt(-e) option may be used to change the end-of-inputs marker.  Note that
 this does em(not) change the end-of-options marker.  For example, to use
 `tt(..)' as the marker:
 
-example(zargs -e.. -- **/*(.) .. ls -l)
+example(zargs -e.. -- **/*(.) .. ls -ld --)
 
 This is a good choice in that example because no plain file can be named
 `tt(..)', but the best end-marker depends on the circumstances.
diff --git a/Doc/Zsh/expn.yo b/Doc/Zsh/expn.yo
index d7147dbd7..6f4700dc4 100644
--- a/Doc/Zsh/expn.yo
+++ b/Doc/Zsh/expn.yo
@@ -400,7 +400,7 @@ backslashes.
 For example, the following piece of filename generation code
 with the tt(EXTENDED_GLOB) option:
 
-example(print *.c+LPAR()#q:s/#%+LPAR()#b+RPAR()s+LPAR()*+RPAR().c/'S${match[1]}.C'/+RPAR())
+example(print -r -- *.c+LPAR()#q:s/#%+LPAR()#b+RPAR()s+LPAR()*+RPAR().c/'S${match[1]}.C'/+RPAR())
 
 takes the expansion of tt(*.c) and applies the glob qualifiers in the
 tt(LPAR()#q)var(...)tt(RPAR()) expression, which consists of a substitution
@@ -2492,11 +2492,11 @@ therefore matches files in the current directory as well as
 subdirectories.
 Thus:
 
-example(ls (*/)#bar)
+example(ls -ld -- (*/)#bar)
 
 or
 
-example(ls **/bar)
+example(ls -ld -- **/bar)
 
 does a recursive directory search for files named `tt(bar)' (potentially
 including the file `tt(bar)' in the current directory).  This form does not
@@ -2511,11 +2511,11 @@ they are treated as if both a tt(/) plus a further tt(*) are present.
 Hence:
 
 example(setopt GLOBSTARSHORT
-ls **.c)
+ls -ld -- **.c)
 
 is equivalent to
 
-example(ls **/*.c)
+example(ls -ld -- **/*.c)
 subsect(Glob Qualifiers)
 cindex(globbing, qualifiers)
 cindex(qualifiers, globbing)
@@ -2707,7 +2707,7 @@ appropriate test.  For example,
 
 example(nt+LPAR()RPAR() { [[ $REPLY -nt $NTREF ]] }
 NTREF=reffile
-ls -l *(+nt))
+ls -ld -- *(+nt))
 
 lists all files in the directory that have been modified more recently than
 tt(reffile).
@@ -2898,36 +2898,36 @@ is performed, although note that the presence of the parentheses
 causes the entire expression to be subjected to any global pattern matching
 options such as tt(NULL_GLOB). Thus:
 
-example(ls *(-/))
+example(ls -ld -- *(-/))
 
 lists all directories and symbolic links that point to directories,
 and
 
-example(ls *(-@))
+example(ls -ld -- *(-@))
 
 lists all broken symbolic links, and
 
-example(ls *(%W))
+example(ls -ld -- *(%W))
 
 lists all world-writable device files in the current directory, and
 
-example(ls *(W,X))
+example(ls -ld -- *(W,X))
 
 lists all files in the current directory that are
 world-writable or world-executable, and
 
-example(echo /tmp/foo*(u0^@:t))
+example(print -rC1 /tmp/foo*(u0^@:t))
 
 outputs the basename of all root-owned files beginning with the string
 `tt(foo)' in tt(/tmp), ignoring symlinks, and
 
-example(ls *.*~(lex|parse).[ch](^D^l1))
+example(ls -ld -- *.*~(lex|parse).[ch](^D^l1))
 
 lists all files having a link count of one whose names contain a dot
 (but not those starting with a dot, since tt(GLOB_DOTS) is explicitly
 switched off) except for tt(lex.c), tt(lex.h), tt(parse.c) and tt(parse.h).
 
-example(print b*.pro+LPAR()#q:s/pro/shmo/+RPAR()(#q.:s/builtin/shmiltin/))
+example(print -rC1 b*.pro+LPAR()#q:s/pro/shmo/+RPAR()(#q.:s/builtin/shmiltin/))
 
 demonstrates how colon modifiers and other qualifiers may be chained
 together.  The ordinary qualifier `tt(.)' is applied first, then the colon



Messages sorted by: Reverse Date, Date, Thread, Author