summaryrefslogtreecommitdiff
path: root/Functions
diff options
context:
space:
mode:
authorAxel Beckert <abe@deuxchevaux.org>2022-04-11 00:17:48 +0200
committerAxel Beckert <abe@deuxchevaux.org>2022-04-11 00:17:48 +0200
commitb09f4483416c54c1782824633dfabaf2ec0265b6 (patch)
tree304bc82642862525ae680c7fbaa249663b10ad57 /Functions
parent12eb3e5356f2fc3351eed58ef1cef1b8fb83b504 (diff)
parent6e55c920503071e917619b8cb1a188cd35d772db (diff)
downloadzsh-b09f4483416c54c1782824633dfabaf2ec0265b6.tar.gz
zsh-b09f4483416c54c1782824633dfabaf2ec0265b6.zip
New upstream version 5.8.1.2-test
Diffstat (limited to 'Functions')
-rw-r--r--Functions/Chpwd/cdr2
-rw-r--r--Functions/Chpwd/zsh_directory_name_cdr4
-rw-r--r--Functions/Example/zpgrep15
-rw-r--r--Functions/Math/zmathfunc26
-rw-r--r--Functions/Misc/add-zle-hook-widget4
-rw-r--r--Functions/Misc/colors11
-rw-r--r--Functions/Misc/regexp-replace102
-rw-r--r--Functions/Misc/run-help15
-rw-r--r--Functions/Misc/run-help-btrfs18
-rw-r--r--Functions/Misc/run-help-git10
-rw-r--r--Functions/Misc/run-help-ip4
-rw-r--r--Functions/Misc/run-help-p42
-rw-r--r--Functions/Misc/run-help-sudo2
-rw-r--r--Functions/Misc/run-help-svk2
-rw-r--r--Functions/Misc/run-help-svn2
-rw-r--r--Functions/Misc/zargs54
-rw-r--r--Functions/Misc/zed62
-rw-r--r--Functions/Misc/zmathfuncdef2
-rw-r--r--Functions/Newuser/zsh-newuser-install2
-rw-r--r--Functions/Prompts/prompt_restore_setup1
-rw-r--r--Functions/Prompts/promptinit188
-rw-r--r--Functions/VCS_Info/Backends/VCS_INFO_detect_cvs17
-rw-r--r--Functions/VCS_Info/Backends/VCS_INFO_detect_git1
-rw-r--r--Functions/VCS_Info/Backends/VCS_INFO_get_data_bzr11
-rw-r--r--Functions/VCS_Info/Backends/VCS_INFO_get_data_cvs11
-rw-r--r--Functions/VCS_Info/Backends/VCS_INFO_get_data_fossil1
-rw-r--r--Functions/VCS_Info/Backends/VCS_INFO_get_data_git114
-rw-r--r--Functions/VCS_Info/Backends/VCS_INFO_get_data_hg31
-rw-r--r--Functions/VCS_Info/Backends/VCS_INFO_get_data_p411
-rw-r--r--Functions/VCS_Info/Backends/VCS_INFO_get_data_svk10
-rw-r--r--Functions/VCS_Info/Backends/VCS_INFO_get_data_svn20
-rw-r--r--Functions/VCS_Info/VCS_INFO_bydir_detect2
-rw-r--r--Functions/VCS_Info/VCS_INFO_patch2subject2
-rw-r--r--Functions/VCS_Info/VCS_INFO_quilt57
-rw-r--r--Functions/VCS_Info/VCS_INFO_set-branch-format24
-rw-r--r--Functions/VCS_Info/VCS_INFO_set-patch-format16
-rwxr-xr-xFunctions/VCS_Info/test-repo-git-rebase-apply59
-rwxr-xr-xFunctions/VCS_Info/test-repo-git-rebase-merge59
-rw-r--r--Functions/VCS_Info/vcs_info1
-rw-r--r--Functions/Zle/edit-command-line60
-rw-r--r--Functions/Zle/zed-set-file-name27
41 files changed, 749 insertions, 313 deletions
diff --git a/Functions/Chpwd/cdr b/Functions/Chpwd/cdr
index 4bed88b13..43745e5aa 100644
--- a/Functions/Chpwd/cdr
+++ b/Functions/Chpwd/cdr
@@ -55,7 +55,7 @@
# pattern from the directory list. The match is against the fully
# expanded directory path and the full string must match (use wildcards
# at the ends if needed). If output is going to a terminal, the
-# function will print the new list for the user to confrim; this can be
+# function will print the new list for the user to confirm; this can be
# skipped by giving -P instead of -p.
#
# Details of directory handling
diff --git a/Functions/Chpwd/zsh_directory_name_cdr b/Functions/Chpwd/zsh_directory_name_cdr
index cb72e4600..b653e7c38 100644
--- a/Functions/Chpwd/zsh_directory_name_cdr
+++ b/Functions/Chpwd/zsh_directory_name_cdr
@@ -16,8 +16,10 @@ elif [[ $1 = c ]]; then
typeset -a keys values
values=(${${(f)"$(cdr -l)"}/ ##/:})
keys=(${values%%:*})
+ local addsuffix
+ [[ $ISUFFIX = *\]* ]] || addsuffix='-S]'
_describe -t dir-index 'recent directory index' \
- values -V unsorted -S']'
+ values -V unsorted $addsuffix
return
fi
fi
diff --git a/Functions/Example/zpgrep b/Functions/Example/zpgrep
index 8b1edaa1c..556e58cd6 100644
--- a/Functions/Example/zpgrep
+++ b/Functions/Example/zpgrep
@@ -2,24 +2,31 @@
#
zpgrep() {
-local file pattern
+local file pattern ret
pattern=$1
shift
+ret=1
if ((! ARGC)) then
set -- -
fi
-pcre_compile $pattern
+zmodload zsh/pcre || return
+pcre_compile -- "$pattern"
pcre_study
for file
do
if [[ "$file" == - ]] then
- while read -u0 buf; do pcre_match $buf && print $buf; done
+ while IFS= read -ru0 buf; do
+ pcre_match -- "$buf" && ret=0 && print -r -- "$buf"
+ done
else
- while read -u0 buf; do pcre_match $buf && print $buf; done < "$file"
+ while IFS= read -ru0 buf; do
+ pcre_match -- "$buf" && ret=0 && print -r -- "$buf"
+ done < "$file"
fi
done
+return "$ret"
}
diff --git a/Functions/Math/zmathfunc b/Functions/Math/zmathfunc
index 4ff40700d..12d2c2f3d 100644
--- a/Functions/Math/zmathfunc
+++ b/Functions/Math/zmathfunc
@@ -1,34 +1,50 @@
#autoload
zsh_math_func_min() {
+ emulate -L zsh
local result=$1
shift
local arg
for arg ; do
- (( $arg < result )) && result=$arg
+ (( arg < result ))
+ case $? in
+ (0) (( result = arg ));;
+ (1) ;;
+ (*) return $?;;
+ esac
done
- (( result )) # return
+ (( result ))
+ true # Careful here: `return 0` evaluates an arithmetic expression
}
functions -M min 1 -1 zsh_math_func_min # at least one argument
zsh_math_func_max() {
+ emulate -L zsh
local result=$1
shift
local arg
for arg ; do
- (( $arg > result )) && result=$arg
+ (( arg > result ))
+ case $? in
+ (0) (( result = arg ));;
+ (1) ;;
+ (*) return $?;;
+ esac
done
- (( result )) # return
+ (( result ))
+ true # Careful here: `return 0` evaluates an arithmetic expression
}
functions -M max 1 -1 zsh_math_func_max # at least one argument
zsh_math_func_sum() {
+ emulate -L zsh
local sum
local arg
for arg ; do
- (( sum += $arg ))
+ (( sum += arg ))
done
(( sum ))
+ true # Careful here: `return 0` evaluates an arithmetic expression
}
functions -M sum 0 -1 zsh_math_func_sum
diff --git a/Functions/Misc/add-zle-hook-widget b/Functions/Misc/add-zle-hook-widget
index 9cc35496f..4d8049083 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" -f "nolast" -N -- "$@"
else
- zle "$hook" -Nw -- "$@"
+ zle "$hook" -f "nolast" -Nw -- "$@"
fi || return
done
return 0
diff --git a/Functions/Misc/colors b/Functions/Misc/colors
index 027ca9a14..5e9d77d10 100644
--- a/Functions/Misc/colors
+++ b/Functions/Misc/colors
@@ -14,11 +14,12 @@ color=(
00 none # 20 gothic
01 bold # 21 double-underline
02 faint 22 normal
- 03 standout 23 no-standout
+ 03 italic 23 no-italic # no-gothic
04 underline 24 no-underline
05 blink 25 no-blink
# 06 fast-blink # 26 proportional
07 reverse 27 no-reverse
+# 07 standout 27 no-standout
08 conceal 28 no-conceal
# 09 strikethrough # 29 no-strikethrough
@@ -82,9 +83,11 @@ for k in ${color[(I)3?]}; do color[fg-${color[$k]}]=$k; done
# This is inaccurate, but the prompt theme system needs it.
-color[grey]=${color[black]}
-color[fg-grey]=${color[grey]}
-color[bg-grey]=${color[bg-black]}
+for k in grey gray; do
+ color[$k]=${color[black]}
+ color[fg-$k]=${color[$k]}
+ color[bg-$k]=${color[bg-black]}
+done
# Assistance for the color-blind.
diff --git a/Functions/Misc/regexp-replace b/Functions/Misc/regexp-replace
index dec105524..d4408f0f7 100644
--- a/Functions/Misc/regexp-replace
+++ b/Functions/Misc/regexp-replace
@@ -8,36 +8,84 @@
# $ and backtick substitutions; in particular, $MATCH will be replaced
# by the portion of the string matched by the regular expression.
-integer pcre
+# we use positional parameters instead of variables to avoid
+# clashing with the user's variable. Make sure we start with 3 and only
+# 3 elements:
+argv=("$1" "$2" "$3")
-[[ -o re_match_pcre ]] && pcre=1
+# $4 records whether pcre is enabled as that information would otherwise
+# be lost after emulate -L zsh
+4=0
+[[ -o re_match_pcre ]] && 4=1
emulate -L zsh
-(( pcre )) && setopt re_match_pcre
-
-# $4 is the string to be matched
-4=${(P)1}
-# $5 is the final string
-5=
-# 6 indicates if we made a change
-6=
+
+
local MATCH MBEGIN MEND
local -a match mbegin mend
-while [[ -n $4 ]]; do
- if [[ $4 =~ $2 ]]; then
- # append initial part and subsituted match
- 5+=${4[1,MBEGIN-1]}${(e)3}
- # truncate remaining string
- 4=${4[MEND+1,-1]}
- # indicate we did something
- 6=1
- else
- break
- fi
-done
-5+=$4
-
-eval ${1}=${(q)5}
-# status 0 if we did something, else 1.
-[[ -n $6 ]]
+if (( $4 )); then
+ # if using pcre, we're using pcre_match and a running offset
+ # That's needed for ^, \A, \b, and look-behind operators to work
+ # properly.
+
+ zmodload zsh/pcre || return 2
+ pcre_compile -- "$2" && pcre_study || return 2
+
+ # $4 is the current *byte* offset, $5, $6 reserved for later use
+ 4=0 6=
+
+ local ZPCRE_OP
+ while pcre_match -b -n $4 -- "${(P)1}"; do
+ # append offsets and computed replacement to the array
+ # we need to perform the evaluation in a scalar assignment so that if
+ # it generates an array, the elements are converted to string (by
+ # joining with the first character of $IFS as usual)
+ 5=${(e)3}
+ argv+=(${(s: :)ZPCRE_OP} "$5")
+
+ # for 0-width matches, increase offset by 1 to avoid
+ # infinite loop
+ 4=$((argv[-2] + (argv[-3] == argv[-2])))
+ done
+
+ (($# > 6)) || return # no match
+
+ set +o multibyte
+
+ # $5 contains the result, $6 the current offset
+ 5= 6=1
+ for 2 3 4 in "$@[7,-1]"; do
+ 5+=${(P)1[$6,$2]}$4
+ 6=$(($3 + 1))
+ done
+ 5+=${(P)1[$6,-1]}
+else
+ # in ERE, we can't use an offset so ^, (and \<, \b, \B, [[:<:]] where
+ # available) won't work properly.
+
+ # $4 is the string to be matched
+ 4=${(P)1}
+
+ while [[ -n $4 ]]; do
+ if [[ $4 =~ $2 ]]; then
+ # append initial part and substituted match
+ 5+=${4[1,MBEGIN-1]}${(e)3}
+ # truncate remaining string
+ if ((MEND < MBEGIN)); then
+ # zero-width match, skip one character for the next match
+ ((MEND++))
+ 5+=${4[1]}
+ fi
+ 4=${4[MEND+1,-1]}
+ # indicate we did something
+ 6=1
+ else
+ break
+ fi
+ done
+ [[ -n $6 ]] || return # no match
+ 5+=$4
+fi
+
+eval $1=\$5
diff --git a/Functions/Misc/run-help b/Functions/Misc/run-help
index e351dd6a6..d52c1b032 100644
--- a/Functions/Misc/run-help
+++ b/Functions/Misc/run-help
@@ -101,12 +101,15 @@ do
builtin getln cmd_args
builtin print -z "$cmd_args"
cmd_args=( ${(z)cmd_args} )
- # Discard environment assignments, etc.
- while [[ $cmd_args[1] != ${run_help_orig_cmd:-$1} ]]
- do
- shift cmd_args || return 1
- done
- eval "run-help-$1:t ${(q@)cmd_args[2,-1]}"
+
+ # Discard the command itself & everything before it.
+ shift $cmd_args[(i)${run_help_orig_cmd:-$1}] cmd_args ||
+ return
+
+ # Discard options, parameter assignments & paths.
+ cmd_args=( ${cmd_args[@]:#([-+]*|*=*|*/*|\~*)} )
+
+ eval "run-help-$1:t ${(@q)cmd_args}"
else
POSIXLY_CORRECT=1 man $@:t
fi
diff --git a/Functions/Misc/run-help-btrfs b/Functions/Misc/run-help-btrfs
new file mode 100644
index 000000000..cb139e9b7
--- /dev/null
+++ b/Functions/Misc/run-help-btrfs
@@ -0,0 +1,18 @@
+case $1 in
+ (b*) man btrfs-balance ;;
+ (c*) man btrfs-check ;;
+ (d*) man btrfs-device ;;
+ (f*) man btrfs-filesystem ;;
+ (i*) man btrfs-inspect-internal ;;
+ (p*) man btrfs-property ;;
+ (qg*) man btrfs-qgroup ;;
+ (qu*) man btrfs-quota ;;
+ (rec*) man btrfs-receive ;;
+ (rep*) man btrfs-replace ;;
+ (resc*) man btrfs-rescue ;;
+ (rest*) man btrfs-restore ;;
+ (sc*) man btrfs-scrub ;;
+ (se*) man btrfs-send ;;
+ (su*) man btrfs-subvolume ;;
+ (*) man btrfs ;;
+esac
diff --git a/Functions/Misc/run-help-git b/Functions/Misc/run-help-git
index ce94d0d02..a841f89d6 100644
--- a/Functions/Misc/run-help-git
+++ b/Functions/Misc/run-help-git
@@ -1,9 +1 @@
-if [ $# -eq 0 ]; then
- man git
-else
- local al
- if al=$(git config --get "alias.$1"); then
- 1=${al%% *}
- fi
- man git-$1
-fi
+git help ${1:-git}
diff --git a/Functions/Misc/run-help-ip b/Functions/Misc/run-help-ip
index 8807f9ef1..b811ce352 100644
--- a/Functions/Misc/run-help-ip
+++ b/Functions/Misc/run-help-ip
@@ -14,10 +14,6 @@ if ! man -w ip-address >/dev/null 2>&1; then
return
fi
-while [[ $# != 0 && $1 == -* ]]; do
- shift
-done
-
case $1 in
(addrl*) man ip-addrlabel ;;
(a*) man ip-address ;;
diff --git a/Functions/Misc/run-help-p4 b/Functions/Misc/run-help-p4
index 662ce94fe..e48a4d068 100644
--- a/Functions/Misc/run-help-p4
+++ b/Functions/Misc/run-help-p4
@@ -2,4 +2,4 @@ if (( ! $# )); then
p4 help commands
else
p4 help $1
-fi | ${=PAGER:-less}
+fi | ${=PAGER:-more}
diff --git a/Functions/Misc/run-help-sudo b/Functions/Misc/run-help-sudo
index f38696e19..a8fa7aa0f 100644
--- a/Functions/Misc/run-help-sudo
+++ b/Functions/Misc/run-help-sudo
@@ -2,6 +2,6 @@
if [ $# -eq 0 ]; then
man sudo
else
- man $1
+ run-help $1
fi
diff --git a/Functions/Misc/run-help-svk b/Functions/Misc/run-help-svk
index 92438a53f..782538246 100644
--- a/Functions/Misc/run-help-svk
+++ b/Functions/Misc/run-help-svk
@@ -1 +1 @@
-svk help ${${@:#-*}[1]} | ${=PAGER:-more}
+svk help $1 | ${=PAGER:-more}
diff --git a/Functions/Misc/run-help-svn b/Functions/Misc/run-help-svn
index 5d1068588..d55a493a6 100644
--- a/Functions/Misc/run-help-svn
+++ b/Functions/Misc/run-help-svn
@@ -1 +1 @@
-svn help ${${@:#-*}[1]} | ${=PAGER:-more}
+svn help $1 | ${=PAGER:-more}
diff --git a/Functions/Misc/zargs b/Functions/Misc/zargs
index 28ebca78f..81916a3ac 100644
--- a/Functions/Misc/zargs
+++ b/Functions/Misc/zargs
@@ -43,14 +43,12 @@
# than 127 for "command not found" so this function incorrectly returns
# 123 in that case if used with zsh 4.0.x.
#
-# With the --max-procs option, zargs may not correctly capture the exit
-# status of the backgrounded jobs, because of limitations of the "wait"
-# builtin. If the zsh/parameter module is not available, the status is
-# NEVER correctly returned, otherwise the status of the longest-running
-# job in each batch is captured.
+# Because of "wait" limitations, --max-procs spawns max-procs jobs, then
+# waits for all of those, then spawns another batch, etc.
#
-# Also because of "wait" limitations, --max-procs spawns max-procs jobs,
-# then waits for all of those, then spawns another batch, etc.
+# The maximum number of parallel jobs for which exit status is available
+# is determined by the sysconf CHILD_MAX parameter, which can't be read
+# or changed from within the shell.
#
# Differences from POSIX xargs:
#
@@ -69,11 +67,27 @@
# -I/-L and implementations reportedly differ.) In zargs, -i/-I have
# this behavior, as do -l/-L, but when -i/-I appear anywhere then -l/-L
# are ignored (forced to 1).
+#
+# * The use of SIGUSR1 and SIGUSR2 to change the number of parallel jobs
+# is not supported.
+
+# First, capture the current setopts as "sticky emulation"
+if zmodload zsh/parameter
+then
+ emulate $(emulate -l) -c "\
+ _zarun() {
+ options=( ${(j: :kv)options[@]} monitor off zle off )"'
+ eval "$@"
+ }'
+else
+ # Warning?
+ emulate $(emulate -l) -c '_zarun() { eval "$@" }'
+fi
emulate -L zsh || return 1
local -a opts eof n s l P i
-local ZARGS_VERSION="1.5"
+local ZARGS_VERSION="1.7"
if zparseopts -a opts -D -- \
-eof::=eof e::=eof \
@@ -186,8 +200,8 @@ local execute='
elif (( $opts[(I)-(-verbose|t)] ))
then print -u2 -r -- "$call"
fi
- eval "{
- \"\${(@)call}\"
+ _zarun "{
+ \"\${call[@]}\"
} $bg"'
local ret=0 analyze='
case $? in
@@ -251,17 +265,19 @@ if (( P != 1 && ARGC > 1 ))
then
# These setopts are necessary for "wait" on multiple jobs to work.
setopt nonotify nomonitor
- bg='&'
- if zmodload -i zsh/parameter 2>/dev/null
- then
- wait='wait ${${jobstates[(R)running:*]/#*:/}/%=*/}'
- else
- wait='wait'
- fi
+ local -a _zajobs
+ local j
+ bg='& _zajobs+=( $! )'
+ wait='wait'
+ analyze='
+ for j in $_zajobs; do
+ wait $j
+ '"$analyze"'
+ done; _zajobs=()'
fi
-# Everything has to be in a subshell just in case of backgrounding jobs,
-# so that we don't unintentionally "wait" for jobs of the parent shell.
+# Everything has to be in a subshell so that we don't "wait" for any
+# unrelated jobs of the parent shell.
(
while ((ARGC))
diff --git a/Functions/Misc/zed b/Functions/Misc/zed
index 9eb4b2d93..7d0d590db 100644
--- a/Functions/Misc/zed
+++ b/Functions/Misc/zed
@@ -5,16 +5,18 @@
# Edit small files with the command line editor.
# Use ^X^W to save (or ZZ in vicmd mode), ^C to abort.
# Option -f: edit shell functions. (Also if called as fned.)
+# Option -h: edit shell history. (Also if called as histed.)
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
+integer TMOUT=0 okargs=1 fun hist bind
local -a expand
-zparseopts -D -A opts f b x:
+zparseopts -D -A opts f h b x:
fun=$+opts[-f]
+hist=$+opts[-h]
bind=$+opts[-b]
if [[ $opts[-x] == <-> ]]; then
expand=(-x $opts[-x])
@@ -24,23 +26,28 @@ elif (( $+opts[-x] )); then
fi
[[ $0 = fned ]] && fun=1
+[[ $0 = histed ]] && hist=1
+(( hist && $# <= 2 )) && okargs=$#
(( bind )) && okargs=0
-if (( $# != okargs )); then
+if (( $# != okargs || bind + fun + hist > 1 )); then
echo 'Usage:
zed filename
zed -f [ -x N ] function
+zed -h [ filename [ size ] ]
zed -b' >&2
return 1
fi
local curcontext=zed:::
-# Matching used in zstyle -m: hide result from caller.
-# Variables not used directly here.
-local -a match mbegin mend
-zstyle -m ":completion:zed:*" insert-tab '*' ||
- zstyle ":completion:zed:*" insert-tab yes
+() {
+ # Matching used in zstyle -m: hide result from caller.
+ # Variables not used directly here.
+ local -a match mbegin mend
+ zstyle -m ":completion:zed:*" insert-tab '*' ||
+ zstyle ":completion:zed:*" insert-tab yes
+}
zmodload zsh/terminfo 2>/dev/null
@@ -124,22 +131,51 @@ fi
setopt localoptions nobanghist
if ((fun)) then
- var="$(functions $expand -- $1)"
+ var="$(functions $expand -- "$1")"
# If function is undefined but autoloadable, load it
if [[ $var = *\#\ undefined* ]] then
- var="$(autoload +X $1; functions -- $1)"
+ var="$(autoload +X "$1"; functions -- "$1")"
elif [[ -z $var ]] then
var="${(q-)1} () {
}"
fi
vared -M zed -m zed-vicmd -i __zed_init var && eval function "$var"
+elif ((hist)) then
+ if [[ -n $1 ]]; then
+ { fc -p -a "$1" ${2:-$({ wc -l <"$1" } 2>/dev/null)} || return }
+ let HISTSIZE++
+ print -s "" # Work around fc -p limitation
+ fi
+ # When editing the current shell history, the "zed -h" command is not
+ # itself included because the current event is not added to the ring
+ # until the next prompt is printed. This means "zed -h" is prepended
+ # to the result of the edit, because of the way "print -s" is defined.
+ var=( "${(@Oav)history}" )
+ IFS=$'\n' vared -M zed -m zed-vicmd -i __zed_init var
+ if (( ? )); then
+ [[ -n $1 ]] && unset HISTFILE
+ else
+ local HISTSIZE=0 savehist=$#var
+ fc -R /dev/null # Remove entries other than those added here
+ HISTSIZE=$savehist # Resets on function exit because local
+ [[ -n $1 ]] && SAVEHIST=$savehist # Resets via foregoing fc -a
+ for (( hist=1; hist <= savehist; hist++ ))
+ do print -rs -- "$var[hist]"
+ done
+ if [[ -n $zed_file_name ]]; then
+ fc -W "$zed_file_name"
+ [[ -n $1 ]] && unset HISTFILE
+ fi
+ # Note prepend effect when global HISTSIZE greater than $savehist.
+ # This does not affect file editing.
+ fi
else
- zed_file_name=$1
- [[ -f $1 ]] && var="$(<$1)"
+ zed_file_name="$1"
+ [[ -f $1 ]] && var="$(<"$1")"
while vared -M zed -m zed-vicmd -i __zed_init var
do
{
- print -r -- "$var" >| $zed_file_name
+ print -r -- "$var" >| "$zed_file_name"
} always {
(( TRY_BLOCK_ERROR = 0 ))
} && break
diff --git a/Functions/Misc/zmathfuncdef b/Functions/Misc/zmathfuncdef
index e5692e769..5ed991f68 100644
--- a/Functions/Misc/zmathfuncdef
+++ b/Functions/Misc/zmathfuncdef
@@ -78,7 +78,7 @@ if ! zmodload -e zsh/mathfunc; then
fi
{
- eval "$fname() { (( $body )) }"
+ eval "$fname() { (( $body )); true }"
} always {
# Remove math function if shell function definition failed.
if (( TRY_BLOCK_ERROR )); then
diff --git a/Functions/Newuser/zsh-newuser-install b/Functions/Newuser/zsh-newuser-install
index 60ac16b13..9e911d07c 100644
--- a/Functions/Newuser/zsh-newuser-install
+++ b/Functions/Newuser/zsh-newuser-install
@@ -627,7 +627,7 @@ Type:
}
-# Print and despatch a submenu.
+# Print and dispatch a submenu.
# The first argument is the title. The remaining arguments
# are pairs of descriptions and functions to execute.
# There shouldn't be more than 9 entries.
diff --git a/Functions/Prompts/prompt_restore_setup b/Functions/Prompts/prompt_restore_setup
index 54c4adbf9..b77dbe815 100644
--- a/Functions/Prompts/prompt_restore_setup
+++ b/Functions/Prompts/prompt_restore_setup
@@ -1,2 +1,3 @@
# Damn that was easy
zstyle -t :prompt-theme cleanup
+zstyle -t :prompt-theme restore
diff --git a/Functions/Prompts/promptinit b/Functions/Prompts/promptinit
index e27b8779a..0c06699e8 100644
--- a/Functions/Prompts/promptinit
+++ b/Functions/Prompts/promptinit
@@ -14,6 +14,8 @@ prompt_themes=()
promptinit () {
emulate -L zsh
setopt extendedglob
+ autoload -Uz add-zsh-hook add-zle-hook-widget
+
local ppath='' name theme
local -a match mbegin mend
@@ -32,9 +34,6 @@ promptinit () {
fi
done
- # To manipulate precmd and preexec hooks...
- autoload -Uz add-zsh-hook
-
# Variables common to all prompt styles
prompt_newline=$'\n%{\r%}'
}
@@ -47,36 +46,23 @@ prompt_preview_safely() {
return
fi
- # This handles all the stuff from the default :prompt-theme cleanup
- local +h PS1=$PS1 PS2=$PS2 PS3=$PS3 PS4=$PS4 RPS1=$RPS1 RPS2=$RPS2
- local +h PROMPT=$PROMPT RPROMPT=$RPOMPT RPROMPT2=$RPROMPT2 PSVAR=$PSVAR
- local -a precmd_functions preexec_functions prompt_preview_cleanup
- local -aLl +h zle_highlight
+ # Run this in a subshell, so we don't need to clean up afterwards.
+ (
+ # Execute current theme's cleanup sequence, if any.
+ zstyle -t :prompt-theme cleanup
- {
- # Save and clear current restore-point if any
- zstyle -g prompt_preview_cleanup :prompt-theme cleanup
- {
- zstyle -d :prompt-theme cleanup
-
- # The next line is a bit ugly. It (perhaps unnecessarily)
- # runs the prompt theme setup function to ensure that if
- # the theme has a _preview function that it's been autoloaded.
+ # If we can't find a _preview function, run the _setup function to see if
+ # it will create one.
+ typeset +f prompt_${1}_preview >&/dev/null ||
prompt_${1}_setup
- if typeset +f prompt_${1}_preview >&/dev/null; then
- prompt_${1}_preview "$@[2,-1]"
- else
- prompt_preview_theme "$@"
- fi
- } always {
- # Run any theme-specific cleanup, then reset restore point
- zstyle -t :prompt-theme cleanup
- }
- } always {
- (( $#prompt_preview_cleanup )) &&
- zstyle -e :prompt-theme cleanup "${prompt_preview_cleanup[@]}"
- }
+ # ...then try again.
+ if typeset +f prompt_${1}_preview >&/dev/null; then
+ prompt_${1}_preview "$@[2,-1]"
+ else
+ prompt_preview_theme "$@"
+ fi
+ )
}
set_prompt() {
@@ -87,7 +73,7 @@ set_prompt() {
Options:
-c Show currently selected theme and parameters
-l List currently available prompt themes
- -p [<themes>] Preview given themes (defaults to all)
+ -p [<themes>] Preview given themes (defaults to all except current theme)
-h [<theme>] Display help (for given theme)
-s <theme> Set and save theme
<theme> Switch to new theme immediately (changes not saved)
@@ -96,19 +82,6 @@ Use prompt -h <theme> for help on specific themes.'
getopts "chlps:" opt
case "$opt" in
- (h|p)
- setopt localtraps
- if [[ -z "$prompt_theme[1]" ]]; then
- # Not using a prompt theme; save settings
- local +h PS1=$PS1 PS2=$PS2 PS3=$PS3 PS4=$PS4 RPS1=$RPS1 RPS2=$RPS2
- local +h PROMPT=$PROMPT RPROMPT=$RPOMPT RPROMPT2=$RPROMPT2 PSVAR=$PSVAR
- local -a precmd_functions preexec_functions
- else
- trap 'prompt_${prompt_theme[1]}_setup "${(@)prompt_theme[2,-1]}"' 0
- fi
- ;;
- esac
- case "$opt" in
c) if [[ -n $prompt_theme ]]; then
print -n "Current prompt theme"
(( $#prompt_theme > 1 )) && print -n " with parameters"
@@ -119,20 +92,26 @@ Use prompt -h <theme> for help on specific themes.'
return
;;
h) if [[ -n "$2" && -n $prompt_themes[(r)$2] ]]; then
- if functions prompt_$2_setup >/dev/null; then
- # The next line is a bit ugly. It (perhaps unnecessarily)
- # runs the prompt theme setup function to ensure that if
- # the theme has a _help function that it's been autoloaded.
- prompt_$2_setup
- fi
- if functions prompt_$2_help >/dev/null; then
- print "Help for $2 theme:\n"
- prompt_$2_help
- else
- print "No help available for $2 theme."
- fi
- print "\nType \`prompt -p $2' to preview the theme, \`prompt $2'"
- print "to try it out, and \`prompt -s $2' to use it in future sessions."
+ # Run this in a subshell, so we don't need to clean up afterwards.
+ (
+ # Execute current theme's cleanup sequence, if any.
+ zstyle -t :prompt-theme cleanup
+
+ # If we can't find a _help function, run the _setup function to see
+ # if it will create one.
+ typeset +f prompt_$2_help >/dev/null ||
+ prompt_$2_setup
+
+ # ...then try again.
+ if typeset +f prompt_$2_help >/dev/null; then
+ print "Help for $2 theme:\n"
+ prompt_$2_help
+ else
+ print "No help available for $2 theme."
+ fi
+ print "\nType \`prompt -p $2' to preview the theme, \`prompt $2'"
+ print "to try it out, and \`prompt -s $2' to use it in future sessions."
+ )
else
print "$usage"
fi
@@ -141,10 +120,9 @@ Use prompt -h <theme> for help on specific themes.'
print $prompt_themes
return
;;
- p) preview=( $prompt_themes )
+ p) preview=( ${prompt_themes:#$prompt_theme} )
(( $#* > 1 )) && preview=( "$@[2,-1]" )
for theme in $preview; do
- [[ "$theme" == "$prompt_theme[*]" ]] && continue
prompt_preview_safely "$=theme"
done
print -P "%b%f%k"
@@ -173,34 +151,46 @@ Use prompt -h <theme> for help on specific themes.'
# Reset some commonly altered bits to the default
local hook
- for hook in chpwd precmd preexec periodic zshaddhistory zshexit; do
- add-zsh-hook -D "${hook}" "prompt_*_${hook}"
+ for hook in chpwd precmd preexec periodic zshaddhistory zshexit \
+ zsh_directory_name; do
+ add-zsh-hook -D "$hook" "prompt_*_$hook"
+ done
+ for hook in isearch-exit isearch-update line-pre-redraw line-init \
+ line-finish history-line-set keymap-select; do
+ add-zle-hook-widget -D "$hook" "prompt_*_$hook"
done
typeset -ga zle_highlight=( ${zle_highlight:#default:*} )
(( ${#zle_highlight} )) || unset zle_highlight
+ zstyle -t :prompt-theme cleanup
prompt_$1_setup "$@[2,-1]" && prompt_theme=( "$@" )
;;
esac
}
prompt_cleanup () {
- local -a cleanup_hooks
- if zstyle -g cleanup_hooks :prompt-theme cleanup
- then
- cleanup_hooks+=(';' "$@")
- zstyle -e :prompt-theme cleanup "${cleanup_hooks[@]}"
- elif (( $+prompt_preview_cleanup == 0 ))
- then
- print -u2 "prompt_cleanup: no prompt theme active"
- return 1
+ local -a cleanup_hooks theme_active
+ if ! zstyle -g cleanup_hooks :prompt-theme cleanup; then
+ if ! zstyle -g theme_active :prompt-theme restore; then
+ print -u2 "prompt_cleanup: no prompt theme active"
+ return 1
+ fi
+
+ # Set the cleanup sequence up.
+ zstyle -e :prompt-theme cleanup \
+ 'zstyle -d :prompt-theme cleanup;' \
+ 'reply=(yes)'
+ zstyle -g cleanup_hooks :prompt-theme cleanup
fi
+
+ cleanup_hooks+=(';' "$@")
+ zstyle -e :prompt-theme cleanup "${cleanup_hooks[@]}"
}
prompt () {
local -a prompt_opts theme_active
- zstyle -g theme_active :prompt-theme cleanup || {
+ zstyle -g theme_active :prompt-theme restore || {
# This is done here rather than in set_prompt so that it
# is safe and sane for set_prompt to setopt localoptions,
# which will be cleared before we arrive back here again.
@@ -210,22 +200,21 @@ prompt () {
[[ -o promptpercent ]] && prompt_opts+=(percent)
[[ -o promptsp ]] && prompt_opts+=(sp)
[[ -o promptsubst ]] && prompt_opts+=(subst)
- zstyle -e :prompt-theme cleanup \
- 'zstyle -d :prompt-theme cleanup;' \
- 'prompt_default_setup;' \
- ${PS1+PS1="${(q)PS1}"} \
- ${PS2+PS2="${(q)PS2}"} \
- ${PS3+PS3="${(q)PS3}"} \
- ${PS4+PS4="${(q)PS4}"} \
- ${RPS1+RPS1="${(q)RPS1}"} \
- ${RPS2+RPS2="${(q)RPS2}"} \
- ${RPROMPT+RPROMPT="${(q)RPROMPT}"} \
- ${RPROMPT2+RPROMPT2="${(q)RPROMPT2}"} \
- ${PSVAR+PSVAR="${(q)PSVAR}"} \
- "precmd_functions=(${(q)precmd_functions[@]})" \
- "preexec_functions=(${(q)preexec_functions[@]})" \
- "prompt_opts=( ${prompt_opts[*]} )" \
- 'reply=(yes)'
+ zstyle -e :prompt-theme restore "
+ zstyle -d :prompt-theme restore
+ prompt_default_setup
+ ${PS1+PS1=${(q+)PS1}}
+ ${PS2+PS2=${(q+)PS2}}
+ ${PS3+PS3=${(q+)PS3}}
+ ${PS4+PS4=${(q+)PS4}}
+ ${RPS1+RPS1=${(q+)RPS1}}
+ ${RPS2+RPS2=${(q+)RPS2}}
+ ${RPROMPT+RPROMPT=${(q+)RPROMPT}}
+ ${RPROMPT2+RPROMPT2=${(q+)RPROMPT2}}
+ ${PSVAR+PSVAR=${(q+)PSVAR}}
+ prompt_opts=( $prompt_opts[*] )
+ reply=( yes )
+ "
}
set_prompt "$@"
@@ -238,26 +227,29 @@ prompt () {
prompt_preview_theme () {
emulate -L zsh
- # Check for proper state handling
- (( $+prompt_preview_cleanup )) || {
- prompt_preview_safely "$@"
- return
- }
-
# Minimal preview for prompts that don't supply one
local -a prompt_opts
print -n "$1 theme"
(( $#* > 1 )) && print -n " with parameters \`$*[2,-1]'"
print ":"
+ zstyle -t :prompt-theme cleanup
prompt_${1}_setup "$@[2,-1]"
(( ${#prompt_opts} )) &&
setopt noprompt{bang,cr,percent,sp,subst} "prompt${^prompt_opts[@]}"
+
+ [[ -n ${chpwd_functions[(r)prompt_${1}_chpwd]} ]] &&
+ prompt_${1}_chpwd
[[ -n ${precmd_functions[(r)prompt_${1}_precmd]} ]] &&
- prompt_${1}_precmd
- [[ -o promptcr ]] && print -n $'\r'; :
- print -P "${PS1}command arg1 arg2 ... argn"
+ prompt_${1}_precmd
+
+ # We'd like to call zle-line-init/finish hooks, too, but that's not possible
+ # while the ZLE is not active.
+
+ [[ -o promptcr ]] && print -n $'\r'
+ :; print -P -- "${PS1}command arg1 arg2 ... argn"
+
[[ -n ${preexec_functions[(r)prompt_${1}_preexec]} ]] &&
- prompt_${1}_preexec
+ prompt_${1}_preexec
}
[[ -o kshautoload ]] || promptinit "$@"
diff --git a/Functions/VCS_Info/Backends/VCS_INFO_detect_cvs b/Functions/VCS_Info/Backends/VCS_INFO_detect_cvs
index 7a5ee1eef..a57959ec9 100644
--- a/Functions/VCS_Info/Backends/VCS_INFO_detect_cvs
+++ b/Functions/VCS_Info/Backends/VCS_INFO_detect_cvs
@@ -7,5 +7,18 @@ setopt localoptions NO_shwordsplit
[[ $1 == '--flavours' ]] && return 1
VCS_INFO_check_com ${vcs_comm[cmd]} || return 1
-[[ -d "./CVS" ]] && [[ -r "./CVS/Repository" ]] && return 0
-return 1
+if ! [[ -d "./CVS" ]] || ! [[ -r "./CVS/Repository" ]] ; then
+ return 1
+fi
+
+# Look for the most distant parent that still has a CVS subdirectory.
+local cvsbase="."
+cvsbase=${cvsbase:P}
+while [[ -d "${cvsbase:h}/CVS" ]]; do
+ cvsbase="${cvsbase:h}"
+ if [[ $cvsbase == '/' ]]; then
+ break
+ fi
+done
+
+vcs_comm[basedir]="${cvsbase}"
diff --git a/Functions/VCS_Info/Backends/VCS_INFO_detect_git b/Functions/VCS_Info/Backends/VCS_INFO_detect_git
index e4191f474..b7955de38 100644
--- a/Functions/VCS_Info/Backends/VCS_INFO_detect_git
+++ b/Functions/VCS_Info/Backends/VCS_INFO_detect_git
@@ -7,6 +7,7 @@ setopt localoptions NO_shwordsplit
[[ $1 == '--flavours' ]] && { print -l git-p4 git-svn; return 0 }
if VCS_INFO_check_com ${vcs_comm[cmd]} && vcs_comm[gitdir]="$(${vcs_comm[cmd]} rev-parse --git-dir 2> /dev/null)" ; then
+ vcs_comm[basedir]="$( ${vcs_comm[cmd]} rev-parse --show-toplevel 2> /dev/null )"
if [[ -d ${vcs_comm[gitdir]}/svn ]] ; then vcs_comm[overwrite_name]='git-svn'
elif [[ -d ${vcs_comm[gitdir]}/refs/remotes/p4 ]] ; then vcs_comm[overwrite_name]='git-p4' ; fi
return 0
diff --git a/Functions/VCS_Info/Backends/VCS_INFO_get_data_bzr b/Functions/VCS_Info/Backends/VCS_INFO_get_data_bzr
index b30e0e12b..f1f5527e8 100644
--- a/Functions/VCS_Info/Backends/VCS_INFO_get_data_bzr
+++ b/Functions/VCS_Info/Backends/VCS_INFO_get_data_bzr
@@ -100,14 +100,7 @@ else
fi
rrn=${bzrbase:t}
-zstyle -s ":vcs_info:${vcs}:${usercontext}:${rrn}" branchformat bzrbr || bzrbr="%b:%r"
-hook_com=( branch "${bzrinfo[2]}" revision "${bzrinfo[1]}" )
-if VCS_INFO_hook 'set-branch-format' "${bzrbr}"; then
- zformat -f bzrbr "${bzrbr}" "b:${hook_com[branch]}" "r:${hook_com[revision]}"
-else
- bzrbr=${hook_com[branch-replace]}
-fi
-hook_com=()
-
+VCS_INFO_set-branch-format "${bzrinfo[2]}" "${bzrinfo[1]}" &&
+ bzrbr="${REPLY}"
VCS_INFO_formats '' "${bzrbr}" "${bzrbase}" '' "${bzr_changes}" "${bzrinfo[1]}" "${bzr_changes}"
return 0
diff --git a/Functions/VCS_Info/Backends/VCS_INFO_get_data_cvs b/Functions/VCS_Info/Backends/VCS_INFO_get_data_cvs
index 9b828bd11..bc0d5cfe5 100644
--- a/Functions/VCS_Info/Backends/VCS_INFO_get_data_cvs
+++ b/Functions/VCS_Info/Backends/VCS_INFO_get_data_cvs
@@ -5,17 +5,8 @@
setopt localoptions NO_shwordsplit
local cvsbranch cvsbase
-# Look for the most distant parent that still has a CVS subdirectory.
+cvsbase="${vcs_comm[basedir]}"
# VCS_INFO_detect_cvs ensured that ./CVS/Repository exists.
-cvsbase="."
-cvsbase=${cvsbase:P}
-while [[ -d "${cvsbase:h}/CVS" ]]; do
- cvsbase="${cvsbase:h}"
- if [[ $cvsbase == '/' ]]; then
- break
- fi
-done
-
cvsbranch=$(< ./CVS/Repository)
rrn=${cvsbase:t}
cvsbranch=${cvsbranch##${rrn}/}
diff --git a/Functions/VCS_Info/Backends/VCS_INFO_get_data_fossil b/Functions/VCS_Info/Backends/VCS_INFO_get_data_fossil
index fd0f8389e..e84b3abc0 100644
--- a/Functions/VCS_Info/Backends/VCS_INFO_get_data_fossil
+++ b/Functions/VCS_Info/Backends/VCS_INFO_get_data_fossil
@@ -20,5 +20,6 @@ if [ -n "$merging" ]; then
action="merging"
fi
+rrn=${fsinfo[local_root]:t}
VCS_INFO_formats "$action" "${fsbranch}" "${fsinfo[local_root]}" '' "$changed" "${fshash}" "${fsinfo[repository]}"
return 0
diff --git a/Functions/VCS_Info/Backends/VCS_INFO_get_data_git b/Functions/VCS_Info/Backends/VCS_INFO_get_data_git
index ceb4f978a..e45eebc8e 100644
--- a/Functions/VCS_Info/Backends/VCS_INFO_get_data_git
+++ b/Functions/VCS_Info/Backends/VCS_INFO_get_data_git
@@ -132,13 +132,17 @@ VCS_INFO_git_handle_patches () {
VCS_INFO_set-patch-format 'git_patches_applied' 'git_applied_s' \
'git_patches_unapplied' 'git_unapplied_s' \
":vcs_info:${vcs}:${usercontext}:${rrn}" gitmsg \
- '' ''
+ '' '' ''
gitmisc=$REPLY
}
gitdir=${vcs_comm[gitdir]}
VCS_INFO_git_getbranch ${gitdir}
-gitbase=$( ${vcs_comm[cmd]} rev-parse --show-toplevel )
+gitbase=${vcs_comm[basedir]}
+if [[ -z ${gitbase} ]]; then
+ # Bare repository
+ gitbase=${gitdir:P}
+fi
rrn=${gitbase:t}
if zstyle -t ":vcs_info:${vcs}:${usercontext}:${rrn}" get-revision ; then
gitsha1=$(${vcs_comm[cmd]} rev-parse --quiet --verify HEAD)
@@ -192,13 +196,19 @@ elif [[ -d "${gitdir}/rebase-merge" ]]; then
# 'git rebase -i'
patchdir="${gitdir}/rebase-merge"
local p
- [[ -f "${patchdir}/done" ]] &&
- for p in ${(f)"$(< "${patchdir}/done")"}; do
+ (( ${+functions[VCS_INFO_git_map_rebase_line_to_hash_and_subject]} )) ||
+ VCS_INFO_git_map_rebase_line_to_hash_and_subject() {
+ local p=$1
+ unset REPLY
# pick/edit/fixup/squash/reword: Add "$hash $subject" to $git_patches_applied.
# exec: Add "exec ${command}" to $git_patches_applied.
# (anything else): As 'exec'.
case $p in
- ((p|pick|e|edit|r|reword|f|fixup|s|squash)' '*)
+ ([#]*)
+ # Comment line. Skip.
+ return 0
+ ;;
+ (''(p|pick|e|edit|r|reword|f|fixup|s|squash)' '*)
# The line is of the form "pick $hash $subject".
# Just strip the verb and we're good to go.
p=${p#* }
@@ -221,11 +231,11 @@ elif [[ -d "${gitdir}/rebase-merge" ]]; then
p="${p%% *} ?"
fi
;;
- (x *)
+ (''(x|exec) *)
# The line is of the form 'exec foo bar baz' where 'foo bar
# baz' is a shell command. There's no way to map _that_ to
# "$hash $subject", but I hope this counts as making an effort.
- p=${p/x /exec }
+ p=${p/#x /exec }
;;
(*)
# Forward compatibility with not-yet-existing 'git rebase -i' verbs.
@@ -233,30 +243,74 @@ elif [[ -d "${gitdir}/rebase-merge" ]]; then
p+=" ?"
fi
esac
- git_patches_applied+=("$p")
- done
+ REPLY=$p
+ }
+ if [[ -f "${patchdir}/done" ]] ; then
+ for p in ${(f)"$(< "${patchdir}/done")"}; do
+ VCS_INFO_git_map_rebase_line_to_hash_and_subject "$p"
+ (( $+REPLY )) && git_patches_applied+=( "$REPLY" )
+ done
+ fi
if [[ -f "${patchdir}/git-rebase-todo" ]] ; then
- # TODO: Process ${patchdir}/git-rebase-todo lines like ${patchdir}/done lines are
- git_patches_unapplied=( ${${(f)${"$(<"${patchdir}/git-rebase-todo")"}}:#[#]*} )
+ for p in ${(f)"$(< "${patchdir}/git-rebase-todo")"}; do
+ VCS_INFO_git_map_rebase_line_to_hash_and_subject "$p"
+ (( $+REPLY )) && git_patches_unapplied+=( "$REPLY" )
+ done
fi
VCS_INFO_git_handle_patches
elif [[ -d "${gitdir}/rebase-apply" ]]; then
- # 'git rebase' without -i
+ # 'git rebase' without -i, or 'git am'
patchdir="${gitdir}/rebase-apply"
local next="${patchdir}/next"
+ local this_patch_file
if [[ -f $next ]]; then
local cur=$(< $next)
local p subject
- # Fake patch names for all but current patch
- for ((p = 1; p < cur; p++)); do
- printf -v "git_patches_applied[$p]" "%04d ?" "$p"
- done
+ # Compute patch names for patches "before" the current patch
+ if [[ -r ${patchdir}/rewritten ]]; then
+ if zstyle -t ":vcs_info:${vcs}:${usercontext}:${rrn}" use-simple; then
+ git_patches_applied=( ${${(f)"$(<${patchdir}/rewritten)"}// */' ?'} )
+ else
+ git_patches_applied=(
+ ${(f)"$(${vcs_comm[cmd]} log --no-walk=unsorted --pretty='%h %s' ${${(f)"$(<${patchdir}/rewritten)"}%% *} --)"}
+ )
+ fi
+ else
+ # Compatibility with old git. In 2.11 and 2.24, at least,
+ # (( cur == 1 )), so the loop body would never run. However, both
+ # of these versions have original-commit and orig-head and would
+ # take the 'if' branch, rather than this 'else' branch.
+ for ((p = 1; p < cur; p++)); do
+ printf -v this_patch_file "%s/%04d" "${patchdir}" "${p}"
+ if [[ -f $this_patch_file ]]; then
+ VCS_INFO_patch2subject "${this_patch_file}"
+ git_patches_applied+=( "$p $REPLY" )
+ else
+ git_patches_applied+=( "$p ?" )
+ fi
+ done
+ fi
+ # Set $subject to the info for the current patch
if [[ -f "${patchdir}/msg-clean" ]]; then
subject="${$(< "${patchdir}/msg-clean")[(f)1]}"
- elif local this_patch_file
- printf -v this_patch_file "%s/%04d" "${patchdir}" "${cur}"
+ elif [[ -f "${patchdir}/final-commit" ]]; then
+ # This value is not rfc2047-encoded. It's also available via
+ # "${patchdir}/info".
+ subject="${$(< "${patchdir}/final-commit")[(f)1]}"
+ elif printf -v this_patch_file "%s/%04d" "${patchdir}" "${cur}"
[[ -f $this_patch_file ]]
then
+ # This branch is last for several reasons:
+ #
+ # - The "Subject" header will be MIME-encoded (rfc2047).
+ #
+ # - If the mail has full rfc822 headers (including "Received" and
+ # so on), we won't find the "Subject:" header, since
+ # VCS_INFO_patch2subject only checks the first few lines.
+ #
+ # - In --scissors mode, we may find the outer "Subject:" header,
+ # whereas the inner one (after the scissors line) will be used,
+ # if present.
() {
local REPLY
VCS_INFO_patch2subject "${this_patch_file}"
@@ -266,14 +320,32 @@ elif [[ -d "${gitdir}/rebase-apply" ]]; then
subject=${subject:-'?'}
if [[ -f "${patchdir}/original-commit" ]]; then
git_patches_applied+=("$(< ${patchdir}/original-commit) $subject")
+ elif [[ -f "${patchdir}/next" ]]; then
+ git_patches_applied+=("$(< ${patchdir}/next) $subject")
else
git_patches_applied+=("? $subject")
fi
- local last="$(< "${patchdir}/last")"
- if (( cur+1 <= last )); then
- git_patches_unapplied=( {$((cur+1))..$last} )
+ # Handle patches scheduled for after the current patch, if instructed to.
+ if zstyle -t ":vcs_info:${vcs}:${usercontext}:${rrn}" get-unapplied; then
+ local last="$(< "${patchdir}/last")"
+ if [[ -r ${patchdir}/original-commit && -r ${patchdir}/orig-head ]] &&
+ ! zstyle -t ":vcs_info:${vcs}:${usercontext}:${rrn}" use-simple
+ then
+ git_patches_unapplied+=( ${(f)"$(${vcs_comm[cmd]} log --reverse --pretty="%h %s" "$(<${patchdir}/original-commit)..$(<${patchdir}/orig-head)")"} )
+ else
+ for ((p = cur+1; p <= last; p++)); do
+ printf -v this_patch_file "%s/%04d" "${patchdir}" "${p}"
+ if [[ -f $this_patch_file ]]; then
+ VCS_INFO_patch2subject "${this_patch_file}"
+ git_patches_unapplied+=( "$p $REPLY" )
+ else
+ git_patches_unapplied+=( "$p ?" )
+ fi
+ done
+ fi
fi
fi
+ unset this_patch_file
VCS_INFO_git_handle_patches
elif [[ -f "${gitdir}/MERGE_HEAD" ]]; then
diff --git a/Functions/VCS_Info/Backends/VCS_INFO_get_data_hg b/Functions/VCS_Info/Backends/VCS_INFO_get_data_hg
index cd5ef321d..ea3798b81 100644
--- a/Functions/VCS_Info/Backends/VCS_INFO_get_data_hg
+++ b/Functions/VCS_Info/Backends/VCS_INFO_get_data_hg
@@ -5,7 +5,7 @@
setopt localoptions extendedglob NO_shwordsplit
-local hgbase bmfile branchfile rebasefile dirstatefile mqseriesfile \
+local hgbase bmfile branchfile topicfile rebasefile dirstatefile mqseriesfile \
curbmfile curbm \
mqstatusfile mqguardsfile patchdir mergedir \
r_csetid r_lrev r_branch i_bmhash i_bmname \
@@ -14,7 +14,7 @@ local hgbase bmfile branchfile rebasefile dirstatefile mqseriesfile \
local -a hgid_args defrevformat defbranchformat \
hgbmarks mqpatches mqguards mqunapplied hgmisc \
- i_patchguards i_negguards i_posguards
+ i_patch i_patchguards i_negguards i_posguards
local -A hook_com
@@ -27,6 +27,7 @@ mergedir="${hgbase}/.hg/merge/"
bmfile="${hgbase}/.hg/bookmarks"
curbmfile="${hgbase}/.hg/bookmarks.current"
branchfile="${hgbase}/.hg/branch"
+topicfile="${hgbase}/.hg/topic"
rebasefile="${hgbase}/.hg/rebasestate"
dirstatefile="${hgbase}/.hg/dirstate"
mqstatusfile="${patchdir}/status" # currently applied patches
@@ -48,27 +49,34 @@ if zstyle -t ":vcs_info:${vcs}:${usercontext}:${rrn}" get-revision ; then
# 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
# available in a single hg invocation
- hgid_args=( id -i -n -b )
+ hgid_args=( id -i -n )
# Looking for changes is a tad bit slower since the dirstate cache must
# first be refreshed before being read
zstyle -t ":vcs_info:${vcs}:${usercontext}:${rrn}" \
"check-for-changes" || hgid_args+=( -r. )
- local HGPLAIN
HGPLAIN=1 ${vcs_comm[cmd]} ${(z)hgid_args} 2> /dev/null \
- | read -r r_csetid r_lrev r_branch
+ | read -r r_csetid r_lrev
fi
fi
# If the user doesn't opt to invoke hg we can still get the current branch
-if [[ -z ${r_branch} && -r ${branchfile} ]] ; then
+if [[ -r ${branchfile} ]] ; then
r_branch=$(< ${branchfile})
fi
# If we still don't know the branch it's safe to assume default
[[ -n ${r_branch} ]] || r_branch="default"
+# Show topic if there is any (the UI for this experimental concept is not yet
+# final, but for a long time the convention has been to join the branch name
+# and the topic name by a colon)
+if [[ -f ${topicfile} && -r ${topicfile} && -s ${topicfile} ]] ; then
+ IFS= read -r REPLY < ${topicfile}
+ r_branch=${r_branch}:${REPLY}
+fi
+
# The working dir has uncommitted-changes if the revision ends with a +
if [[ $r_lrev[-1] == + ]] ; then
hgchanges=1
@@ -175,6 +183,9 @@ if zstyle -T ":vcs_info:${vcs}:${usercontext}:${rrn}" get-mq \
# Skip commented lines
[[ ${i_patch} == [[:space:]]#"#"* ]] && continue
+ # Skip applied patches
+ (( ${+mqpatches[(re)${i_patch}]} )) && continue
+
# Separate negative and positive guards to more easily find the
# intersection of active guards with patch guards
i_patchguards=( ${(s: :)i_patchguards} )
@@ -208,12 +219,16 @@ if zstyle -T ":vcs_info:${vcs}:${usercontext}:${rrn}" get-mq \
fi
local -A extra_hook_com=( guards "${guards_string}" guards-n ${#mqguards} )
- local -a extra_zformats=( "g:${extra_hook_com[guards]}" "G:${#mqguards}" )
+
+ (( ${+functions[VCS_INFO_hg_extra_zformats]} )) ||
+ VCS_INFO_hg_extra_zformats() {
+ reply=( "g:${hook_com[guards]}" "G:${#mqguards}" )
+ }
VCS_INFO_set-patch-format 'mqpatches' 'applied_string' \
'mqunapplied' 'unapplied_string' \
":vcs_info:${vcs}:${usercontext}:${rrn}" hgmqstring \
- extra_hook_com extra_zformats
+ extra_hook_com VCS_INFO_hg_extra_zformats ''
hgmqstring=$REPLY
fi
diff --git a/Functions/VCS_Info/Backends/VCS_INFO_get_data_p4 b/Functions/VCS_Info/Backends/VCS_INFO_get_data_p4
index 329884982..e8a08a663 100644
--- a/Functions/VCS_Info/Backends/VCS_INFO_get_data_p4
+++ b/Functions/VCS_Info/Backends/VCS_INFO_get_data_p4
@@ -17,13 +17,8 @@ local p4branch change
# here down is synced as the revision.
# I suppose the following might be slow on a tortuous client view.
change="${${$(${vcs_comm[cmd]} changes -m 1 ...\#have)##Change }%% *}"
-zstyle -s ":vcs_info:${vcs}:${usercontext}:${rrn}" branchformat p4branch || p4branch="%b:%r"
-hook_com=( branch "${p4info[Client_name]}" revision "${change}" )
-if VCS_INFO_hook 'set-branch-format' "${p4branch}"; then
- zformat -f p4branch "${p4branch}" "b:${hook_com[branch]}" "r:${hook_com[revision]}"
-else
- p4branch=${hook_com[branch-replace]}
-fi
-hook_com=()
+rrn=${p4base:t}
+VCS_INFO_set-branch-format "${p4info[Client_name]}" "${change}" &&
+ p4branch="${REPLY}"
VCS_INFO_formats '' "${p4branch}" "${p4base}" '' '' "$change" ''
return 0
diff --git a/Functions/VCS_Info/Backends/VCS_INFO_get_data_svk b/Functions/VCS_Info/Backends/VCS_INFO_get_data_svk
index 1d2d22ffb..149e30222 100644
--- a/Functions/VCS_Info/Backends/VCS_INFO_get_data_svk
+++ b/Functions/VCS_Info/Backends/VCS_INFO_get_data_svk
@@ -8,13 +8,7 @@ local -A hook_com
svkbase=${vcs_comm[basedir]}
rrn=${svkbase:t}
-zstyle -s ":vcs_info:${vcs}:${usercontext}:${rrn}" branchformat svkbranch || svkbranch="%b:%r"
-hook_com=( branch "${vcs_comm[branch]}" revision "${vcs_comm[revision]}" )
-if VCS_INFO_hook 'set-branch-format' "${svkbranch}"; then
- zformat -f svkbranch "${svkbranch}" "b:${hook_com[branch]}" "r:${hook_com[revision]}"
-else
- svkbranch=${hook_com[branch-replace]}
-fi
-hook_com=()
+VCS_INFO_set-branch-format "${vcs_comm[branch]}" "${vcs_comm[revision]}" &&
+ svkbranch="${REPLY}"
VCS_INFO_formats '' "${svkbranch}" "${svkbase}" '' '' "${vcs_comm[revision]}" ''
return 0
diff --git a/Functions/VCS_Info/Backends/VCS_INFO_get_data_svn b/Functions/VCS_Info/Backends/VCS_INFO_get_data_svn
index 21590addd..b33efc2fb 100644
--- a/Functions/VCS_Info/Backends/VCS_INFO_get_data_svn
+++ b/Functions/VCS_Info/Backends/VCS_INFO_get_data_svn
@@ -10,6 +10,7 @@ local -i rc
local -A svninfo parentinfo cwdinfo
local -A hook_com
integer -r SVN_ERR_WC_UPGRADE_REQUIRED=155036 # from /usr/local/include/subversion-1/svn_error_codes.h
+integer -r SVN_ERR_WC_UNSUPPORTED_FORMAT=155021
svnbase=".";
svninfo=()
@@ -22,7 +23,14 @@ rc=$?
if (( rc != 0 )) ; then
if (( rc == 1 )) && [[ -n ${(M)dat:#"svn: E${SVN_ERR_WC_UPGRADE_REQUIRED}: "*} ]]; then
hook_com=()
- VCS_INFO_formats '' '?' '?' '' '' '?' 'upgrade required'
+ # User should run 'svn upgrade'
+ VCS_INFO_formats '' '?' '?' '' '' '?' 'working copy upgrade required'
+ return $?
+ elif (( rc == 1 )) && [[ -n ${(M)dat:#"svn: E${SVN_ERR_WC_UNSUPPORTED_FORMAT}: "*} ]]; then
+ hook_com=()
+ # User probably needs to install a newer svn, but we're not sure, so point
+ # the user to svn's error message.
+ VCS_INFO_formats '' '?' '?' '' '' '?' 'svn error'
return $?
else
return 1
@@ -60,13 +68,7 @@ else
fi
rrn=${svnbase:t}
-zstyle -s ":vcs_info:${vcs}:${usercontext}:${rrn}" branchformat svnbranch || svnbranch="%b:%r"
-hook_com=( branch "${svninfo[URL]##*/}" revision "${cwdinfo[Revision]}" )
-if VCS_INFO_hook 'set-branch-format' "${svnbranch}"; then
- zformat -f svnbranch "${svnbranch}" "b:${hook_com[branch]}" "r:${hook_com[revision]}"
-else
- svnbranch=${hook_com[branch-replace]}
-fi
-hook_com=()
+VCS_INFO_set-branch-format "${svninfo[URL]##*/}" "${cwdinfo[Revision]}" &&
+ svnbranch="${REPLY}"
VCS_INFO_formats '' "${svnbranch}" "${svnbase}" '' '' "${cwdinfo[Revision]}" ''
return 0
diff --git a/Functions/VCS_Info/VCS_INFO_bydir_detect b/Functions/VCS_Info/VCS_INFO_bydir_detect
index 29b261413..89b4d6503 100644
--- a/Functions/VCS_Info/VCS_INFO_bydir_detect
+++ b/Functions/VCS_Info/VCS_INFO_bydir_detect
@@ -36,4 +36,6 @@ done
[[ ${basedir} == "/" ]] && return 1
vcs_comm[basedir]=${basedir}
+# TODO: Would the following be correct? ---
+# rrn=${vcs_comm[basedir]:t}
return 0
diff --git a/Functions/VCS_Info/VCS_INFO_patch2subject b/Functions/VCS_Info/VCS_INFO_patch2subject
index a467edcdb..5aa9efd23 100644
--- a/Functions/VCS_Info/VCS_INFO_patch2subject
+++ b/Functions/VCS_Info/VCS_INFO_patch2subject
@@ -1,3 +1,5 @@
+## vim:ft=zsh
+#
# 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.
{
diff --git a/Functions/VCS_Info/VCS_INFO_quilt b/Functions/VCS_Info/VCS_INFO_quilt
index fef85964a..ce5b41f24 100644
--- a/Functions/VCS_Info/VCS_INFO_quilt
+++ b/Functions/VCS_Info/VCS_INFO_quilt
@@ -92,7 +92,7 @@ function VCS_INFO_quilt-patch2subject() {
emulate -L zsh
setopt extendedglob
local mode="$1"
- local patches pc tmp qstring root
+ local patches pc qstring root
local -i ret
local context
local -a applied unapplied applied_string unapplied_string quiltcommand quilt_env
@@ -113,9 +113,12 @@ function VCS_INFO_quilt-patch2subject() {
;;
esac
- VCS_INFO_quilt-dirfind .pc .version
- ret=$? pc=$REPLY
- if (( ret == 0 )); then
+ # Look for the patches directory.
+ #
+ # 1. Check if there's a .pc/.version file in a parent dir. If so, use the
+ # patches dir from the corresponding .pc/.quilt_patches.
+ if VCS_INFO_quilt-dirfind .pc .version; then
+ pc=$REPLY
[[ ${quiltmode} == 'standalone' ]] && root=${pc}
pc=${pc}/.pc
if [[ -e ${pc}/applied-patches ]]; then
@@ -128,33 +131,35 @@ function VCS_INFO_quilt-patch2subject() {
fi
patches=$(<$pc/.quilt_patches)
patches=`builtin cd -q "${pc:h}" && print -r - ${patches:P}`
+ # 2. Else, locate a patches dir using the style settings.
+ else
+ zstyle -s "${context}" quilt-patch-dir patches || patches="${QUILT_PATCHES}"
+ : ${patches:="patches"}
+ if [[ "${patches}" != /* ]]; then
+ if VCS_INFO_quilt-dirfind "${patches}"; then
+ patches=$REPLY/$patches
+ else
+ return $?
+ fi
+ else
+ [[ -d ${patches} ]] || return 1
+ fi
+ quilt_env+=(QUILT_PATCHES="$patches")
fi
+ # At this point, $patches is set and points to an existing directory.
+
if zstyle -t "${context}" get-unapplied; then
# This zstyle call needs to be moved further up if `quilt' needs
# to be run in more places than this one.
zstyle -s "${context}" quiltcommand quiltcommand || quiltcommand='quilt'
- quilt_env=(env)
- if [ -z "$patches" ]; then
- zstyle -s "${context}" quilt-patch-dir patches || patches="${QUILT_PATCHES}"
- if [[ "${patches}" != /* ]]; then
- tmp=${patches:-patches}
- VCS_INFO_quilt-dirfind "${tmp}"
- ret=$? patches=$REPLY
- (( ret )) && return ${ret}
- patches=${patches}/${tmp}
- else
- [[ -d ${patches} ]] || return 1
- fi
- quilt_env+=(QUILT_PATCHES="$patches")
- fi
- unapplied=( ${(f)"$(${quilt_env[@]} $quiltcommand --quiltrc /dev/null unapplied 2> /dev/null)"} )
+ unapplied=( ${(f)"$(if (( $+quilt_env[1] )); then export ${quilt_env[@]}; fi
+ $quiltcommand --quiltrc /dev/null unapplied 2> /dev/null)"} )
unapplied=( ${unapplied:#} )
else
unapplied=()
fi
- if [[ -n $patches ]]; then
- () {
+ {
local i
for ((i=1; i<=$#applied; i++)); do
if VCS_INFO_quilt-patch2subject "$patches/$applied[$i]" && (( $+REPLY ))
@@ -172,13 +177,17 @@ function VCS_INFO_quilt-patch2subject() {
unapplied[$i]+=" ?"
fi
done
- }
- fi
+ }
+
+ typeset -A quilt_extra_info=(
+ quilt-patches-dir ${patches}
+ ${pc:+"quilt-pc-dir"} $pc
+ )
VCS_INFO_set-patch-format 'applied' 'applied_string' \
'unapplied' 'unapplied_string' \
${context} qstring \
- '' ''
+ quilt_extra_info '' quilt_extra_info
qstring=$REPLY
case ${mode} in
diff --git a/Functions/VCS_Info/VCS_INFO_set-branch-format b/Functions/VCS_Info/VCS_INFO_set-branch-format
new file mode 100644
index 000000000..cbab60e29
--- /dev/null
+++ b/Functions/VCS_Info/VCS_INFO_set-branch-format
@@ -0,0 +1,24 @@
+## vim:ft=zsh
+#
+# A function for calling the branch-format hook
+#
+# Return the value to use in REPLY
+#
+# Parameters:
+readonly branch=$1
+readonly revision=$2
+#
+
+[[ -n $rrn ]] || return 1
+local -A hook_com
+local branchformat
+
+zstyle -s ":vcs_info:${vcs}:${usercontext}:${rrn}" branchformat branchformat || branchformat="%b:%r"
+hook_com=( branch "${branch}" revision "${revision}" )
+if VCS_INFO_hook 'set-branch-format' "${branchformat}"; then
+ zformat -f REPLY "${branchformat}" "b:${hook_com[branch]}" "r:${hook_com[revision]}"
+else
+ REPLY=${hook_com[branch-replace]}
+fi
+hook_com=()
+return 0
diff --git a/Functions/VCS_Info/VCS_INFO_set-patch-format b/Functions/VCS_Info/VCS_INFO_set-patch-format
index 917ebf6bf..1c774a7f6 100644
--- a/Functions/VCS_Info/VCS_INFO_set-patch-format
+++ b/Functions/VCS_Info/VCS_INFO_set-patch-format
@@ -1,3 +1,5 @@
+## vim:ft=zsh
+#
# This function is the common guts of the gen-applied-string /
# gen-unapplied-string / set-patch-format dance of several backends.
#
@@ -12,7 +14,9 @@
# $6 - name of a parameter to store a patch-format format string in
# $7 - name of an assoc parameter with extra $hook_com key-value pairs for the
# set-patch-format hook invocation, or '' for none
-# $8 - name of an array parameter with extra arguments for the patch-format zformat call, or '' for empty
+# $8 - name of a function that sets $reply to extra arguments for the patch-format zformat call, or '' for none
+# $9 - name of an assoc parameter with extra $hook_com key-value pairs for the
+# gen-applied-string & gen-unapplied-string hook invocations, or '' for none
#
# The expanded patch-format string is returned in $REPLY.
#
@@ -20,8 +24,10 @@
# - $hook_com is overwritten and the keys 'applied', 'applied-n',
# 'unapplied', 'unapplied-n', 'all-n' are set.
{
+ hook_com=()
+
local applied_needs_escaping='unknown'
- local unapplied_needs_escaping='unknown'
+ hook_com+=( ${9:+"${(@kvP)9}"} )
if VCS_INFO_hook 'gen-applied-string' "${(@P)1}"; then
if (( ${(P)#1} )); then
REPLY=${(P)1[1]}
@@ -35,6 +41,8 @@
: ${(P)2::=$REPLY}
hook_com=()
+ local unapplied_needs_escaping='unknown'
+ hook_com+=( ${9:+"${(@kvP)9}"} )
if VCS_INFO_hook 'gen-unapplied-string' "${(@P)3}"; then
REPLY=${(P)#3}
unapplied_needs_escaping='yes'
@@ -68,10 +76,12 @@
hook_com[unapplied]=${hook_com[unapplied]//'%'/%%}
fi
+ reply=()
+ [[ -n $8 ]] && "$8"
zformat -f REPLY "${(P)6}" "p:${hook_com[applied]}" "u:${hook_com[unapplied]}" \
"n:${hook_com[applied-n]}" "c:${hook_com[unapplied-n]}" \
"a:${hook_com[all-n]}" \
- ${8:+"${(@P)8}"}
+ "${reply[@]}"
else
unset applied_needs_escaping unapplied_needs_escaping # the hook deals with escaping
REPLY=${hook_com[patch-replace]}
diff --git a/Functions/VCS_Info/test-repo-git-rebase-apply b/Functions/VCS_Info/test-repo-git-rebase-apply
new file mode 100755
index 000000000..ce49690cd
--- /dev/null
+++ b/Functions/VCS_Info/test-repo-git-rebase-apply
@@ -0,0 +1,59 @@
+#!/usr/local/bin/zsh -f
+#
+# This script creates a test repository for testing the git backend's behaviour during rebase-apply operations.
+#
+# It works in ./vcs-test/.
+#
+# Suggested zshrc settings:
+#
+# autoload vcs_info
+# precmd() { vcs_info; typeset -pm vcs\* }
+# zstyle ':vcs_info:*' actionformats %m
+# zstyle ':vcs_info:*' patch-format '[%n+%c=%a] [%p] [%u]'
+# zstyle :vcs_info:\*gen-applied-string\* hooks f1
+# +vi-f1() { typeset -p argv hook_com }
+# zstyle :vcs_info:\*gen-unapplied-string\* hooks f2
+# +vi-f2() { typeset -p argv hook_com }
+# zstyle :vcs_info:\* get-unapplied true
+#
+mkdir "vcs-test"
+cd "vcs-test"
+git init
+
+append_lines() { for 1; do echo line from r$1 >> iota && git commit -am "r$1: Append a line"; done }
+
+echo "This is the file 'iota'." > iota
+git add iota
+git commit -m "r1: Add iota"
+git tag rebase_onto_this HEAD
+
+# Make another change to iota
+append_lines 2
+git tag rebase_from_this HEAD
+
+# Make non-conflicting changes
+for 1 in 3 4 5 6; do
+ touch kappa$1
+ git add kappa$1
+ git commit -m "r${1}: non-conflicting change"
+done
+
+# Make more changes to iota
+append_lines 7 8 9
+
+# Specify a rebase that would create the history [1,3,4,5,6,7,8,9].
+# This will conflict because r7 depends on r2 which is not included.
+git checkout -b myref
+case $0:P in
+ (*/test-repo-git-rebase-apply)
+ git rebase --onto=rebase_onto_this rebase_from_this myref
+ ;;
+ (*/test-repo-git-rebase-merge)
+ git -c core.editor=true rebase -i --onto=rebase_onto_this rebase_from_this myref
+ ;;
+ (*)
+ echo >&2 "$0: unrecognized basename"
+ ;;
+esac
+
+
diff --git a/Functions/VCS_Info/test-repo-git-rebase-merge b/Functions/VCS_Info/test-repo-git-rebase-merge
new file mode 100755
index 000000000..ce49690cd
--- /dev/null
+++ b/Functions/VCS_Info/test-repo-git-rebase-merge
@@ -0,0 +1,59 @@
+#!/usr/local/bin/zsh -f
+#
+# This script creates a test repository for testing the git backend's behaviour during rebase-apply operations.
+#
+# It works in ./vcs-test/.
+#
+# Suggested zshrc settings:
+#
+# autoload vcs_info
+# precmd() { vcs_info; typeset -pm vcs\* }
+# zstyle ':vcs_info:*' actionformats %m
+# zstyle ':vcs_info:*' patch-format '[%n+%c=%a] [%p] [%u]'
+# zstyle :vcs_info:\*gen-applied-string\* hooks f1
+# +vi-f1() { typeset -p argv hook_com }
+# zstyle :vcs_info:\*gen-unapplied-string\* hooks f2
+# +vi-f2() { typeset -p argv hook_com }
+# zstyle :vcs_info:\* get-unapplied true
+#
+mkdir "vcs-test"
+cd "vcs-test"
+git init
+
+append_lines() { for 1; do echo line from r$1 >> iota && git commit -am "r$1: Append a line"; done }
+
+echo "This is the file 'iota'." > iota
+git add iota
+git commit -m "r1: Add iota"
+git tag rebase_onto_this HEAD
+
+# Make another change to iota
+append_lines 2
+git tag rebase_from_this HEAD
+
+# Make non-conflicting changes
+for 1 in 3 4 5 6; do
+ touch kappa$1
+ git add kappa$1
+ git commit -m "r${1}: non-conflicting change"
+done
+
+# Make more changes to iota
+append_lines 7 8 9
+
+# Specify a rebase that would create the history [1,3,4,5,6,7,8,9].
+# This will conflict because r7 depends on r2 which is not included.
+git checkout -b myref
+case $0:P in
+ (*/test-repo-git-rebase-apply)
+ git rebase --onto=rebase_onto_this rebase_from_this myref
+ ;;
+ (*/test-repo-git-rebase-merge)
+ git -c core.editor=true rebase -i --onto=rebase_onto_this rebase_from_this myref
+ ;;
+ (*)
+ echo >&2 "$0: unrecognized basename"
+ ;;
+esac
+
+
diff --git a/Functions/VCS_Info/vcs_info b/Functions/VCS_Info/vcs_info
index 9f48bee75..786b61918 100644
--- a/Functions/VCS_Info/vcs_info
+++ b/Functions/VCS_Info/vcs_info
@@ -22,6 +22,7 @@ static_functions=(
VCS_INFO_hexdump
VCS_INFO_hook
VCS_INFO_set-patch-format
+ VCS_INFO_set-branch-format
VCS_INFO_maxexports
VCS_INFO_nvcsformats
VCS_INFO_patch2subject
diff --git a/Functions/Zle/edit-command-line b/Functions/Zle/edit-command-line
index 991775ea5..5f7ea321f 100644
--- a/Functions/Zle/edit-command-line
+++ b/Functions/Zle/edit-command-line
@@ -7,6 +7,23 @@
# except that it will handle multi-line buffers properly.
emulate -L zsh
+local left right prebuffer buffer=$BUFFER lbuffer=$LBUFFER
+local TMPSUFFIX=.zsh
+# set up parameters depending on which context we are called from,
+# see below comment for more details
+if (( REGION_ACTIVE )); then
+ if (( CURSOR < MARK )); then
+ left=$CURSOR right=$MARK
+ lbuffer=
+ else
+ left=$MARK right=$CURSOR
+ lbuffer[right-left,-1]=
+ fi
+ (( left++ ))
+ buffer=$BUFFER[left,right]
+elif (( ! ZLE_RECURSIVE )); then
+ prebuffer=$PREBUFFER
+fi
() {
exec </dev/tty
@@ -17,13 +34,17 @@ emulate -L zsh
(( $+zle_bracketed_paste )) && print -r -n - $zle_bracketed_paste[2]
# Open the editor, placing the cursor at the right place if we know how.
- local editor=( "${(@Q)${(z)${VISUAL:-${EDITOR:-vi}}}}" )
- case $editor in
+ local -a editor
+ zstyle -a :zle:$WIDGET editor editor
+ if (( ! $#editor )); then
+ editor=( "${(@Q)${(z)${VISUAL:-${EDITOR:-vi}}}}" )
+ fi
+ case $editor in
(*vim*)
- integer byteoffset=$(( $#PREBUFFER + $#LBUFFER + 1 ))
+ integer byteoffset=$(( $#prebuffer + $#lbuffer + 1 ))
"${(@)editor}" -c "normal! ${byteoffset}go" -- $1;;
(*emacs*)
- local lines=( "${(@f):-"$PREBUFFER$LBUFFER"}" )
+ local lines=( "${(@f):-"$prebuffer$lbuffer"}" )
"${(@)editor}" +${#lines}:$((${#lines[-1]} + 1)) $1;;
(*) "${(@)editor}" $1;;
esac
@@ -31,7 +52,32 @@ emulate -L zsh
(( $+zle_bracketed_paste )) && print -r -n - $zle_bracketed_paste[1]
# Replace the buffer with the editor output.
- print -Rz - "$(<$1)"
-} =(<<<"$PREBUFFER$BUFFER")
+ # avoid drawing a new prompt when we can:
+ # - in recursive-edit, the send-break will just cancel the recursive-edit
+ # rather than reload the line from print -z so in that case we want to
+ # just set $BUFFER (unfortunately, recursive-edit doesn't reset CONTEXT
+ # or PREBUFFER so we have to explicitly handle this case, which overrides
+ # the following point)
+ # - when we are at PS2 (CONTEXT == cont && ! ZLE_RECURSIVE) we do want the
+ # break or otherwise the text from PREBUFFER will be inserted twice
+ # - when the region is active, we only want to change the parts of BUFFER
+ # covered by the region, and any PREBUFFER stays as PREBUFFER
+ # - in all other cases (that I can think of) we also just want to set
+ # $BUFFER directly.
+ if (( REGION_ACTIVE )); then
+ # adjust the length of the region to the length of the edited text
+ local prelen=$#BUFFER
+ BUFFER[left,right]="$(<$1)"
+ if (( MARK > CURSOR )); then
+ (( MARK += $#BUFFER - prelen ))
+ else
+ (( CURSOR += $#BUFFER - prelen ))
+ fi
+ elif [[ $CONTEXT != cont ]] || (( ZLE_RECURSIVE )); then
+ BUFFER="$(<$1)"
+ else
+ print -Rz - "$(<$1)"
+ zle send-break
+ fi
-zle send-break # Force reload from the buffer stack
+} =(<<<"$prebuffer$buffer")
diff --git a/Functions/Zle/zed-set-file-name b/Functions/Zle/zed-set-file-name
index da3421e71..745610660 100644
--- a/Functions/Zle/zed-set-file-name
+++ b/Functions/Zle/zed-set-file-name
@@ -2,8 +2,25 @@ emulate -L zsh
autoload -Uz read-from-minibuffer
-zle -K zed-normal-keymap
-
-local REPLY
-read-from-minibuffer "File name: "
-zed_file_name=$REPLY
+case $curcontext in
+ (zed:::)
+ local curcontext=zed-set-file-name:::
+ # The call to vared from zed does the equivalent of
+ # bindkey -A zed main
+ # which confuses read-from-minibuffer. Fix it.
+ bindkey -A zed-normal-keymap main;;
+ (zed-set-file-name:::)
+ zle -M "zed-set-file-name: may not be called recursively"
+ return 1;;
+ (*)
+ zle -M "zed-set-file-name: not called from within zed"
+ return 1;;
+esac
+{
+ local REPLY
+ read-from-minibuffer "File name: "
+ zed_file_name=$REPLY
+} always {
+ # Re-install the zed keymap in the way vared should have all along
+ zle -K zed
+}