From mboxrd@z Thu Jan 1 00:00:00 1970 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on inbox.vuxu.org X-Spam-Level: X-Spam-Status: No, score=-3.4 required=5.0 tests=DKIM_SIGNED,DKIM_VALID, DKIM_VALID_AU,MAILING_LIST_MULTI,RCVD_IN_DNSWL_MED,UNPARSEABLE_RELAY autolearn=ham autolearn_force=no version=3.4.4 Received: (qmail 29904 invoked from network); 10 Nov 2021 23:08:40 -0000 Received: from zero.zsh.org (2a02:898:31:0:48:4558:7a:7368) by inbox.vuxu.org with ESMTPUTF8; 10 Nov 2021 23:08:40 -0000 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=zsh.org; s=rsa-20210803; h=List-Archive:List-Owner:List-Post:List-Unsubscribe: List-Subscribe:List-Help:List-Id:Sender:Message-ID:Date:Content-ID: Content-Type:MIME-Version:Subject:To:References:From:In-reply-to:cc:Reply-To: Content-Transfer-Encoding:Content-Description:Resent-Date:Resent-From: Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID; bh=ZL1BVx9DgGRzqh/nfR/IP7Xv0sgfe3wK5Y++V6pPLQA=; b=rwLWcg7W7AqKhYeHNxyyM22sLs 95sU6xYkQ9i9h49Vu7LgJ1nTQKEF0eXcgcX3kskT2ZO/TKWga3JNhEBzaw9OmSb6uKP2lZwKKVQsG F56+VtBEMBP5nLyQ5FORy+3aMZTV11QkZtxpUkalOxAxfa3IwD7ToazoABCMUtFmnJiY8WekK9WOt dj8LHDeH7bSdPmIS1Qux7G3RLQDI7irSWkZnoqr/TrdmHWGShkCHzjr1cLIDiHD1u0gdev1NGYkYk n2LN/a64jYHOIi8TB0uF09ovKyoaPr8YMRHYHcbmW8NGkbxnc0boL+6RNiOqWeFfK46BdD6MwOPjW df+jD/dg==; Received: from authenticated user by zero.zsh.org with local id 1mkwhs-000MEl-GU; Wed, 10 Nov 2021 23:08:40 +0000 Received: from authenticated user by zero.zsh.org with esmtpsa (TLS1.3:TLS_AES_256_GCM_SHA384:256) id 1mkwhJ-000Lwe-NS; Wed, 10 Nov 2021 23:08:07 +0000 Received: from [192.168.178.21] (helo=hydra) by mail.kiddle.eu with esmtp(Exim 4.94.2) (envelope-from ) id 1mkwhI-000JhD-BL; Thu, 11 Nov 2021 00:08:04 +0100 cc: zsh-workers@zsh.org In-reply-to: <2C471545-3339-4B78-BADD-B98336D3833D@kba.biglobe.ne.jp> From: Oliver Kiddle References: <73806-1630065135.858692@atah.qJX1.Jyyu> <846a355a-d3e8-404a-ac80-4b0f5776d115@www.fastmail.com> <89303-1635367918.379239@3fX8._yj_.piD6> <6DF97A0F-0544-4D6C-BBD6-0D83B0AF272E@kba.biglobe.ne.jp> <72984-1636247814.729146@gNqB.dXT4.M5JK> <2C471545-3339-4B78-BADD-B98336D3833D@kba.biglobe.ne.jp> To: Jun T Subject: PATCH: zformat (was list units in brackets at the end of completion group descriptions) MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-ID: <75713.1636585684.1@hydra> Date: Thu, 11 Nov 2021 00:08:04 +0100 Message-ID: <75714-1636585684.348103@RLBx.KaGK.RKdB> X-Seq: 49561 Archived-At: X-Loop: zsh-workers@zsh.org Errors-To: zsh-workers-owner@zsh.org Precedence: list Precedence: bulk Sender: zsh-workers-request@zsh.org X-no-archive: yes List-Id: List-Help: List-Subscribe: List-Unsubscribe: List-Post: List-Owner: List-Archive: On 8 Nov, Jun T wrote: > I think %1(M is enough for the current purpose. > (or set %M to 0 if unit is given, and nonzero otherwise; i.e., never leave > it undefined). We can't retrospectively set M to nonzero for users of older versions of zsh. I'd like to be able to configure a format that'll work with new or old versions. > But, in zshcompsys(1), neither the section for the 'format' style nor the > section for '_description' says that the ternary expression of zformat can > be used (or is it mentioned somewhere?). So if adding a new option to > zformat would have wider use, then I think adding the option and using it in > _description would not break the compatibility. As you say, it doesn't appear to be documented anywhere and I can't see any cases where we pass values that are intended for use with it. Given that math evaluation will treat words as variable names, it won't even be useful with the specs that we do pass. Being able to check for the presence of specs is more useful so how about the following patch? This adds -F as an alternative to -f. That was largely chosen out of lazyness because a second option to be combined with -f requires proper option parsing rather than the existing string compare on the first argument. But we can do that if someone is bothered enough to argue in favour. With this form, where d:word is passed, a %(d ternary will follow the true path. Numeric arguments allow for a string width test. I'm not sure how useful that is but it is consistent with the basic presence checking (absence being a width of zero) and could have uses like for truncating long suffix lists. Or if there's objections to this then the %1(M approach does work. Oliver diff --git a/Completion/Base/Core/_description b/Completion/Base/Core/_description index bdb4007a6..5b54484c7 100644 --- a/Completion/Base/Core/_description +++ b/Completion/Base/Core/_description @@ -78,7 +78,7 @@ shift 2 if [[ -z "$1" && $# -eq 1 ]]; then format= elif [[ -n "$format" ]]; then - zformat -f format "$format" "d:$1" "${(@)argv[2,-1]}" + zformat -F format "$format" "d:$1" "${(@)argv[2,-1]}" fi if [[ -n "$gname" ]]; then diff --git a/Completion/Base/Core/_message b/Completion/Base/Core/_message index 4d5645eaf..dbeed4a88 100644 --- a/Completion/Base/Core/_message +++ b/Completion/Base/Core/_message @@ -39,7 +39,7 @@ else fi if [[ -n "$format$raw" ]]; then - [[ -z "$raw" ]] && zformat -f format "$format" "d:$1" "${(@)argv[2,-1]}" + [[ -z "$raw" ]] && zformat -F format "$format" "d:$1" "${(@)argv[2,-1]}" builtin compadd "$gopt[@]" -x "$format" _comp_mesg=yes fi diff --git a/Doc/Zsh/mod_zutil.yo b/Doc/Zsh/mod_zutil.yo index 41d3dfdb0..3cf9e5028 100644 --- a/Doc/Zsh/mod_zutil.yo +++ b/Doc/Zsh/mod_zutil.yo @@ -150,8 +150,9 @@ enditem() ) findex(zformat) xitem(tt(zformat -f) var(param) var(format) var(spec) ...) +xitem(tt(zformat -F) var(param) var(format) var(spec) ...) item(tt(zformat -a) var(array) var(sep) var(spec) ...)( -This builtin provides two different forms of formatting. The first form +This builtin provides different forms of formatting. The first form is selected with the tt(-f) option. In this case the var(format) string will be modified by replacing sequences starting with a percent sign in it with strings from the var(spec)s. Each var(spec) should be @@ -195,7 +196,13 @@ outputs "The answer is 'yes'." to tt(REPLY) since the value for the format specifier tt(c) is 3, agreeing with the digit argument to the ternary expression. -The second form, using the tt(-a) option, can be used for aligning +With tt(-F) instead of tt(-f), ternary expressions choose between the +`true' or `false' text on the basis of whether the format specifier is +present and non-empty. A test number indicates a minimum width for the +value given in the format specifier. Negative numbers reverse this, +so the test is for whether the value exceeds a maximum width. + +The form, using the tt(-a) option, can be used for aligning strings. Here, the var(spec)s are of the form `var(left)tt(:)var(right)' where `var(left)' and `var(right)' are arbitrary strings. These strings are modified by replacing the colons diff --git a/Src/Modules/zutil.c b/Src/Modules/zutil.c index 691ba6c2f..2f17c03f1 100644 --- a/Src/Modules/zutil.c +++ b/Src/Modules/zutil.c @@ -776,10 +776,12 @@ bin_zstyle(char *nam, char **args, UNUSED(Options ops), UNUSED(int func)) * ousedp (*outp)[*ousedp] is where to write next * olenp *olenp is the size allocated for *outp * endchar Terminator character in addition to `\0' (may be '\0') + * presence -F: Ternary expressions test emptyness instead * skip If 1, don't output, just parse. */ static char *zformat_substring(char* instr, char **specs, char **outp, - int *ousedp, int *olenp, int endchar, int skip) + int *ousedp, int *olenp, int endchar, + int presence, int skip) { char *s; @@ -813,20 +815,29 @@ static char *zformat_substring(char* instr, char **specs, char **outp, if (testit && STOUC(*s)) { int actval, testval, endcharl; - /* - * One one number is useful for ternary expressions. - * Remember to put the sign back. - */ + /* Only one number is useful for ternary expressions. */ testval = (min >= 0) ? min : (max >= 0) ? max : 0; - if (right) - testval *= -1; - if (specs[STOUC(*s)]) - actval = (int)mathevali(specs[STOUC(*s)]); - else - actval = 0; - /* zero means values are equal, i.e. true */ - actval -= testval; + if (specs[STOUC(*s)] && *specs[STOUC(*s)]) { + if (presence) { + if (testval) +#ifdef MULTIBYTE_SUPPORT + if (isset(MULTIBYTE)) + actval = MB_METASTRWIDTH(specs[STOUC(*s)]); + else +#endif + actval = strlen(specs[STOUC(*s)]); + else + actval = 1; + actval = right ? (testval < actval) : (testval >= actval); + } else { + if (right) /* put the sign back */ + testval *= -1; + /* zero means values are equal, i.e. true */ + actval = (int)mathevali(specs[STOUC(*s)]) - testval; + } + } else + actval = presence ? !right : testval; /* careful about premature end of string */ if (!(endcharl = *++s)) @@ -837,10 +848,10 @@ static char *zformat_substring(char* instr, char **specs, char **outp, * vice versa... unless we are already skipping. */ if (!(s = zformat_substring(s+1, specs, outp, ousedp, - olenp, endcharl, skip || actval))) + olenp, endcharl, presence, skip || actval))) return NULL; if (!(s = zformat_substring(s+1, specs, outp, ousedp, - olenp, ')', skip || !actval))) + olenp, ')', presence, skip || !actval))) return NULL; } else if (skip) { continue; @@ -912,6 +923,7 @@ static int bin_zformat(char *nam, char **args, UNUSED(Options ops), UNUSED(int func)) { char opt; + int presence = 0; if (args[0][0] != '-' || !(opt = args[0][1]) || args[0][2]) { zwarnnam(nam, "invalid argument: %s", args[0]); @@ -920,6 +932,9 @@ bin_zformat(char *nam, char **args, UNUSED(Options ops), UNUSED(int func)) args++; switch (opt) { + case 'F': + presence = 1; + /* fall-through */ case 'f': { char **ap, *specs[256] = {0}, *out; @@ -939,7 +954,8 @@ bin_zformat(char *nam, char **args, UNUSED(Options ops), UNUSED(int func)) } out = (char *) zhalloc(olen = 128); - zformat_substring(args[1], specs, &out, &oused, &olen, '\0', 0); + zformat_substring(args[1], specs, &out, &oused, &olen, '\0', + presence, 0); out[oused] = '\0'; setsparam(args[0], ztrdup(out)); diff --git a/Test/V13zformat.ztst b/Test/V13zformat.ztst index 982866e13..36038fa6e 100644 --- a/Test/V13zformat.ztst +++ b/Test/V13zformat.ztst @@ -58,6 +58,30 @@ 0:nested conditionals test >yes + () { + zformat -f 1 '%(w.zero.fail) %(x.fail.present) %(y.empty.fail) %(z.missing.fail)' w:0 x:1 y: + zformat -F 2 '%(w.zero.fail) %(x.present.fail) %(y.fail.empty) %(z.fail.missing)' w:0 x:1 y: + echo $1 + echo $2 + } +0:conditionals with empty and missing values +>zero present empty missing +>zero present empty missing + + () { + local l + for l in 0 1 2 3; do + zformat -F 1 "%$l(a.a.A)%$l(b.b.B)%$l(c.c.C)%$l(d.d.D)" a: b:1 c:12 d:123 + zformat -F 2 "%-$l(a.a.A)%-$l(b.b.B)%-$l(c.c.C)%-$l(d.d.D)" a: b:1 c:12 d:123 + print - $1 $2 + done + } +0:minimum and maximum widths +>Abcd aBCD +>ABcd abCD +>ABCd abcD +>ABCD abcd + zformat -a argv . foo:lorem ipsum:bar bazbaz '\\esc\:ape' print -rl -- "$@" 0:basic -a test