From c7edb354c78717e369230401f09de0199d56cf4a Mon Sep 17 00:00:00 2001 From: Kamil Dudka Date: Wed, 27 Jan 2016 10:35:08 +0100 Subject: 37814: run-help-ip: use an absolute path for the shebang. --- Functions/Misc/run-help-ip | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Functions/Misc') diff --git a/Functions/Misc/run-help-ip b/Functions/Misc/run-help-ip index 3f15b01fb..740af52b5 100644 --- a/Functions/Misc/run-help-ip +++ b/Functions/Misc/run-help-ip @@ -1,4 +1,4 @@ -#! zsh -f +#!/bin/zsh -f # # Install this function by placing it in your FPATH and then # adding to your .zshrc the line if you use run-help function: -- cgit v1.2.3 From 4cacf1624f0393c43a9a2c3259957b8d78eb7609 Mon Sep 17 00:00:00 2001 From: Peter Stephenson Date: Thu, 16 Jun 2016 11:39:42 +0100 Subject: 38693: Add RPN mode to zcalc --- ChangeLog | 3 + Doc/Zsh/contrib.yo | 42 ++++++++++++- Functions/Misc/zcalc | 136 +++++++++++++++++++++++++++++++++------- Functions/Zle/zcalc-auto-insert | 3 +- 4 files changed, 160 insertions(+), 24 deletions(-) (limited to 'Functions/Misc') diff --git a/ChangeLog b/ChangeLog index b567cf6f0..2ac9ceb63 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,8 @@ 2016-06-16 Peter Stephenson + * 38693: Doc/Zsh/contrib.yo, Functions/Misc/zcalc, + Functions/Zle/zcalc-auto-insert: Add RPN mode to zcalc. + * unposted: Doc/Zsh/params.yo: fix parentheses for getrusage(). 2016-06-16 Jun-ichi Takimoto diff --git a/Doc/Zsh/contrib.yo b/Doc/Zsh/contrib.yo index 2164c04c9..64d93f9dc 100644 --- a/Doc/Zsh/contrib.yo +++ b/Doc/Zsh/contrib.yo @@ -2993,6 +2993,9 @@ the variable tt(ZCALC_AUTO_INSERT_PREFIX). Hence, for example, typing `tt(PLUS()12)' followed by return adds 12 to the previous result. +If zcalc is in RPN mode (tt(-r) option) the effect of this binding is +automatically suppressed as operators alone on a line are meaningful. + When not in zcalc, the key simply inserts the symbol itself. ) enditem() @@ -3706,7 +3709,7 @@ sect(Mathematical Functions) startitem() findex(zcalc) -item(tt(zcalc) [ tt(-ef) ] [ var(expression) ... ])( +item(tt(zcalc) [ tt(-erf) ] [ var(expression) ... ])( A reasonably powerful calculator based on zsh's arithmetic evaluation facility. The syntax is similar to that of formulae in most programming languages; see @@ -3772,6 +3775,39 @@ If the option `tt(-f)' is set, all numbers are treated as floating point, hence for example the expression `tt(3/4)' evaluates to 0.75 rather than 0. Options must appear in separate words. +If the option `tt(-r)' is set, RPN (Reverse Polish Notation) mode is +entered. This has various additional properties: +startitem() +item(Stack)( +Evaluated values are maintained in a stack; this is contained in +an array named tt(stack) with the most recent value in tt(${stack[1]}). +) +item(Operators and functions)( +If the line entered matches an operator (tt(+), tt(-), tt(*), +tt(/), tt(**), tt(^), tt(|) or tt(&)) or a function supplied by the +tt(zsh/mathfunc) library, the bottom element or elements of the stack +are popped to use as the argument or arguments. The higher elements +of stack (least recent) are used as earlier arguments. The result is +then pushed into tt(${stack[1]}). +) +item(Expressions)( +Other expressions are evaluated normally, printed, and added to the +stack as numeric values. The syntax within expressions on a single line +is normal shell arithmetic (not RPN). +) +item(Stack listing)( +If an integer follows the option tt(-r) with no space, then +on every evaluation that many elements of the stack, where available, +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 +are printed. +) +item(Duplication)( +The pseudo-operator tt(=) causes the most recent element of +the stack to be duplicated onto the stack. +) +enditem() + The prompt is configurable via the parameter tt(ZCALCPROMPT), which undergoes standard prompt expansion. The index of the current entry is stored locally in the first element of the array tt(psvar), which can be @@ -3844,6 +3880,10 @@ always specified in decimal. `tt([#])' restores the normal output format. Note that setting an output base suppresses floating point output; use `tt([#])' to return to normal operation. ) +item(tt($)var(var))( +Print out the value of var literally; does not affect the calculation. +To use the value of var, omit the leading `tt($)'. +) enditem() See the comments in the function for a few extra tips. diff --git a/Functions/Misc/zcalc b/Functions/Misc/zcalc index 857007a94..eb240b2ec 100644 --- a/Functions/Misc/zcalc +++ b/Functions/Misc/zcalc @@ -96,6 +96,20 @@ emulate -L zsh setopt extendedglob +zcalc_show_value() { + if [[ -n $base ]]; then + print -- $(( $base $1 )) + elif [[ $1 = *.* ]] || (( outdigits )); then + if [[ -z $forms[outform] ]]; then + print -- $(( $1 )) + else + printf "$forms[outform]\n" $outdigits $1 + fi + else + printf "%d\n" $1 + fi +} + # For testing in ZLE functions. local ZCALC_ACTIVE=1 @@ -103,15 +117,20 @@ local ZCALC_ACTIVE=1 # begin with _. local line ans base defbase forms match mbegin mend psvar optlist opt arg local compcontext="-zcalc-line-" -integer num outdigits outform=1 expression_mode -local -a expressions +integer num outdigits outform=1 expression_mode rpn_mode matched show_stack i +integer max_stack +local -a expressions stack match mbegin mend # We use our own history file with an automatic pop on exit. history -ap "${ZDOTDIR:-$HOME}/.zcalc_history" forms=( '%2$g' '%.*g' '%.*f' '%.*E' '') -zmodload -i zsh/mathfunc 2>/dev/null +local mathfuncs +if zmodload -i zsh/mathfunc 2>/dev/null; then + zmodload -P mathfuncs -FL zsh/mathfunc + mathfuncs="("${(j.|.)${mathfuncs##f:}}")" +fi autoload -Uz zmathfuncdef if (( ! ${+ZCALCPROMPT} )); then @@ -127,7 +146,7 @@ if [[ -f "${ZDOTDIR:-$HOME}/.zcalcrc" ]]; then fi # Process command line -while [[ -n $1 && $1 = -(|[#-]*|f|e) ]]; do +while [[ -n $1 && $1 = -(|[#-]*|f|e|r(<->|)) ]]; do optlist=${1[2,-1]} shift [[ $optlist = (|-) ]] && break @@ -158,6 +177,14 @@ while [[ -n $1 && $1 = -(|[#-]*|f|e) ]]; do (e) # Arguments are expressions (( expression_mode = 1 )); ;; + (r) # RPN mode. + (( rpn_mode = 1 )) + ZCALC_ACTIVE=rpn + if [[ $optlist = (#b)(<->)* ]]; then + (( show_stack = ${match[1]} )) + optlist=${optlist[${#match[1]}+1,-2]} + fi + ;; esac done done @@ -281,30 +308,95 @@ while (( expression_mode )) || continue ;; + (\$[[:IDENT:]]##) + # Display only, no calculation + line=${line##\$} + print -r -- ${(P)line} + line= + continue + ;; + (*) - # Latest value is stored as a string, because it might be floating - # point or integer --- we don't know till after the evaluation, and - # arrays always store scalars anyway. - # - # 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. - eval "ans=\$(( $line ))" - # on error $ans is not set; let user re-edit line - [[ -n $ans ]] || continue + line=${${line##[[:blank:]]##}%%[[:blank:]]##} + if (( rpn_mode )); then + matched=1 + case $line in + (=) + if (( ${#stack} < 1 )); then + print -r -- "${line}: not enough values on stack" >&2 + line= + continue + fi + ans=${stack[1]} + ;; + + (+|-|\^|\||\&|\*|\*\*|/) + # Operators with two arguments + if (( ${#stack} < 2 )); then + print -r -- "${line}: not enough values on stack" >&2 + line= + continue + fi + eval "(( ans = \${stack[2]} $line \${stack[1]} ))" + shift 2 stack + ;; + + (ldexp|jn|yn|scalb) + # Functions with two arguments + if (( ${#stack} < 2 )); then + print -r -- "${line}: not enough values on stack" >&2 + line= + continue + fi + eval "(( ans = ${line}(\${stack[2]},\${stack[1]}) ))" + shift 2 stack + ;; + + (${~mathfuncs}) + # Functions with a single argument. + # This is actually a superset, but we should have matched + # any that shouldn't be in it in previous cases. + if (( ${#stack} < 1 )); then + print -r -- "${line}: not enough values on stack" >&2 + line= + continue + fi + eval "(( ans = ${line}(\${stack[1]}) ))" + shift stack + ;; + + (*) + # Treat as expression evaluating to new value to go on stack. + matched=0 + ;; + esac + else + matched=0 + fi + if (( ! matched )); then + # Latest value is stored` as a string, because it might be floating + # point or integer --- we don't know till after the evaluation, and + # arrays always store scalars anyway. + # + # 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. + eval "ans=\$(( $line ))" + # on error $ans is not set; let user re-edit line + [[ -n $ans ]] || continue + fi argv[num++]=$ans psvar[1]=$num + stack=($ans $stack) ;; esac - if [[ -n $base ]]; then - print -- $(( $base $ans )) - elif [[ $ans = *.* ]] || (( outdigits )); then - if [[ -z $forms[outform] ]]; then - print -- $(( $ans )) - else - printf "$forms[outform]\n" $outdigits $ans - fi + if (( show_stack )); then + (( max_stack = (show_stack > ${#stack}) ? ${#stack} : show_stack )) + for (( i = max_stack; i > 0; i-- )); do + printf "%3d: " $i + zcalc_show_value ${stack[i]} + done else - printf "%d\n" $ans + zcalc_show_value $ans fi line= done diff --git a/Functions/Zle/zcalc-auto-insert b/Functions/Zle/zcalc-auto-insert index c9a5c8867..e1affd1c3 100644 --- a/Functions/Zle/zcalc-auto-insert +++ b/Functions/Zle/zcalc-auto-insert @@ -1,6 +1,7 @@ # Bind to a binary operator keystroke for use with zcalc +# Not useful in RPN mode. -if [[ -n $ZCALC_ACTIVE ]]; then +if [[ -n $ZCALC_ACTIVE && $ZCALC_ACTIVE != rpn ]]; then if [[ $CURSOR -eq 0 || $LBUFFER[-1] = "(" ]]; then LBUFFER+=${ZCALC_AUTO_INSERT_PREFIX:-"ans "} fi -- cgit v1.2.3 From 61a383ec4d21b90dc5ff138a76baf0a930b91c7a Mon Sep 17 00:00:00 2001 From: "Barton E. Schaefer" Date: Sat, 18 Jun 2016 16:18:52 -0700 Subject: unposted: zed needs localoptions noksharrays --- ChangeLog | 4 ++++ Functions/Misc/zed | 2 ++ 2 files changed, 6 insertions(+) (limited to 'Functions/Misc') diff --git a/ChangeLog b/ChangeLog index 4efaa1b22..e97c22b84 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2016-06-18 Barton E. Schaefer + + * unposted: Functions/Misc/zed: localoptions noksharrays + 2016-06-18 Oliver Kiddle * 38713: Completion/Unix/Type/_dates: don't add calendar matches diff --git a/Functions/Misc/zed b/Functions/Misc/zed index eb8f557ea..0ea90c7df 100644 --- a/Functions/Misc/zed +++ b/Functions/Misc/zed @@ -6,6 +6,8 @@ # Use ^X^W to save, ^C to abort. # Option -f: edit shell functions. (Also if called as fned.) +setopt localoptions noksharrays + local var opts zed_file_name # We do not want timeout while we are editing a file integer TMOUT=0 okargs=1 fun bind -- cgit v1.2.3 From 5103c85abb239a12a3d29da9b41515cd4af19a9f Mon Sep 17 00:00:00 2001 From: Peter Stephenson Date: Tue, 21 Jun 2016 16:34:55 +0100 Subject: 38736: various RPN mode enhancements for zcalc --- ChangeLog | 4 ++ Completion/Zsh/Type/_module_math_func | 2 +- Completion/Zsh/Type/_user_math_func | 2 +- Doc/Zsh/contrib.yo | 23 ++++++++++- Functions/Misc/zcalc | 78 +++++++++++++++++++++++++++++------ 5 files changed, 93 insertions(+), 16 deletions(-) (limited to 'Functions/Misc') diff --git a/ChangeLog b/ChangeLog index fd58e7aa6..4ca92814a 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,9 @@ 2016-06-21 Peter Stephenson + * 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 clauses terminating with ;&. diff --git a/Completion/Zsh/Type/_module_math_func b/Completion/Zsh/Type/_module_math_func index 4df8d9714..6be9c006a 100644 --- a/Completion/Zsh/Type/_module_math_func +++ b/Completion/Zsh/Type/_module_math_func @@ -6,4 +6,4 @@ local -a funcs funcs=(${${${(f)"$(zmodload -Fl zsh/mathfunc 2>/dev/null)"}:#^+f:*}##+f:}) _wanted module-math-functions expl 'math function from zsh/mathfunc' \ - compadd -S '(' "$@" -a funcs + compadd -S '(' -q "$@" -a funcs diff --git a/Completion/Zsh/Type/_user_math_func b/Completion/Zsh/Type/_user_math_func index 16774f70b..35a49d50e 100644 --- a/Completion/Zsh/Type/_user_math_func +++ b/Completion/Zsh/Type/_user_math_func @@ -6,4 +6,4 @@ local -a funcs funcs=(${${${(f)"$(functions -M)"}##functions -M }%% *}) _wanted user-math-functions expl 'user math function' \ - compadd -S '(' "$@" -a funcs + compadd -S '(' -q "$@" -a funcs diff --git a/Doc/Zsh/contrib.yo b/Doc/Zsh/contrib.yo index b9c1c0a80..c875c95da 100644 --- a/Doc/Zsh/contrib.yo +++ b/Doc/Zsh/contrib.yo @@ -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 are printed. ) -item(Duplication)( +item(Duplication: tt(=))( The pseudo-operator tt(=) causes the most recent element of 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() 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) -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(]))( This is not a special command, rather part of normal arithmetic diff --git a/Functions/Misc/zcalc b/Functions/Misc/zcalc index eb240b2ec..fa1a8f600 100644 --- a/Functions/Misc/zcalc +++ b/Functions/Misc/zcalc @@ -100,7 +100,8 @@ zcalc_show_value() { if [[ -n $base ]]; then print -- $(( $base $1 )) 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 )) else 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 # 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-" -integer num outdigits outform=1 expression_mode rpn_mode matched show_stack i -integer max_stack +integer num outdigits outform=1 expression_mode rpn_mode matched show_stack i n +integer max_stack push local -a expressions stack match mbegin mend # 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 mathfuncs="("${(j.|.)${mathfuncs##f:}}")" 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 if (( ! ${+ZCALCPROMPT} )); then @@ -298,6 +306,7 @@ while (( expression_mode )) || ((function|:f(unc(tion|)|))[[:blank:]]##(#b)([^[:blank:]]##)(|[[:blank:]]##([^[:blank:]]*))) zmathfuncdef $match[1] $match[3] + userfuncs[$match[1]]=${$(functions -Mm $match[1])[4]} line= continue ;; @@ -318,19 +327,38 @@ while (( expression_mode )) || (*) line=${${line##[[:blank:]]##}%%[[:blank:]]##} - if (( rpn_mode )); then + if [[ rpn_mode -ne 0 && $line != '' ]]; then + push=1 matched=1 case $line in - (=) + (\=|pop|\<[[:IDENT:]]#) if (( ${#stack} < 1 )); then print -r -- "${line}: not enough values on stack" >&2 line= continue fi - ans=${stack[1]} + case $line in + (=) + 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 ;; - (+|-|\^|\||\&|\*|\*\*|/) + (+|-|\^|\||\&|\*|/|\*\*|\>\>|\<\&2 @@ -341,15 +369,22 @@ while (( expression_mode )) || shift 2 stack ;; - (ldexp|jn|yn|scalb) + (ldexp|jn|yn|scalb|xy) # Functions with two arguments if (( ${#stack} < 2 )); then print -r -- "${line}: not enough values on stack" >&2 line= continue fi - eval "(( ans = ${line}(\${stack[2]},\${stack[1]}) ))" - shift 2 stack + if [[ $line = xy ]]; then + tmp=${stack[1]} + stack[1]=${stack[2]} + stack[2]=$tmp + push=0 + else + eval "(( ans = ${line}(\${stack[2]},\${stack[1]}) ))" + shift 2 stack + fi ;; (${~mathfuncs}) @@ -365,6 +400,25 @@ while (( expression_mode )) || 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. matched=0 @@ -386,7 +440,7 @@ while (( expression_mode )) || fi argv[num++]=$ans psvar[1]=$num - stack=($ans $stack) + (( push )) && stack=($ans $stack) ;; esac if (( show_stack )); then -- cgit v1.2.3 From 26c01f57113cc76e20ec562ffcec60a1ab9f8b1e Mon Sep 17 00:00:00 2001 From: Peter Stephenson Date: Tue, 21 Jun 2016 17:26:35 +0100 Subject: 38737: clean up zcalc variables. Undocumented variables now start with "_". --- ChangeLog | 3 + Doc/Zsh/contrib.yo | 17 ++- Functions/Misc/zcalc | 289 ++++++++++++++++++++++++++------------------------- 3 files changed, 163 insertions(+), 146 deletions(-) (limited to 'Functions/Misc') diff --git a/ChangeLog b/ChangeLog index 4ca92814a..b95b0fe31 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,8 @@ 2016-06-21 Peter Stephenson + * 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, Completion/Zsh/Type/_user_math_func, Doc/Zsh/contrib.yo, Functions/Misc/zcalc: various RPN mode enhancments for zcalc. diff --git a/Doc/Zsh/contrib.yo b/Doc/Zsh/contrib.yo index c875c95da..53ae96dad 100644 --- a/Doc/Zsh/contrib.yo +++ b/Doc/Zsh/contrib.yo @@ -3764,8 +3764,14 @@ first few positional parameters. A visual indication of this is given when the calculator starts. 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 -into the global namespace. +Parameter assignment is possible, but note that all parameters will be +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)', 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 `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. For backward compatibility, the colon may be omitted for certain 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(:!). ) item(tt(:local) var(arg) ...)( -Declare variables local to the function. Note that certain variables -are used by the function for its own purposes. Other variables +Declare variables local to the function. Other variables may be used, too, but they will be taken from or put into the global scope. ) diff --git a/Functions/Misc/zcalc b/Functions/Misc/zcalc index fa1a8f600..86b1e4a5b 100644 --- a/Functions/Misc/zcalc +++ b/Functions/Misc/zcalc @@ -97,14 +97,14 @@ emulate -L zsh setopt extendedglob zcalc_show_value() { - if [[ -n $base ]]; then - print -- $(( $base $1 )) - elif [[ $1 = *.* ]] || (( outdigits )); then + if [[ -n $_base ]]; then + print -- $(( $_base $1 )) + elif [[ $1 = *.* ]] || (( _outdigits )); then # 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 )) else - printf "$forms[outform]\n" $outdigits $1 + printf "$_forms[_outform]\n" $_outdigits $1 fi else printf "%d\n" $1 @@ -116,29 +116,31 @@ local ZCALC_ACTIVE=1 # TODO: make local variables that shouldn't be visible in expressions # 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-" -integer num outdigits outform=1 expression_mode rpn_mode matched show_stack i n -integer max_stack push -local -a expressions stack match mbegin mend +integer _num _outdigits _outform=1 _expression_mode +integer _rpn_mode _matched _show_stack _i _n +integer _max_stack _push +local -a _expressions stack # We use our own history file with an automatic pop on exit. 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 - zmodload -P mathfuncs -FL zsh/mathfunc - mathfuncs="("${(j.|.)${mathfuncs##f:}}")" + zmodload -P _mathfuncs -FL zsh/mathfunc + _mathfuncs="("${(j.|.)${_mathfuncs##f:}}")" fi -local -A userfuncs -for line in ${(f)"$(functions -M)"}; do - match=(${=line}) +local -A _userfuncs +for _line in ${(f)"$(functions -M)"}; do + match=(${=_line}) # get minimum number of arguments - userfuncs[${match[3]}]=${match[4]} + _userfuncs[${match[3]}]=${match[4]} done -line= +_line= autoload -Uz zmathfuncdef if (( ! ${+ZCALCPROMPT} )); then @@ -155,118 +157,118 @@ fi # Process command line while [[ -n $1 && $1 = -(|[#-]*|f|e|r(<->|)) ]]; do - optlist=${1[2,-1]} + _optlist=${1[2,-1]} shift - [[ $optlist = (|-) ]] && break - while [[ -n $optlist ]]; do - opt=${optlist[1]} - optlist=${optlist[2,-1]} - case $opt in + [[ $_optlist = (|-) ]] && break + while [[ -n $_optlist ]]; do + _opt=${_optlist[1]} + _optlist=${_optlist[2,-1]} + case $_opt in ('#') # Default base - if [[ -n $optlist ]]; then - arg=$optlist - optlist= + if [[ -n $_optlist ]]; then + _arg=$_optlist + _optlist= elif [[ -n $1 ]]; then - arg=$1 + _arg=$1 shift else print -- "-# requires an argument" >&2 return 1 fi - if [[ $arg != (|\#)[[:digit:]]## ]]; then + if [[ $_arg != (|\#)[[:digit:]]## ]]; then print -- "-# requires a decimal number as an argument" >&2 return 1 fi - defbase="[#${arg}]" + _defbase="[#${_arg}]" ;; (f) # Force floating point operation setopt forcefloat ;; (e) # Arguments are expressions - (( expression_mode = 1 )); + (( _expression_mode = 1 )); ;; (r) # RPN mode. - (( rpn_mode = 1 )) + (( _rpn_mode = 1 )) ZCALC_ACTIVE=rpn - if [[ $optlist = (#b)(<->)* ]]; then - (( show_stack = ${match[1]} )) - optlist=${optlist[${#match[1]}+1,-2]} + if [[ $_optlist = (#b)(<->)* ]]; then + (( _show_stack = ${match[1]} )) + _optlist=${_optlist[${#match[1]}+1,-2]} fi ;; esac done done -if (( expression_mode )); then - expressions=("$@") +if (( _expression_mode )); then + _expressions=("$@") argv=() fi -for (( num = 1; num <= $#; num++ )); do +for (( _num = 1; _num <= $#; _num++ )); do # Make sure all arguments have been evaluated. # The `$' before the second argv forces string rather than numeric # substitution. - (( argv[$num] = $argv[$num] )) - print "$num> $argv[$num]" + (( argv[$_num] = $argv[$_num] )) + print "$_num> $argv[$_num]" done -psvar[1]=$num -local prev_line cont_prompt -while (( expression_mode )) || - vared -cehp "${cont_prompt}${ZCALCPROMPT}" line; do - if (( expression_mode )); then - (( ${#expressions} )) || break - line=$expressions[1] - shift expressions +psvar[1]=$_num +local _prev_line _cont_prompt +while (( _expression_mode )) || + vared -cehp "${_cont_prompt}${ZCALCPROMPT}" _line; do + if (( _expression_mode )); then + (( ${#_expressions} )) || break + _line=$_expressions[1] + shift _expressions fi - if [[ $line = (|*[^\\])('\\')#'\' ]]; then - prev_line+=$line[1,-2] - cont_prompt="..." - line= + if [[ $_line = (|*[^\\])('\\')#'\' ]]; then + _prev_line+=$_line[1,-2] + _cont_prompt="..." + _line= continue fi - line="$prev_line$line" - prev_line= - cont_prompt= + _line="$_prev_line$_line" + _prev_line= + _cont_prompt= # Test whether there are as many open as close - # parentheses in the line so far. - if [[ ${#line//[^\(]} -gt ${#line//[^\)]} ]]; then - prev_line+=$line - cont_prompt="..." - line= + # parentheses in the _line so far. + if [[ ${#_line//[^\(]} -gt ${#_line//[^\)]} ]]; then + _prev_line+=$_line + _cont_prompt="..." + _line= continue fi - [[ -z $line ]] && break + [[ -z $_line ]] && break # special cases # Set default base if `[#16]' or `[##16]' etc. on its own. # Unset it if `[#]' or `[##]'. - if [[ $line = (#b)[[:blank:]]#('[#'(\#|)((<->|)(|_|_<->))']')[[:blank:]]#(*) ]]; then + if [[ $_line = (#b)[[:blank:]]#('[#'(\#|)((<->|)(|_|_<->))']')[[:blank:]]#(*) ]]; then if [[ -z $match[6] ]]; then if [[ -z $match[3] ]]; then - defbase= + _defbase= else - defbase=$match[1] + _defbase=$match[1] fi - print -s -- $line - print -- $(( ${defbase} ans )) - line= + print -s -- $_line + print -- $(( ${_defbase} ans )) + _line= continue else - base=$match[1] + _base=$match[1] fi else - base=$defbase + _base=$_defbase fi - print -s -- $line + print -s -- $_line - line="${${line##[[:blank:]]#}%%[[:blank:]]#}" - case "$line" in + _line="${${_line##[[:blank:]]#}%%[[:blank:]]#}" + case "$_line" in # Escapes begin with a colon (:(\\|)\!*) # shell escape: handle completion's habit of quoting the ! - eval ${line##:(\\|)\![[:blank:]]#} - line= + eval ${_line##:(\\|)\![[:blank:]]#} + _line= continue ;; @@ -276,83 +278,83 @@ while (( expression_mode )) || ;; ((:|)norm) # restore output format to default - outform=1 + _outform=1 ;; ((:|)sci[[:blank:]]#(#b)(<->)(#B)) - outdigits=$match[1] - outform=2 + _outdigits=$match[1] + _outform=2 ;; ((:|)fix[[:blank:]]#(#b)(<->)(#B)) - outdigits=$match[1] - outform=3 + _outdigits=$match[1] + _outform=3 ;; ((:|)eng[[:blank:]]#(#b)(<->)(#B)) - outdigits=$match[1] - outform=4 + _outdigits=$match[1] + _outform=4 ;; (:raw) - outform=5 + _outform=5 ;; ((:|)local([[:blank:]]##*|)) - eval $line - line= + eval $_line + _line= continue ;; ((function|:f(unc(tion|)|))[[:blank:]]##(#b)([^[:blank:]]##)(|[[:blank:]]##([^[:blank:]]*))) zmathfuncdef $match[1] $match[3] - userfuncs[$match[1]]=${$(functions -Mm $match[1])[4]} - line= + _userfuncs[$match[1]]=${$(functions -Mm $match[1])[4]} + _line= continue ;; (:*) print "Unrecognised escape" - line= + _line= continue ;; (\$[[:IDENT:]]##) # Display only, no calculation - line=${line##\$} - print -r -- ${(P)line} - line= + _line=${_line##\$} + print -r -- ${(P)_line} + _line= continue ;; (*) - line=${${line##[[:blank:]]##}%%[[:blank:]]##} - if [[ rpn_mode -ne 0 && $line != '' ]]; then - push=1 - matched=1 - case $line in + _line=${${_line##[[:blank:]]##}%%[[:blank:]]##} + if [[ _rpn_mode -ne 0 && $_line != '' ]]; then + _push=1 + _matched=1 + case $_line in (\=|pop|\<[[:IDENT:]]#) if (( ${#stack} < 1 )); then - print -r -- "${line}: not enough values on stack" >&2 - line= + print -r -- "${_line}: not enough values on stack" >&2 + _line= continue fi - case $line in + case $_line in (=) ans=${stack[1]} ;; (pop|\<) - push=0 + _push=0 shift stack ;; (\<[[:IDENT:]]##) - (( ${line##\<} = ${stack[1]} )) - push=0 + (( ${_line##\<} = ${stack[1]} )) + _push=0 shift stack ;; (*) print "BUG in special RPN functions" >&2 - line= + _line= continue ;; esac @@ -361,98 +363,101 @@ while (( expression_mode )) || (+|-|\^|\||\&|\*|/|\*\*|\>\>|\<\&2 - line= + print -r -- "${_line}: not enough values on stack" >&2 + _line= continue fi - eval "(( ans = \${stack[2]} $line \${stack[1]} ))" + eval "(( ans = \${stack[2]} $_line \${stack[1]} ))" shift 2 stack ;; (ldexp|jn|yn|scalb|xy) # Functions with two arguments if (( ${#stack} < 2 )); then - print -r -- "${line}: not enough values on stack" >&2 - line= + print -r -- "${_line}: not enough values on stack" >&2 + _line= continue fi - if [[ $line = xy ]]; then - tmp=${stack[1]} + if [[ $_line = xy ]]; then + _tmp=${stack[1]} stack[1]=${stack[2]} - stack[2]=$tmp - push=0 + stack[2]=$_tmp + _push=0 else - eval "(( ans = ${line}(\${stack[2]},\${stack[1]}) ))" + eval "(( ans = ${_line}(\${stack[2]},\${stack[1]}) ))" shift 2 stack fi ;; - (${~mathfuncs}) + (${~_mathfuncs}) # Functions with a single argument. # This is actually a superset, but we should have matched # any that shouldn't be in it in previous cases. if (( ${#stack} < 1 )); then - print -r -- "${line}: not enough values on stack" >&2 - line= + print -r -- "${_line}: not enough values on stack" >&2 + _line= continue fi - eval "(( ans = ${line}(\${stack[1]}) ))" + eval "(( ans = ${_line}(\${stack[1]}) ))" shift stack ;; - (${(kj.|.)~userfuncs}) + (${(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= + _n=${_userfuncs[$_line]} + if (( ${#stack} < n_ )); then + print -r -- "${_line}: not enough values ($_n) on stack" >&2 + _line= continue fi - line+="(" + _line+="(" # least recent elements on stack are earlier arguments - for (( i = n; i > 0; i-- )); do - line+=${stack[i]} - (( i > 1 )) && line+="," + for (( _i = _n; _i > 0; _i-- )); do + _line+=${stack[_i]} + (( _i > 1 )) && _line+="," done - line+=")" - shift $n stack - eval "(( ans = $line ))" + _line+=")" + shift $_n stack + eval "(( ans = $_line ))" ;; (*) # Treat as expression evaluating to new value to go on stack. - matched=0 + _matched=0 ;; esac else - matched=0 + _matched=0 fi - if (( ! matched )); then + if (( ! _matched )); then # Latest value is stored` as a string, because it might be floating # point or integer --- we don't know till after the evaluation, and # arrays always store scalars anyway. # # 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. - eval "ans=\$(( $line ))" - # on error $ans is not set; let user re-edit line + if ! eval "ans=\$(( $_line ))"; then + _line= + continue + fi + # on error $ans is not set; let user re-edit _line [[ -n $ans ]] || continue fi - argv[num++]=$ans - psvar[1]=$num - (( push )) && stack=($ans $stack) + argv[_num++]=$ans + psvar[1]=$_num + (( _push )) && stack=($ans $stack) ;; esac - if (( show_stack )); then - (( max_stack = (show_stack > ${#stack}) ? ${#stack} : show_stack )) - for (( i = max_stack; i > 0; i-- )); do - printf "%3d: " $i - zcalc_show_value ${stack[i]} + if (( _show_stack )); then + (( _max_stack = (_show_stack > ${#stack}) ? ${#stack} : _show_stack )) + for (( _i = _max_stack; _i > 0; _i-- )); do + printf "%3d: " $_i + zcalc_show_value ${stack[_i]} done else zcalc_show_value $ans fi - line= + _line= done return 0 -- cgit v1.2.3 From a7d5d239e6ab729515083a88cfaf955e078c1685 Mon Sep 17 00:00:00 2001 From: Peter Stephenson Date: Mon, 4 Jul 2016 12:08:14 +0100 Subject: 38783: zcalc tweaks for RPN mode. Make it more straightforward to exchange variables with stack. --- ChangeLog | 5 +++++ Doc/Zsh/contrib.yo | 16 ++++++++++++---- Functions/Misc/zcalc | 26 ++++++++++++++++++-------- 3 files changed, 35 insertions(+), 12 deletions(-) (limited to 'Functions/Misc') diff --git a/ChangeLog b/ChangeLog index 831ea4e69..952b240c6 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2016-07-04 Peter Stephenson + + * 38783: Doc/Zsh/contrib.yo, Functions/Misc/zcalc: tweaks for + variable and stack interation in RPN mode. + 2016-06-29 Oliver Kiddle * 38770: Src/Zle/zle_keymap.c, Src/Zle/zle_vi.c, Doc/Zsh/zle.yo, diff --git a/Doc/Zsh/contrib.yo b/Doc/Zsh/contrib.yo index f1208e843..d4a453849 100644 --- a/Doc/Zsh/contrib.yo +++ b/Doc/Zsh/contrib.yo @@ -3829,16 +3829,24 @@ 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. +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 variable with that name. The variable is +local to the tt(zcalc) function. ) 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. +causes the value of the variable with that name to be pushed +onto the stack. var(ident) may be an integer, in which +case the previous result with that number (as shown before +the tt(>) in th standard standard tt(zcalc) prompt) is put on the stack. ) item(Exchange: tt(xy))( The pseudo-function tt(xy) causes the most recent two elements of -the stack to be exchanged. +the stack to be exchanged. `tt(<>)' has the same effect. ) enditem() diff --git a/Functions/Misc/zcalc b/Functions/Misc/zcalc index 86b1e4a5b..480373345 100644 --- a/Functions/Misc/zcalc +++ b/Functions/Misc/zcalc @@ -94,7 +94,7 @@ # sequentially just as if read automatically. emulate -L zsh -setopt extendedglob +setopt extendedglob typesetsilent zcalc_show_value() { if [[ -n $_base ]]; then @@ -301,7 +301,7 @@ while (( _expression_mode )) || ;; ((:|)local([[:blank:]]##*|)) - eval $_line + eval ${_line##:} _line= continue ;; @@ -333,7 +333,11 @@ while (( _expression_mode )) || _push=1 _matched=1 case $_line in - (\=|pop|\<[[:IDENT:]]#) + (\<[[:IDENT:]]##) + ans=${(P)${_line##\<}} + ;; + + (\=|pop|\>[[:IDENT:]]#) if (( ${#stack} < 1 )); then print -r -- "${_line}: not enough values on stack" >&2 _line= @@ -343,12 +347,18 @@ while (( _expression_mode )) || (=) ans=${stack[1]} ;; - (pop|\<) + (pop|\>) _push=0 shift stack ;; - (\<[[:IDENT:]]##) - (( ${_line##\<} = ${stack[1]} )) + (\>[[:IDENT:]]##) + if [[ ${_line##\>} = (_*|stack|ans|PI|E) ]]; then + print "${_line##\>}: reserved variable" >&2 + _line= + continue + fi + local ${_line##\>} + (( ${_line##\>} = ${stack[1]} )) _push=0 shift stack ;; @@ -371,14 +381,14 @@ while (( _expression_mode )) || shift 2 stack ;; - (ldexp|jn|yn|scalb|xy) + (ldexp|jn|yn|scalb|xy|\<\>) # Functions with two arguments if (( ${#stack} < 2 )); then print -r -- "${_line}: not enough values on stack" >&2 _line= continue fi - if [[ $_line = xy ]]; then + if [[ $_line = (xy|\<\>) ]]; then _tmp=${stack[1]} stack[1]=${stack[2]} stack[2]=$_tmp -- cgit v1.2.3 From b3dba0f7c1e2accb18dcdb8d6329b4d6a8a568e8 Mon Sep 17 00:00:00 2001 From: "Barton E. Schaefer" Date: Sun, 17 Jul 2016 12:07:43 -0700 Subject: Relocate add-zle-hook-widget, everything else in Functions/Zle is a widget. --- ChangeLog | 2 + Functions/Misc/add-zle-hook-widget | 186 +++++++++++++++++++++++++++++++++++++ Functions/Zle/add-zle-hook-widget | 186 ------------------------------------- 3 files changed, 188 insertions(+), 186 deletions(-) create mode 100644 Functions/Misc/add-zle-hook-widget delete mode 100644 Functions/Zle/add-zle-hook-widget (limited to 'Functions/Misc') diff --git a/ChangeLog b/ChangeLog index bb33f16b2..8d75759ec 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,7 @@ 2016-07-17 Barton E. Schaefer + * unposted: Functions/Misc/add-zle-hook-widget: Move from Zle/. + * 38866: Doc/Zsh/contrib.yo: update add-zle-hook-widget for 38850. * 38866 (+ tweak 38872): Functions/Zle/add-zle-hook-widget: fix diff --git a/Functions/Misc/add-zle-hook-widget b/Functions/Misc/add-zle-hook-widget new file mode 100644 index 000000000..04be50478 --- /dev/null +++ b/Functions/Misc/add-zle-hook-widget @@ -0,0 +1,186 @@ +# Add to HOOK the given WIDGET +# +# HOOK is one of isearch-exit, isearch-update, line-pre-redraw, line-init, +# line-finish, history-line-set, keymap-select (the zle- prefix is allowed +# but not required). If a widget corresponding to HOOK already exists, it +# is preserved and called first in the new set of HOOK widgets. +# +# With -d, remove the WIDGET from the hook instead; deletes the hook +# linkage if it is empty. +# +# -D behaves like -d, but pattern characters are active in WIDGET, so +# any matching widget will be deleted from the hook. +# +# Without -d, if the WIDGET is not already defined, a function having the +# same name is marked for autoload; -U is passed down to autoload if that +# is given, as are -z and -k. (This is harmless if the function is +# already defined.) The WIDGET is then created with zle -N. +# +# The -L option lists the hooks and their associated widgets. + +() { # Preserve caller global option settings + +emulate -L zsh + +# This is probably more safeguarding than necessary +zmodload -e zsh/zle || return 1 +{ zmodload zsh/parameter && zmodload zsh/zleparameter } || { + print -u2 "Need parameter modules for zle hooks" + return 1 +} + +# Setup - create the base functions for hook widgets that call the others + +local -a hooktypes=( zle-isearch-exit zle-isearch-update + zle-line-pre-redraw zle-line-init zle-line-finish + zle-history-line-set zle-keymap-select ) +# Stash in zstyle to make it global +zstyle zle-hook types ${hooktypes#zle-} + +# Relying on multifuncdef option here +function azhw:${^hooktypes} { + local -a hook_widgets + local hook + # Values of these styles look like number:name + # and we run them in number order + zstyle -a $WIDGET widgets hook_widgets + for hook in "${(@)${(@on)hook_widgets[@]}#<->:}"; do + if [[ "$hook" = user:* ]]; then + # Preserve $WIDGET within the renamed widget + zle "$hook" -N "$@" + else + zle "$hook" -Nw "$@" + fi || return + done + return 0 +} + +# Redefine ourself with the setup left out + +function add-zle-hook-widget { + local -a hooktypes + zstyle -a zle-hook types hooktypes + + # This part copied from add-zsh-hook + local usage="Usage: $0 hook widgetname\nValid hooks are:\n $hooktypes" + + local opt + local -a autoopts + integer del list help + + while getopts "dDhLUzk" opt; do + case $opt in + (d) + del=1 + ;; + + (D) + del=2 + ;; + + (h) + help=1 + ;; + + (L) + list=1 + ;; + + ([Uzk]) + autoopts+=(-$opt) + ;; + + (*) + return 1 + ;; + esac + done + shift $(( OPTIND - 1 )) + + 1=${1#zle-} # Strip prefix not stored in zle-hook types style + + if (( list )); then + zstyle -L "zle-(${1:-${(@j:|:)hooktypes[@]}})" widgets + return $? + elif (( help || $# != 2 || ${hooktypes[(I)$1]} == 0 )); then + print -u$(( 2 - help )) $usage + return $(( 1 - help )) + fi + + local -aU extant_hooks + local hook="zle-$1" + local fn="$2" + + if (( del )); then + # delete, if hook is set + if zstyle -g extant_hooks "$hook" widgets; then + if (( del == 2 )); then + set -A extant_hooks ${extant_hooks[@]:#(<->:|)${~fn}} + else + set -A extant_hooks ${extant_hooks[@]:#(<->:|)$fn} + fi + # unset if no remaining entries + if (( ${#extant_hooks} )); then + zstyle "$hook" widgets "${extant_hooks[@]}" + else + zstyle -d "$hook" widgets + fi + fi + else + # Check whether attempting to add a widget named for the hook + if [[ "$fn" = "$hook" ]]; then + if [[ -n "${widgets[$fn]}" ]]; then + print -u2 "Cannot hook $fn to itself" + return 1 + fi + # No point in building the array until another is added + autoload "${autoopts[@]}" -- "$fn" + zle -N "$fn" + return 0 + fi + integer i=${#options[ksharrays]}-2 + zstyle -g extant_hooks "$hook" widgets + # Check for an existing widget, add it as the first hook + if [[ ${widgets[$hook]} != "user:azhw:$hook" ]]; then + if [[ -n ${widgets[$hook]} ]]; then + zle -A "$hook" "${widgets[$hook]}" + extant_hooks=(0:"${widgets[$hook]}" "${extant_hooks[@]}") + fi + zle -N "$hook" azhw:"$hook" + fi + # Add new widget only if not already in the hook list + if [[ -z ${(M)extant_hooks[@]:#(<->:|)$fn} ]]; then + # no index and not already hooked + # assign largest existing index plus 1 + i=${${(On@)${(@M)extant_hooks[@]#<->:}%:}[i]}+1 + else + return 0 + fi + extant_hooks+=("${i}:${fn}") + zstyle -- "$hook" widgets "${extant_hooks[@]}" + if [[ -z "${widgets[$fn]}" ]]; then + autoload "${autoopts[@]}" -- "$fn" + zle -N -- "$fn" + fi + if [[ -z "${widgets[$hook]}" ]]; then + zle -N "$hook" azhw:"$hook" + fi + fi +} + +} "$@" # Resume caller global options + +# Handle zsh autoloading conventions: +# - "file" appears last in zsh_eval_context when "source"-ing +# - "evalautofunc" appears with kshautoload set or autoload -k +# - "loadautofunc" appears with kshautoload unset or autoload -z +# - use of autoload +X cannot reliably be detected, use best guess +case "$zsh_eval_context" in +*file) ;; +*evalautofunc) ;; +*loadautofunc) add-zle-hook-widget "$@";; +*) [[ -o kshautoload ]] || add-zle-hook-widget "$@";; +esac +# Note fallback here is equivalent to the usual best-guess used by +# functions written for zsh before $zsh_eval_context was available +# so this case-statement is backward-compatible. diff --git a/Functions/Zle/add-zle-hook-widget b/Functions/Zle/add-zle-hook-widget deleted file mode 100644 index 04be50478..000000000 --- a/Functions/Zle/add-zle-hook-widget +++ /dev/null @@ -1,186 +0,0 @@ -# Add to HOOK the given WIDGET -# -# HOOK is one of isearch-exit, isearch-update, line-pre-redraw, line-init, -# line-finish, history-line-set, keymap-select (the zle- prefix is allowed -# but not required). If a widget corresponding to HOOK already exists, it -# is preserved and called first in the new set of HOOK widgets. -# -# With -d, remove the WIDGET from the hook instead; deletes the hook -# linkage if it is empty. -# -# -D behaves like -d, but pattern characters are active in WIDGET, so -# any matching widget will be deleted from the hook. -# -# Without -d, if the WIDGET is not already defined, a function having the -# same name is marked for autoload; -U is passed down to autoload if that -# is given, as are -z and -k. (This is harmless if the function is -# already defined.) The WIDGET is then created with zle -N. -# -# The -L option lists the hooks and their associated widgets. - -() { # Preserve caller global option settings - -emulate -L zsh - -# This is probably more safeguarding than necessary -zmodload -e zsh/zle || return 1 -{ zmodload zsh/parameter && zmodload zsh/zleparameter } || { - print -u2 "Need parameter modules for zle hooks" - return 1 -} - -# Setup - create the base functions for hook widgets that call the others - -local -a hooktypes=( zle-isearch-exit zle-isearch-update - zle-line-pre-redraw zle-line-init zle-line-finish - zle-history-line-set zle-keymap-select ) -# Stash in zstyle to make it global -zstyle zle-hook types ${hooktypes#zle-} - -# Relying on multifuncdef option here -function azhw:${^hooktypes} { - local -a hook_widgets - local hook - # Values of these styles look like number:name - # and we run them in number order - zstyle -a $WIDGET widgets hook_widgets - for hook in "${(@)${(@on)hook_widgets[@]}#<->:}"; do - if [[ "$hook" = user:* ]]; then - # Preserve $WIDGET within the renamed widget - zle "$hook" -N "$@" - else - zle "$hook" -Nw "$@" - fi || return - done - return 0 -} - -# Redefine ourself with the setup left out - -function add-zle-hook-widget { - local -a hooktypes - zstyle -a zle-hook types hooktypes - - # This part copied from add-zsh-hook - local usage="Usage: $0 hook widgetname\nValid hooks are:\n $hooktypes" - - local opt - local -a autoopts - integer del list help - - while getopts "dDhLUzk" opt; do - case $opt in - (d) - del=1 - ;; - - (D) - del=2 - ;; - - (h) - help=1 - ;; - - (L) - list=1 - ;; - - ([Uzk]) - autoopts+=(-$opt) - ;; - - (*) - return 1 - ;; - esac - done - shift $(( OPTIND - 1 )) - - 1=${1#zle-} # Strip prefix not stored in zle-hook types style - - if (( list )); then - zstyle -L "zle-(${1:-${(@j:|:)hooktypes[@]}})" widgets - return $? - elif (( help || $# != 2 || ${hooktypes[(I)$1]} == 0 )); then - print -u$(( 2 - help )) $usage - return $(( 1 - help )) - fi - - local -aU extant_hooks - local hook="zle-$1" - local fn="$2" - - if (( del )); then - # delete, if hook is set - if zstyle -g extant_hooks "$hook" widgets; then - if (( del == 2 )); then - set -A extant_hooks ${extant_hooks[@]:#(<->:|)${~fn}} - else - set -A extant_hooks ${extant_hooks[@]:#(<->:|)$fn} - fi - # unset if no remaining entries - if (( ${#extant_hooks} )); then - zstyle "$hook" widgets "${extant_hooks[@]}" - else - zstyle -d "$hook" widgets - fi - fi - else - # Check whether attempting to add a widget named for the hook - if [[ "$fn" = "$hook" ]]; then - if [[ -n "${widgets[$fn]}" ]]; then - print -u2 "Cannot hook $fn to itself" - return 1 - fi - # No point in building the array until another is added - autoload "${autoopts[@]}" -- "$fn" - zle -N "$fn" - return 0 - fi - integer i=${#options[ksharrays]}-2 - zstyle -g extant_hooks "$hook" widgets - # Check for an existing widget, add it as the first hook - if [[ ${widgets[$hook]} != "user:azhw:$hook" ]]; then - if [[ -n ${widgets[$hook]} ]]; then - zle -A "$hook" "${widgets[$hook]}" - extant_hooks=(0:"${widgets[$hook]}" "${extant_hooks[@]}") - fi - zle -N "$hook" azhw:"$hook" - fi - # Add new widget only if not already in the hook list - if [[ -z ${(M)extant_hooks[@]:#(<->:|)$fn} ]]; then - # no index and not already hooked - # assign largest existing index plus 1 - i=${${(On@)${(@M)extant_hooks[@]#<->:}%:}[i]}+1 - else - return 0 - fi - extant_hooks+=("${i}:${fn}") - zstyle -- "$hook" widgets "${extant_hooks[@]}" - if [[ -z "${widgets[$fn]}" ]]; then - autoload "${autoopts[@]}" -- "$fn" - zle -N -- "$fn" - fi - if [[ -z "${widgets[$hook]}" ]]; then - zle -N "$hook" azhw:"$hook" - fi - fi -} - -} "$@" # Resume caller global options - -# Handle zsh autoloading conventions: -# - "file" appears last in zsh_eval_context when "source"-ing -# - "evalautofunc" appears with kshautoload set or autoload -k -# - "loadautofunc" appears with kshautoload unset or autoload -z -# - use of autoload +X cannot reliably be detected, use best guess -case "$zsh_eval_context" in -*file) ;; -*evalautofunc) ;; -*loadautofunc) add-zle-hook-widget "$@";; -*) [[ -o kshautoload ]] || add-zle-hook-widget "$@";; -esac -# Note fallback here is equivalent to the usual best-guess used by -# functions written for zsh before $zsh_eval_context was available -# so this case-statement is backward-compatible. -- cgit v1.2.3 From 74722c7392ae95069df6966b1194d3e10320f3de Mon Sep 17 00:00:00 2001 From: Daniel Shahaf Date: Wed, 27 Jul 2016 14:04:44 +0000 Subject: unposted: Prefix function's name to its error messages. --- ChangeLog | 3 +++ Functions/Misc/add-zle-hook-widget | 4 ++-- 2 files changed, 5 insertions(+), 2 deletions(-) (limited to 'Functions/Misc') diff --git a/ChangeLog b/ChangeLog index 15fe53b70..bf74cbe3c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,8 @@ 2016-07-27 Daniel Shahaf + * unposted: Functions/Misc/add-zle-hook-widget: Prefix function's + name to its error messages. + * unposted (after 38939): Completion/Unix/Command/_git: _git-rebase: Unbreak. diff --git a/Functions/Misc/add-zle-hook-widget b/Functions/Misc/add-zle-hook-widget index 04be50478..82a404d7a 100644 --- a/Functions/Misc/add-zle-hook-widget +++ b/Functions/Misc/add-zle-hook-widget @@ -25,7 +25,7 @@ emulate -L zsh # This is probably more safeguarding than necessary zmodload -e zsh/zle || return 1 { zmodload zsh/parameter && zmodload zsh/zleparameter } || { - print -u2 "Need parameter modules for zle hooks" + print -u2 "add-zle-hook-widget: Need parameter modules for zle hooks" return 1 } @@ -130,7 +130,7 @@ function add-zle-hook-widget { # Check whether attempting to add a widget named for the hook if [[ "$fn" = "$hook" ]]; then if [[ -n "${widgets[$fn]}" ]]; then - print -u2 "Cannot hook $fn to itself" + print -u2 "${0}: Cannot hook $fn to itself" return 1 fi # No point in building the array until another is added -- cgit v1.2.3 From 8e029323a76b48cdbeeb03045e2fc6348e2b060b Mon Sep 17 00:00:00 2001 From: Daniel Shahaf Date: Thu, 28 Jul 2016 18:01:36 +0000 Subject: unposted: Avoid $0 for POSIX_ARGZERO compatibility. --- ChangeLog | 6 ++++++ Functions/Misc/add-zle-hook-widget | 4 ++-- Functions/Misc/add-zsh-hook | 2 +- 3 files changed, 9 insertions(+), 3 deletions(-) (limited to 'Functions/Misc') diff --git a/ChangeLog b/ChangeLog index 1d68cf75d..9153ff197 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2016-07-28 Daniel Shahaf + + * unposted: Functions/Misc/add-zle-hook-widget, + Functions/Misc/add-zsh-hook: Avoid $0 for POSIX_ARGZERO + compatibility. + 2016-07-28 Oliver Kiddle * 38957: Functions/Zle/select-word-match, diff --git a/Functions/Misc/add-zle-hook-widget b/Functions/Misc/add-zle-hook-widget index 82a404d7a..c47d9a3cb 100644 --- a/Functions/Misc/add-zle-hook-widget +++ b/Functions/Misc/add-zle-hook-widget @@ -62,7 +62,7 @@ function add-zle-hook-widget { zstyle -a zle-hook types hooktypes # This part copied from add-zsh-hook - local usage="Usage: $0 hook widgetname\nValid hooks are:\n $hooktypes" + local usage="Usage: $funcstack[1] hook widgetname\nValid hooks are:\n $hooktypes" local opt local -a autoopts @@ -130,7 +130,7 @@ function add-zle-hook-widget { # Check whether attempting to add a widget named for the hook if [[ "$fn" = "$hook" ]]; then if [[ -n "${widgets[$fn]}" ]]; then - print -u2 "${0}: Cannot hook $fn to itself" + print -u2 "$funcstack[1]: Cannot hook $fn to itself" return 1 fi # No point in building the array until another is added diff --git a/Functions/Misc/add-zsh-hook b/Functions/Misc/add-zsh-hook index fc39659ae..3bc952e2f 100644 --- a/Functions/Misc/add-zsh-hook +++ b/Functions/Misc/add-zsh-hook @@ -19,7 +19,7 @@ hooktypes=( chpwd precmd preexec periodic zshaddhistory zshexit zsh_directory_name ) -local usage="Usage: $0 hook function\nValid hooks are:\n $hooktypes" +local usage="Usage: add-zsh-hook hook function\nValid hooks are:\n $hooktypes" local opt local -a autoopts -- cgit v1.2.3 From 70166178bdc7ea149eb1cd29bcdb549a392c46dd Mon Sep 17 00:00:00 2001 From: "Barton E. Schaefer" Date: Tue, 30 Aug 2016 20:31:21 -0700 Subject: 39131: return on error needs to be at the outer scope. --- ChangeLog | 5 +++++ Functions/Misc/add-zle-hook-widget | 8 ++++---- 2 files changed, 9 insertions(+), 4 deletions(-) (limited to 'Functions/Misc') diff --git a/ChangeLog b/ChangeLog index 866e2add1..2f8f5b7a9 100644 --- a/ChangeLog +++ b/ChangeLog @@ -3,6 +3,11 @@ * 39122: Completion/Unix/Command/_git: __git_recent_branches: Silence warning on an edge case. +2016-08-30 Barton E. Schaefer + + * 39131: Functions/Misc/add-zle-hook-widget: return on error + needs to be at the outer scope. + 2016-08-30 Daniel Shahaf * 39108: Completion/Unix/Command/_postfix: Support diff --git a/Functions/Misc/add-zle-hook-widget b/Functions/Misc/add-zle-hook-widget index c47d9a3cb..572de2561 100644 --- a/Functions/Misc/add-zle-hook-widget +++ b/Functions/Misc/add-zle-hook-widget @@ -18,10 +18,6 @@ # # The -L option lists the hooks and their associated widgets. -() { # Preserve caller global option settings - -emulate -L zsh - # This is probably more safeguarding than necessary zmodload -e zsh/zle || return 1 { zmodload zsh/parameter && zmodload zsh/zleparameter } || { @@ -29,6 +25,10 @@ zmodload -e zsh/zle || return 1 return 1 } +() { # Preserve caller global option settings + +emulate -L zsh + # Setup - create the base functions for hook widgets that call the others local -a hooktypes=( zle-isearch-exit zle-isearch-update -- cgit v1.2.3 From 4f2a1810f2fa1d74008e03a09d66eaff3e5edc9e Mon Sep 17 00:00:00 2001 From: Daniel Shahaf Date: Thu, 29 Sep 2016 09:50:09 +0000 Subject: 39495: add-zle-hook-widget: Add end-of-options guard to hook invocation. Currently, the only special widget that takes arguments is zle-keymap-select. --- ChangeLog | 3 +++ Doc/Zsh/contrib.yo | 2 +- Functions/Misc/add-zle-hook-widget | 4 ++-- 3 files changed, 6 insertions(+), 3 deletions(-) (limited to 'Functions/Misc') diff --git a/ChangeLog b/ChangeLog index 9df255631..b1b000025 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,8 @@ 2016-09-30 Daniel Shahaf + * 39495: Doc/Zsh/contrib.yo, Functions/Misc/add-zle-hook-widget: + add-zle-hook-widget: Add end-of-options guard to hook invocation. + * 39480: Completion/Debian/Command/_bug: _reportbug: Complete absolute filenames, too. diff --git a/Doc/Zsh/contrib.yo b/Doc/Zsh/contrib.yo index 63df292ac..189a084ba 100644 --- a/Doc/Zsh/contrib.yo +++ b/Doc/Zsh/contrib.yo @@ -346,7 +346,7 @@ as the var(hook) argument. var(widgetname) is the name of a ZLE widget. If no options are given this is added to the array of widgets to be invoked in the given hook context. Note that the hooks are called as widgets, that is, with -example(tt(zle )var(widgetname)tt( -Nw "$@")) +example(tt(zle )var(widgetname)tt( -Nw -- "$@")) vindex(WIDGET, in hooks) Note that this means that the `tt(WIDGET)' special parameter tracks the diff --git a/Functions/Misc/add-zle-hook-widget b/Functions/Misc/add-zle-hook-widget index 572de2561..d8a3950fb 100644 --- a/Functions/Misc/add-zle-hook-widget +++ b/Functions/Misc/add-zle-hook-widget @@ -47,9 +47,9 @@ function azhw:${^hooktypes} { for hook in "${(@)${(@on)hook_widgets[@]}#<->:}"; do if [[ "$hook" = user:* ]]; then # Preserve $WIDGET within the renamed widget - zle "$hook" -N "$@" + zle "$hook" -N -- "$@" else - zle "$hook" -Nw "$@" + zle "$hook" -Nw -- "$@" fi || return done return 0 -- cgit v1.2.3