1
0
Fork 0
mirror of git://git.code.sf.net/p/zsh/code synced 2025-09-04 22:51:42 +02:00

38737: clean up zcalc variables.

Undocumented variables now start with "_".
This commit is contained in:
Peter Stephenson 2016-06-21 17:26:35 +01:00
parent 5103c85abb
commit 26c01f5711
3 changed files with 163 additions and 146 deletions

View file

@ -1,5 +1,8 @@
2016-06-21 Peter Stephenson <p.stephenson@samsung.com> 2016-06-21 Peter Stephenson <p.stephenson@samsung.com>
* 38737: Functions/Misc/zcalc, Doc/Zsh/contrib.yo: document some
zcalc variable usage and make other variables start with "_".
* 38736: Completion/Zsh/Type/_module_math_func, * 38736: Completion/Zsh/Type/_module_math_func,
Completion/Zsh/Type/_user_math_func, Doc/Zsh/contrib.yo, Completion/Zsh/Type/_user_math_func, Doc/Zsh/contrib.yo,
Functions/Misc/zcalc: various RPN mode enhancments for zcalc. Functions/Misc/zcalc: various RPN mode enhancments for zcalc.

View file

@ -3764,8 +3764,14 @@ first few positional parameters. A visual indication of this is given when
the calculator starts. the calculator starts.
The constants tt(PI) (3.14159...) and tt(E) (2.71828...) are provided. The constants tt(PI) (3.14159...) and tt(E) (2.71828...) are provided.
Parameter assignment is possible, but note that all parameters will be put Parameter assignment is possible, but note that all parameters will be
into the global namespace. put into the global namespace unless the tt(:local) special command is
used. The function creates local variables whose names start with
tt(_), so users should avoid doing so. The variables tt(ans) (the last
answer) and tt(stack) (the stack in RPN mode) may be referred to
directly; tt(stack) is an array but elements of it are numeric. Various
other special variables are used locally with their standard meaning,
for example tt(compcontext), tt(match), tt(mbegin), tt(mend), tt(psvar).
The output base can be initialised by passing the option `tt(-#)var(base)', The output base can be initialised by passing the option `tt(-#)var(base)',
for example `tt(zcalc -#16)' (the `tt(#)' may have to be quoted, depending for example `tt(zcalc -#16)' (the `tt(#)' may have to be quoted, depending
@ -3831,6 +3837,10 @@ stored locally in the first element of the array tt(psvar), which can be
referred to in tt(ZCALCPROMPT) as `tt(%1v)'. The default prompt is referred to in tt(ZCALCPROMPT) as `tt(%1v)'. The default prompt is
`tt(%1v> )'. `tt(%1v> )'.
The variable tt(ZCALC_ACTIVE) is set within the function and can
be tested by nested functions; it has the value tt(rpn) if RPN mode is
active, else 1.
A few special commands are available; these are introduced by a colon. A few special commands are available; these are introduced by a colon.
For backward compatibility, the colon may be omitted for certain For backward compatibility, the colon may be omitted for certain
commands. Completion is available if tt(compinit) has been run. commands. Completion is available if tt(compinit) has been run.
@ -3870,8 +3880,7 @@ is executed in the context of the function, i.e. with local variables.
Space is optional after tt(:!). Space is optional after tt(:!).
) )
item(tt(:local) var(arg) ...)( item(tt(:local) var(arg) ...)(
Declare variables local to the function. Note that certain variables Declare variables local to the function. Other variables
are used by the function for its own purposes. Other variables
may be used, too, but they will be taken from or put into the global may be used, too, but they will be taken from or put into the global
scope. scope.
) )

View file

