mirror of
https://github.com/zsh-users/zsh
synced 2024-10-02 22:24:37 +00:00
49561: add zformat -F option, similar to -f but ternary expressions check for existence instead of doing math evaluation
This commit is contained in:
parent
631576de0f
commit
dfb7ac94bb
|
@ -1,3 +1,11 @@
|
|||
2021-11-12 Oliver Kiddle <opk@zsh.org>
|
||||
|
||||
* 49561: Src/Modules/zutil.c, Doc/Zsh/mod_zutil.yo,
|
||||
Completion/Base/Core/_description, Completion/Base/Core/_message,
|
||||
Test/V13zformat.ztst: Add zformat -F option, similar to -f but
|
||||
ternary expressions check for existence instead of doing math
|
||||
evaluation. Make use it with the format style.
|
||||
|
||||
2021-11-07 Oliver Kiddle <opk@zsh.org>
|
||||
|
||||
* 49544: Src/Modules/watch.c: only tie watch/WATCH if both come
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue