From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 24913 invoked by alias); 23 Jan 2015 16:37:19 -0000 Mailing-List: contact zsh-users-help@zsh.org; run by ezmlm Precedence: bulk X-No-Archive: yes List-Id: Zsh Users List List-Post: List-Help: X-Seq: 19771 Received: (qmail 15357 invoked from network); 23 Jan 2015 16:37:07 -0000 X-Spam-Checker-Version: SpamAssassin 3.3.2 (2011-06-06) on f.primenet.com.au X-Spam-Level: X-Spam-Status: No, score=-2.7 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_FROM,RCVD_IN_DNSWL_LOW,T_FSL_HELO_BARE_IP_2 autolearn=ham version=3.3.2 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=yandex.ru; s=mail; t=1422031021; bh=UQhVTiB6I3OrUt4W1kPMUvZ9cmqtaoqxNKfUu2oMg8Y=; h=From:To:In-Reply-To:References:Subject:Date; b=WHpW0aHli62LbZifnzmCVZIENoppMTOinn01UIOsPfT8BycfGD1OKh96C21/AvYp4 /Q2rtAS9wVa+6GmHmlJMBnoRjlzoQEFzT5iv/WMNvcInK/beQh5ofGks4/NyHcvpP0 jw3t1fcMEdJzhnalth8vWg7H6pg6fc7gNir/8tr4= From: ZyX To: TJ Luoma , Zsh-Users List In-Reply-To: References: Subject: Re: zparseopts help MIME-Version: 1.0 Message-Id: <7476371422031020@web23g.yandex.ru> X-Mailer: Yamail [ http://yandex.ru ] 5.0 Date: Fri, 23 Jan 2015 19:37:00 +0300 Content-Transfer-Encoding: 8bit Content-Type: text/plain; charset=utf-8 23.01.2015, 18:42, "TJ Luoma" : > As I've mentioned before, I have been using zsh forever but feel like I > missed out on learning about 97% of what it can do. > > For example, today I learned about zparseopts. > > (Feel free to mock.) > > I took a look through the `man` entry, but… I don't know what it is about > my brain, but I can read and re-read man pages and still fail to understand > what it is saying. I do much better with examples. > > I did some googling and found > http://emg-2.blogspot.com/2008/01/zsh-unique-features.html and once I had > that I could go back and look at the `man` page to understand what it was > doing. > > So here is my first attempt at using `zparseopts`: > > zparseopts -D -E -A MyVariableNameHere -- a b -orange -grape -apple > > if (( ${+MyVariableNameHere[-a]} )); then >         echo "Apple"; > fi > > if (( ${+MyVariableNameHere[--apple]} )); then >         echo "Apple"; > fi > > if (( ${+MyVariableNameHere[-b]} )); then >         echo "Banana"; > fi > > if (( ${+MyVariableNameHere[--orange]} )); then >         echo "orange"; > fi > > if (( ${+MyVariableNameHere[--grape]} )); then >         echo "grape"; > fi > > Questions: > > 1. Is there a way to combine the -a and --apple statements into one? zparseopts -- a=A -apple=A if (( $#A )) ; then echo Apple fi > > 2. Are a series of 'if' statements the best way to handle these sorts of > options? I guess this is why zparseopts has `option_definition=ARRNAME` syntax. > > What I have been doing is something like this: > > for MyVariableNameHere in "$@" > do > case "$MyVariableNameHere" in > -a|--apple) > echo "Apple" > shift > ;; > -b|--banana) > echo "Banana" > shift > ;; > esac > done > > but that has the disadvantage of not being able to parse "-ab" as two > separate arguments. OTOH it's very readable and I don't have to worry about > very many chances of missing a closing bracket or brace! I did not know about `zparseopts` and have written the following interesting piece of code which handles `-ab`, `-c{arg}`, `--foo {arg}`. No `--foo={arg}`, but you can easily imagine how it would look: ``` function parseargs() { local -i ENDOFARGS=0 local -i OUTPUT=0 for arg in $@ ; do if (( OUTPUT == 1 )) then OUTPUTFILE=${arg} OUTPUT=0 continue elif (( OUTPUT == 2 )) then OUTPUT=0 fi [[ "${METHOD}" == "1" ]] && METHOD=${arg} && continue [[ "${ARCHTYPE}" == "1" ]] && ARCHTYPE=${arg} && continue if (( ! $ENDOFARGS )) && [[ ${arg[1]} == "-" ]] then case ${arg} in --) ENDOFARGS=1 ;; --type) ARCHTYPE=1 ;; --method) METHOD=1 ;; --debug) DEBUG=1 ;; --help) Help ;; --stdout) setargument 1 1 ;; --decompress) setargument 2 1 ;; --compress) setargument 3 1 ;; --test) setargument 4 1 ;; --force) setargument 5 1 ;; --keep) setargument 6 1 ;; --quiet) setargument 7 1 ;; --show-progress) setargument 8 1 ;; --fast) setargument 9 1 ;; --best) setargument 9 9 ;; --onefile) setargument 10 1 ;; --verbose) setargument 11 1 ;; -) setargument 12 1 ;; --*) eerror 64 "Unknown key: ${arg}!" ;; -*) local -i I=2 while [[ ! -z "${arg[$I]}" ]] do local CUR="${arg[$I]}" if (( OUTPUT )) then OUTPUT=2 OUTPUTFILE="${arg[$I,-1]}" && break fi case ${CUR} in o) OUTPUT=1 ;; c) setargument 1 1 ;; d) setargument 2 1 ;; z) setargument 3 1 ;; t) setargument 4 1 ;; f) setargument 5 1 ;; k) setargument 6 1 ;; q) setargument 7 1 ;; p) setargument 8 1 ;; O) setargument 10 1 ;; v) setargument 11 1 ;; [1-9]) setargument 9 ${CUR} ;; *) eerror 64 "Unknown key: -${CUR}!" ;; esac (( I++ )) done ;; esac else FILES+=( ${arg:a} ) fi done [[ -z $ARCHTYPE ]] && EXT="7z" \ || EXT="$ARCHTYPE" [[ "${OUTPUTFILE}" == "-" ]] && setargument 1 1 && unset OUTPUTFILE ARGUMENTS[3]=$(( ! ${ARGUMENTS[2]} && ! ${ARGUMENTS[4]} )) (( ${ARGUMENTS[3]} )) && [[ -z ${OUTPUTFILE} ]] && [[ ! -z ${FILES} ]] &&\ OUTPUTFILE="${FILES[1]}.$EXT" } ``` Not particularly readable (and is in fact one part of my first big zsh scripts). (If you are wondering this is the part of a wrapper script for `7z` archiver that makes it able to be used as `gzip` (but only if both `-so` and `-si` options are fully supported and they are not).) > > TjL > > ps - if anyone knows of a good place for zparseopts examples, please let me > know. Google was not very much help.