From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on inbox.vuxu.org X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=DKIM_ADSP_CUSTOM_MED, FORGED_GMAIL_RCVD,FREEMAIL_FROM,MAILING_LIST_MULTI,RCVD_IN_DNSWL_NONE autolearn=ham autolearn_force=no version=3.4.2 Received: from primenet.com.au (ns1.primenet.com.au [203.24.36.2]) by inbox.vuxu.org (OpenSMTPD) with ESMTP id c6aad231 for ; Wed, 1 Jan 2020 21:20:54 +0000 (UTC) Received: (qmail 1526 invoked by alias); 1 Jan 2020 21:20:48 -0000 Mailing-List: contact zsh-workers-help@zsh.org; run by ezmlm Precedence: bulk X-No-Archive: yes List-Id: Zsh Workers List List-Post: List-Help: List-Unsubscribe: X-Seq: 45183 Received: (qmail 27050 invoked by uid 1010); 1 Jan 2020 21:20:48 -0000 X-Qmail-Scanner-Diagnostics: from 195-159-176-226.customer.powertech.no by f.primenet.com.au (envelope-from , uid 7791) with qmail-scanner-2.11 (clamdscan: 0.102.1/25677. spamassassin: 3.4.2. Clear:RC:0(195.159.176.226):SA:0(1.6/5.0):. Processed in 0.770555 secs); 01 Jan 2020 21:20:48 -0000 X-Envelope-From: gcszd-zsh-workers@m.gmane.org X-Qmail-Scanner-Mime-Attachments: | X-Qmail-Scanner-Zip-Files: | Received-SPF: none (ns1.primenet.com.au: domain at m.gmane.org does not designate permitted sender hosts) X-Injected-Via-Gmane: http://gmane.org/ To: zsh-workers@zsh.org From: Stephane Chazelas Subject: [PATCH v2] coding practice in examples (-- with globs mostly) Date: Wed, 1 Jan 2020 21:18:09 +0000 Message-ID: <20200101211809.muon7k6uzzxsitom@chaz.gmail.com> References: <20191231091618.v2erkblkwkiy3i5a@chaz.gmail.com> <20191231171638.en6olco722w4ldcc@tarpaulin.shahaf.local2> <20200101120009.24l375svthztyszj@chaz.gmail.com> <20200101125213.fo75ca2wdkwrbzi4@tarpaulin.shahaf.local2> Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii User-Agent: NeoMutt/20180716 Content-Disposition: inline In-Reply-To: <20200101125213.fo75ca2wdkwrbzi4@tarpaulin.shahaf.local2> 2020-01-01 12:52:13 +0000, Daniel Shahaf: [...] > Looks good, thanks. Please commit. > > Further suggestions (nice-to-have's, not blockers): > > - Clarify that the third -- isn't syntactically significant, and is just passed > to ls verbatim. [...] Please find a new version below, with a small change that goes in that direction. Note that I'm not a commiter (I don't mind it staying that way), someone else would have to commit for me. diff --git a/Doc/Zsh/builtins.yo b/Doc/Zsh/builtins.yo index 415bce613..ada69c99a 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,10 @@ 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) will still output one empty +line. To print a possibly-empty list of arguments one per line, use +tt(print -C1), as in `tt(print -rC1 -- "$list[@]")'. ) item(tt(-m))( Take the first argument as a pattern (should be quoted), and remove @@ -1269,7 +1272,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..871c3e6f5 100644 --- a/Doc/Zsh/contrib.yo +++ b/Doc/Zsh/contrib.yo @@ -4418,24 +4421,28 @@ the elements from the tt(input) list in each run. If no var(command) is provided, then no var(arg) list may be provided, and in that event the default command is `tt(print)' with arguments `tt(-r -)tt(-)'. -For example, to get a long tt(ls) listing of all plain files in the -current directory or its subdirectories: +For example, to get a long tt(ls) listing of all non-hidden plain files +in the current directory or its subdirectories: example(autoload -U zargs -zargs -- **/*(.) -- ls -l) +zargs -- **/*(.) -- ls -ld --) + +The first and third occurrences of `tt(-)tt(-)' are used to mark the end +of options for tt(zargs) and tt(ls) respectively to guard against +filenames starting with `tt(-)', while the second is used to separate the +list of files from the command to run (`tt(ls -ld --)'). + +The first `tt(-)tt(-)' would also be needed if there was a chance the +list might be empty as in: -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 -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. +example(zargs -r -- ./*.back(#qN) -- rm -f) In the event that the string `tt(-)tt(-)' is or may be an var(input), the 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