mirror of
git://git.code.sf.net/p/zsh/code
synced 2025-10-30 05:40:58 +01:00
38736: various RPN mode enhancements for zcalc
This commit is contained in:
parent
016929e043
commit
5103c85abb
5 changed files with 93 additions and 16 deletions
|
|
@ -1,5 +1,9 @@
|
||||||
2016-06-21 Peter Stephenson <p.stephenson@samsung.com>
|
2016-06-21 Peter Stephenson <p.stephenson@samsung.com>
|
||||||
|
|
||||||
|
* 38736: Completion/Zsh/Type/_module_math_func,
|
||||||
|
Completion/Zsh/Type/_user_math_func, Doc/Zsh/contrib.yo,
|
||||||
|
Functions/Misc/zcalc: various RPN mode enhancments for zcalc.
|
||||||
|
|
||||||
* 38734: Src/loop.c, Test/A01grammar.ztst: fix final case
|
* 38734: Src/loop.c, Test/A01grammar.ztst: fix final case
|
||||||
clauses terminating with ;&.
|
clauses terminating with ;&.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -6,4 +6,4 @@ local -a funcs
|
||||||
funcs=(${${${(f)"$(zmodload -Fl zsh/mathfunc 2>/dev/null)"}:#^+f:*}##+f:})
|
funcs=(${${${(f)"$(zmodload -Fl zsh/mathfunc 2>/dev/null)"}:#^+f:*}##+f:})
|
||||||
|
|
||||||
_wanted module-math-functions expl 'math function from zsh/mathfunc' \
|
_wanted module-math-functions expl 'math function from zsh/mathfunc' \
|
||||||
compadd -S '(' "$@" -a funcs
|
compadd -S '(' -q "$@" -a funcs
|
||||||
|
|
|
||||||
|
|
@ -6,4 +6,4 @@ local -a funcs
|
||||||
funcs=(${${${(f)"$(functions -M)"}##functions -M }%% *})
|
funcs=(${${${(f)"$(functions -M)"}##functions -M }%% *})
|
||||||
|
|
||||||
_wanted user-math-functions expl 'user math function' \
|
_wanted user-math-functions expl 'user math function' \
|
||||||
compadd -S '(' "$@" -a funcs
|
compadd -S '(' -q "$@" -a funcs
|
||||||
|
|
|
||||||
|
|
@ -3806,10 +3806,23 @@ are printed instead of just the most recent result. Hence, for example,
|
||||||
tt(zcalc -r4) shows tt($stack[4]) to tt($stack[1]) each time results
|
tt(zcalc -r4) shows tt($stack[4]) to tt($stack[1]) each time results
|
||||||
are printed.
|
are printed.
|
||||||
)
|
)
|
||||||
item(Duplication)(
|
item(Duplication: tt(=))(
|
||||||
The pseudo-operator tt(=) causes the most recent element of
|
The pseudo-operator tt(=) causes the most recent element of
|
||||||
the stack to be duplicated onto the stack.
|
the stack to be duplicated onto the stack.
|
||||||
)
|
)
|
||||||
|
item(tt(pop))(
|
||||||
|
The pseudo-function tt(pop) causes the most recent element of
|
||||||
|
the stack to be popped. A `tt(<)' on its own has the same effect.
|
||||||
|
)
|
||||||
|
item(tt(<)var(ident))(
|
||||||
|
The expression tt(<) followed (with no space) by a shell identifier
|
||||||
|
causes the most recent element of the stack to be popped and
|
||||||
|
assigned to the identifier.
|
||||||
|
)
|
||||||
|
item(Exchange: tt(xy))(
|
||||||
|
The pseudo-function tt(xy) causes the most recent two elements of
|
||||||
|
the stack to be exchanged.
|
||||||
|
)
|
||||||
enditem()
|
enditem()
|
||||||
|
|
||||||
The prompt is configurable via the parameter tt(ZCALCPROMPT), which
|
The prompt is configurable via the parameter tt(ZCALCPROMPT), which
|
||||||
|
|
@ -3872,7 +3885,13 @@ Note that tt(zcalc) takes care of all quoting. Hence for example:
|
||||||
|
|
||||||
example(:f cube $1 * $1 * $1)
|
example(:f cube $1 * $1 * $1)
|
||||||
|
|
||||||
defines a function to cube the sole argument.
|
defines a function to cube the sole argument. Functions so defined, or
|
||||||
|
indeed any functions defined directly or indirectly using tt(functions
|
||||||
|
-M), are available to execute by typing only the name on the line in RPN
|
||||||
|
mode; this pops the appropriate number of arguments off the stack
|
||||||
|
to pass to the function, i.e. 1 in the case of the example tt(cube)
|
||||||
|
function. If there are optional arguments only the mandatory
|
||||||
|
arguments are supplied by this means.
|
||||||
)
|
)
|
||||||
item(tt([#)var(base)tt(]))(
|
item(tt([#)var(base)tt(]))(
|
||||||
This is not a special command, rather part of normal arithmetic
|
This is not a special command, rather part of normal arithmetic
|
||||||
|
|
|
||||||
|
|
@ -100,7 +100,8 @@ zcalc_show_value() {
|
||||||
if [[ -n $base ]]; then
|
if [[ -n $base ]]; then
|
||||||
print -- $(( $base $1 ))
|
print -- $(( $base $1 ))
|
||||||
elif [[ $1 = *.* ]] || (( outdigits )); then
|
elif [[ $1 = *.* ]] || (( outdigits )); then
|
||||||
if [[ -z $forms[outform] ]]; then
|
# With normal output, ensure trailing "." doesn't get lost.
|
||||||
|
if [[ -z $forms[outform] || ($outform -eq 1 && $1 = *.) ]]; then
|
||||||
print -- $(( $1 ))
|
print -- $(( $1 ))
|
||||||
else
|
else
|
||||||
printf "$forms[outform]\n" $outdigits $1
|
printf "$forms[outform]\n" $outdigits $1
|
||||||
|
|
@ -115,10 +116,10 @@ local ZCALC_ACTIVE=1
|
||||||
|
|
||||||
# TODO: make local variables that shouldn't be visible in expressions
|
# TODO: make local variables that shouldn't be visible in expressions
|
||||||
# begin with _.
|
# begin with _.
|
||||||
local line ans base defbase forms match mbegin mend psvar optlist opt arg
|
local line ans base defbase forms match mbegin mend psvar optlist opt arg tmp
|
||||||
local compcontext="-zcalc-line-"
|
local compcontext="-zcalc-line-"
|
||||||
integer num outdigits outform=1 expression_mode rpn_mode matched show_stack i
|
integer num outdigits outform=1 expression_mode rpn_mode matched show_stack i n
|
||||||
integer max_stack
|
integer max_stack push
|
||||||
local -a expressions stack match mbegin mend
|
local -a expressions stack match mbegin mend
|
||||||
|
|
||||||
# We use our own history file with an automatic pop on exit.
|
# We use our own history file with an automatic pop on exit.
|
||||||
|
|
@ -131,6 +132,13 @@ if zmodload -i zsh/mathfunc 2>/dev/null; then
|
||||||
zmodload -P mathfuncs -FL zsh/mathfunc
|
zmodload -P mathfuncs -FL zsh/mathfunc
|
||||||
mathfuncs="("${(j.|.)${mathfuncs##f:}}")"
|
mathfuncs="("${(j.|.)${mathfuncs##f:}}")"
|
||||||
fi
|
fi
|
||||||
|
local -A userfuncs
|
||||||
|
for line in ${(f)"$(functions -M)"}; do
|
||||||
|
match=(${=line})
|
||||||
|
# get minimum number of arguments
|
||||||
|
userfuncs[${match[3]}]=${match[4]}
|
||||||
|
done
|
||||||
|
line=
|
||||||
autoload -Uz zmathfuncdef
|
autoload -Uz zmathfuncdef
|
||||||
|
|
||||||
if (( ! ${+ZCALCPROMPT} )); then
|
if (( ! ${+ZCALCPROMPT} )); then
|
||||||
|
|
@ -298,6 +306,7 @@ while (( expression_mode )) ||
|
||||||
|
|
||||||
((function|:f(unc(tion|)|))[[:blank:]]##(#b)([^[:blank:]]##)(|[[:blank:]]##([^[:blank:]]*)))
|
((function|:f(unc(tion|)|))[[:blank:]]##(#b)([^[:blank:]]##)(|[[:blank:]]##([^[:blank:]]*)))
|
||||||
zmathfuncdef $match[1] $match[3]
|
zmathfuncdef $match[1] $match[3]
|
||||||
|
userfuncs[$match[1]]=${$(functions -Mm $match[1])[4]}
|
||||||
line=
|
line=
|
||||||
continue
|
continue
|
||||||
;;
|
;;
|
||||||
|
|
@ -318,19 +327,38 @@ while (( expression_mode )) ||
|
||||||
|
|
||||||
(*)
|
(*)
|
||||||
line=${${line##[[:blank:]]##}%%[[:blank:]]##}
|
line=${${line##[[:blank:]]##}%%[[:blank:]]##}
|
||||||
if (( rpn_mode )); then
|
if [[ rpn_mode -ne 0 && $line != '' ]]; then
|
||||||
|
push=1
|
||||||
matched=1
|
matched=1
|
||||||
case $line in
|
case $line in
|
||||||
(=)
|
(\=|pop|\<[[:IDENT:]]#)
|
||||||
if (( ${#stack} < 1 )); then
|
if (( ${#stack} < 1 )); then
|
||||||
print -r -- "${line}: not enough values on stack" >&2
|
print -r -- "${line}: not enough values on stack" >&2
|
||||||
line=
|
line=
|
||||||
continue
|
continue
|
||||||
fi
|
fi
|
||||||
|
case $line in
|
||||||
|
(=)
|
||||||
ans=${stack[1]}
|
ans=${stack[1]}
|
||||||
;;
|
;;
|
||||||
|
(pop|\<)
|
||||||
|
push=0
|
||||||
|
shift stack
|
||||||
|
;;
|
||||||
|
(\<[[:IDENT:]]##)
|
||||||
|
(( ${line##\<} = ${stack[1]} ))
|
||||||
|
push=0
|
||||||
|
shift stack
|
||||||
|
;;
|
||||||
|
(*)
|
||||||
|
print "BUG in special RPN functions" >&2
|
||||||
|
line=
|
||||||
|
continue
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
;;
|
||||||
|
|
||||||
(+|-|\^|\||\&|\*|\*\*|/)
|
(+|-|\^|\||\&|\*|/|\*\*|\>\>|\<\</)
|
||||||
# Operators with two arguments
|
# Operators with two arguments
|
||||||
if (( ${#stack} < 2 )); then
|
if (( ${#stack} < 2 )); then
|
||||||
print -r -- "${line}: not enough values on stack" >&2
|
print -r -- "${line}: not enough values on stack" >&2
|
||||||
|
|
@ -341,15 +369,22 @@ while (( expression_mode )) ||
|
||||||
shift 2 stack
|
shift 2 stack
|
||||||
;;
|
;;
|
||||||
|
|
||||||
(ldexp|jn|yn|scalb)
|
(ldexp|jn|yn|scalb|xy)
|
||||||
# Functions with two arguments
|
# Functions with two arguments
|
||||||
if (( ${#stack} < 2 )); then
|
if (( ${#stack} < 2 )); then
|
||||||
print -r -- "${line}: not enough values on stack" >&2
|
print -r -- "${line}: not enough values on stack" >&2
|
||||||
line=
|
line=
|
||||||
continue
|
continue
|
||||||
fi
|
fi
|
||||||
|
if [[ $line = xy ]]; then
|
||||||
|
tmp=${stack[1]}
|
||||||
|
stack[1]=${stack[2]}
|
||||||
|
stack[2]=$tmp
|
||||||
|
push=0
|
||||||
|
else
|
||||||
eval "(( ans = ${line}(\${stack[2]},\${stack[1]}) ))"
|
eval "(( ans = ${line}(\${stack[2]},\${stack[1]}) ))"
|
||||||
shift 2 stack
|
shift 2 stack
|
||||||
|
fi
|
||||||
;;
|
;;
|
||||||
|
|
||||||
(${~mathfuncs})
|
(${~mathfuncs})
|
||||||
|
|
@ -365,6 +400,25 @@ while (( expression_mode )) ||
|
||||||
shift stack
|
shift stack
|
||||||
;;
|
;;
|
||||||
|
|
||||||
|
(${(kj.|.)~userfuncs})
|
||||||
|
# Get minimum number of arguments to user function
|
||||||
|
n=${userfuncs[$line]}
|
||||||
|
if (( ${#stack} < n )); then
|
||||||
|
print -r -- "${line}: not enough vlaues ($n) on stack" >&2
|
||||||
|
line=
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
line+="("
|
||||||
|
# least recent elements on stack are earlier arguments
|
||||||
|
for (( i = n; i > 0; i-- )); do
|
||||||
|
line+=${stack[i]}
|
||||||
|
(( i > 1 )) && line+=","
|
||||||
|
done
|
||||||
|
line+=")"
|
||||||
|
shift $n stack
|
||||||
|
eval "(( ans = $line ))"
|
||||||
|
;;
|
||||||
|
|
||||||
(*)
|
(*)
|
||||||
# Treat as expression evaluating to new value to go on stack.
|
# Treat as expression evaluating to new value to go on stack.
|
||||||
matched=0
|
matched=0
|
||||||
|
|
@ -386,7 +440,7 @@ while (( expression_mode )) ||
|
||||||
fi
|
fi
|
||||||
argv[num++]=$ans
|
argv[num++]=$ans
|
||||||
psvar[1]=$num
|
psvar[1]=$num
|
||||||
stack=($ans $stack)
|
(( push )) && stack=($ans $stack)
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
if (( show_stack )); then
|
if (( show_stack )); then
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue