mirror of
git://git.code.sf.net/p/zsh/code
synced 2025-01-01 05:16:05 +01:00
39332: support ksh's [[ -v varname ]] condition for checking if variables are set
This commit is contained in:
parent
00708285e9
commit
fbafc5b509
7 changed files with 63 additions and 2 deletions
|
@ -1,5 +1,9 @@
|
||||||
2016-09-15 Oliver Kiddle <opk@zsh.org>
|
2016-09-15 Oliver Kiddle <opk@zsh.org>
|
||||||
|
|
||||||
|
* 39332: Doc/Zsh/cond.yo, Src/cond.c, Src/params.c, Src/parse.c,
|
||||||
|
Completion/Zsh/Context/_condition, Test/C02cond.ztst: support
|
||||||
|
ksh's [[ -v varname ]] condition for checking if variables are set
|
||||||
|
|
||||||
* unposted: Src/parse.c: remove duplicated assignment
|
* unposted: Src/parse.c: remove duplicated assignment
|
||||||
|
|
||||||
2016-09-14 Peter Stephenson <p.stephenson@samsung.com>
|
2016-09-14 Peter Stephenson <p.stephenson@samsung.com>
|
||||||
|
|
|
@ -8,6 +8,8 @@ elif [[ "$prev" = -([a-hkprsuwxLOGSN]|[no]t|ef) ]]; then
|
||||||
_tags -C "$prev" files && _files
|
_tags -C "$prev" files && _files
|
||||||
elif [[ "$prev" = -t ]]; then
|
elif [[ "$prev" = -t ]]; then
|
||||||
_file_descriptors
|
_file_descriptors
|
||||||
|
elif [[ "$prev" = -v ]]; then
|
||||||
|
_parameters -r "\= \t\n\[\-"
|
||||||
else
|
else
|
||||||
if [[ "$PREFIX" = -* ]] ||
|
if [[ "$PREFIX" = -* ]] ||
|
||||||
! zstyle -T ":completion:${curcontext}:options" prefix-needed; then
|
! zstyle -T ":completion:${curcontext}:options" prefix-needed; then
|
||||||
|
@ -30,6 +32,7 @@ else
|
||||||
-s:non-empty\ file
|
-s:non-empty\ file
|
||||||
-t:terminal\ file\ descriptor
|
-t:terminal\ file\ descriptor
|
||||||
-u:setuid\ bit
|
-u:setuid\ bit
|
||||||
|
-v:set\ variable
|
||||||
-w:writable\ file
|
-w:writable\ file
|
||||||
-x:executable\ file
|
-x:executable\ file
|
||||||
-z:empty\ string
|
-z:empty\ string
|
||||||
|
|
|
@ -63,6 +63,9 @@ is open and associated with a terminal device.
|
||||||
item(tt(-u) var(file))(
|
item(tt(-u) var(file))(
|
||||||
true if var(file) exists and has its setuid bit set.
|
true if var(file) exists and has its setuid bit set.
|
||||||
)
|
)
|
||||||
|
item(tt(-v) var(varname))(
|
||||||
|
true if shell variable var(varname) is set.
|
||||||
|
)
|
||||||
item(tt(-w) var(file))(
|
item(tt(-w) var(file))(
|
||||||
true if var(file) exists and is writable by current process.
|
true if var(file) exists and is writable by current process.
|
||||||
)
|
)
|
||||||
|
|
|
@ -351,6 +351,8 @@ evalcond(Estate state, char *fromtest)
|
||||||
return (!S_ISSOCK(dostat(left)));
|
return (!S_ISSOCK(dostat(left)));
|
||||||
case 'u':
|
case 'u':
|
||||||
return (!(dostat(left) & S_ISUID));
|
return (!(dostat(left) & S_ISUID));
|
||||||
|
case 'v':
|
||||||
|
return (!issetvar(left));
|
||||||
case 'w':
|
case 'w':
|
||||||
return (!doaccess(left, W_OK));
|
return (!doaccess(left, W_OK));
|
||||||
case 'x':
|
case 'x':
|
||||||
|
|
30
Src/params.c
30
Src/params.c
|
@ -626,6 +626,36 @@ getvaluearr(Value v)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Return whether the variable is set *
|
||||||
|
* checks that array slices are within range *
|
||||||
|
* used for [[ -v ... ]] condition test */
|
||||||
|
|
||||||
|
/**/
|
||||||
|
int
|
||||||
|
issetvar(char *name)
|
||||||
|
{
|
||||||
|
struct value vbuf;
|
||||||
|
Value v;
|
||||||
|
int slice;
|
||||||
|
char **arr;
|
||||||
|
|
||||||
|
if (!(v = getvalue(&vbuf, &name, 1)) || *name)
|
||||||
|
return 0; /* no value or more chars after the variable name */
|
||||||
|
if (v->isarr & ~SCANPM_ARRONLY)
|
||||||
|
return v->end > 1; /* for extracted elements, end gives us a count */
|
||||||
|
|
||||||
|
slice = v->start != 0 || v->end != -1;
|
||||||
|
if (PM_TYPE(v->pm->node.flags) != PM_ARRAY || !slice)
|
||||||
|
return !slice && !(v->pm->node.flags & PM_UNSET);
|
||||||
|
|
||||||
|
if (!v->end) /* empty array slice */
|
||||||
|
return 0;
|
||||||
|
/* get the array and check end is within range */
|
||||||
|
if (!(arr = getvaluearr(v)))
|
||||||
|
return 0;
|
||||||
|
return arrlen_ge(arr, v->end < 0 ? - v->end : v->end);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Split environment string into (name, value) pair.
|
* Split environment string into (name, value) pair.
|
||||||
* this is used to avoid in-place editing of environment table
|
* this is used to avoid in-place editing of environment table
|
||||||
|
|
|
@ -2385,7 +2385,7 @@ par_cond_2(void)
|
||||||
s1 = tokstr;
|
s1 = tokstr;
|
||||||
dble = (s1 && *s1 == '-'
|
dble = (s1 && *s1 == '-'
|
||||||
&& (!n_testargs
|
&& (!n_testargs
|
||||||
|| strspn(s1+1, "abcdefghknoprstuwxzLONGS") == 1)
|
|| strspn(s1+1, "abcdefghknoprstuvwxzLONGS") == 1)
|
||||||
&& !s1[2]);
|
&& !s1[2]);
|
||||||
if (tok != STRING) {
|
if (tok != STRING) {
|
||||||
/* Check first argument for [[ STRING ]] re-interpretation */
|
/* Check first argument for [[ STRING ]] re-interpretation */
|
||||||
|
@ -2464,7 +2464,7 @@ par_cond_double(char *a, char *b)
|
||||||
{
|
{
|
||||||
if (a[0] != '-' || !a[1])
|
if (a[0] != '-' || !a[1])
|
||||||
COND_ERROR("parse error: condition expected: %s", a);
|
COND_ERROR("parse error: condition expected: %s", a);
|
||||||
else if (!a[2] && strspn(a+1, "abcdefgknoprstuwxzhLONGS") == 1) {
|
else if (!a[2] && strspn(a+1, "abcdefgknoprstuvwxzhLONGS") == 1) {
|
||||||
ecadd(WCB_COND(a[1], 0));
|
ecadd(WCB_COND(a[1], 0));
|
||||||
ecstr(b);
|
ecstr(b);
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -269,6 +269,25 @@ F:Failures in these cases do not indicate a problem in the shell.
|
||||||
0:-nt shouldn't abort on non-existent files
|
0:-nt shouldn't abort on non-existent files
|
||||||
>status = 1
|
>status = 1
|
||||||
|
|
||||||
|
str='string' empty=''
|
||||||
|
[[ -v IFS && -v str && -v empty && ! -v str[3] && ! -v not_a_variable ]]
|
||||||
|
0:-v cond
|
||||||
|
|
||||||
|
arr=( 1 2 3 4 ) empty=()
|
||||||
|
[[ -v arr && -v arr[1,4] && -v arr[1] && -v arr[4] && -v arr[-4] &&
|
||||||
|
-v arr[(i)3] && ! -v arr[(i)x] &&
|
||||||
|
! -v arr[0] && ! -v arr[5] && ! -v arr[-5] && ! -v arr[2][1] &&
|
||||||
|
! -v arr[3]extra && -v empty && ! -v empty[1] ]]
|
||||||
|
0:-v cond with array
|
||||||
|
|
||||||
|
typeset -A assoc=( key val num 4 )
|
||||||
|
[[ -v assoc && -v assoc[key] && -v assoc[(i)*] && -v assoc[(I)*] &&
|
||||||
|
! -v assoc[x] && ! -v assoc[key][1] ]]
|
||||||
|
0:-v cond with association
|
||||||
|
|
||||||
|
() { [[ -v 0 && -v 1 && -v 2 && ! -v 3 ]] } arg ''
|
||||||
|
0:-v cond with positional parameters
|
||||||
|
|
||||||
# core dumps on failure
|
# core dumps on failure
|
||||||
if zmodload zsh/regex 2>/dev/null; then
|
if zmodload zsh/regex 2>/dev/null; then
|
||||||
echo >regex_test.sh 'if [[ $# = 1 ]]; then
|
echo >regex_test.sh 'if [[ $# = 1 ]]; then
|
||||||
|
|
Loading…
Reference in a new issue