From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: zsh-workers-return-43670-ml=inbox.vuxu.org@zsh.org X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on inbox.vuxu.org X-Spam-Level: X-Spam-Status: No, score=-1.0 required=5.0 tests=DKIM_SIGNED,DKIM_VALID, MAILING_LIST_MULTI,RCVD_IN_DNSWL_NONE,T_DKIMWL_WL_MED 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 eeeee99a for ; Thu, 11 Oct 2018 01:34:12 +0000 (UTC) Received: (qmail 26017 invoked by alias); 11 Oct 2018 01:33:56 -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: 43670 Received: (qmail 24410 invoked by uid 1010); 11 Oct 2018 01:33:56 -0000 X-Qmail-Scanner-Diagnostics: from mail-it1-f194.google.com by f.primenet.com.au (envelope-from , uid 7791) with qmail-scanner-2.11 (clamdscan: 0.99.2/21882. spamassassin: 3.4.1. Clear:RC:0(209.85.166.194):SA:0(-1.9/5.0):. Processed in 3.756573 secs); 11 Oct 2018 01:33:56 -0000 X-Envelope-From: dana@dana.is X-Qmail-Scanner-Mime-Attachments: | X-Qmail-Scanner-Zip-Files: | DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=dana-is.20150623.gappssmtp.com; s=20150623; h=from:content-transfer-encoding:mime-version:subject:message-id:date :to; bh=C/LDMc3ZkNTLCf97cxc1so4RJupFwVeXlQcJ+2+asVs=; b=bvN26pRrzbJ9UUQXzmTGX/uyX4koU2LEsHFmCxuKmlS0b1Qorlo+WPYjp4ZkjmtDgN hcluL9X/0vTMjPQRsIomLujNJiYSkS6jeX0bicnO85lQc1j2LTUxI2Fwl3xQPEfQ0f/n DIDaTtimhbgTfpCi8uJ1lKitKIYLl4PhMOnH2ym0LMLGRCX/6f0ksQpITRdy8aVvYVpZ qA/hR6qiBpV7ry3bm9tIKyS9BBKcEgaf5/wZRle0TvW3Km6kjWsTVIm+3P4LIHqg7NPt tq0IH9v03/nLTVtL8m+jl5rJXMDD97Y6OGgYm2GBAKlVeISiT3esPxu/5bUZBbpSSV3S LQmA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:content-transfer-encoding:mime-version :subject:message-id:date:to; bh=C/LDMc3ZkNTLCf97cxc1so4RJupFwVeXlQcJ+2+asVs=; b=cVlhDepl2QcChs9kRO/daW8Zd3Qq/7Y4ZwIJncXNZfU6nsMLnoEhmPQEWIeiT4sbeQ URzLGKwCzKoIrnCWVwJg7Ix0o5u3zoaUOK20SLrEQimvo9z3pSOnnUhOVCfq0/iWRa7A 9sNt82CyOVNMH/0vV2gVSfaCyyKHCf6XeWG0TfG7ygaEmNuzQcq8OjHrNoMNcAWLOwkl D/YBSSvxFzks87sVzXBymnQg1Md2AFpvV7zhQOPnxu6XkNyKA0oWHYAv0mTzoRVyTyoF o5LFC/Re8A+wvcSVjXfJmMl8Mj6ycUxC71f2FTQNd3bHyMlKY1bDVeGHbEJ92K9oMRqM 8T9A== X-Gm-Message-State: ABuFfoi+ei0TOTjoTBYFrA9Opr8114O6AgYfHVKdhbGT1fzt5B7jtxUl 3tiBKS3ngxD0FsHKIUPwECNacQXD9w4BQw== X-Google-Smtp-Source: ACcGV63BS377wqM4jUnv3/NciXcqDukvlLrjW65RMGzPH3U+ubMo5nlNGrv3kXduwzBdLz6fi6KvXQ== X-Received: by 2002:a02:6a16:: with SMTP id l22-v6mr28642264jac.9.1539221629740; Wed, 10 Oct 2018 18:33:49 -0700 (PDT) From: dana Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: quoted-printable Mime-Version: 1.0 (Mac OS X Mail 11.5 \(3445.9.1\)) Subject: [RFC] Teach getopts to handle -o and +o separately Message-Id: <9A1ABCB6-0FF1-4E8E-83BE-3B8D84954525@dana.is> Date: Wed, 10 Oct 2018 20:33:48 -0500 To: Zsh hackers list X-Mailer: Apple Mail (2.3445.9.1) I really like that zsh's getopts handles both -o and +o option variants, = but a major limitation is that the two variants are linked by the one letter specification =E2=80=94 there's no way to tell zsh that you don't want = one or the other, and more importantly there's no way to specify that one variant should = take an argument and one should not. I'd like to propose that a - or + following an option letter (or = preceding it, if that seems nicer) restrict that letter specification to the - or + = variant respectively. With this change, the following sort of thing becomes = possible: % which testopts testopts () { local OPTARG OPTIND opt while getopts a-a:+bc opt do print -r - $opt${OPTARG:+:$OPTARG} done } % testopts -a +a a testopts:2: argument expected after +a option : % testopts -bab +bab b a b +b +a:b Of course, this eliminates - and + as valid 'letters' in the optstring. = But it seems unlikely that anyone actually needs +-, -+, or ++ (-- is already effectively unusable for obvious reasons). Also, POSIX says: >The use of other option characters that are not alphanumeric produces >unspecified results. So we're fine there. Below is a kind of silly-looking patch that implements the change. If = the idea is sound i can try to make it nicer (along with adding docs and tests = obv), but in any case i think it can be done without too many LOC and without = touching the scarier parts of that function. Does this seem viable at all? dana diff --git a/Src/builtin.c b/Src/builtin.c index 8dcdcc024..f099e3263 100644 --- a/Src/builtin.c +++ b/Src/builtin.c @@ -5512,7 +5512,8 @@ bin_getopts(UNUSED(char *name), char **argv, = UNUSED(Options ops), UNUSED(int fun optbuf[lenoptbuf - 1] =3D opch; =20 /* check for legality */ - if(opch =3D=3D ':' || !(p =3D memchr(optstr, opch, lenoptstr))) { + if(opch =3D=3D ':' || opch =3D=3D '?' || opch =3D=3D '-' || opch =3D=3D= '+' + || !(p =3D memchr(optstr, opch, lenoptstr))) { p =3D "?"; err: zsfree(zoptarg); @@ -5528,6 +5529,19 @@ bin_getopts(UNUSED(char *name), char **argv, = UNUSED(Options ops), UNUSED(int fun return 0; } =20 + scan: + if (!p) { + p =3D "?"; + goto err; + } + if ((lenoptbuf =3D=3D 1 && (p[1] =3D=3D '+' || (p[1] =3D=3D ':' = && p[2] =3D=3D '+'))) + || (lenoptbuf =3D=3D 2 && (p[1] =3D=3D '-' || (p[1] =3D=3D = ':' && p[2] =3D=3D '-'))) + ) { + p++; + p =3D memchr(p, opch, strlen(p)); + goto scan; + } + /* check for required argument */ if(p[1] =3D=3D ':') { if(optcind =3D=3D lenstr) {