mirror of
git://git.code.sf.net/p/zsh/code
synced 2025-09-03 10:21:46 +02: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
6 changed files with 75 additions and 20 deletions
|
@ -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>
|
2021-11-07 Oliver Kiddle <opk@zsh.org>
|
||||||
|
|
||||||
* 49544: Src/Modules/watch.c: only tie watch/WATCH if both come
|
* 49544: Src/Modules/watch.c: only tie watch/WATCH if both come
|
||||||
|
|
|
@ -78,7 +78,7 @@ shift 2
|
||||||
if [[ -z "$1" && $# -eq 1 ]]; then
|
if [[ -z "$1" && $# -eq 1 ]]; then
|
||||||
format=
|
format=
|
||||||
elif [[ -n "$format" ]]; then
|
elif [[ -n "$format" ]]; then
|
||||||
zformat -f format "$format" "d:$1" "${(@)argv[2,-1]}"
|
zformat -F format "$format" "d:$1" "${(@)argv[2,-1]}"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [[ -n "$gname" ]]; then
|
if [[ -n "$gname" ]]; then
|
||||||
|
|
|
@ -39,7 +39,7 @@ else
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [[ -n "$format$raw" ]]; then
|
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"
|
builtin compadd "$gopt[@]" -x "$format"
|
||||||
_comp_mesg=yes
|
_comp_mesg=yes
|
||||||
fi
|
fi
|
||||||
|
|
|
@ -150,8 +150,9 @@ enditem()
|
||||||
)
|
)
|
||||||
findex(zformat)
|
findex(zformat)
|
||||||
xitem(tt(zformat -f) var(param) var(format) var(spec) ...)
|
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) ...)(
|
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)
|
is selected with the tt(-f) option. In this case the var(format)
|
||||||
string will be modified by replacing sequences starting with a percent
|
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
|
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
|
specifier tt(c) is 3, agreeing with the digit argument to the ternary
|
||||||
expression.
|
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
|
strings. Here, the var(spec)s are of the form
|
||||||
`var(left)tt(:)var(right)' where `var(left)' and `var(right)' are
|
`var(left)tt(:)var(right)' where `var(left)' and `var(right)' are
|
||||||
arbitrary strings. These strings are modified by replacing the colons
|
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
|
* ousedp (*outp)[*ousedp] is where to write next
|
||||||
* olenp *olenp is the size allocated for *outp
|
* olenp *olenp is the size allocated for *outp
|
||||||
* endchar Terminator character in addition to `\0' (may be '\0')
|
* 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.
|
* skip If 1, don't output, just parse.
|
||||||
*/
|
*/
|
||||||
static char *zformat_substring(char* instr, char **specs, char **outp,
|
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;
|
char *s;
|
||||||
|
|
||||||
|
@ -813,20 +815,29 @@ static char *zformat_substring(char* instr, char **specs, char **outp,
|
||||||
if (testit && STOUC(*s)) {
|
if (testit && STOUC(*s)) {
|
||||||
int actval, testval, endcharl;
|
int actval, testval, endcharl;
|
||||||
|
|
||||||
/*
|
/* Only one number is useful for ternary expressions. */
|
||||||
* One one number is useful for ternary expressions.
|
|
||||||
* Remember to put the sign back.
|
|
||||||
*/
|
|
||||||
testval = (min >= 0) ? min : (max >= 0) ? max : 0;
|
testval = (min >= 0) ? min : (max >= 0) ? max : 0;
|
||||||
if (right)
|
|
||||||
testval *= -1;
|
|
||||||
|
|
||||||
if (specs[STOUC(*s)])
|
if (specs[STOUC(*s)] && *specs[STOUC(*s)]) {
|
||||||
actval = (int)mathevali(specs[STOUC(*s)]);
|
if (presence) {
|
||||||
else
|
if (testval)
|
||||||
actval = 0;
|
#ifdef MULTIBYTE_SUPPORT
|
||||||
/* zero means values are equal, i.e. true */
|
if (isset(MULTIBYTE))
|
||||||
actval -= testval;
|
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 */
|
/* careful about premature end of string */
|
||||||
if (!(endcharl = *++s))
|
if (!(endcharl = *++s))
|
||||||
|
@ -837,10 +848,10 @@ static char *zformat_substring(char* instr, char **specs, char **outp,
|
||||||
* vice versa... unless we are already skipping.
|
* vice versa... unless we are already skipping.
|
||||||
*/
|
*/
|
||||||
if (!(s = zformat_substring(s+1, specs, outp, ousedp,
|
if (!(s = zformat_substring(s+1, specs, outp, ousedp,
|
||||||
olenp, endcharl, skip || actval)))
|
olenp, endcharl, presence, skip || actval)))
|
||||||
return NULL;
|
return NULL;
|
||||||
if (!(s = zformat_substring(s+1, specs, outp, ousedp,
|
if (!(s = zformat_substring(s+1, specs, outp, ousedp,
|
||||||
olenp, ')', skip || !actval)))
|
olenp, ')', presence, skip || !actval)))
|
||||||
return NULL;
|
return NULL;
|
||||||
} else if (skip) {
|
} else if (skip) {
|
||||||
continue;
|
continue;
|
||||||
|
@ -912,6 +923,7 @@ static int
|
||||||
bin_zformat(char *nam, char **args, UNUSED(Options ops), UNUSED(int func))
|
bin_zformat(char *nam, char **args, UNUSED(Options ops), UNUSED(int func))
|
||||||
{
|
{
|
||||||
char opt;
|
char opt;
|
||||||
|
int presence = 0;
|
||||||
|
|
||||||
if (args[0][0] != '-' || !(opt = args[0][1]) || args[0][2]) {
|
if (args[0][0] != '-' || !(opt = args[0][1]) || args[0][2]) {
|
||||||
zwarnnam(nam, "invalid argument: %s", args[0]);
|
zwarnnam(nam, "invalid argument: %s", args[0]);
|
||||||
|
@ -920,6 +932,9 @@ bin_zformat(char *nam, char **args, UNUSED(Options ops), UNUSED(int func))
|
||||||
args++;
|
args++;
|
||||||
|
|
||||||
switch (opt) {
|
switch (opt) {
|
||||||
|
case 'F':
|
||||||
|
presence = 1;
|
||||||
|
/* fall-through */
|
||||||
case 'f':
|
case 'f':
|
||||||
{
|
{
|
||||||
char **ap, *specs[256] = {0}, *out;
|
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);
|
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';
|
out[oused] = '\0';
|
||||||
|
|
||||||
setsparam(args[0], ztrdup(out));
|
setsparam(args[0], ztrdup(out));
|
||||||
|
|
|
@ -58,6 +58,30 @@
|
||||||
0:nested conditionals test
|
0:nested conditionals test
|
||||||
>yes
|
>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'
|
zformat -a argv . foo:lorem ipsum:bar bazbaz '\\esc\:ape'
|
||||||
print -rl -- "$@"
|
print -rl -- "$@"
|
||||||
0:basic -a test
|
0:basic -a test
|
||||||
|
|
Loading…
Reference in a new issue