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') 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 e54578ff74754b70e230106d292eb645f61176f1 Mon Sep 17 00:00:00 2001 From: "Barton E. Schaefer" Date: Sun, 14 Feb 2016 11:35:18 -0800 Subject: 37971: fix potential issues when interacting with user-defined widgets Cf. users/21284: Eric Freese --- ChangeLog | 4 ++++ Functions/Zle/bracketed-paste-magic | 4 ++-- 2 files changed, 6 insertions(+), 2 deletions(-) (limited to 'Functions') diff --git a/ChangeLog b/ChangeLog index 18e4eed59..a081f0ad4 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,9 @@ 2016-02-14 Barton E. Schaefer + * 37971 (cf. users/21284: Eric Freese): + Functions/Zle/bracketed-paste-magic: fix potential issues when + interacting with user-defined widgets + * 37961: Src/Zle/complist.c: in interactive menuselection, use of "compadd -x" (e.g. the "warnings" zstyle) may have replaced the completion list, so skip highlighting of the current selection diff --git a/Functions/Zle/bracketed-paste-magic b/Functions/Zle/bracketed-paste-magic index 2b2bc630d..498cf554d 100644 --- a/Functions/Zle/bracketed-paste-magic +++ b/Functions/Zle/bracketed-paste-magic @@ -175,7 +175,7 @@ bracketed-paste-magic() { case $REPLY in (${~bpm_active}) function () { emulate -L $bpm_emulate; set -$bpm_opts - zle $REPLY + zle $REPLY -w };; (*) zle .self-insert;; esac @@ -184,7 +184,7 @@ bracketed-paste-magic() { PASTED=$BUFFER # Reset the undo state - zle undo $bpm_undo + zle .undo $bpm_undo UNDO_LIMIT_NO=$bpm_limit zle -K $bpm_keymap -- cgit v1.2.3 From c5c2fa4fb5dbf242f94860ff5e2d40670560d0ae Mon Sep 17 00:00:00 2001 From: "Barton E. Schaefer" Date: Mon, 9 May 2016 08:27:52 -0700 Subject: unposted: update documentary comments to remove references to self-insert-unmeta. --- ChangeLog | 5 +++++ Functions/Zle/bracketed-paste-magic | 4 ++-- 2 files changed, 7 insertions(+), 2 deletions(-) (limited to 'Functions') diff --git a/ChangeLog b/ChangeLog index 9ddab6da6..0238e0664 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2016-05-09 Barton E. Schaefer + + * unposted: Functions/Zle/bracketed-paste-magic: update documentary + comments to remove references to self-insert-unmeta. + 2016-05-09 Frank Terbeck * 38422: Completion/Unix/Type/_baudrate, diff --git a/Functions/Zle/bracketed-paste-magic b/Functions/Zle/bracketed-paste-magic index 498cf554d..cafe18ed7 100644 --- a/Functions/Zle/bracketed-paste-magic +++ b/Functions/Zle/bracketed-paste-magic @@ -20,7 +20,7 @@ # active-widgets # Looked up in the context :bracketed-paste-magic to obtain a list of # patterns that match widget names that should be activated during the -# paste. All other key sequences are processed as self-insert-unmeta. +# paste. All other key sequences are processed as "zle .self-insert". # The default is 'self-*' so any user-defined widgets named with that # prefix are active along with the builtin self-insert. If this style is # not set (note: it must be explicitly deleted after loading this @@ -31,7 +31,7 @@ # # inactive-keys # This is the inverse of active-widgets, it lists key sequences that -# always use self-insert-unmeta even when bound to an active-widget. +# always use "zle .self-insert" even when bound to an active-widget. # Note that this is a list of literal key sequences, not patterns. # This style is in context :bracketed-paste-magic and has no default. # -- cgit v1.2.3 From 29e88b3ea3e13c7c86c707b6119cadad669e55aa Mon Sep 17 00:00:00 2001 From: Daniel Shahaf Date: Tue, 10 May 2016 01:31:52 +0000 Subject: unposted: Commit forgotten part of users/21256. --- ChangeLog | 3 +++ Functions/Math/.distfiles | 2 ++ Functions/Math/zmathfunc | 34 ++++++++++++++++++++++++++++++++++ 3 files changed, 39 insertions(+) create mode 100644 Functions/Math/.distfiles create mode 100644 Functions/Math/zmathfunc (limited to 'Functions') diff --git a/ChangeLog b/ChangeLog index 2abb44b42..5caeeccef 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,8 @@ 2016-05-10 Daniel Shahaf + * unposted: Functions/Math/.distfiles, Functions/Math/zmathfunc: + Commit forgotten part of users/21256. + * 38453: Completion/Debian/Command/_apt: Complete ${package}/${release} for 'source' and 'build-dep', too. diff --git a/Functions/Math/.distfiles b/Functions/Math/.distfiles new file mode 100644 index 000000000..f03668b3a --- /dev/null +++ b/Functions/Math/.distfiles @@ -0,0 +1,2 @@ +DISTFILES_SRC=' +' diff --git a/Functions/Math/zmathfunc b/Functions/Math/zmathfunc new file mode 100644 index 000000000..4ff40700d --- /dev/null +++ b/Functions/Math/zmathfunc @@ -0,0 +1,34 @@ +#autoload + +zsh_math_func_min() { + local result=$1 + shift + local arg + for arg ; do + (( $arg < result )) && result=$arg + done + (( result )) # return +} +functions -M min 1 -1 zsh_math_func_min # at least one argument + +zsh_math_func_max() { + local result=$1 + shift + local arg + for arg ; do + (( $arg > result )) && result=$arg + done + (( result )) # return +} +functions -M max 1 -1 zsh_math_func_max # at least one argument + +zsh_math_func_sum() { + local sum + local arg + for arg ; do + (( sum += $arg )) + done + (( sum )) +} +functions -M sum 0 -1 zsh_math_func_sum + -- cgit v1.2.3 From e8943e7007d27143d17cf66acf659e92fcea1fe9 Mon Sep 17 00:00:00 2001 From: Daniel Shahaf Date: Sat, 4 Jun 2016 16:57:48 +0000 Subject: 38609: vcs_info quilt: Factor out a helper function. No functional change. --- ChangeLog | 5 +++++ Functions/VCS_Info/VCS_INFO_quilt | 35 ++++++++++++++++++++++------------- 2 files changed, 27 insertions(+), 13 deletions(-) (limited to 'Functions') diff --git a/ChangeLog b/ChangeLog index d79ebc235..5f0cae6ce 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2016-06-06 Daniel Shahaf + + * 38609: Functions/VCS_Info/VCS_INFO_quilt: vcs_info quilt: + Factor out a helper function. No functional change. + 2016-06-05 Barton E. Schaefer * 38622: Src/jobs.c: consistent handling of "--" in "kill" builtin diff --git a/Functions/VCS_Info/VCS_INFO_quilt b/Functions/VCS_Info/VCS_INFO_quilt index c3c3d864d..e31deb0bd 100644 --- a/Functions/VCS_Info/VCS_INFO_quilt +++ b/Functions/VCS_Info/VCS_INFO_quilt @@ -80,6 +80,23 @@ function VCS_INFO_quilt-dirfind() { return ${ret} } +# This function takes as an argument a filename of a patch and sets $REPLY to +# a single-line "subject", or unsets it if no subject could be extracted. +function VCS_INFO_quilt-patch2subject() { + local line + if [[ -f "$1" ]] && read -r line < "$1"; then + if [[ $line != (#b)(---|Index:)* ]]; then + REPLY=$line + else + unset REPLY + return 0 + fi + else + unset REPLY + return 1 + fi +} + function VCS_INFO_quilt() { emulate -L zsh setopt extendedglob @@ -147,27 +164,19 @@ function VCS_INFO_quilt() { if [[ -n $patches ]]; then () { - local i line + local i for ((i=1; i<=$#applied; i++)); do - if [[ -f "$patches/$applied[$i]" ]] && - read -r line < "$patches/$applied[$i]" && - [[ $line != (#b)(---|Index:)* ]] && - true - ; + if VCS_INFO_quilt-patch2subject "$patches/$applied[$i]" && (( $+REPLY )) then - applied[$i]+=" $line" + applied[$i]+=" $REPLY" else applied[$i]+=" ?" fi done for ((i=1; i<=$#unapplied; i++)); do - if [[ -f "$patches/$unapplied[$i]" ]] && - read -r line < "$patches/$unapplied[$i]" && - [[ $line != (#b)(---|Index:)* ]] && - true - ; + if VCS_INFO_quilt-patch2subject "$patches/$unapplied[$i]" && (( $+REPLY )) then - unapplied[$i]+=" $line" + unapplied[$i]+=" $REPLY" else unapplied[$i]+=" ?" fi -- cgit v1.2.3 From 7a5ecf4909bb73550012c4b580f054a29a255380 Mon Sep 17 00:00:00 2001 From: Daniel Shahaf Date: Sat, 4 Jun 2016 16:57:49 +0000 Subject: 38610: vcs_info quilt: Extract a patch subject, 2.0. --- ChangeLog | 3 +++ Functions/VCS_Info/VCS_INFO_quilt | 42 +++++++++++++++++++++++++++++++++++---- 2 files changed, 41 insertions(+), 4 deletions(-) (limited to 'Functions') diff --git a/ChangeLog b/ChangeLog index 5f0cae6ce..5ff60c6f2 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,8 @@ 2016-06-06 Daniel Shahaf + * 38610: Functions/VCS_Info/VCS_INFO_quilt: vcs_info quilt: + Extract a patch subject, 2.0. + * 38609: Functions/VCS_Info/VCS_INFO_quilt: vcs_info quilt: Factor out a helper function. No functional change. diff --git a/Functions/VCS_Info/VCS_INFO_quilt b/Functions/VCS_Info/VCS_INFO_quilt index e31deb0bd..e7cd89f78 100644 --- a/Functions/VCS_Info/VCS_INFO_quilt +++ b/Functions/VCS_Info/VCS_INFO_quilt @@ -83,15 +83,49 @@ function VCS_INFO_quilt-dirfind() { # This function takes as an argument a filename of a patch and sets $REPLY to # a single-line "subject", or unsets it if no subject could be extracted. function VCS_INFO_quilt-patch2subject() { - local line - if [[ -f "$1" ]] && read -r line < "$1"; then - if [[ $line != (#b)(---|Index:)* ]]; then - REPLY=$line + integer i + integer -r LIMIT=10 + local -a lines + local needle + if [[ -f "$1" ]]; then + # Extract the first LIMIT lines, or up to the first empty line or the start of the unidiffs, + # whichever comes first. + while (( i++ < LIMIT )); do + IFS= read -r "lines[$i]" + if [[ -z ${lines[$i]} ]] || [[ ${lines[$i]} == (#b)(---|Index:)* ]]; then + lines[$i]=() + break + fi + done < "$1" + + if needle=${lines[(i)Subject:*]}; (( needle <= $#lines )); then + # "Subject: foo" line, plus rfc822 whitespace unfolding. + # + # Example: 'git format-patch' patches. + REPLY=${lines[needle]} + REPLY=${REPLY#*: } + REPLY=${REPLY#\[PATCH\] } + while [[ ${${lines[++needle]}[1]} == ' ' ]]; do + REPLY+=${lines[needle]} + done + elif needle=${lines[(r)Description:*]}; [[ -n $needle ]]; then + # "Description: foo" line. + # + # Example: DEP-3 patches. + REPLY=${needle#*: } + elif [[ ${lines[1]} == '# HG changeset patch' ]] && { needle=${${lines:#([#]*)}[1]}; [[ -n $needle ]] }; then + # Mercurial patch + REPLY=$needle + elif (( ${+lines[1]} )); then + # The first line of the file is not part of the diff. + REPLY=${lines[1]} else + # The patch has no subject. unset REPLY return 0 fi else + # The patch cannot be examined, or invalid arguments. unset REPLY return 1 fi -- cgit v1.2.3 From 20948d088994dc7b26a26b94926432985fa6863e Mon Sep 17 00:00:00 2001 From: Oliver Kiddle Date: Thu, 9 Jun 2016 22:58:45 +0200 Subject: 38579: simplify saving and restoring of state --- ChangeLog | 3 +++ Functions/Zle/bracketed-paste-magic | 44 ++++++++++++++++--------------------- 2 files changed, 22 insertions(+), 25 deletions(-) (limited to 'Functions') diff --git a/ChangeLog b/ChangeLog index 5063796f8..8c8a08948 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,8 @@ 2016-06-09 Oliver Kiddle + * 38579: Functions/Zle/bracketed-paste-magic: simplify saving + and restoring of state + * 38641: Completion/Base/Utility/_values: allow for values which resemble compadd options diff --git a/Functions/Zle/bracketed-paste-magic b/Functions/Zle/bracketed-paste-magic index cafe18ed7..cf3cc6a59 100644 --- a/Functions/Zle/bracketed-paste-magic +++ b/Functions/Zle/bracketed-paste-magic @@ -145,27 +145,26 @@ bracketed-paste-magic() { done fi - # Save context, create a clean slate for the paste - integer bpm_mark=$MARK bpm_cursor=$CURSOR bpm_region=$REGION_ACTIVE - integer bpm_numeric=${NUMERIC:-1} - local bpm_buffer=$BUFFER - fc -p -a /dev/null 0 0 - BUFFER= - zstyle -a :bracketed-paste-magic inactive-keys bpm_inactive if zstyle -s :bracketed-paste-magic active-widgets bpm_active '|'; then - # There are active widgets. Reprocess $PASTED as keystrokes. - NUMERIC=1 - zle -U - $PASTED - + # Save context, create a clean slate for the paste + integer bpm_mark=$MARK bpm_region=$REGION_ACTIVE + integer bpm_numeric=${NUMERIC:-1} + integer bpm_limit=$UNDO_LIMIT_NO bpm_undo=$UNDO_CHANGE_NO + BUFFER= + CURSOR=1 + zle .split-undo + UNDO_LIMIT_NO=$UNDO_CHANGE_NO + fc -p -a /dev/null 0 0 if [[ $bmp_keymap = vicmd ]]; then zle -K viins fi + # There are active widgets. Reprocess $PASTED as keystrokes. + NUMERIC=1 + zle -U - $PASTED + # Just in case there are active undo widgets - zle .split-undo - integer bpm_limit=$UNDO_LIMIT_NO bpm_undo=$UNDO_CHANGE_NO - UNDO_LIMIT_NO=$UNDO_CHANGE_NO while [[ -n $PASTED ]] && zle .read-command; do PASTED=${PASTED#$KEYS} @@ -183,21 +182,16 @@ bracketed-paste-magic() { done PASTED=$BUFFER - # Reset the undo state + # Restore state + zle -K $bpm_keymap + fc -P + MARK=$bpm_mark + REGION_ACTIVE=$bpm_region + NUMERIC=$bpm_numeric zle .undo $bpm_undo UNDO_LIMIT_NO=$bpm_limit - - zle -K $bpm_keymap fi - # Restore state - BUFFER=$bpm_buffer - MARK=$bpm_mark - CURSOR=$bpm_cursor - REGION_ACTIVE=$bpm_region - NUMERIC=$bpm_numeric - fc -P - # PASTED has been updated, run the paste-finish functions if zstyle -a :bracketed-paste-magic paste-finish bpm_hooks; then for bpm_func in $bpm_hooks; do -- cgit v1.2.3 From 8e2ec4517fcce11475d579abb827d851f858d9aa Mon Sep 17 00:00:00 2001 From: "Barton E. Schaefer" Date: Sun, 12 Jun 2016 18:50:10 -0700 Subject: 38670: New function for managing ZLE special widgets, modeled after Functions/Misc/add-zsh-hook. --- ChangeLog | 6 ++ Doc/Zsh/contrib.yo | 56 ++++++++++++++- Functions/Zle/add-zle-hook-widget | 140 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 200 insertions(+), 2 deletions(-) create mode 100644 Functions/Zle/add-zle-hook-widget (limited to 'Functions') diff --git a/ChangeLog b/ChangeLog index 8c8a08948..8952bd009 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2016-06-12 Barton E. Schaefer + + * 38670: Doc/Zsh/contrib.yo, Functions/Zle/add-zle-hook-widget: + New function for managing ZLE special widgets, modeled after + Functions/Misc/add-zsh-hook. + 2016-06-09 Oliver Kiddle * 38579: Functions/Zle/bracketed-paste-magic: simplify saving diff --git a/Doc/Zsh/contrib.yo b/Doc/Zsh/contrib.yo index 923bb29a9..dd643a140 100644 --- a/Doc/Zsh/contrib.yo +++ b/Doc/Zsh/contrib.yo @@ -292,11 +292,11 @@ cindex(hook function utility) startitem() findex(add-zsh-hook) -item(tt(add-zsh-hook) [ tt(-dD) ] [ tt(-Uzk) ] var(hook) var(function))( +item(tt(add-zsh-hook) [ tt(-L) | tt(-dD) ] [ tt(-Uzk) ] var(hook) var(function))( Several functions are special to the shell, as described in the section ifnzman(Special Functions, noderef(Functions))\ ifzman(SPECIAL FUNCTIONS, see zmanref(zshmisc)), -in that they are automatic called at a specific point during shell execution. +in that they are automatically called at specific points during shell execution. Each has an associated array consisting of names of functions to be called at the same point; these are so-called `hook functions'. The shell function tt(add-zsh-hook) provides a simple way of adding or @@ -312,6 +312,9 @@ var(function) is name of an ordinary shell function. If no options are given this will be added to the array of functions to be executed in the given context. +If the option tt(-L) is given, the current values for the hook arrays +are listed with tt(typeset). + If the option tt(-d) is given, the var(function) is removed from the array of functions to be executed. @@ -323,6 +326,55 @@ The options tt(-U), tt(-z) and tt(-k) are passed as arguments to tt(autoload) for var(function). For functions contributed with zsh, the options tt(-Uz) are appropriate. ) +findex(add-zle-hook-widget) +item(tt(add-zle-hook-widget) [ tt(-L) | tt(-dD) ] [ tt(-Uzk) ] var(hook) var(widgetname))( +Several widget names are special to the line editor, as described in the section +ifnzman(Special Widgets, noderef(Zle Widgets))\ +ifzman(Special Widgets, see zmanref(zshzle)), +in that they are automatically called at specific points during editing. +Unlike function hooks, these do not use a predefined array of other names +to call at the same point; the shell function tt(add-zle-hook-widget) +maintains a similar array and arranges for the special widget to invoke +those additional widgets. + +var(hook) is one of tt(isearch-exit), tt(isearch-update), +tt(line-pre-redraw), tt(line-init), tt(line-finish), tt(history-line-set), +or tt(keymap-select), corresponding to each of the special widgets +tt(zle-isearch-exit), etc. + +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 +`tt(zle var(widgetname) -Nw)' rather than as a function call. + +The arrays of var(widgetname) are maintained in several tt(zstyle) +contexts, one for each var(hook) context, with a style of `tt(widgets)'. +If the tt(-L) option is given, this set of styles is listed with +`tt(zstyle -L)'. These styles may be updated directly with tt(zstyle) +commands, but the special widgets that refer to the styles are created +only if tt(add-zle-hook-widget) is called to add at least one widget. + +If the option tt(-d) is given, the var(widgename) is removed from +the array of widgets to be executed. + +If the option tt(-D) is given, the var(widgetname) is treated as a pattern +and any matching names of widgets are removed from the array. + +If var(widgetname) does not name an existing widget when added to the +array, it is assumed that a shell function also named var(widgetname) is +meant to provide the implementation of the widget. This name is therefore +marked for autoloading, and the options tt(-U), tt(-z) and tt(-k) are +passed as arguments to tt(autoload) as with tt(add-zsh-hook). The +widget is also created with `tt(zle -N var(widgetname))' to cause the +corresponding function to be loaded the first time the hook is called. + +In addition, var(widgetname) may be of the form var(index)tt(:)var(name). +In this case var(index) is an integer which determines the order in +which the widget var(name) will be called relative to other widgets in +the array. Widgets having the same var(index) are called in unspecified +order, and all widgets declared with an index are called before any +widgets that have no index. +) enditem() texinode(Recent Directories)(Other Directory Functions)(Utilities)(User Contributions) diff --git a/Functions/Zle/add-zle-hook-widget b/Functions/Zle/add-zle-hook-widget new file mode 100644 index 000000000..eeb0191f0 --- /dev/null +++ b/Functions/Zle/add-zle-hook-widget @@ -0,0 +1,140 @@ +# 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 not +# required). +# +# WIDGET may be of the form INDEX:NAME in which case the INDEX determines +# the order in which the widget executes relative to other hook widgets. +# +# With -d, remove the widget from the hook instead; delete the hook +# variable if it is empty. +# +# -D behaves like -d, but pattern characters are active in the +# widget name, 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. + +emulate -L zsh + +# Setup - create the base functions for hook widgets that call the others + +zmodload zsh/parameter || { + print -u2 "Need parameter module for zle hooks" + return 1 +} + +local -a hooktypes=( isearch-exit isearch-update + line-pre-redraw line-init line-finish + history-line-set keymap-select ) +# Stash in zstyle to make it global +zstyle zle-hook types $hooktypes + +for hook in $hooktypes +do + function zle-$hook { + local -a hook_widgets + local hook + # Values of these styles look like number:name + # and we run them in number order + # $funcstack is more reliable than $0 + # Also, ksh_arrays is annoying + emulate zsh -c 'zstyle -a $funcstack[2] widgets hook_widgets' + for hook in "${@${(@on)hook_widgets}#*:}" + do + zle "$hook" -Nw || return + done + return 0 + } +done + +# 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 )) + + if (( list )); then + zstyle -L "zle-(${1:-${(@j:|:)hooktypes}})" widgets + return $? + elif (( help || $# != 2 || ${hooktypes[(I)${1#zle-}]} == 0 )); then + print -u$(( 2 - help )) $usage + return $(( 1 - help )) + fi + + local -aU extant_hooks + local hook="zle-${1#zle-}" + 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 + zstyle -g extant_hooks "$hook" widgets + extant_hooks+=("$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" + fi + fi +} + +# Handle zsh autoloading conventions +if [[ "$zsh_eval_context" = *loadautofunc && ! -o kshautoload ]]; then + add-zle-hook-widget "$@" +fi -- 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') 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') 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 0b8ab3a21a15c12b22f39cd19ce5ef90fdc31ad1 Mon Sep 17 00:00:00 2001 From: "Barton E. Schaefer" Date: Sun, 19 Jun 2016 19:50:37 -0700 Subject: 38715: add-zle-hook-widget: assorted ksharrays fixes; assign an index to any hook that is added without one, to preserve append ordering --- ChangeLog | 6 ++++ Doc/Zsh/contrib.yo | 30 +++++++++-------- Functions/Zle/add-zle-hook-widget | 69 ++++++++++++++++++++++++++------------- 3 files changed, 69 insertions(+), 36 deletions(-) (limited to 'Functions') diff --git a/ChangeLog b/ChangeLog index cc547e5fc..52a655069 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2016-06-19 Barton E. Schaefer + + * 38715: Doc/Zsh/contrib.yo, Functions/Zle/add-zle-hook-widget: + assorted ksharrays fixes; assign an index to any hook that is + added without one, to preserve append ordering + 2016-06-18 Barton E. Schaefer * unposted: Functions/Misc/zed: localoptions noksharrays diff --git a/Doc/Zsh/contrib.yo b/Doc/Zsh/contrib.yo index 64d93f9dc..b9c1c0a80 100644 --- a/Doc/Zsh/contrib.yo +++ b/Doc/Zsh/contrib.yo @@ -345,14 +345,16 @@ tt(zle-isearch-exit), etc. 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 -`tt(zle )var(widgetname)tt( -Nw)' rather than as a function call. +example(tt(zle )var(widgetname)tt( -Nw "$@")) +rather than as a function call. -The arrays of var(widgetname) are maintained in several tt(zstyle) -contexts, one for each var(hook) context, with a style of `tt(widgets)'. -If the tt(-L) option is given, this set of styles is listed with -`tt(zstyle -L)'. These styles may be updated directly with tt(zstyle) -commands, but the special widgets that refer to the styles are created -only if tt(add-zle-hook-widget) is called to add at least one widget. +In typical usage, var(widgetname) has the form var(index)tt(:)var(name). +In this case var(index) is an integer which determines the order in which +the widget var(name) will be called relative to other widgets in the +array. Widgets having the same var(index) are called in unspecified +order. However, var(widgetname) may omit the index, in which case an +index is computed for it to arrange for it to be called in the order +in which it was added to the array. If the option tt(-d) is given, the var(widgename) is removed from the array of widgets to be executed. @@ -368,12 +370,14 @@ passed as arguments to tt(autoload) as with tt(add-zsh-hook). The widget is also created with `tt(zle -N )var(widgetname)' to cause the corresponding function to be loaded the first time the hook is called. -In addition, var(widgetname) may be of the form var(index)tt(:)var(name). -In this case var(index) is an integer which determines the order in -which the widget var(name) will be called relative to other widgets in -the array. Widgets having the same var(index) are called in unspecified -order, and all widgets declared with an index are called before any -widgets that have no index. + +The arrays of var(widgetname) are currently maintained in tt(zstyle) +contexts, one for each var(hook) context, with a style of `tt(widgets)'. +If the tt(-L) option is given, this set of styles is listed with +`tt(zstyle -L)'. This implementation may change, and the special widgets +that refer to the styles are created only if tt(add-zle-hook-widget) is +called to add at least one widget, so if this function is used for any +hooks, then all hooks should be managed only via this function. ) enditem() diff --git a/Functions/Zle/add-zle-hook-widget b/Functions/Zle/add-zle-hook-widget index eeb0191f0..608a77607 100644 --- a/Functions/Zle/add-zle-hook-widget +++ b/Functions/Zle/add-zle-hook-widget @@ -6,6 +6,7 @@ # # WIDGET may be of the form INDEX:NAME in which case the INDEX determines # the order in which the widget executes relative to other hook widgets. +# Othewise the widget is assigned an index that appends it to the array. # # With -d, remove the widget from the hook instead; delete the hook # variable if it is empty. @@ -17,38 +18,45 @@ # 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. emulate -L zsh -# Setup - create the base functions for hook widgets that call the others - -zmodload zsh/parameter || { - print -u2 "Need parameter module for zle hooks" +# 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 } -local -a hooktypes=( isearch-exit isearch-update - line-pre-redraw line-init line-finish - history-line-set keymap-select ) +# 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 +zstyle zle-hook types ${hooktypes#zle-} for hook in $hooktypes do - function zle-$hook { + function azhw:$hook { local -a hook_widgets local hook # Values of these styles look like number:name # and we run them in number order - # $funcstack is more reliable than $0 - # Also, ksh_arrays is annoying - emulate zsh -c 'zstyle -a $funcstack[2] widgets hook_widgets' - for hook in "${@${(@on)hook_widgets}#*:}" - do - zle "$hook" -Nw || return + zstyle -a $WIDGET widgets hook_widgets + for hook in "${(@)${(@on)hook_widgets[@]}#<->:}"; do + zle "$hook" -Nw "$@" || return done return 0 } + # Check for an existing widget, add it as the first hook + if [[ ${widgets[$hook]} = user:* ]]; then + zle -A "$hook" "${widgets[$hook]}" + zstyle -- "$hook" widgets 0:"${widgets[$hook]}" + zle -N "$hook" azhw:"$hook" + fi done # Redefine ourself with the setup left out @@ -93,25 +101,27 @@ function add-zle-hook-widget { 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 + zstyle -L "zle-(${1:-${(@j:|:)hooktypes[@]}})" widgets return $? - elif (( help || $# != 2 || ${hooktypes[(I)${1#zle-}]} == 0 )); then + 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#zle-}" + 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}} + set -A extant_hooks ${extant_hooks[@]:#(<->:|)${~fn}} else - set -A extant_hooks ${extant_hooks:#(<->:|)$fn} + set -A extant_hooks ${extant_hooks[@]:#(<->:|)$fn} fi # unset if no remaining entries if (( ${#extant_hooks} )); then @@ -121,15 +131,28 @@ function add-zle-hook-widget { fi fi else + integer i=${#options[ksharrays]}-2 zstyle -g extant_hooks "$hook" widgets - extant_hooks+=("$fn") + if [[ "$fn" != <->:* ]]; then + if [[ -z ${(M)extant_hooks[@]:#(<->:|)$fn} ]]; then + # no index and not already hooked + # assign largest existing index plus 10 + i=${${(On@)${(@M)extant_hooks[@]#<->:}%:}[i]}+10 + else + return 0 + fi + else + i=${${(M)fn#<->:}%:} + fn=${fn#<->:} + fi + extant_hooks+=("${i}:${fn}") zstyle -- "$hook" widgets "${extant_hooks[@]}" if [[ -z "${widgets[$fn]}" ]]; then autoload "${autoopts[@]}" -- "$fn" - zle -N "$fn" + zle -N -- "$fn" fi if [[ -z "${widgets[$hook]}" ]]; then - zle -N "$hook" + zle -N "$hook" azhw:"$hook" fi fi } -- 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') 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') 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 76f28cc908b8c7ce72bc54496c5af74f6ca29c63 Mon Sep 17 00:00:00 2001 From: Oliver Kiddle Date: Wed, 22 Jun 2016 22:15:52 +0200 Subject: 38749: fixes for case at start of a line and for ksharrays --- ChangeLog | 5 +++++ Functions/Zle/select-bracketed | 2 ++ Functions/Zle/surround | 6 +++++- 3 files changed, 12 insertions(+), 1 deletion(-) (limited to 'Functions') diff --git a/ChangeLog b/ChangeLog index a3b91cf4b..b2a8ee585 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2016-06-22 Oliver Kiddle + + * 38749: Functions/Zle/surround, Functions/Zle/select-bracketed: + fixes for case at start of a line and for ksharrays + 2016-06-22 Peter Stephenson * unposted: Src/lex.c: remove unused and no longer defined flag diff --git a/Functions/Zle/select-bracketed b/Functions/Zle/select-bracketed index 00f51be2c..d467bb804 100644 --- a/Functions/Zle/select-bracketed +++ b/Functions/Zle/select-bracketed @@ -12,6 +12,8 @@ # done # done +setopt localoptions noksharrays + local style=${${1:-$KEYS}[1]} matching="(){}[]<>bbBB" local -i find=${NUMERIC:-1} idx=${matching[(I)[${${1:-$KEYS}[2]}]]}%9 (( idx )) || return 1 # no corresponding closing bracket diff --git a/Functions/Zle/surround b/Functions/Zle/surround index b7be30b75..348ceecc2 100644 --- a/Functions/Zle/surround +++ b/Functions/Zle/surround @@ -69,7 +69,11 @@ case $WIDGET in before="${(k)matching[(r)[$before:q]]}" fi CUTBUFFER="$before$CUTBUFFER$after" - zle .vi-put-after -n 1 + if [[ CURSOR -eq 0 || $BUFFER[CURSOR] = $'\n' ]]; then + zle .vi-put-before -n 1 + else + zle .vi-put-after -n 1 + fi CUTBUFFER="$save_cut" CURSOR="$save_cur" ;; esac -- cgit v1.2.3 From a73ae70e8217d7163aecdbdad4d8af08eced8a55 Mon Sep 17 00:00:00 2001 From: Oliver Kiddle Date: Wed, 29 Jun 2016 17:05:06 +0200 Subject: 38770: vi upper/lowercase widgets and shell widget example that reads a vi movement --- ChangeLog | 4 ++++ Doc/Zsh/contrib.yo | 11 +++++++++++ Doc/Zsh/zle.yo | 14 ++++++++++++++ Functions/Zle/vi-pipe | 31 +++++++++++++++++++++++++++++++ Src/Zle/iwidgets.list | 2 ++ Src/Zle/zle_keymap.c | 5 ++++- Src/Zle/zle_vi.c | 46 ++++++++++++++++++++++++++++++++++++++++++++++ 7 files changed, 112 insertions(+), 1 deletion(-) create mode 100644 Functions/Zle/vi-pipe (limited to 'Functions') diff --git a/ChangeLog b/ChangeLog index 4f0a49397..831ea4e69 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,9 @@ 2016-06-29 Oliver Kiddle + * 38770: Src/Zle/zle_keymap.c, Src/Zle/zle_vi.c, Doc/Zsh/zle.yo, + Doc/Zsh/contrib.yo, Functions/Zle/vi-pipe: vi upper/lowercase + widgets and shell widget example that reads a vi movement + * 38752: Src/builtin.c: add comments to explain use of stdout instead of stderr for the which builtin diff --git a/Doc/Zsh/contrib.yo b/Doc/Zsh/contrib.yo index 53ae96dad..f1208e843 100644 --- a/Doc/Zsh/contrib.yo +++ b/Doc/Zsh/contrib.yo @@ -2968,6 +2968,17 @@ and aliases `tt(globurl)' to `tt(noglob urlglobber)'. This function takes a local URL apart, attempts to pattern-match the local file portion of the URL path, and then puts the results back into URL format again. ) +tindex(vi-pipe) +item(tt(vi-pipe))( +This function reads a movement command from the keyboard and then +prompts for an external command. The part of the buffer covered by +the movement is piped to the external command and then replaced by +the command's output. If the movement command is bound to vi-pipe, +the current line is used. + +The function serves as an example for reading a vi movement command +from within a user-defined widget. +) tindex(which-command) item(tt(which-command))( This function is a drop-in replacement for the builtin widget diff --git a/Doc/Zsh/zle.yo b/Doc/Zsh/zle.yo index 80d3f39d8..1bae0ccf7 100644 --- a/Doc/Zsh/zle.yo +++ b/Doc/Zsh/zle.yo @@ -1781,6 +1781,13 @@ tindex(down-case-word) item(tt(down-case-word) (tt(ESC-L ESC-l)) (unbound) (unbound))( Convert the current word to all lowercase and move past it. ) +tindex(vi-down-case) +item(tt(vi-down-case)) ((unbound) (tt(gu)) (unbound))( +Read a movement command from the keyboard, and convert all characters +from the cursor position to the endpoint of the movement to lowercase. +If the movement command is tt(vi-down-case), swap the case of all +characters on the current line. +) tindex(kill-word) item(tt(kill-word) (tt(ESC-D ESC-d)) (unbound) (unbound))( Kill the current word. @@ -1946,6 +1953,13 @@ tindex(vi-unindent) item(tt(vi-unindent) (unbound) (tt(<)) (unbound))( Unindent a number of lines. ) +tindex(vi-up-case) +item(tt(vi-up-case)) ((unbound) (tt(gU)) (unbound))( +Read a movement command from the keyboard, and convert all characters +from the cursor position to the endpoint of the movement to lowercase. +If the movement command is tt(vi-up-case), swap the case of all +characters on the current line. +) tindex(up-case-word) item(tt(up-case-word) (tt(ESC-U ESC-u)) (unbound) (unbound))( Convert the current word to all caps and move past it. diff --git a/Functions/Zle/vi-pipe b/Functions/Zle/vi-pipe new file mode 100644 index 000000000..2d2e29587 --- /dev/null +++ b/Functions/Zle/vi-pipe @@ -0,0 +1,31 @@ +# Example of a widget that takes a vi motion + +# Filter part of buffer corresponding to a vi motion through an external +# program. + +# To enable with vi compatible bindings use: +# autoload -Uz vi-pipe +# bindkey -a '!' vi-pipe + +autoload -Uz read-from-minibuffer +local _save_cut="$CUTBUFFER" REPLY + +# Use the standard vi-delete to accept a vi motion. +zle .vi-delete || return +read-from-minibuffer "!" +local _save_cur=$CURSOR + +# cut buffer contains the deleted text and can be modified +CUTBUFFER="$(eval $REPLY <<<$CUTBUFFER)" + +# put the modified text back in position. +if [[ CURSOR -eq 0 || $BUFFER[CURSOR] = $'\n' ]]; then + # at the beginning of a line, vi-delete won't have moved the cursor + # back to a previous line + zle .vi-put-before -n 1 +else + zle .vi-put-after -n 1 +fi + +# restore cut buffer and cursor to the start of the range +CUTBUFFER="$_save_cut" CURSOR="$_save_cur" diff --git a/Src/Zle/iwidgets.list b/Src/Zle/iwidgets.list index 2b2654c5d..58310cd74 100644 --- a/Src/Zle/iwidgets.list +++ b/Src/Zle/iwidgets.list @@ -143,6 +143,7 @@ "vi-delete", videlete, ZLE_KEEPSUFFIX | ZLE_LASTCOL | ZLE_VIOPER "vi-delete-char", videletechar, ZLE_KEEPSUFFIX "vi-digit-or-beginning-of-line", vidigitorbeginningofline, 0 +"vi-down-case", vidowncase, ZLE_LASTCOL | ZLE_VIOPER "vi-down-line-or-history", vidownlineorhistory, ZLE_LINEMOVE "vi-end-of-line", viendofline, ZLE_LASTCOL "vi-fetch-history", vifetchhistory, ZLE_LINEMOVE @@ -188,6 +189,7 @@ "vi-swap-case", viswapcase, ZLE_LASTCOL "vi-undo-change", viundochange, ZLE_KEEPSUFFIX "vi-unindent", viunindent, ZLE_LASTCOL | ZLE_VIOPER +"vi-up-case", viupcase, ZLE_LASTCOL | ZLE_VIOPER "vi-up-line-or-history", viuplineorhistory, ZLE_LINEMOVE "vi-yank", viyank, ZLE_LASTCOL | ZLE_VIOPER "vi-yank-eol", viyankeol, 0 diff --git a/Src/Zle/zle_keymap.c b/Src/Zle/zle_keymap.c index f547dbf17..3db4207d9 100644 --- a/Src/Zle/zle_keymap.c +++ b/Src/Zle/zle_keymap.c @@ -1374,8 +1374,11 @@ default_bindings(void) bindkey(amap, "ge", refthingy(t_vibackwardwordend), NULL); bindkey(amap, "gE", refthingy(t_vibackwardblankwordend), NULL); bindkey(amap, "gg", refthingy(t_beginningofbufferorhistory), NULL); - bindkey(amap, "g~", refthingy(t_vioperswapcase), NULL); + bindkey(amap, "gu", refthingy(t_vidowncase), NULL); + bindkey(amap, "gU", refthingy(t_viupcase), NULL); bindkey(amap, "g~~", NULL, "g~g~"); + bindkey(amap, "guu", NULL, "gugu"); + bindkey(amap, "gUU", NULL, "gUgU"); /* emacs mode: arrow keys */ add_cursor_key(emap, TCUPCURSOR, t_uplineorhistory, 'A'); diff --git a/Src/Zle/zle_vi.c b/Src/Zle/zle_vi.c index 953af2401..baa2064e9 100644 --- a/Src/Zle/zle_vi.c +++ b/Src/Zle/zle_vi.c @@ -729,6 +729,52 @@ vioperswapcase(UNUSED(char **args)) return ret; } +/**/ +int +viupcase(UNUSED(char **args)) +{ + int oldcs, c2, ret = 1; + + /* get the range */ + startvichange(1); + if ((c2 = getvirange(0)) != -1) { + oldcs = zlecs; + /* covert the case of all letters within range */ + while (zlecs < c2) { + zleline[zlecs] = ZC_toupper(zleline[zlecs]); + INCCS(); + } + /* go back to the first line of the range */ + zlecs = oldcs; + ret = 0; + } + vichgflag = 0; + return ret; +} + +/**/ +int +vidowncase(UNUSED(char **args)) +{ + int oldcs, c2, ret = 1; + + /* get the range */ + startvichange(1); + if ((c2 = getvirange(0)) != -1) { + oldcs = zlecs; + /* convert the case of all letters within range */ + while (zlecs < c2) { + zleline[zlecs] = ZC_tolower(zleline[zlecs]); + INCCS(); + } + /* go back to the first line of the range */ + zlecs = oldcs; + ret = 0; + } + vichgflag = 0; + return ret; +} + /**/ int virepeatchange(UNUSED(char **args)) -- 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') 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 c135c416b2ecab332b1fb10d164d426e78ccd6ac Mon Sep 17 00:00:00 2001 From: Peter Stephenson Date: Fri, 8 Jul 2016 15:32:44 +0100 Subject: 38796: Fix subword matching on last character of subword. --- ChangeLog | 5 +++++ Functions/Zle/match-words-by-style | 8 +++++++- 2 files changed, 12 insertions(+), 1 deletion(-) (limited to 'Functions') diff --git a/ChangeLog b/ChangeLog index 417408d81..27ce01dd4 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2016-07-08 Peter Stephenson + + * 38796: Functions/Zle/match-words-by-style: fix subword + matching on last character of subword. + 2016-07-05 Oliver Kiddle * arno: 38780: Completion/X/Command/_setxkbmap: include diff --git a/Functions/Zle/match-words-by-style b/Functions/Zle/match-words-by-style index 54e019d23..6cdec7551 100644 --- a/Functions/Zle/match-words-by-style +++ b/Functions/Zle/match-words-by-style @@ -202,7 +202,7 @@ if [[ $wordstyle = *subword* ]]; then # followed by a lower case letter, or an upper case letter at # the start of a group of upper case letters. To make # it easier to be consistent, we just use anything that - # isn't an upper case characer instead of a lower case + # isn't an upper case character instead of a lower case # character. # Here the initial "*" will match greedily, so we get the # last such match, as we want. @@ -237,6 +237,12 @@ if [[ $wordstyle = *subword* ]]; then -n $match[2] ]]; then # Yes, so the last one is new word boundary. (( epos = ${#match[1]} - 1 )) + # Otherwise, are we in the middle of a word? + # In other, er, words, we've got something on the left with no + # white space following and something that doesn't start a word here. + elif [[ -n $word1 && -z $ws1 && -z $ws2 && \ + $word2 = (#b)([^${~subwordrange}]##)* ]]; then + (( epos = ${#match[1]} )) # Otherwise, do we have upper followed by non-upper not # at the start? Ignore the initial character, we already # know it's a word boundary so it can be an upper case character -- cgit v1.2.3 From 3e61af3ff47ff47391a39f88ad34e8e1904b527e Mon Sep 17 00:00:00 2001 From: "Barton E. Schaefer" Date: Wed, 13 Jul 2016 22:14:54 -0700 Subject: 38850: Simplify indexing scheme to store hooks in the order they are added Also, better handling of edge cases and of autoloading/sourcing file --- ChangeLog | 6 ++++ Functions/Zle/add-zle-hook-widget | 70 ++++++++++++++++++++++----------------- 2 files changed, 45 insertions(+), 31 deletions(-) (limited to 'Functions') diff --git a/ChangeLog b/ChangeLog index ebb936dc1..e89a494c5 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2016-07-13 Barton E. Schaefer + + * 38850: Functions/Zle/add-zle-hook-widget: Simplify indexing + scheme to store hooks strictly in the order they are added; + better handling of edge cases and autoloading/sourcing file. + 2016-07-13 Eric Cook * 38833: Completion/Unix/Command/_iostat diff --git a/Functions/Zle/add-zle-hook-widget b/Functions/Zle/add-zle-hook-widget index 608a77607..760e26d29 100644 --- a/Functions/Zle/add-zle-hook-widget +++ b/Functions/Zle/add-zle-hook-widget @@ -1,18 +1,15 @@ # 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 not -# required). +# 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. # -# WIDGET may be of the form INDEX:NAME in which case the INDEX determines -# the order in which the widget executes relative to other hook widgets. -# Othewise the widget is assigned an index that appends it to the array. -# -# With -d, remove the widget from the hook instead; delete the hook -# variable if it is empty. +# 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 the -# widget name, so any matching widget will be deleted from the hook. +# -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 @@ -47,16 +44,15 @@ do # and we run them in number order zstyle -a $WIDGET widgets hook_widgets for hook in "${(@)${(@on)hook_widgets[@]}#<->:}"; do - zle "$hook" -Nw "$@" || return + if [[ "$hook" = user:* ]]; then + # Preserve $WIDGET within the renamed widget + zle "$hook" -N "$@" + else + zle "$hook" -Nw "$@" + fi || return done return 0 } - # Check for an existing widget, add it as the first hook - if [[ ${widgets[$hook]} = user:* ]]; then - zle -A "$hook" "${widgets[$hook]}" - zstyle -- "$hook" widgets 0:"${widgets[$hook]}" - zle -N "$hook" azhw:"$hook" - fi done # Redefine ourself with the setup left out @@ -133,17 +129,19 @@ function add-zle-hook-widget { else integer i=${#options[ksharrays]}-2 zstyle -g extant_hooks "$hook" widgets - if [[ "$fn" != <->:* ]]; then - if [[ -z ${(M)extant_hooks[@]:#(<->:|)$fn} ]]; then - # no index and not already hooked - # assign largest existing index plus 10 - i=${${(On@)${(@M)extant_hooks[@]#<->:}%:}[i]}+10 - else - return 0 - fi + # Check for an existing widget, add it as the first hook + if [[ ${widgets[$hook]} != "user:azhw:$hook" ]]; then + zle -A "$hook" "${widgets[$hook]}" + extant_hooks=(0:"${widgets[$hook]}" "${extant_hooks[@]}") + 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 - i=${${(M)fn#<->:}%:} - fn=${fn#<->:} + return 0 fi extant_hooks+=("${i}:${fn}") zstyle -- "$hook" widgets "${extant_hooks[@]}" @@ -157,7 +155,17 @@ function add-zle-hook-widget { fi } -# Handle zsh autoloading conventions -if [[ "$zsh_eval_context" = *loadautofunc && ! -o kshautoload ]]; then - add-zle-hook-widget "$@" -fi +# 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 e3884c60ed1a247af1e1578710629f2ca79630d8 Mon Sep 17 00:00:00 2001 From: "Barton E. Schaefer" Date: Sun, 17 Jul 2016 12:04:48 -0700 Subject: 38866: update add-zle-hook-widget doc for 38850, bug fixes Edge case handling, wrap in anonymous function for kshautoload management. --- ChangeLog | 8 ++++++ Doc/Zsh/contrib.yo | 18 +++++-------- Functions/Zle/add-zle-hook-widget | 57 ++++++++++++++++++++++++--------------- 3 files changed, 51 insertions(+), 32 deletions(-) (limited to 'Functions') diff --git a/ChangeLog b/ChangeLog index f092e815b..bb33f16b2 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,11 @@ +2016-07-17 Barton E. Schaefer + + * 38866: Doc/Zsh/contrib.yo: update add-zle-hook-widget for 38850. + + * 38866 (+ tweak 38872): Functions/Zle/add-zle-hook-widget: fix + edge case handling, wrap in anonymous function for kshautoload + management. + 2016-07-17 Daniel Shahaf * users/21752: Doc/Zsh/mod_zleparameter.yo: Extend diff --git a/Doc/Zsh/contrib.yo b/Doc/Zsh/contrib.yo index d4a453849..1d2b7ca6e 100644 --- a/Doc/Zsh/contrib.yo +++ b/Doc/Zsh/contrib.yo @@ -340,23 +340,20 @@ those additional widgets. var(hook) is one of tt(isearch-exit), tt(isearch-update), tt(line-pre-redraw), tt(line-init), tt(line-finish), tt(history-line-set), or tt(keymap-select), corresponding to each of the special widgets -tt(zle-isearch-exit), etc. +tt(zle-isearch-exit), etc. The special widget names are also accepted +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 "$@")) -rather than as a function call. -In typical usage, var(widgetname) has the form var(index)tt(:)var(name). -In this case var(index) is an integer which determines the order in which -the widget var(name) will be called relative to other widgets in the -array. Widgets having the same var(index) are called in unspecified -order. However, var(widgetname) may omit the index, in which case an -index is computed for it to arrange for it to be called in the order -in which it was added to the array. +vindex(WIDGET, in hooks) +Note that this means that the `tt(WIDGET)' special parameter tracks the +var(widgetname) when the widget function is called, rather than tracking +the name of the corresponding special hook widget. -If the option tt(-d) is given, the var(widgename) is removed from +If the option tt(-d) is given, the var(widgetname) is removed from the array of widgets to be executed. If the option tt(-D) is given, the var(widgetname) is treated as a pattern @@ -370,7 +367,6 @@ passed as arguments to tt(autoload) as with tt(add-zsh-hook). The widget is also created with `tt(zle -N )var(widgetname)' to cause the corresponding function to be loaded the first time the hook is called. - The arrays of var(widgetname) are currently maintained in tt(zstyle) contexts, one for each var(hook) context, with a style of `tt(widgets)'. If the tt(-L) option is given, this set of styles is listed with diff --git a/Functions/Zle/add-zle-hook-widget b/Functions/Zle/add-zle-hook-widget index 760e26d29..04be50478 100644 --- a/Functions/Zle/add-zle-hook-widget +++ b/Functions/Zle/add-zle-hook-widget @@ -18,6 +18,8 @@ # # 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 @@ -35,25 +37,23 @@ local -a hooktypes=( zle-isearch-exit zle-isearch-update # Stash in zstyle to make it global zstyle zle-hook types ${hooktypes#zle-} -for hook in $hooktypes -do - function azhw:$hook { - 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 - } -done +# 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 @@ -127,12 +127,25 @@ function add-zle-hook-widget { 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 - zle -A "$hook" "${widgets[$hook]}" - extant_hooks=(0:"${widgets[$hook]}" "${extant_hooks[@]}") + 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 @@ -155,6 +168,8 @@ function add-zle-hook-widget { 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 -- 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') 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 932ff2b6f8990b027facc93fb23bc1dc0163707e Mon Sep 17 00:00:00 2001 From: Oliver Kiddle Date: Sun, 24 Jul 2016 22:18:34 +0200 Subject: 38929: new vim style text object using match-words-by-style mechanism --- ChangeLog | 3 + Doc/Zsh/contrib.yo | 12 ++-- Functions/Zle/select-word-match | 121 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 132 insertions(+), 4 deletions(-) create mode 100644 Functions/Zle/select-word-match (limited to 'Functions') diff --git a/ChangeLog b/ChangeLog index 20c401b04..086298775 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,8 @@ 2016-07-24 Oliver Kiddle + * 38929: Doc/Zsh/contrib.yo, Functions/Zle/select-word-match: + new vim style text object using match-words-by-style mechanism + * 38935: Matthew Martin: Completion/Unix/Command/_tcpdump: update for Free and Open BSD diff --git a/Doc/Zsh/contrib.yo b/Doc/Zsh/contrib.yo index 1d2b7ca6e..c3dec34cd 100644 --- a/Doc/Zsh/contrib.yo +++ b/Doc/Zsh/contrib.yo @@ -1940,6 +1940,8 @@ tindex(transpose-words-match) tindex(capitalize-word-match) tindex(up-case-word-match) tindex(down-case-word-match) +tindex(delete-whole-word-match) +tindex(select-word-match) tindex(select-word-style) tindex(match-word-context) tindex(match-words-by-style) @@ -1947,12 +1949,14 @@ xitem(tt(forward-word-match), tt(backward-word-match)) xitem(tt(kill-word-match), tt(backward-kill-word-match)) xitem(tt(transpose-words-match), tt(capitalize-word-match)) xitem(tt(up-case-word-match), tt(down-case-word-match)) +xitem(tt(delete-whole-word-match), tt(select-word-match)) item(tt(select-word-style), tt(match-word-context), tt(match-words-by-style))( -The eight `tt(-match)' functions are drop-in replacements for the +The first eight `tt(-match)' functions are drop-in replacements for the builtin widgets without the suffix. By default they behave in a similar way. However, by the use of styles and the function tt(select-word-style), -the way words are matched can be altered. For comparison, the widgets -described in ifzman(zmanref(zshzle) under Text Objects)\ +the way words are matched can be altered. tt(select-word-match) is intended +to be used as a text object in vi mode but with custom word styles. For +comparison, the widgets described in ifzman(zmanref(zshzle) under Text Objects)\ ifnzman(noderef(Text Objects)) use fixed definitions of words, compatible with the tt(vim) editor. @@ -1960,7 +1964,7 @@ The simplest way of configuring the functions is to use tt(select-word-style), which can either be called as a normal function with the appropriate argument, or invoked as a user-defined widget that will prompt for the first character of the word style to be used. The first -time it is invoked, the eight tt(-match) functions will automatically +time it is invoked, the first eight tt(-match) functions will automatically replace the builtin versions, so they do not need to be loaded explicitly. The word styles available are as follows. Only the first character diff --git a/Functions/Zle/select-word-match b/Functions/Zle/select-word-match new file mode 100644 index 000000000..24620c995 --- /dev/null +++ b/Functions/Zle/select-word-match @@ -0,0 +1,121 @@ +# Select the entire word around the cursor. Intended for use as +# a vim-style text object in vi mode but with customisable +# word boundaries. +# +# For example: +# autoload -U select-word-match +# zle -N select-in-camel select-word-match +# bindkey -M viopp ic select-in-camel +# zstyle ':zle:*-camel' word-style normal-subword + +emulate -L zsh +setopt extendedglob + +local curcontext=:zle:$WIDGET +local -a matched_words +# Start and end of range of characters +integer pos1 pos2 num=${NUMERIC:-1} +local style word + +# choose between inner word or a word style of widget +for style in $1 ${${WIDGET#*-}[1]} $KEYS[1] "i"; do + [[ $style = [ai] ]] && break +done + +autoload -Uz match-words-by-style + +while (( num-- )); do + if (( MARK > CURSOR )); then + # if cursor is at the start of the selection, just move back a word + match-words-by-style + if [[ $style = i && -n $matched_words[3] ]]; then + word=$matched_words[3] + else + word=$matched_words[2]$matched_words[3] + fi + if [[ -n $word ]]; then + (( CURSOR -= ${#word} )) + else + return 1 + fi + elif (( MARK >= 0 && MARK < CURSOR )); then + # cursor at the end, move forward a word + (( CURSOR+1 == $#BUFFER )) && return 1 + (( CURSOR++ )) + match-words-by-style + if [[ -n $matched_words[4] ]]; then + if [[ $style = i ]]; then + # just skip the whitespace + word=$matched_words[4] + else + # skip the whitespace plus word + word=$matched_words[4]$matched_words[5] + fi + else + if [[ $style = i ]]; then + # skip the word + word=$matched_words[5] + else + # skip word and following whitespace + word=$matched_words[5]$matched_words[6] + fi + fi + (( CURSOR += ${#word} - 1 )) + else + match-words-by-style + + if [[ -n "${matched_words[3]}" ]]; then + # There's whitespace before the cursor, so the word we are selecting + # starts at the cursor position. + pos1=$CURSOR + else + # No whitespace before us, so select any wordcharacters there. + pos1="${#matched_words[1]}" + fi + + if [[ -n "${matched_words[4]}" ]]; then + if [[ -n "${matched_words[3]}" ]] || (( CURSOR == 0 )); then + # whitespace either side, select it + (( pos1 = CURSOR - ${#matched_words[3]} )) + (( pos2 = CURSOR + ${#matched_words[4]} )) + else + # There's whitespace at the cursor position, so only select + # up to the cursor position. + (( pos2 = CURSOR + 1 )) + fi + else + # No whitespace at the cursor position, so select the + # current character and any following wordcharacters. + (( pos2 = CURSOR + ${#matched_words[5]} )) + fi + + if [[ $style = a ]]; then + if [[ -n "${matched_words[4]}" && ( -n "${matched_words[3]}" || CURSOR -eq 0 ) ]]; then + # in the middle of whitespace so grab a word + if [[ -n "${matched_words[5]}" ]]; then + (( pos2 += ${#matched_words[5]} )) # preferably the one after + else + (( pos1 -= ${#matched_words[2]} )) # otherwise the one before + fi + elif [[ -n "${matched_words[6]}" ]]; then + (( pos2 += ${#matched_words[6]} )) + elif [[ -n "${matched_words[3]}" ]]; then + # couldn't grab whitespace forwards so try backwards + (( pos1 -= ${#matched_words[3]} )) + elif (( pos1 > 0 )); then + # There might have been whitespace before the word + (( CURSOR = pos1 )) + match-words-by-style + if [[ -n "${matched_words[3]}" ]]; then + (( pos1 -= ${#matched_words[3]} )) + fi + fi + fi + + (( MARK = pos1, CURSOR = pos2-1 )) + fi +done + +if [[ $KEYMAP == vicmd ]] && (( !REGION_ACTIVE )); then + (( CURSOR++ )) # Need to include cursor position for operators +fi -- cgit v1.2.3 From ac05343049e7a092c711a97d616abfd5e85ca58e Mon Sep 17 00:00:00 2001 From: Oliver Kiddle Date: Sun, 24 Jul 2016 22:33:14 +0200 Subject: 38936: fix vi-pipe function for option compatibility --- ChangeLog | 2 ++ Functions/Zle/vi-pipe | 11 ++++++++--- 2 files changed, 10 insertions(+), 3 deletions(-) (limited to 'Functions') diff --git a/ChangeLog b/ChangeLog index 086298775..4fb827c71 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,7 @@ 2016-07-24 Oliver Kiddle + * 38936: Functions/Zle/vi-pipe: fix for option compatibility + * 38929: Doc/Zsh/contrib.yo, Functions/Zle/select-word-match: new vim style text object using match-words-by-style mechanism diff --git a/Functions/Zle/vi-pipe b/Functions/Zle/vi-pipe index 2d2e29587..028f1e1ce 100644 --- a/Functions/Zle/vi-pipe +++ b/Functions/Zle/vi-pipe @@ -7,16 +7,21 @@ # autoload -Uz vi-pipe # bindkey -a '!' vi-pipe +setopt localoptions noksharrays + autoload -Uz read-from-minibuffer local _save_cut="$CUTBUFFER" REPLY -# Use the standard vi-delete to accept a vi motion. -zle .vi-delete || return +# force movement to default to line mode +zle -U V +# Use the standard vi-change to accept a vi motion. +zle .vi-change || return read-from-minibuffer "!" +zle .vi-cmd-mode local _save_cur=$CURSOR # cut buffer contains the deleted text and can be modified -CUTBUFFER="$(eval $REPLY <<<$CUTBUFFER)" +CUTBUFFER=$(eval "$REPLY" <<<"$CUTBUFFER") # put the modified text back in position. if [[ CURSOR -eq 0 || $BUFFER[CURSOR] = $'\n' ]]; then -- 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') 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 26361e438b41862f5495ae263bc004cfffbd6b44 Mon Sep 17 00:00:00 2001 From: Peter Stephenson Date: Thu, 28 Jul 2016 09:50:03 +0100 Subject: 38953: Fix some issues with match-words-by-style. Add keyword retrieval of words. Improve test for start of word in subwords for use in delete-whole-word. If line after cursor is empty, white space is treated as ws-after-cursor. --- ChangeLog | 5 ++++ Doc/Zsh/contrib.yo | 11 +++++++++ Functions/Zle/delete-whole-word-match | 15 ++++++------ Functions/Zle/match-words-by-style | 45 +++++++++++++++++++++++++++++------ 4 files changed, 61 insertions(+), 15 deletions(-) (limited to 'Functions') diff --git a/ChangeLog b/ChangeLog index 88cf4cd19..03a2e29fe 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,10 @@ 2016-07-28 Peter Stephenson + * 38953: Doc/Zsh/contrib.yo, + Functions/Zle/delete-whole-word-match, + Functions/Zle/match-words-by-style: Fix some problems with + match-words-by-style and add keyword retrieval of matched data. + * users/21793: README, Src/glob.c: remove ancient undocumented pre-"f" glob qualifer feature that unqualified integers were treated as octal file mode. diff --git a/Doc/Zsh/contrib.yo b/Doc/Zsh/contrib.yo index c3dec34cd..8db7395d0 100644 --- a/Doc/Zsh/contrib.yo +++ b/Doc/Zsh/contrib.yo @@ -2132,6 +2132,17 @@ non-word characters following that word (7) the remainder of the line. Any of the elements may be an empty string; the calling function should test for this to decide whether it can perform its function. +If the variable tt(matched_words) is defined by the caller to +tt(match-words-by-style) as an associative array (tt(local -A +matched_words)), then the seven values given above should be retrieved +from it as elements named tt(start), tt(word-before-cursor), +tt(ws-before-cursor), tt(ws-after-cursor), tt(word-after-cursor), +tt(ws-after-word), and tt(end). In addition the element +tt(is-word-start) is 1 if the cursor is on the start of a word or +subword, or on white space before it (the cases can be distinguished by +testing the tt(ws-after-cursor) element) and 0 otherwise. This form is +recommended for future compatibility. + It is possible to pass options with arguments to tt(match-words-by-style) to override the use of styles. The options are: startsitem() diff --git a/Functions/Zle/delete-whole-word-match b/Functions/Zle/delete-whole-word-match index aece86065..3d52dd3d7 100644 --- a/Functions/Zle/delete-whole-word-match +++ b/Functions/Zle/delete-whole-word-match @@ -12,30 +12,29 @@ emulate -L zsh setopt extendedglob local curcontext=:zle:$WIDGET -local -a matched_words +local -A matched_words # Start and end of range of characters to remove. integer pos1 pos2 autoload -Uz match-words-by-style match-words-by-style -if [[ -n "${matched_words[3]}" ]]; then - # There's whitespace before the cursor, so the word we are deleting - # starts at the cursor position. +if (( ${matched_words[is-word-start]} )); then + # The word we are deleting starts at the cursor position. pos1=$CURSOR else - # No whitespace before us, so delete any wordcharacters there. - pos1="${#matched_words[1]}" + # Not, so delete any wordcharacters before, too + pos1="${#matched_words[start]}" fi -if [[ -n "${matched_words[4]}" ]]; then +if [[ -n "${matched_words[ws-after-cursor]}" ]]; then # There's whitespace at the cursor position, so only delete # up to the cursor position. (( pos2 = CURSOR + 1 )) else # No whitespace at the cursor position, so delete the # current character and any following wordcharacters. - (( pos2 = CURSOR + ${#matched_words[5]} + 1 )) + (( pos2 = CURSOR + ${#matched_words[word-after-cursor]} + 1 )) fi # Move the cursor then delete the block in one go for the diff --git a/Functions/Zle/match-words-by-style b/Functions/Zle/match-words-by-style index 6cdec7551..fc59c2764 100644 --- a/Functions/Zle/match-words-by-style +++ b/Functions/Zle/match-words-by-style @@ -5,8 +5,16 @@ # # # where the cursor position is always after the third item and `after' -# is to be interpreted as `after or on'. Some -# of the array elements will be empty; this depends on the style. +# is to be interpreted as `after or on'. +# +# matched_words may be an associative array, in which case the +# values above are now given by the elements named start, word-before-cursor, +# ws-before-cursor, ws-after-cursor, word-after-cursor, ws-after-word, +# end. In addition, the element is-word-start is 1 if the cursor +# is on the start of a word; this is non-trivial in the case of subword +# (camel case) matching as there may be no white space to test. +# +# Some of the array elements will be empty; this depends on the style. # For example # foo bar rod stick # ^ @@ -224,11 +232,18 @@ charskip=${(l:skip::?:)} eval pat2='${RBUFFER##(#b)('${charskip}${spacepat}')('\ ${wordpat2}')('${spacepat}')}' +if [[ -n $match[2] ]]; then + ws2=$match[1] + word2=$match[2] + ws3=$match[3] +else + # No more words, so anything left is white space after cursor. + ws2=$RBUFFER + pat2= +fi -ws2=$match[1] -word2=$match[2] -ws3=$match[3] - +integer wordstart +[[ ( -n $ws1 || -n $ws2 ) && -n $word2 ]] && wordstart=1 if [[ $wordstyle = *subword* ]]; then # Do we have a group of upper case characters at the start # of word2 (that don't form the entire word)? @@ -249,6 +264,7 @@ if [[ $wordstyle = *subword* ]]; then # if it wants. elif [[ $word2 = (#b)(?[^${~subwordrange}]##)[${~subwordrange}]* ]]; then (( epos = ${#match[1]} )) + (( wordstart = 1 )) else (( epos = 0 )) fi @@ -262,4 +278,19 @@ if [[ $wordstyle = *subword* ]]; then fi fi -matched_words=("$pat1" "$word1" "$ws1" "$ws2" "$word2" "$ws3" "$pat2") +# matched_words should be local to caller. +# Just fix type here. +if [[ ${(t)matched_words} = *association* ]]; then + matched_words=( + start "$pat1" + word-before-cursor "$word1" + ws-before-cursor "$ws1" + ws-after-cursor "$ws2" + word-after-cursor "$word2" + ws-after-word "$ws3" + end "$pat2" + is-word-start $wordstart + ) +else + matched_words=("$pat1" "$word1" "$ws1" "$ws2" "$word2" "$ws3" "$pat2") +fi -- cgit v1.2.3 From 7830a8c498730cd08dad27d4d6ec9722f9cd637a Mon Sep 17 00:00:00 2001 From: Oliver Kiddle Date: Thu, 28 Jul 2016 16:07:59 +0200 Subject: unposted: fix vi-pipe for visual mode: don't need to force line mode --- ChangeLog | 4 ++++ Functions/Zle/vi-pipe | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) (limited to 'Functions') diff --git a/ChangeLog b/ChangeLog index 03a2e29fe..4c208cbcf 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2016-07-28 Oliver Kiddle + + * unposted: Functions/Zle/vi-pipe: fix for visual mode + 2016-07-28 Peter Stephenson * 38953: Doc/Zsh/contrib.yo, diff --git a/Functions/Zle/vi-pipe b/Functions/Zle/vi-pipe index 028f1e1ce..c32e64a59 100644 --- a/Functions/Zle/vi-pipe +++ b/Functions/Zle/vi-pipe @@ -13,7 +13,7 @@ autoload -Uz read-from-minibuffer local _save_cut="$CUTBUFFER" REPLY # force movement to default to line mode -zle -U V +(( REGION_ACTIVE )) || zle -U V # Use the standard vi-change to accept a vi motion. zle .vi-change || return read-from-minibuffer "!" -- cgit v1.2.3 From b816bb42cfc4d0fa05abb63ebf4098af05a3d593 Mon Sep 17 00:00:00 2001 From: Oliver Kiddle Date: Thu, 28 Jul 2016 16:16:25 +0200 Subject: 38957: make use of updates to match-words-by-style and better support completion of word-style styles for zstyle --- ChangeLog | 5 ++++ Completion/Zsh/Command/_zstyle | 7 ++++-- Doc/Zsh/contrib.yo | 2 +- Functions/Zle/select-word-match | 55 ++++++++++++++++++++--------------------- 4 files changed, 38 insertions(+), 31 deletions(-) (limited to 'Functions') diff --git a/ChangeLog b/ChangeLog index 6a5b0e5c4..1d68cf75d 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,10 @@ 2016-07-28 Oliver Kiddle + * 38957: Functions/Zle/select-word-match, + Completion/Zsh/Command/_zstyle, Doc/Zsh/contrib.yo: + make use of updates to match-words-by-style and better support + completion of word-style styles for zstyle + * 38956: Completion/Zsh/Command/_bindkey, Completion/Zsh/Command/_vared, Completion/Zsh/Command/_zle, Completion/Zsh/Function/_add-zle-hook-widget, diff --git a/Completion/Zsh/Command/_zstyle b/Completion/Zsh/Command/_zstyle index 9a6d61891..20ff47f87 100644 --- a/Completion/Zsh/Command/_zstyle +++ b/Completion/Zsh/Command/_zstyle @@ -173,6 +173,7 @@ styles=( url-seps e: whence e: word-chars e: + word-class e: word-style e:word-style word-context e: @@ -241,11 +242,13 @@ while (( $#state )); do case "$state[1]" in (contexts) if [[ ! -prefix :*: ]]; then - _wanted contexts expl context compadd -P : -qS : completion vcs_info zftp + _wanted contexts expl context compadd -P : -qS : chpwd completion vcs_info zftp zle elif compset -P :completion:; then contexts=( functions _completers cmdorcont argument tag ) elif compset -P :vcs_info:; then contexts=( vcs-string user-context repo-root-name ) + elif compset -P :zle:; then + _wanted widgets expl widget _widgets -qS : fi if (( $#contexts )); then for ostate in $contexts; do @@ -521,7 +524,7 @@ while (( $#state )); do ;; (word-style) - _wanted word-styles expl 'word style' compadd normal shell space + _wanted word-styles expl 'word style' compadd {normal,specified,unspecified,shell,whitespace}-subword ;; (vcs-string) diff --git a/Doc/Zsh/contrib.yo b/Doc/Zsh/contrib.yo index 8db7395d0..00ed08029 100644 --- a/Doc/Zsh/contrib.yo +++ b/Doc/Zsh/contrib.yo @@ -2105,7 +2105,7 @@ Here are some examples of use of the tt(word-context) style to extend the context. example(zstyle ':zle:*' word-context \ - "*/*" file "[[:space:]]" whitespace + "*/*" filename "[[:space:]]" whitespace zstyle ':zle:transpose-words:whitespace' word-style shell zstyle ':zle:transpose-words:filename' word-style normal zstyle ':zle:transpose-words:filename' word-chars '') diff --git a/Functions/Zle/select-word-match b/Functions/Zle/select-word-match index 24620c995..8440852ab 100644 --- a/Functions/Zle/select-word-match +++ b/Functions/Zle/select-word-match @@ -12,7 +12,7 @@ emulate -L zsh setopt extendedglob local curcontext=:zle:$WIDGET -local -a matched_words +local -A matched_words # Start and end of range of characters integer pos1 pos2 num=${NUMERIC:-1} local style word @@ -28,10 +28,10 @@ while (( num-- )); do if (( MARK > CURSOR )); then # if cursor is at the start of the selection, just move back a word match-words-by-style - if [[ $style = i && -n $matched_words[3] ]]; then - word=$matched_words[3] + if [[ $style = i && -n $matched_words[ws-before-cursor] ]]; then + word=$matched_words[ws-before-cursor] else - word=$matched_words[2]$matched_words[3] + word=$matched_words[word-before-cursor]$matched_words[ws-before-cursor] fi if [[ -n $word ]]; then (( CURSOR -= ${#word} )) @@ -43,41 +43,40 @@ while (( num-- )); do (( CURSOR+1 == $#BUFFER )) && return 1 (( CURSOR++ )) match-words-by-style - if [[ -n $matched_words[4] ]]; then + if [[ -n $matched_words[ws-after-cursor] ]]; then if [[ $style = i ]]; then # just skip the whitespace - word=$matched_words[4] + word=$matched_words[ws-after-cursor] else # skip the whitespace plus word - word=$matched_words[4]$matched_words[5] + word=$matched_words[ws-after-cursor]$matched_words[word-after-cursor] fi else if [[ $style = i ]]; then # skip the word - word=$matched_words[5] + word=$matched_words[word-after-cursor] else # skip word and following whitespace - word=$matched_words[5]$matched_words[6] + word=$matched_words[word-after-cursor]$matched_words[ws-after-word] fi fi (( CURSOR += ${#word} - 1 )) else match-words-by-style - if [[ -n "${matched_words[3]}" ]]; then - # There's whitespace before the cursor, so the word we are selecting - # starts at the cursor position. + if (( ${matched_words[is-word-start]} )); then + # The word we are selecting starts at the cursor position. pos1=$CURSOR else # No whitespace before us, so select any wordcharacters there. - pos1="${#matched_words[1]}" + pos1="${#matched_words[start]}" fi - if [[ -n "${matched_words[4]}" ]]; then - if [[ -n "${matched_words[3]}" ]] || (( CURSOR == 0 )); then + if [[ -n "${matched_words[ws-after-cursor]}" ]]; then + if [[ -n "${matched_words[ws-before-cursor]}" ]] || (( CURSOR == 0 )); then # whitespace either side, select it - (( pos1 = CURSOR - ${#matched_words[3]} )) - (( pos2 = CURSOR + ${#matched_words[4]} )) + (( pos1 = CURSOR - ${#matched_words[ws-before-cursor]} )) + (( pos2 = CURSOR + ${#matched_words[ws-after-cursor]} )) else # There's whitespace at the cursor position, so only select # up to the cursor position. @@ -86,28 +85,28 @@ while (( num-- )); do else # No whitespace at the cursor position, so select the # current character and any following wordcharacters. - (( pos2 = CURSOR + ${#matched_words[5]} )) + (( pos2 = CURSOR + ${#matched_words[word-after-cursor]} )) fi if [[ $style = a ]]; then - if [[ -n "${matched_words[4]}" && ( -n "${matched_words[3]}" || CURSOR -eq 0 ) ]]; then + if [[ -n "${matched_words[ws-after-cursor]}" && ( -n "${matched_words[ws-before-cursor]}" || CURSOR -eq 0 ) ]]; then # in the middle of whitespace so grab a word - if [[ -n "${matched_words[5]}" ]]; then - (( pos2 += ${#matched_words[5]} )) # preferably the one after + if [[ -n "${matched_words[word-after-cursor]}" ]]; then + (( pos2 += ${#matched_words[word-after-cursor]} )) # preferably the one after else - (( pos1 -= ${#matched_words[2]} )) # otherwise the one before + (( pos1 -= ${#matched_words[word-before-cursor]} )) # otherwise the one before fi - elif [[ -n "${matched_words[6]}" ]]; then - (( pos2 += ${#matched_words[6]} )) - elif [[ -n "${matched_words[3]}" ]]; then + elif [[ -n "${matched_words[ws-after-word]}" ]]; then + (( pos2 += ${#matched_words[ws-after-word]} )) + elif [[ -n "${matched_words[ws-before-cursor]}" ]]; then # couldn't grab whitespace forwards so try backwards - (( pos1 -= ${#matched_words[3]} )) + (( pos1 -= ${#matched_words[ws-before-cursor]} )) elif (( pos1 > 0 )); then # There might have been whitespace before the word (( CURSOR = pos1 )) match-words-by-style - if [[ -n "${matched_words[3]}" ]]; then - (( pos1 -= ${#matched_words[3]} )) + if [[ -n "${matched_words[ws-before-cursor]}" ]]; then + (( pos1 -= ${#matched_words[ws-before-cursor]} )) fi fi fi -- 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') 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 7154052ebe3d810390164a05c39ff83f98a1d858 Mon Sep 17 00:00:00 2001 From: Daniel Shahaf Date: Sat, 30 Jul 2016 16:16:22 +0000 Subject: 39046 + 39061: New :P history modifier. --- ChangeLog | 10 ++++++++++ Completion/Base/Completer/_external_pwds | 2 +- Completion/Zsh/Type/_history_modifiers | 5 +++-- Doc/Zsh/contrib.yo | 2 +- Doc/Zsh/expn.yo | 9 +++++++++ Functions/MIME/zsh-mime-handler | 2 +- Functions/VCS_Info/VCS_INFO_quilt | 2 +- Functions/Zle/expand-absolute-path | 2 +- NEWS | 11 +++++++++++ Src/params.c | 2 +- Src/subst.c | 13 +++++++++++++ Src/utils.c | 14 ++++++++------ Test/D02glob.ztst | 8 ++++++++ 13 files changed, 68 insertions(+), 14 deletions(-) (limited to 'Functions') diff --git a/ChangeLog b/ChangeLog index 65263033a..d3a7d3356 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,13 @@ +2016-08-22 Daniel Shahaf + + * 39046 + 39061: Completion/Base/Completer/_external_pwds, + Completion/Zsh/Type/_history_modifiers, Doc/Zsh/contrib.yo, + Doc/Zsh/expn.yo, Functions/MIME/zsh-mime-handler, + Functions/VCS_Info/VCS_INFO_quilt, + Functions/Zle/expand-absolute-path, NEWS, Src/params.c, + Src/subst.c, Src/utils.c, Test/D02glob.ztst: New :P history + modifier. + 2016-08-20 Jun-ichi Takimoto * 39064: configure.ac, Src/Modules/mathfuc.c: use scalbn() instead diff --git a/Completion/Base/Completer/_external_pwds b/Completion/Base/Completer/_external_pwds index 4ad50f02b..79e3ba0eb 100644 --- a/Completion/Base/Completer/_external_pwds +++ b/Completion/Base/Completer/_external_pwds @@ -22,7 +22,7 @@ case $OSTYPE in ) ;; linux*) - dirs=( /proc/${^$(pidof zsh):#$$}/cwd(N:A) ) + dirs=( /proc/${^$(pidof zsh):#$$}/cwd(N:P) ) dirs=( $^dirs(N^@) ) ;; *) diff --git a/Completion/Zsh/Type/_history_modifiers b/Completion/Zsh/Type/_history_modifiers index 658f9f346..1a049d6cb 100644 --- a/Completion/Zsh/Type/_history_modifiers +++ b/Completion/Zsh/Type/_history_modifiers @@ -64,8 +64,8 @@ while true; do ) if (( ! global )); then list+=( - "a:absolute path" - "A:absolute path resolving symbolic links" + "a:absolute path, resolve '..' lexically" + "A:as ':a', then resolve symlinks" "c:PATH search for command" "g:globally apply s or &" "h:head - strip trailing path element" @@ -73,6 +73,7 @@ while true; do "r:root - strip suffix" "e:leave only extension" "Q:strip quotes" + "P:realpath, resolve '..' physically" "l:lower case all words" "u:upper case all words" ) diff --git a/Doc/Zsh/contrib.yo b/Doc/Zsh/contrib.yo index 00ed08029..63df292ac 100644 --- a/Doc/Zsh/contrib.yo +++ b/Doc/Zsh/contrib.yo @@ -3477,7 +3477,7 @@ will ensure that any files found in that area will be executed as MIME types even if they are executable. As this example shows, the complete file name is matched against the pattern, regardless of how the file was passed to the handler. The file is resolved to a full path using -the tt(:A) modifier described in +the tt(:P) modifier described in ifzman(the subsection Modifiers in zmanref(zshexpn))\ ifnzman(noderef(Modifiers)); this means that symbolic links are resolved where possible, so that diff --git a/Doc/Zsh/expn.yo b/Doc/Zsh/expn.yo index ca4b94f5e..ecb1877a2 100644 --- a/Doc/Zsh/expn.yo +++ b/Doc/Zsh/expn.yo @@ -240,6 +240,7 @@ function, symbolic links are not resolved, so on those systems `tt(a)' and `tt(A)' are equivalent. Note: tt(foo:A) and tt(realpath+LPAR()foo+RPAR()) are different on some inputs. +For tt(realpath+LPAR()foo+RPAR()) semantics, see the `tt(P)` modifier. ) item(tt(c))( Resolve a command name into an absolute path by searching the command @@ -265,6 +266,14 @@ item(tt(p))( Print the new command but do not execute it. Only works with history expansion. ) +item(tt(P))( +Turn a file name into an absolute path, like tt(realpath+LPAR()3+RPAR()). +The resulting path will be absolute, have neither `tt(.)' nor `tt(..)' components, +and refer to the same directory entry as the input filename. + +Unlike tt(realpath+LPAR()3+RPAR()), non-existent trailing components are +permitted and preserved. +) item(tt(q))( Quote the substituted words, escaping further substitutions. Works with history expansion and parameter expansion, though for parameters diff --git a/Functions/MIME/zsh-mime-handler b/Functions/MIME/zsh-mime-handler index 24e5184fc..288a0796d 100644 --- a/Functions/MIME/zsh-mime-handler +++ b/Functions/MIME/zsh-mime-handler @@ -127,7 +127,7 @@ for pattern in $exec_asis; do files=(${dirpref}${~pattern}) if [[ -n ${files[(r)$1]} ]]; then for pattern in $exec_never; do - [[ ${1:A} = ${~pattern} ]] && break 2 + [[ ${1:P} = ${~pattern} ]] && break 2 done if (( list )); then for (( i = 1; i <= $#; i++ )); do diff --git a/Functions/VCS_Info/VCS_INFO_quilt b/Functions/VCS_Info/VCS_INFO_quilt index e7cd89f78..6adf0a358 100644 --- a/Functions/VCS_Info/VCS_INFO_quilt +++ b/Functions/VCS_Info/VCS_INFO_quilt @@ -170,7 +170,7 @@ function VCS_INFO_quilt() { applied=() fi patches=$(<$pc/.quilt_patches) - patches=`builtin cd -q "${pc:h}" && print -r - ${patches:A}` + patches=`builtin cd -q "${pc:h}" && print -r - ${patches:P}` fi if zstyle -t "${context}" get-unapplied; then # This zstyle call needs to be moved further up if `quilt' needs diff --git a/Functions/Zle/expand-absolute-path b/Functions/Zle/expand-absolute-path index b85757600..4887f3c60 100644 --- a/Functions/Zle/expand-absolute-path +++ b/Functions/Zle/expand-absolute-path @@ -10,7 +10,7 @@ autoload -Uz modify-current-argument if (( ! ${+functions[glob-expand-absolute-path]} )); then glob-expand-absolute-path() { local -a files - files=(${~1}(N:A)) + files=(${~1}(N:P)) (( ${#files} )) || return REPLY=${(D)files[1]} } diff --git a/NEWS b/NEWS index 15822ad34..65b246d33 100644 --- a/NEWS +++ b/NEWS @@ -4,6 +4,17 @@ CHANGES FROM PREVIOUS VERSIONS OF ZSH Note also the list of incompatibilities in the README file. +Changes from 5.2 to 5.3 +----------------------- + +The new word modifier ':P' computes the physical path of the argument. +It is different from the existing ':a' modifier which always resolves +'/before/here/../after' to '/before/after', and differs from the +existing ':A' modifier which resolves symlinks only after 'here/..' is +removed, even when /before/here is itself a symbolic link. It is +recommended to review uses of ':A' and, if appropriate, convert them +to ':P' as soon as compatibility with 5.2 is no longer a requirement. + Changes from 5.1.1 to 5.2 ------------------------- diff --git a/Src/params.c b/Src/params.c index 0eda7848f..842b2f0d1 100644 --- a/Src/params.c +++ b/Src/params.c @@ -4336,7 +4336,7 @@ void homesetfn(UNUSED(Param pm), char *x) { zsfree(home); - if (x && isset(CHASELINKS) && (home = xsymlink(x))) + if (x && isset(CHASELINKS) && (home = xsymlink(x, 0))) zsfree(x); else home = x ? x : ztrdup(""); diff --git a/Src/subst.c b/Src/subst.c index c61551bf6..15eb59b64 100644 --- a/Src/subst.c +++ b/Src/subst.c @@ -4081,6 +4081,7 @@ modify(char **str, char **ptr) case 'u': case 'q': case 'Q': + case 'P': c = **ptr; break; @@ -4287,6 +4288,12 @@ modify(char **str, char **ptr) untokenize(copy); } break; + case 'P': + if (*copy != '/') { + copy = zhtricat(metafy(zgetcwd(), -1, META_HEAPDUP), "/", copy); + } + copy = xsymlink(copy, 1); + break; } tc = *tt; *tt = '\0'; @@ -4363,6 +4370,12 @@ modify(char **str, char **ptr) untokenize(*str); } break; + case 'P': + if (**str != '/') { + *str = zhtricat(metafy(zgetcwd(), -1, META_HEAPDUP), "/", *str); + } + *str = xsymlink(*str, 1); + break; } } if (rec < 0) { diff --git a/Src/utils.c b/Src/utils.c index 0a5954f65..45fd19286 100644 --- a/Src/utils.c +++ b/Src/utils.c @@ -801,9 +801,9 @@ findpwd(char *s) char *t; if (*s == '/') - return xsymlink(s); + return xsymlink(s, 0); s = tricat((pwd[1]) ? pwd : "", "/", s); - t = xsymlink(s); + t = xsymlink(s, 0); zsfree(s); return t; } @@ -969,11 +969,13 @@ xsymlinks(char *s, int full) /* * expand symlinks in s, and remove other weird things: * note that this always expands symlinks. + * + * 'heap' indicates whether to malloc() or allocate on the heap. */ /**/ char * -xsymlink(char *s) +xsymlink(char *s, int heap) { if (*s != '/') return NULL; @@ -981,8 +983,8 @@ xsymlink(char *s) if (xsymlinks(s + 1, 1) < 0) zwarn("path expansion failed, using root directory"); if (!*xbuf) - return ztrdup("/"); - return ztrdup(xbuf); + return heap ? dupstring("/") : ztrdup("/"); + return heap ? dupstring(xbuf) : ztrdup(xbuf); } /**/ @@ -1260,7 +1262,7 @@ getnameddir(char *name) /* Retrieve an entry from the password table/database for this user. */ struct passwd *pw; if ((pw = getpwnam(name))) { - char *dir = isset(CHASELINKS) ? xsymlink(pw->pw_dir) + char *dir = isset(CHASELINKS) ? xsymlink(pw->pw_dir, 0) : ztrdup(pw->pw_dir); if (dir) { adduserdir(name, dir, ND_USERNAME, 1); diff --git a/Test/D02glob.ztst b/Test/D02glob.ztst index 7befbc21f..1385d57d9 100644 --- a/Test/D02glob.ztst +++ b/Test/D02glob.ztst @@ -678,3 +678,11 @@ rm glob.tmp/link 0:modifier ':A' resolves '..' components before symlinks # There should be no output + + ln -s dir3/subdir glob.tmp/link + () { + print ${1:P} + } glob.tmp/link/../../hello/world + rm glob.tmp/link +0:modifier ':P' resolves symlinks before '..' components +*>*glob.tmp/hello/world -- 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') 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 c3fbd97f9bf1b7fb6ec962d78761d872d570a850 Mon Sep 17 00:00:00 2001 From: Mikael Magnusson Date: Thu, 15 Sep 2016 20:13:29 +0200 Subject: bracketed-paste-url-magic: Handle magnet links too, and allow for schemes without // --- ChangeLog | 5 +++++ Functions/Zle/bracketed-paste-url-magic | 4 ++-- 2 files changed, 7 insertions(+), 2 deletions(-) (limited to 'Functions') diff --git a/ChangeLog b/ChangeLog index e68ed6d5d..e92c7b24d 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2016-09-19 Mikael Magnusson + + * 39351: Functions/Zle/bracketed-paste-url-magic: Handle magnet + links too, and allow for schemes without // + 2016-09-18 Daniel Shahaf * 39374: Completion/Debian/Command/_apt: Complete package diff --git a/Functions/Zle/bracketed-paste-url-magic b/Functions/Zle/bracketed-paste-url-magic index 06dee2657..b894696bb 100644 --- a/Functions/Zle/bracketed-paste-url-magic +++ b/Functions/Zle/bracketed-paste-url-magic @@ -19,7 +19,7 @@ # The default can be seen just below. local -a schema -zstyle -a :bracketed-paste-url-magic schema schema || schema=(http https ftp ftps file ssh sftp) +zstyle -a :bracketed-paste-url-magic schema schema || schema=(http:// https:// ftp:// ftps:// file:// ssh:// sftp:// magnet:) local wantquote=${NUMERIC:-0} local content @@ -28,7 +28,7 @@ local start=$#LBUFFER zle .$WIDGET -N content if (( $wantquote == 0 )); then - if [[ $content = (${(~j:|:)schema})://* ]]; then + if [[ $content = (${(~j:|:)schema})* ]]; then wantquote=1 fi fi -- cgit v1.2.3 From 889f6690fd678ed2fdeb4d467e5b8db49b9c6667 Mon Sep 17 00:00:00 2001 From: Daniel Shahaf Date: Fri, 23 Sep 2016 06:47:31 +0000 Subject: 39423: vcs_info git: Produce nicer applied-string messages for 'exec' actions. This changes the behaviour on "unknown" git-rebase actions (those other than pick/reword/edit/fixup/squash/execute). --- ChangeLog | 6 ++++++ Functions/VCS_Info/Backends/VCS_INFO_get_data_git | 8 ++++++-- 2 files changed, 12 insertions(+), 2 deletions(-) (limited to 'Functions') diff --git a/ChangeLog b/ChangeLog index 608a296e0..8362d3e7b 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2016-09-24 Daniel Shahaf + + * 39423: Functions/VCS_Info/Backends/VCS_INFO_get_data_git: + vcs_info git: Produce nicer applied-string messages for 'exec' + actions. + 2016-09-23 Daniel Shahaf * 39412: Src/Zle/computil.c: Fix directory completion when diff --git a/Functions/VCS_Info/Backends/VCS_INFO_get_data_git b/Functions/VCS_Info/Backends/VCS_INFO_get_data_git index 472c10d5d..18ba89a9a 100644 --- a/Functions/VCS_Info/Backends/VCS_INFO_get_data_git +++ b/Functions/VCS_Info/Backends/VCS_INFO_get_data_git @@ -213,8 +213,12 @@ elif [[ -d "${gitdir}/rebase-merge" ]]; then local p [[ -f "${patchdir}/done" ]] && for p in ${(f)"$(< "${patchdir}/done")"}; do - # remove action - git_patches_applied+=("${${(s: :)p}[2,-1]}") + # pick/edit/fixup/squash/reword: Add "$hash $subject" to $git_patches_applied. + # exec: Add "exec ${command}" to $git_patches_applied. + # (anything else): As 'exec'. + p=${p/(#s)(p|pick|e|edit|r|reword|f|fixup|s|squash) /} + p=${p/(#s)x /exec } + git_patches_applied+=("$p") done if [[ -f "${patchdir}/git-rebase-todo" ]] ; then git_patches_unapplied=(${(f)"$(grep -v '^$' "${patchdir}/git-rebase-todo" | grep -v '^#')"}) -- 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') 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 From 9cfd26bf10f530d746afadf3a04c4cf401fbbb9d Mon Sep 17 00:00:00 2001 From: "Barton E. Schaefer" Date: Fri, 28 Oct 2016 16:44:35 -0700 Subject: unposted: handle empty pastes and "zle bracketed-paste variablename" form. --- ChangeLog | 5 +++++ Functions/Zle/bracketed-paste-magic | 4 ++-- 2 files changed, 7 insertions(+), 2 deletions(-) (limited to 'Functions') diff --git a/ChangeLog b/ChangeLog index 45ab87de5..f7487f01a 100644 --- a/ChangeLog +++ b/ChangeLog @@ -3,6 +3,11 @@ * users/22036: Doc/Zsh/zle.yo: bracketed-paste: Document cutbuffer behaviour; clarify. +2016-10-27 Barton E. Schaefer + + * unposted: Functions/Zle/bracketed-paste-magic: handle empty + pastes and "zle bracketed-paste variablename" form. + 2016-10-27 Daniel Shahaf * unposted: Doc/Zsh/compsys.yo, Doc/Zsh/contrib.yo: Minor diff --git a/Functions/Zle/bracketed-paste-magic b/Functions/Zle/bracketed-paste-magic index cf3cc6a59..a82045e08 100644 --- a/Functions/Zle/bracketed-paste-magic +++ b/Functions/Zle/bracketed-paste-magic @@ -162,7 +162,7 @@ bracketed-paste-magic() { # There are active widgets. Reprocess $PASTED as keystrokes. NUMERIC=1 - zle -U - $PASTED + zle -U - "$PASTED" # Just in case there are active undo widgets @@ -206,7 +206,7 @@ bracketed-paste-magic() { # Reprocess $PASTED as an actual paste this time zle -U - $PASTED$'\e[201~' # append paste-end marker - zle .bracketed-paste + zle .bracketed-paste "$@" zle .split-undo # Arrange to display highlighting if necessary -- cgit v1.2.3 From 87c951c6bd5f889ec849ea45353969b407f8d5d5 Mon Sep 17 00:00:00 2001 From: "Barton E. Schaefer" Date: Sat, 29 Oct 2016 10:08:53 -0700 Subject: unposted: add "--" to zle widget call for conventional sanity --- Functions/Zle/bracketed-paste-magic | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Functions') diff --git a/Functions/Zle/bracketed-paste-magic b/Functions/Zle/bracketed-paste-magic index a82045e08..fb584d595 100644 --- a/Functions/Zle/bracketed-paste-magic +++ b/Functions/Zle/bracketed-paste-magic @@ -206,7 +206,7 @@ bracketed-paste-magic() { # Reprocess $PASTED as an actual paste this time zle -U - $PASTED$'\e[201~' # append paste-end marker - zle .bracketed-paste "$@" + zle .bracketed-paste -- "$@" zle .split-undo # Arrange to display highlighting if necessary -- cgit v1.2.3 From 74aa45910b3711622e9eb5ccf8adef9566db6f62 Mon Sep 17 00:00:00 2001 From: Daniel Shahaf Date: Mon, 31 Oct 2016 18:35:19 +0000 Subject: 39786: vcs_info (hg): Use native hexdump implementation instead of external command. Fixes issue whereby the external command would print "*" for repeated octets. Includes comment change, cf 39790. --- ChangeLog | 7 +++++++ Functions/VCS_Info/Backends/VCS_INFO_get_data_hg | 7 ++++--- Functions/VCS_Info/VCS_INFO_hexdump | 16 ++++++++++++++++ Functions/VCS_Info/vcs_info | 1 + 4 files changed, 28 insertions(+), 3 deletions(-) create mode 100644 Functions/VCS_Info/VCS_INFO_hexdump (limited to 'Functions') diff --git a/ChangeLog b/ChangeLog index e08cafd30..9dd63251e 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,10 @@ +2016-10-31 Daniel Shahaf + + * 39786: Functions/VCS_Info/Backends/VCS_INFO_get_data_hg, + Functions/VCS_Info/VCS_INFO_hexdump, Functions/VCS_Info/vcs_info: + vcs_info (hg): Use native hexdump implementation instead of + external command. + 2016-10-30 Peter Stephenson * 39777: Src/parse.c, Test/D08cmdsubst.ztst: $() is a valid diff --git a/Functions/VCS_Info/Backends/VCS_INFO_get_data_hg b/Functions/VCS_Info/Backends/VCS_INFO_get_data_hg index f35ad5965..69b7db304 100644 --- a/Functions/VCS_Info/Backends/VCS_INFO_get_data_hg +++ b/Functions/VCS_Info/Backends/VCS_INFO_get_data_hg @@ -40,9 +40,10 @@ VCS_INFO_adjust # Disabled by default anyway, so no harm done. if zstyle -t ":vcs_info:${vcs}:${usercontext}:${rrn}" get-revision ; then if zstyle -t ":vcs_info:${vcs}:${usercontext}:${rrn}" use-simple \ - && ( VCS_INFO_check_com hexdump ) && [[ -r ${dirstatefile} ]] ; then - # Calling hexdump is (much) faster than hg but doesn't get the local rev - r_csetid=$(hexdump -n 20 -e '1/1 "%02x"' ${dirstatefile}) + && VCS_INFO_hexdump ${dirstatefile} 20 ; then + # Calling VCS_INFO_hexdump is (much) faster than hg but doesn't get + # the local rev + r_csetid=$REPLY else # Settling for a short (but unique!) hash because getting the full # 40-char hash in addition to all the other info we want isn't diff --git a/Functions/VCS_Info/VCS_INFO_hexdump b/Functions/VCS_Info/VCS_INFO_hexdump new file mode 100644 index 000000000..11f1c1a50 --- /dev/null +++ b/Functions/VCS_Info/VCS_INFO_hexdump @@ -0,0 +1,16 @@ +## vim:ft=zsh + +# VCS_INFO_hexdump FILENAME BYTECOUNT +# +# Return in $REPLY a hexadecimal representation (lowercase, no whitespace) +# of the first BYTECOUNT bytes of FILENAME. + +if [[ -r $1 ]]; then + setopt localoptions nomultibyte extendedglob + local val + read -k $2 -u 0 val <$1 + REPLY=${(Lj::)${(l:2::0:)${(@s//)val}//(#m)*/$(( [##16] ##$MATCH ))}} +else + return 1 +fi + diff --git a/Functions/VCS_Info/vcs_info b/Functions/VCS_Info/vcs_info index f13f6b501..c0c1182e6 100644 --- a/Functions/VCS_Info/vcs_info +++ b/Functions/VCS_Info/vcs_info @@ -19,6 +19,7 @@ static_functions=( VCS_INFO_check_com VCS_INFO_formats VCS_INFO_get_cmd + VCS_INFO_hexdump VCS_INFO_hook VCS_INFO_maxexports VCS_INFO_nvcsformats -- cgit v1.2.3 From 488d73c07dbbd2f2a2c6ee934aee71d4aa776c3a Mon Sep 17 00:00:00 2001 From: Oliver Kiddle Date: Wed, 9 Nov 2016 16:53:23 +0100 Subject: 39884: fix history-beginning-search-menu for history lines containing a pipe character --- ChangeLog | 5 +++++ Functions/Zle/history-beginning-search-menu | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) (limited to 'Functions') diff --git a/ChangeLog b/ChangeLog index 9a223e1f1..8303a5446 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2016-11-09 Oliver Kiddle + + * 39884: Functions/Zle/history-beginning-search-menu: + fix for history lines containing a pipe character + 2016-11-09 Barton E. Schaefer * 39882: Doc/Zsh/expn.yo: mention ${name:/pattern/replacement} diff --git a/Functions/Zle/history-beginning-search-menu b/Functions/Zle/history-beginning-search-menu index 105518102..0e1bbc734 100644 --- a/Functions/Zle/history-beginning-search-menu +++ b/Functions/Zle/history-beginning-search-menu @@ -112,7 +112,7 @@ fi # go to the last one. This allows accept-line-and-down-history etc. # to work. local -a lines -local matchq=${matches[$chars]//(#m)[\][()\\*?#<>~^]/\\$MATCH} +local matchq=${matches[$chars]//(#m)[\][|()\\*?#<>~^]/\\$MATCH} lines=(${(kon)history[(R)$matchq]}) HISTNO=$lines[-1] -- cgit v1.2.3 From cb5f100bd38a3b21739897fb4236db0700b39477 Mon Sep 17 00:00:00 2001 From: Oliver Kiddle Date: Sun, 20 Nov 2016 23:54:45 +0100 Subject: 39986, 39989: improve handling of vi-repeat-change Save previous vi change and throw away a new change that fails. Add zle -f vichange to allow shell widget to be a single change. Fix repeat of command where numeric arguments were multiplied. --- ChangeLog | 7 +++ Doc/Zsh/zle.yo | 7 +++ Functions/Zle/vi-pipe | 3 ++ Src/Zle/zle.h | 14 ++++++ Src/Zle/zle_keymap.c | 2 +- Src/Zle/zle_main.c | 34 +++++++++++-- Src/Zle/zle_misc.c | 8 ++- Src/Zle/zle_thingy.c | 11 +++- Src/Zle/zle_utils.c | 1 + Src/Zle/zle_vi.c | 137 +++++++++++++++++++++++--------------------------- Test/X02zlevi.ztst | 10 ++-- 11 files changed, 147 insertions(+), 87 deletions(-) (limited to 'Functions') diff --git a/ChangeLog b/ChangeLog index 1095a1e5c..24fb8a3f3 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,12 @@ 2016-11-20 Oliver Kiddle + * 39986, 39989: Src/Zle/zle.h, Src/Zle/zle_keymap.c, + Src/Zle/zle_main.c, Src/Zle/zle_misc.c, Src/Zle/zle_thingy.c, + Src/Zle/zle_utils.c, Src/Zle/zle_vi.c, Test/X02zlevi.ztst, + Doc/Zsh/zle.yo, Functions/Zle/vi-pipe: make vi-repeat-change + work better with shell based widgets and save old change + when recording a new change in case the new one fails + * 39974: Completion/Unix/Command/_ssh: complete shared libraries for -e and -s options to ssh-add diff --git a/Doc/Zsh/zle.yo b/Doc/Zsh/zle.yo index fe6a7e93b..ff3144802 100644 --- a/Doc/Zsh/zle.yo +++ b/Doc/Zsh/zle.yo @@ -479,6 +479,13 @@ tt(kill) for indicating that text has been killed into the cutbuffer. When repeatedly invoking a kill widget, text is appended to the cutbuffer instead of replacing it, but when wrapping such widgets, it is necessary to call `tt(zle -f kill)' to retain this effect. + +tt(vichange) for indicating that the widget represents a vi change that +can be repeated as a whole with `tt(vi-repeat-change)'. The flag should be set +early in the function before inspecting the value of tt(NUMERIC) or invoking +other widgets. This has no effect for a widget invoked from insert mode. If +insert mode is active when the widget finishes, the change extends until next +returning to command mode. ) cindex(completion widgets, creating) item(tt(-C) var(widget) var(completion-widget) var(function))( diff --git a/Functions/Zle/vi-pipe b/Functions/Zle/vi-pipe index c32e64a59..1729cb6e1 100644 --- a/Functions/Zle/vi-pipe +++ b/Functions/Zle/vi-pipe @@ -12,6 +12,9 @@ setopt localoptions noksharrays autoload -Uz read-from-minibuffer local _save_cut="$CUTBUFFER" REPLY +# mark this widget as a vi change so it can be repeated as a whole +zle -f vichange + # force movement to default to line mode (( REGION_ACTIVE )) || zle -U V # Use the standard vi-change to accept a vi motion. diff --git a/Src/Zle/zle.h b/Src/Zle/zle.h index e9b14281d..8f92e5611 100644 --- a/Src/Zle/zle.h +++ b/Src/Zle/zle.h @@ -284,6 +284,20 @@ struct change { #define CH_NEXT (1<<0) /* next structure is also part of this change */ #define CH_PREV (1<<1) /* previous structure is also part of this change */ +/* vi change handling for vi-repeat-change */ + +/* + * Examination of the code suggests vichgbuf is consistently tied + * to raw byte input, so it is left as a character array rather + * than turned into wide characters. In particular, when we replay + * it we use ungetbytes(). + */ +struct vichange { + struct modifier mod; /* value of zmod associated with vi change */ + char *buf; /* bytes for keys that make up the vi command */ + int bufsz, bufptr; /* allocated and in use sizes of buf */ +}; + /* known thingies */ #define Th(X) (&thingies[X]) diff --git a/Src/Zle/zle_keymap.c b/Src/Zle/zle_keymap.c index 24e8d1964..04eb70675 100644 --- a/Src/Zle/zle_keymap.c +++ b/Src/Zle/zle_keymap.c @@ -1634,7 +1634,7 @@ getkeymapcmd(Keymap km, Thingy *funcp, char **strp) unmetafy(keybuf + lastlen, &keybuflen); ungetbytes(keybuf+lastlen, keybuflen); if(vichgflag) - vichgbufptr -= keybuflen; + curvichg.bufptr -= keybuflen; keybuf[keybuflen = lastlen] = 0; } *funcp = func; diff --git a/Src/Zle/zle_main.c b/Src/Zle/zle_main.c index 1652b7cd4..938dc0e29 100644 --- a/Src/Zle/zle_main.c +++ b/Src/Zle/zle_main.c @@ -924,13 +924,13 @@ getbyte(long do_keytmout, int *timeout) ret = STOUC(cc); } /* - * vichgbuf is raw bytes, not wide characters, so is dealt + * curvichg.buf is raw bytes, not wide characters, so is dealt * with here. */ if (vichgflag) { - if (vichgbufptr == vichgbufsz) - vichgbuf = realloc(vichgbuf, vichgbufsz *= 2); - vichgbuf[vichgbufptr++] = ret; + if (curvichg.bufptr == curvichg.bufsz) + curvichg.buf = realloc(curvichg.buf, curvichg.bufsz *= 2); + curvichg.buf[curvichg.bufptr++] = ret; } errno = old_errno; return lastchar = ret; @@ -1260,6 +1260,7 @@ zleread(char **lp, char **rp, int flags, int context, char *init, char *finish) *zleline = ZWC('\0'); virangeflag = lastcmd = done = zlecs = zlell = mark = yankb = yanke = 0; vichgflag = 0; + viinrepeat = 0; viinsbegin = 0; statusline = NULL; selectkeymap("main", 1); @@ -1389,6 +1390,8 @@ int execzlefunc(Thingy func, char **args, int set_bindk) { int r = 0, ret = 0, remetafy = 0; + int nestedvichg = vichgflag; + int isrepeat = (viinrepeat == 3); Widget w; Thingy save_bindk = bindk; @@ -1398,6 +1401,8 @@ execzlefunc(Thingy func, char **args, int set_bindk) unmetafy_line(); remetafy = 1; } + if (isrepeat) + viinrepeat = 2; if (func->flags & DISABLED) { /* this thingy is not the name of a widget */ @@ -1523,6 +1528,25 @@ execzlefunc(Thingy func, char **args, int set_bindk) CCRIGHT(); if (remetafy) metafy_line(); + + /* if this widget constituted the vi change, end it */ + if (vichgflag == 2 && !nestedvichg) { + if (invicmdmode()) { + if (ret) { + free(curvichg.buf); + } else { + if (lastvichg.buf) + free(lastvichg.buf); + lastvichg = curvichg; + } + vichgflag = 0; + curvichg.buf = NULL; + } else + vichgflag = 1; /* vi change continues while in insert mode */ + } + if (isrepeat) + viinrepeat = !invicmdmode(); + return ret; } @@ -2230,7 +2254,7 @@ finish_(UNUSED(Module m)) cleanup_keymaps(); deletehashtable(thingytab); - zfree(vichgbuf, vichgbufsz); + zfree(lastvichg.buf, lastvichg.bufsz); zfree(kungetbuf, kungetsz); free_isrch_spots(); if (rdstrs) diff --git a/Src/Zle/zle_misc.c b/Src/Zle/zle_misc.c index fbd40cd03..898b552de 100644 --- a/Src/Zle/zle_misc.c +++ b/Src/Zle/zle_misc.c @@ -609,8 +609,10 @@ viputbefore(UNUSED(char **args)) int n = zmult; startvichange(-1); - if (n < 0 || zmod.flags & MOD_NULL) + if (n < 0) return 1; + if (zmod.flags & MOD_NULL) + return 0; if (zmod.flags & MOD_VIBUF) kctbuf = &vibuf[zmod.vibuf]; else @@ -630,8 +632,10 @@ viputafter(UNUSED(char **args)) int n = zmult; startvichange(-1); - if (n < 0 || zmod.flags & MOD_NULL) + if (n < 0) return 1; + if (zmod.flags & MOD_NULL) + return 0; if (zmod.flags & MOD_VIBUF) kctbuf = &vibuf[zmod.vibuf]; else diff --git a/Src/Zle/zle_thingy.c b/Src/Zle/zle_thingy.c index 2d4674785..c7092854a 100644 --- a/Src/Zle/zle_thingy.c +++ b/Src/Zle/zle_thingy.c @@ -678,7 +678,16 @@ bin_zle_flags(char *name, char **args, UNUSED(Options ops), UNUSED(char func)) else if (!strcmp(*flag, "keepsuffix")) w->flags |= ZLE_KEEPSUFFIX; */ - else { + else if (!strcmp(*flag, "vichange")) { + if (invicmdmode()) { + startvichange(-1); + if (zmod.flags & (MOD_MULT|MOD_TMULT)) { + Param pm = (Param) paramtab->getnode(paramtab, "NUMERIC"); + if (pm && pm->node.flags & PM_SPECIAL) + pm->node.flags &= ~PM_UNSET; + } + } + } else { zwarnnam(name, "invalid flag `%s' given to zle -f", *flag); ret = 1; } diff --git a/Src/Zle/zle_utils.c b/Src/Zle/zle_utils.c index 4007c1112..c6df3d89c 100644 --- a/Src/Zle/zle_utils.c +++ b/Src/Zle/zle_utils.c @@ -1704,6 +1704,7 @@ mergeundo(void) current->flags |= CH_PREV; current->prev->flags |= CH_NEXT; } + vistartchange = -1; } /* diff --git a/Src/Zle/zle_vi.c b/Src/Zle/zle_vi.c index fc0e49b32..e0923db3e 100644 --- a/Src/Zle/zle_vi.c +++ b/Src/Zle/zle_vi.c @@ -45,46 +45,41 @@ int wordflag; /**/ int vilinerange; -/* last vi change buffer, for vi change repetition */ +/* + * lastvichg: last vi change buffer, for vi change repetition + * curvichg: current incomplete vi change + */ + +/**/ +struct vichange lastvichg, curvichg; /* - * vichgbufsz: Allocated size of vichgbuf. - * vichgbufptr: Length in use. - * vichgflag: true whilst inputting a vi normal mode; causes it to be - * accumulated in vichgbuf, incrementing vichgbufptr. + * true whilst a vi change is active causing keys to be + * accumulated in curvichg.buf + * first set to 2 and when the initial widget finishes, reduced to 1 if + * in insert mode implying that the change continues until returning to + * normal mode */ /**/ -int vichgbufsz, vichgbufptr, vichgflag; +int vichgflag; /* - * The bytes that make up the current vi command. See vichgbuf* above. - * - * Examination of the code suggests vichgbuf is consistently tied - * to raw byte input, so it is left as a character array rather - * than turned into wide characters. In particular, when we replay - * it we use ungetbytes(). + * analogous to vichgflag for a repeated change with the value following + * a similar pattern (is 3 until first repeated widget starts) */ + /**/ -char *vichgbuf; +int viinrepeat; /* point where vi insert mode was last entered */ /**/ int viinsbegin; -/* value of zmod associated with vi change */ -static struct modifier lastmod; - -/* - * inrepeat: current widget is the vi change being repeated - * vichgrepeat: nested widget call within a repeat - */ -static int inrepeat, vichgrepeat; - /** * im: >= 0: is an insertmode - * -1: skip setting insert mode + * -1: skip setting insert/overwrite mode * -2: entering viins at start of editing from clean --- don't use * inrepeat or keybuf, synthesise an entry to insert mode. * Note that zmult is updated so this should be called before zmult is used. @@ -94,30 +89,27 @@ static int inrepeat, vichgrepeat; void startvichange(int im) { - if (im != -1) { - vichgflag = 1; - if (im > -1) - insmode = im; - } - if (inrepeat && im != -2) { - zmod = lastmod; - inrepeat = vichgflag = 0; - vichgrepeat = 1; - } else { - lastmod = zmod; - if (vichgbuf) - free(vichgbuf); - vichgbuf = (char *)zalloc(vichgbufsz = 16 + keybuflen); + if (im > -1) + insmode = im; + if (viinrepeat && im != -2) { + zmod = lastvichg.mod; + vichgflag = 0; + } else if (!vichgflag) { + curvichg.mod = zmod; + if (curvichg.buf) + free(curvichg.buf); + curvichg.buf = (char *)zalloc(curvichg.bufsz = 16 + keybuflen); if (im == -2) { - vichgbuf[0] = + vichgflag = 1; + curvichg.buf[0] = zlell ? (insmode ? (zlecs < zlell ? 'i' : 'a') : 'R') : 'o'; - vichgbuf[1] = '\0'; - vichgbufptr = 1; + curvichg.buf[1] = '\0'; + curvichg.bufptr = 1; } else { - strcpy(vichgbuf, keybuf); - unmetafy(vichgbuf, &vichgbufptr); + vichgflag = 2; + strcpy(curvichg.buf, keybuf); + unmetafy(curvichg.buf, &curvichg.bufptr); } - vichgrepeat = 0; } } @@ -226,10 +218,13 @@ getvirange(int wf) */ if ((k2 == bindk) ? dovilinerange() : execzlefunc(k2, zlenoargs, 1)) ret = -1; - if(vichgrepeat) + if (viinrepeat) zmult = mult1; - else + else { zmult = mult1 * zmod.tmult; + if (vichgflag == 2) + curvichg.mod.mult = zmult; + } } while(prefixflag && !ret); wordflag = 0; selectlocalmap(NULL); @@ -401,7 +396,6 @@ videlete(UNUSED(char **args)) vifirstnonblank(zlenoargs); } } - vichgflag = 0; return ret; } @@ -518,7 +512,6 @@ viyank(UNUSED(char **args)) cut(zlecs, c2 - zlecs, CUT_YANK); ret = 0; } - vichgflag = 0; /* cursor now at the start of the range yanked. For line mode * restore the column position */ if (vilinerange && lastcol != -1) { @@ -593,8 +586,7 @@ vireplace(UNUSED(char **args)) * a change, we always read the argument normally, even if the count * * was bad. When recording a change for repeating, and a bad count is * * given, we squash the repeat buffer to avoid repeating the partial * - * command; we've lost the previous change, but that can't be avoided * - * without a rewrite of the repeat code. */ + * command. */ /**/ int @@ -644,18 +636,12 @@ vireplacechars(UNUSED(char **args)) /* check argument range */ if (n < 1 || fail) { - if(vichgrepeat) + if (viinrepeat) vigetkey(); - if(vichgflag) { - free(vichgbuf); - vichgbuf = NULL; - vichgflag = 0; - } return 1; } /* get key */ if((ch = vigetkey()) == ZLEEOF) { - vichgflag = 0; return 1; } /* do change */ @@ -682,7 +668,6 @@ vireplacechars(UNUSED(char **args)) zleline[zlecs++] = ch; zlecs--; } - vichgflag = 0; return 0; } @@ -693,7 +678,16 @@ vicmdmode(UNUSED(char **args)) if (invicmdmode() || selectkeymap("vicmd", 0)) return 1; mergeundo(); - vichgflag = 0; + insmode = unset(OVERSTRIKE); + if (vichgflag == 1) { + vichgflag = 0; + if (lastvichg.buf) + free(lastvichg.buf); + lastvichg = curvichg; + curvichg.buf = NULL; + } + if (viinrepeat == 1) + viinrepeat = 0; if (zlecs != findbol()) DECCS(); return 0; @@ -748,7 +742,6 @@ vioperswapcase(UNUSED(char **args)) vifirstnonblank(); #endif } - vichgflag = 0; return ret; } @@ -771,7 +764,6 @@ viupcase(UNUSED(char **args)) zlecs = oldcs; ret = 0; } - vichgflag = 0; return ret; } @@ -794,7 +786,6 @@ vidowncase(UNUSED(char **args)) zlecs = oldcs; ret = 0; } - vichgflag = 0; return ret; } @@ -803,23 +794,23 @@ int virepeatchange(UNUSED(char **args)) { /* make sure we have a change to repeat */ - if (!vichgbuf || vichgflag || virangeflag) + if (!lastvichg.buf || vichgflag || virangeflag) return 1; /* restore or update the saved count and buffer */ if (zmod.flags & MOD_MULT) { - lastmod.mult = zmod.mult; - lastmod.flags |= MOD_MULT; + lastvichg.mod.mult = zmod.mult; + lastvichg.mod.flags |= MOD_MULT; } if (zmod.flags & MOD_VIBUF) { - lastmod.vibuf = zmod.vibuf; - lastmod.flags = (lastmod.flags & ~MOD_VIAPP) | + lastvichg.mod.vibuf = zmod.vibuf; + lastvichg.mod.flags = (lastvichg.mod.flags & ~MOD_VIAPP) | MOD_VIBUF | (zmod.flags & MOD_VIAPP); - } else if (lastmod.flags & MOD_VIBUF && - lastmod.vibuf >= 27 && lastmod.vibuf <= 34) - lastmod.vibuf++; /* for "1 to "8 advance to next buffer */ + } else if (lastvichg.mod.flags & MOD_VIBUF && + lastvichg.mod.vibuf >= 27 && lastvichg.mod.vibuf <= 34) + lastvichg.mod.vibuf++; /* for "1 to "8 advance to next buffer */ /* repeat the command */ - inrepeat = 1; - ungetbytes(vichgbuf, vichgbufptr); + viinrepeat = 3; + ungetbytes(lastvichg.buf, lastvichg.bufptr); return 0; } @@ -835,10 +826,8 @@ viindent(UNUSED(char **args)) region_active = 2; /* get the range */ if ((c2 = getvirange(0)) == -1) { - vichgflag = 0; return 1; } - vichgflag = 0; /* must be a line range */ if (!vilinerange) { zlecs = oldcs; @@ -873,10 +862,8 @@ viunindent(UNUSED(char **args)) region_active = 2; /* get the range */ if ((c2 = getvirange(0)) == -1) { - vichgflag = 0; return 1; } - vichgflag = 0; /* must be a line range */ if (!vilinerange) { zlecs = oldcs; diff --git a/Test/X02zlevi.ztst b/Test/X02zlevi.ztst index c19573241..d3b533490 100644 --- a/Test/X02zlevi.ztst +++ b/Test/X02zlevi.ztst @@ -140,6 +140,12 @@ >BUFFER: xxe xxx xxxee >CURSOR: 10 + zletest $'one two three four five six seven eight\e.03d2wk.1.' +0:numeric args to both action and movement are multiplied (and saved for any repeat) +>BUFFER: eight +>seven eight +>CURSOR: 0 + zletest $'yankee doodle\ebhDyy0"1P' 0:paste register 1 to get last deletion >BUFFER: doodleyankee @@ -262,10 +268,8 @@ print -u $ZTST_fd 'This test may hang the shell when it fails...' zletest $'worm\erdhd..' 0:use of vi-repeat as the motion and repeat after a failed change ->BUFFER: word +>BUFFER: wodd >CURSOR: 2 -F:For vi compatibility, "." should repeat the "rd" change after "d." -F:Update result to ">BUFFER: wodd" if compatibility is repaired. zpty_run 'bindkey "^_" undo' zletest $'undoc\037e' -- cgit v1.2.3 From 5dc7b35ff6edbecad8ee077de44d880eb7907a6f Mon Sep 17 00:00:00 2001 From: Oliver Kiddle Date: Fri, 25 Nov 2016 23:07:46 +0100 Subject: unposted: set new vichange flag for surround widget --- ChangeLog | 2 ++ Functions/Zle/surround | 1 + 2 files changed, 3 insertions(+) (limited to 'Functions') diff --git a/ChangeLog b/ChangeLog index 8ec718973..0c8e81776 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,7 @@ 2016-11-25 Oliver Kiddle + * unposted: Functions/Zle/surround: set new vichange flag + * 40020: Completion/Unix/Command/_cscope: new completion 2016-11-25 Laurent Arnoud diff --git a/Functions/Zle/surround b/Functions/Zle/surround index 348ceecc2..b51b77c04 100644 --- a/Functions/Zle/surround +++ b/Functions/Zle/surround @@ -19,6 +19,7 @@ local before after local -A matching matching=( \( \) \{ \} \< \> \[ \] ) +zle -f vichange case $WIDGET in change-*) local MARK="$MARK" CURSOR="$CURSOR" call -- cgit v1.2.3 From 8891f5a33d2617b7c7bb4f37c4340a1dd159529e Mon Sep 17 00:00:00 2001 From: Daniel Shahaf Date: Thu, 1 Dec 2016 17:11:58 +0000 Subject: unposted: vcs_info: Break out VCS_INFO_quilt-patch2subject into VCS_INFO_patch2subject ... so other places can use it; compare 40030 in the 39990 thread. --- ChangeLog | 7 +++++ Functions/VCS_Info/VCS_INFO_patch2subject | 50 +++++++++++++++++++++++++++++++ Functions/VCS_Info/VCS_INFO_quilt | 49 +----------------------------- Functions/VCS_Info/vcs_info | 1 + 4 files changed, 59 insertions(+), 48 deletions(-) create mode 100644 Functions/VCS_Info/VCS_INFO_patch2subject (limited to 'Functions') diff --git a/ChangeLog b/ChangeLog index fc49df000..98baf3ed1 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,10 @@ +2016-12-01 Daniel Shahaf + + * unposted: Functions/VCS_Info/VCS_INFO_patch2subject, + Functions/VCS_Info/VCS_INFO_quilt, Functions/VCS_Info/vcs_info: + vcs_info: Break out VCS_INFO_quilt-patch2subject into + VCS_INFO_patch2subject + 2016-12-01 Mikael Magnusson * 40024: Completion/Unix/Type/_path_files: Update _path_files diff --git a/Functions/VCS_Info/VCS_INFO_patch2subject b/Functions/VCS_Info/VCS_INFO_patch2subject new file mode 100644 index 000000000..583467bc8 --- /dev/null +++ b/Functions/VCS_Info/VCS_INFO_patch2subject @@ -0,0 +1,50 @@ +# This function takes as an argument a filename of a patch and sets $REPLY to +# a single-line "subject", or unsets it if no subject could be extracted. +{ + integer i + integer -r LIMIT=10 + local -a lines + local needle + if [[ -f "$1" ]]; then + # Extract the first LIMIT lines, or up to the first empty line or the start of the unidiffs, + # whichever comes first. + while (( i++ < LIMIT )); do + IFS= read -r "lines[$i]" + if [[ -z ${lines[$i]} ]] || [[ ${lines[$i]} == (#b)(---|Index:)* ]]; then + lines[$i]=() + break + fi + done < "$1" + + if needle=${lines[(i)Subject:*]}; (( needle <= $#lines )); then + # "Subject: foo" line, plus rfc822 whitespace unfolding. + # + # Example: 'git format-patch' patches. + REPLY=${lines[needle]} + REPLY=${REPLY#*: } + REPLY=${REPLY#\[PATCH\] } + while [[ ${${lines[++needle]}[1]} == ' ' ]]; do + REPLY+=${lines[needle]} + done + elif needle=${lines[(r)Description:*]}; [[ -n $needle ]]; then + # "Description: foo" line. + # + # Example: DEP-3 patches. + REPLY=${needle#*: } + elif [[ ${lines[1]} == '# HG changeset patch' ]] && { needle=${${lines:#([#]*)}[1]}; [[ -n $needle ]] }; then + # Mercurial patch + REPLY=$needle + elif (( ${+lines[1]} )); then + # The first line of the file is not part of the diff. + REPLY=${lines[1]} + else + # The patch has no subject. + unset REPLY + return 0 + fi + else + # The patch cannot be examined, or invalid arguments. + unset REPLY + return 1 + fi +} diff --git a/Functions/VCS_Info/VCS_INFO_quilt b/Functions/VCS_Info/VCS_INFO_quilt index 6adf0a358..4c61506cd 100644 --- a/Functions/VCS_Info/VCS_INFO_quilt +++ b/Functions/VCS_Info/VCS_INFO_quilt @@ -80,55 +80,8 @@ function VCS_INFO_quilt-dirfind() { return ${ret} } -# This function takes as an argument a filename of a patch and sets $REPLY to -# a single-line "subject", or unsets it if no subject could be extracted. function VCS_INFO_quilt-patch2subject() { - integer i - integer -r LIMIT=10 - local -a lines - local needle - if [[ -f "$1" ]]; then - # Extract the first LIMIT lines, or up to the first empty line or the start of the unidiffs, - # whichever comes first. - while (( i++ < LIMIT )); do - IFS= read -r "lines[$i]" - if [[ -z ${lines[$i]} ]] || [[ ${lines[$i]} == (#b)(---|Index:)* ]]; then - lines[$i]=() - break - fi - done < "$1" - - if needle=${lines[(i)Subject:*]}; (( needle <= $#lines )); then - # "Subject: foo" line, plus rfc822 whitespace unfolding. - # - # Example: 'git format-patch' patches. - REPLY=${lines[needle]} - REPLY=${REPLY#*: } - REPLY=${REPLY#\[PATCH\] } - while [[ ${${lines[++needle]}[1]} == ' ' ]]; do - REPLY+=${lines[needle]} - done - elif needle=${lines[(r)Description:*]}; [[ -n $needle ]]; then - # "Description: foo" line. - # - # Example: DEP-3 patches. - REPLY=${needle#*: } - elif [[ ${lines[1]} == '# HG changeset patch' ]] && { needle=${${lines:#([#]*)}[1]}; [[ -n $needle ]] }; then - # Mercurial patch - REPLY=$needle - elif (( ${+lines[1]} )); then - # The first line of the file is not part of the diff. - REPLY=${lines[1]} - else - # The patch has no subject. - unset REPLY - return 0 - fi - else - # The patch cannot be examined, or invalid arguments. - unset REPLY - return 1 - fi + VCS_INFO_patch2subject "$@" } function VCS_INFO_quilt() { diff --git a/Functions/VCS_Info/vcs_info b/Functions/VCS_Info/vcs_info index c0c1182e6..24ae98e52 100644 --- a/Functions/VCS_Info/vcs_info +++ b/Functions/VCS_Info/vcs_info @@ -23,6 +23,7 @@ static_functions=( VCS_INFO_hook VCS_INFO_maxexports VCS_INFO_nvcsformats + VCS_INFO_patch2subject VCS_INFO_quilt VCS_INFO_realpath VCS_INFO_reposub -- cgit v1.2.3