mirror of
git://git.code.sf.net/p/cdesktopenv/code
synced 2025-02-13 03:32:24 +00:00
Revert "[1.0 release prep] Remove tilde expansion discipline"
This revertsc0334e32
, thereby restoring936a1939
. After the fixes in0a343244
anda2bc49be
, the tilde expansion disciplines work nicely, so they can come back to the 1.0 branch.
This commit is contained in:
parent
a2bc49bed1
commit
350e52877b
9 changed files with 134 additions and 1 deletions
6
ANNOUNCE
6
ANNOUNCE
|
@ -82,6 +82,12 @@ New shell language features:
|
|||
useful; it now matches all hidden files (dotfiles) in the current
|
||||
directory, without the harmful inclusion of '.' and '..'.
|
||||
|
||||
- Tilde expansion can now be extended or modified by defining a
|
||||
.sh.tilde.get or .sh.tilde.set discipline function. This replaces a
|
||||
2004 undocumented attempt to add this functionality via a .sh.tilde
|
||||
command, which never worked and crashed the shell. See the manual for
|
||||
details on the new method.
|
||||
|
||||
New features in built-in commands:
|
||||
|
||||
- Usage error messages now show the --help/--man self-documentation options.
|
||||
|
|
5
NEWS
5
NEWS
|
@ -422,6 +422,11 @@ Any uppercase BUG_* names are modernish shell bug IDs.
|
|||
|
||||
2021-03-16:
|
||||
|
||||
- Tilde expansion can now be extended or modified by defining a .sh.tilde.get
|
||||
or .sh.tilde.set discipline function. This replaces a 2004 undocumented
|
||||
attempt to add this functionality via a .sh.tilde built-in, which never
|
||||
worked and crashed the shell. See the manual for details on the new method.
|
||||
|
||||
- Fixed a bug in interactive shells: if a variable used by the shell called
|
||||
a discipline function (such as PS1.get() or COLUMNS.set()), the value of $?
|
||||
was set to the exit status of the discipline function instead of the last
|
||||
|
|
|
@ -104,6 +104,7 @@ const struct shtable2 shtab_variables[] =
|
|||
".sh.math", 0, (char*)0,
|
||||
".sh.pool", 0, (char*)0,
|
||||
".sh.pid", NV_INTEGER|NV_NOFREE, (char*)0,
|
||||
".sh.tilde", 0, (char*)0,
|
||||
"SHLVL", NV_INTEGER|NV_NOFREE|NV_EXPORT, (char*)0,
|
||||
#if SHOPT_MULTIBYTE
|
||||
"CSWIDTH", 0, (char*)0,
|
||||
|
|
|
@ -104,6 +104,7 @@ extern void sh_save_rand_seed(struct rand *, int);
|
|||
#define SH_MATHNOD (shgd->bltin_nodes+62)
|
||||
#define SH_JOBPOOL (shgd->bltin_nodes+63)
|
||||
#define SH_PIDNOD (shgd->bltin_nodes+64)
|
||||
#define SHLVL (shgd->bltin_nodes+65)
|
||||
#define SH_TILDENOD (shgd->bltin_nodes+65)
|
||||
#define SHLVL (shgd->bltin_nodes+66)
|
||||
|
||||
#endif /* SH_VALNOD */
|
||||
|
|
|
@ -849,6 +849,37 @@ A
|
|||
.B :
|
||||
also terminates a user name following a
|
||||
.BR \(ap .
|
||||
.PP
|
||||
The tilde expansion mechanism may be extended or modified
|
||||
by defining one of the discipline functions
|
||||
.B .sh.tilde.set
|
||||
or
|
||||
.B .sh.tilde.get
|
||||
(see
|
||||
.I Functions
|
||||
and
|
||||
.I Discipline Functions
|
||||
below).
|
||||
If either exists,
|
||||
then upon encountering a tilde word to expand,
|
||||
that function is called with the tilde word assigned to either
|
||||
.B .sh.value
|
||||
(for the
|
||||
.B .sh.tilde.set
|
||||
function) or
|
||||
.B .sh.tilde
|
||||
(for the
|
||||
.B .sh.tilde.get
|
||||
function).
|
||||
Performing tilde expansion within a discipline function will not recursively
|
||||
call that function, but default tilde expansion remains active,
|
||||
so literal tildes should still be quoted where required.
|
||||
Either function may assign a replacement string to
|
||||
.BR .sh.value .
|
||||
If this value is non-empty and does not start with a
|
||||
.BR \(ap ,
|
||||
it replaces the default tilde expansion when the function terminates.
|
||||
Otherwise, the tilde expansion is left unchanged.
|
||||
.SS Command Substitution.
|
||||
The standard output from a command list enclosed in
|
||||
parentheses preceded by a dollar sign (
|
||||
|
|
|
@ -2631,7 +2631,23 @@ static void tilde_expand2(Shell_t *shp, register int offset)
|
|||
char *cp = NIL(char*); /* character pointer for tilde expansion result */
|
||||
char *stakp = stakptr(0); /* current stack object (&stakp[offset] is tilde string) */
|
||||
int curoff = staktell(); /* current offset of current stack object */
|
||||
static char block; /* for disallowing tilde expansion in .get/.set to change ${.sh.tilde} */
|
||||
/*
|
||||
* Allow overriding tilde expansion with a .sh.tilde.set or .get discipline function.
|
||||
*/
|
||||
if(!block && SH_TILDENOD->nvfun && SH_TILDENOD->nvfun->disc)
|
||||
{
|
||||
stakfreeze(1); /* terminate current stack object to avoid data corruption */
|
||||
block++;
|
||||
nv_putval(SH_TILDENOD, &stakp[offset], 0);
|
||||
cp = nv_getval(SH_TILDENOD);
|
||||
block--;
|
||||
if(cp[0]=='\0' || cp[0]=='~')
|
||||
cp = NIL(char*); /* do not use empty or unexpanded result */
|
||||
stakset(stakp,curoff); /* restore stack to state on function entry */
|
||||
}
|
||||
/*
|
||||
* Perform default tilde expansion unless overridden.
|
||||
* Write the result to the stack, if any.
|
||||
*/
|
||||
stakputc(0);
|
||||
|
|
|
@ -751,6 +751,24 @@ r ^:test-2: echo Success\r\n$
|
|||
r ^Success\r\n$
|
||||
!
|
||||
|
||||
# err_exit #
|
||||
((SHOPT_VSH || SHOPT_ESH)) && tst $LINENO <<"!"
|
||||
L value of $? after tilde expansion in tab completion
|
||||
|
||||
# Make sure that a .sh.tilde.set discipline function
|
||||
# cannot influence the exit status.
|
||||
|
||||
w .sh.tilde.set() { true; }
|
||||
w HOME=/tmp
|
||||
w false ~\t
|
||||
u false /tmp
|
||||
w echo "Exit status is: $?"
|
||||
u Exit status is: 1
|
||||
w (exit 42)
|
||||
w echo $? ~\t
|
||||
u 42 /tmp
|
||||
!
|
||||
|
||||
# err_exit #
|
||||
((SHOPT_MULTIBYTE && (SHOPT_VSH || SHOPT_ESH))) &&
|
||||
[[ ${LC_ALL:-${LC_CTYPE:-${LANG:-}}} =~ [Uu][Tt][Ff]-?8 ]] &&
|
||||
|
|
|
@ -107,6 +107,8 @@ got=~
|
|||
HOME=$saveHOME
|
||||
|
||||
# ======
|
||||
# Tilde expansion discipline function tests
|
||||
|
||||
# This nonfunctional mess was removed in ksh 93u+m ...
|
||||
if builtin .sh.tilde 2>/dev/null
|
||||
then got=$(.sh.tilde & wait "$!" 2>&1)
|
||||
|
@ -114,5 +116,57 @@ then got=$(.sh.tilde & wait "$!" 2>&1)
|
|||
"(got status $e$( ((e>128)) && print -n / && kill -l "$e"), $(printf %q "$got"))"
|
||||
fi
|
||||
|
||||
# ... and replaced by a proper use of discipline functions that allows customising tilde expansion.
|
||||
((.sh.version >= 20210316)) &&
|
||||
for disc in get set
|
||||
do (
|
||||
ulimit -t unlimited 2>/dev/null # fork subshell to cope with a possible crash
|
||||
|
||||
eval ".sh.tilde.$disc()
|
||||
{
|
||||
case \${.sh.${ [[ $disc == get ]] && print tilde || print value; }} in
|
||||
'~tmp') .sh.value=\$tmp ;;
|
||||
'~INC') .sh.value=\$((++i)) ;;
|
||||
'~spc') .sh.value=$'one\ttwo three\n\tfour' ;;
|
||||
'~') .sh.value=~/addition ;; # this should not recurse
|
||||
esac
|
||||
}"
|
||||
|
||||
got=~/foo
|
||||
exp=$HOME/addition/foo
|
||||
[[ $got == "$exp" ]] || err_exit "$disc discipline: bare tilde expansion:" \
|
||||
"expected $(printf %q "$exp"), got $(printf %q "$got")"
|
||||
|
||||
.sh.tilde=oldvalue
|
||||
got=$(print ~tmp/foo.$$; print "${.sh.tilde}")
|
||||
exp=$tmp/foo.$$$'\n'$tmp
|
||||
[[ $got == "$exp" ]] || err_exit "$disc discipline: result left in \${.sh.tilde}:" \
|
||||
"expected $(printf %q "$tmp"), got $(printf %q "${.sh.tilde}")"
|
||||
[[ ${.sh.tilde} == oldvalue ]] || err_exit "$disc discipline: \${.sh.tilde} subshell leak"
|
||||
|
||||
i=0
|
||||
set -- ~INC ~INC ~INC ~INC ~INC
|
||||
got=$#,$1,$2,$3,$4,$5
|
||||
exp=5,1,2,3,4,5
|
||||
[[ $got == "$exp" ]] || err_exit "$disc discipline: counter:" \
|
||||
"expected $(printf %q "$exp"), got $(printf %q "$got")"
|
||||
((i==5)) || err_exit "$disc discipline: counter: $i != 5"
|
||||
|
||||
set -- ~spc ~spc ~spc
|
||||
got=$#,$1,$2,$3
|
||||
exp=$'3,one\ttwo three\n\tfour,one\ttwo three\n\tfour,one\ttwo three\n\tfour'
|
||||
[[ $got == "$exp" ]] || err_exit "$disc discipline: quoting of whitespace:" \
|
||||
"expected $(printf %q "$exp"), got $(printf %q "$got")"
|
||||
|
||||
print "$Errors" >$tmp/Errors
|
||||
) &
|
||||
wait "$!" 2>crashmsg
|
||||
if ((!(e = $?)))
|
||||
then read Errors <$tmp/Errors
|
||||
else err_exit ".sh.tilde.$disc discipline function crashes the shell" \
|
||||
"(got status $e$( ((e>128)) && print -n / && kill -l "$e"), $(printf %q "$(<crashmsg)"))"
|
||||
fi
|
||||
done
|
||||
|
||||
# ======
|
||||
exit $((Errors<125?Errors:125))
|
||||
|
|
|
@ -1029,6 +1029,7 @@ set -- \
|
|||
".sh.math" \
|
||||
".sh.pool" \
|
||||
".sh.pid" \
|
||||
".sh.tilde" \
|
||||
"SHLVL" \
|
||||
"CSWIDTH"
|
||||
|
||||
|
|
Loading…
Reference in a new issue