@ -97,14 +97,14 @@ emulate -L zsh
setopt extendedglob setopt extendedglob
zcalc_show_value() { 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
# With normal output, ensure trailing "." doesn't get lost. # With normal output, ensure trailing "." doesn't get lost.
if [[ -z $forms[outform] || ($outform -eq 1 && $1 = *.) ]]; then 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
fi fi
else else
printf "%d\n" $1 printf "%d\n" $1
@ -116,29 +116,31 @@ 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 tmp local _line ans _base _defbase _forms match mbegin mend
local 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 n integer _num _outdigits _outform=1 _expression_mode
integer max_stack push integer _rpn_mode _matched _show_stack _i _n
local -a expressions stack match mbegin mend integer _max_stack _push
local -a _expressions stack
# We use our own history file with an automatic pop on exit. # We use our own history file with an automatic pop on exit.
history -ap "${ZDOTDIR:-$HOME}/.zcalc_history" history -ap "${ZDOTDIR:-$HOME}/.zcalc_history"
forms=( '%2$g' '%.*g' '%.*f' '%.*E' '') _forms=( '%2$g' '%.*g' '%.*f' '%.*E' '')
local mathfuncs local _mathfuncs
if zmodload -i zsh/mathfunc 2>/dev/null; then 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 local -A _userfuncs
for line in ${(f)"$(functions -M)"}; do for _line in ${(f)"$(functions -M)"}; do
match=(${=line}) match=(${=_line})
# get minimum number of arguments # get minimum number of arguments
userfuncs[${match[3]}]=${match[4]} _userfuncs[${match[3]}]=${match[4]}
done done
line= _line=
autoload -Uz zmathfuncdef autoload -Uz zmathfuncdef
if (( ! ${+ZCALCPROMPT} )); then if (( ! ${+ZCALCPROMPT} )); then
@ -155,118 +157,118 @@ fi
# Process command line # Process command line
while [[ -n $1 && $1 = -(|[#-]*|f|e|r(<->|)) ]]; do while [[ -n $1 && $1 = -(|[#-]*|f|e|r(<->|)) ]]; do
optlist=${1[2,-1]} _optlist=${1[2,-1]}
shift shift
[[ $optlist = (|-) ]] && break [[ $_optlist = (|-) ]] && break
while [[ -n $optlist ]]; do while [[ -n $_optlist ]]; do
opt=${optlist[1]} _opt=${_optlist[1]}
optlist=${optlist[2,-1]} _optlist=${_optlist[2,-1]}
case $opt in case $_opt in
('#') # Default base ('#') # Default base
if [[ -n $optlist ]]; then if [[ -n $_optlist ]]; then
arg=$optlist _arg=$_optlist
optlist= _optlist=
elif [[ -n $1 ]]; then elif [[ -n $1 ]]; then
arg=$1 _arg=$1
shift shift
else else
print -- "-# requires an argument" >&2 print -- "-# requires an argument" >&2
return 1 return 1
fi fi
if [[ $arg != (|\#)[[:digit:]]## ]]; then if [[ $_arg != (|\#)[[:digit:]]## ]]; then
print -- "-# requires a decimal number as an argument" >&2 print -- "-# requires a decimal number as an argument" >&2
return 1 return 1
fi fi
defbase="[#${arg}]" _defbase="[#${_arg}]"
;; ;;
(f) # Force floating point operation (f) # Force floating point operation
setopt forcefloat setopt forcefloat
;; ;;
(e) # Arguments are expressions (e) # Arguments are expressions
(( expression_mode = 1 )); (( _expression_mode = 1 ));
;; ;;
(r) # RPN mode. (r) # RPN mode.
(( rpn_mode = 1 )) (( _rpn_mode = 1 ))
ZCALC_ACTIVE=rpn ZCALC_ACTIVE=rpn
if [[ $optlist = (#b)(<->)* ]]; then if [[ $_optlist = (#b)(<->)* ]]; then
(( show_stack = ${match[1]} )) (( _show_stack = ${match[1]} ))
optlist=${optlist[${#match[1]}+1,-2]} _optlist=${_optlist[${#match[1]}+1,-2]}
fi fi
;; ;;
esac esac
done done
done done
if (( expression_mode )); then if (( _expression_mode )); then
expressions=("$@") _expressions=("$@")
argv=() argv=()
fi fi
for (( num = 1; num <= $#; num++ )); do for (( _num = 1; _num <= $#; _num++ )); do
# Make sure all arguments have been evaluated. # Make sure all arguments have been evaluated.
# The `$' before the second argv forces string rather than numeric # The `$' before the second argv forces string rather than numeric
# substitution. # substitution.
(( argv[$num] = $argv[$num] )) (( argv[$_num] = $argv[$_num] ))
print "$num> $argv[$num]" print "$_num> $argv[$_num]"
done done
psvar[1]=$num psvar[1]=$_num
local prev_line cont_prompt local _prev_line _cont_prompt
while (( expression_mode )) || while (( _expression_mode )) ||
vared -cehp "${cont_prompt}${ZCALCPROMPT}" line; do vared -cehp "${_cont_prompt}${ZCALCPROMPT}" _line; do
if (( expression_mode )); then if (( _expression_mode )); then
(( ${#expressions} )) || break (( ${#_expressions} )) || break
line=$expressions[1] _line=$_expressions[1]
shift expressions shift _expressions
fi fi
if [[ $line = (|*[^\\])('\\')#'\' ]]; then if [[ $_line = (|*[^\\])('\\')#'\' ]]; then
prev_line+=$line[1,-2] _prev_line+=$_line[1,-2]
cont_prompt="..." _cont_prompt="..."
line= _line=
continue continue
fi fi
line="$prev_line$line" _line="$_prev_line$_line"
prev_line= _prev_line=
cont_prompt= _cont_prompt=
# Test whether there are as many open as close # Test whether there are as many open as close
# parentheses in the line so far. # parentheses in the _line so far.
if [[ ${#line//[^\(]} -gt ${#line//[^\)]} ]]; then if [[ ${#_line//[^\(]} -gt ${#_line//[^\)]} ]]; then
prev_line+=$line _prev_line+=$_line
cont_prompt="..." _cont_prompt="..."
line= _line=
continue continue
fi fi
[[ -z $line ]] && break [[ -z $_line ]] && break
# special cases # special cases
# Set default base if `[#16]' or `[##16]' etc. on its own. # Set default base if `[#16]' or `[##16]' etc. on its own.
# Unset it if `[#]' or `[##]'. # Unset it if `[#]' or `[##]'.
if [[ $line = (#b)[[:blank:]]#('[#'(\#|)((<->|)(|_|_<->))']')[[:blank:]]#(*) ]]; then if [[ $_line = (#b)[[:blank:]]#('[#'(\#|)((<->|)(|_|_<->))']')[[:blank:]]#(*) ]]; then
if [[ -z $match[6] ]]; then if [[ -z $match[6] ]]; then
if [[ -z $match[3] ]]; then if [[ -z $match[3] ]]; then
defbase= _defbase=
else else
defbase=$match[1] _defbase=$match[1]
fi fi
print -s -- $line print -s -- $_line
print -- $(( ${defbase} ans )) print -- $(( ${_defbase} ans ))
line= _line=
continue continue
else else
base=$match[1] _base=$match[1]
fi fi
else else
base=$defbase _base=$_defbase
fi fi
print -s -- $line print -s -- $_line
line="${${line##[[:blank:]]#}%%[[:blank:]]#}" _line="${${_line##[[:blank:]]#}%%[[:blank:]]#}"
case "$line" in case "$_line" in
# Escapes begin with a colon # Escapes begin with a colon
(:(\\|)\!*) (:(\\|)\!*)
# shell escape: handle completion's habit of quoting the ! # shell escape: handle completion's habit of quoting the !
eval ${line##:(\\|)\![[:blank:]]#} eval ${_line##:(\\|)\![[:blank:]]#}
line= _line=
continue continue
;; ;;
@ -276,83 +278,83 @@ while (( expression_mode )) ||
;; ;;
((:|)norm) # restore output format to default ((:|)norm) # restore output format to default
outform=1 _outform=1
;; ;;
((:|)sci[[:blank:]]#(#b)(<->)(#B)) ((:|)sci[[:blank:]]#(#b)(<->)(#B))
outdigits=$match[1] _outdigits=$match[1]
outform=2 _outform=2
;; ;;
((:|)fix[[:blank:]]#(#b)(<->)(#B)) ((:|)fix[[:blank:]]#(#b)(<->)(#B))
outdigits=$match[1] _outdigits=$match[1]
outform=3 _outform=3
;; ;;
((:|)eng[[:blank:]]#(#b)(<->)(#B)) ((:|)eng[[:blank:]]#(#b)(<->)(#B))
outdigits=$match[1] _outdigits=$match[1]
outform=4 _outform=4
;; ;;
(:raw) (:raw)
outform=5 _outform=5
;; ;;
((:|)local([[:blank:]]##*|)) ((:|)local([[:blank:]]##*|))
eval $line eval $_line
line= _line=
continue continue
;; ;;
((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]} _userfuncs[$match[1]]=${$(functions -Mm $match[1])[4]}
line= _line=
continue continue
;; ;;
(:*) (:*)
print "Unrecognised escape" print "Unrecognised escape"
line= _line=
continue continue
;; ;;
(\$[[:IDENT:]]##) (\$[[:IDENT:]]##)
# Display only, no calculation # Display only, no calculation
line=${line##\$} _line=${_line##\$}
print -r -- ${(P)line} print -r -- ${(P)_line}
line= _line=
continue continue
;; ;;
(*) (*)
line=${${line##[[:blank:]]##}%%[[:blank:]]##} _line=${${_line##[[:blank:]]##}%%[[:blank:]]##}
if [[ rpn_mode -ne 0 && $line != '' ]]; then if [[ _rpn_mode -ne 0 && $_line != '' ]]; then
push=1 _push=1
matched=1 _matched=1
case $line in case $_line in
(\=|pop|\<[[:IDENT:]]#) (\=|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 case $_line in
(=) (=)
ans=${stack[1]} ans=${stack[1]}
;; ;;
(pop|\<) (pop|\<)
push=0 _push=0
shift stack shift stack
;; ;;
(\<[[:IDENT:]]##) (\<[[:IDENT:]]##)
(( ${line##\<} = ${stack[1]} )) (( ${_line##\<} = ${stack[1]} ))
push=0 _push=0
shift stack shift stack
;; ;;
(*) (*)
print "BUG in special RPN functions" >&2 print "BUG in special RPN functions" >&2
line= _line=
continue continue
;; ;;
esac esac
@ -361,98 +363,101 @@ while (( expression_mode )) ||
(+|-|\^|\||\&|\*|/|\*\*|\>\>|\<\</) (+|-|\^|\||\&|\*|/|\*\*|\>\>|\<\</)
# 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
line= _line=
continue continue
fi fi
eval "(( ans = \${stack[2]} $line \${stack[1]} ))" eval "(( ans = \${stack[2]} $_line \${stack[1]} ))"
shift 2 stack shift 2 stack
;; ;;
(ldexp|jn|yn|scalb|xy) (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 if [[ $_line = xy ]]; then
tmp=${stack[1]} _tmp=${stack[1]}
stack[1]=${stack[2]} stack[1]=${stack[2]}
stack[2]=$tmp stack[2]=$_tmp
push=0 _push=0
else else
eval "(( ans = ${line}(\${stack[2]},\${stack[1]}) ))" eval "(( ans = ${_line}(\${stack[2]},\${stack[1]}) ))"
shift 2 stack shift 2 stack
fi fi
;; ;;
(${~mathfuncs}) (${~_mathfuncs})
# Functions with a single argument. # Functions with a single argument.
# This is actually a superset, but we should have matched # This is actually a superset, but we should have matched
# any that shouldn't be in it in previous cases. # any that shouldn't be in it in previous cases.
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
eval "(( ans = ${line}(\${stack[1]}) ))" eval "(( ans = ${_line}(\${stack[1]}) ))"
shift stack shift stack
;; ;;
(${(kj.|.)~userfuncs}) (${(kj.|.)~_userfuncs})
# Get minimum number of arguments to user function # Get minimum number of arguments to user function
n=${userfuncs[$line]} _n=${_userfuncs[$_line]}
if (( ${#stack} < n )); then if (( ${#stack} < n_ )); then
print -r -- "${line}: not enough vlaues ($n) on stack" >&2 print -r -- "${_line}: not enough values ($_n) on stack" >&2
line= _line=
continue continue
fi fi
line+="(" _line+="("
# least recent elements on stack are earlier arguments # least recent elements on stack are earlier arguments
for (( i = n; i > 0; i-- )); do for (( _i = _n; _i > 0; _i-- )); do
line+=${stack[i]} _line+=${stack[_i]}
(( i > 1 )) && line+="," (( _i > 1 )) && _line+=","
done done
line+=")" _line+=")"
shift $n stack shift $_n stack
eval "(( ans = $line ))" 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
;; ;;
esac esac
else else
matched=0 _matched=0
fi fi
if (( ! matched )); then if (( ! _matched )); then
# Latest value is stored` as a string, because it might be floating # Latest value is stored` as a string, because it might be floating
# point or integer --- we don't know till after the evaluation, and # point or integer --- we don't know till after the evaluation, and
# arrays always store scalars anyway. # arrays always store scalars anyway.
# #
# Since it's a string, we'd better make sure we know which # Since it's a string, we'd better make sure we know which
# base it's in, so don't change that until we actually print it. # base it's in, so don't change that until we actually print it.
eval "ans=\$(( $line ))" if ! eval "ans=\$(( $_line ))"; then
# on error $ans is not set; let user re-edit line _line=
continue
fi
# on error $ans is not set; let user re-edit _line
[[ -n $ans ]] || continue [[ -n $ans ]] || continue
fi fi
argv[num++]=$ans argv[_num++]=$ans
psvar[1]=$num psvar[1]=$_num
(( push )) && stack=($ans $stack) (( _push )) && stack=($ans $stack)
;; ;;
esac esac
if (( show_stack )); then if (( _show_stack )); then
(( max_stack = (show_stack > ${#stack}) ? ${#stack} : show_stack )) (( _max_stack = (_show_stack > ${#stack}) ? ${#stack} : _show_stack ))
for (( i = max_stack; i > 0; i-- )); do for (( _i = _max_stack; _i > 0; _i-- )); do
printf "%3d: " $i printf "%3d: " $_i
zcalc_show_value ${stack[i]} zcalc_show_value ${stack[_i]}
done done
else else
zcalc_show_value $ans zcalc_show_value $ans
fi fi
line= _line=
done done
return 0 return 0