summaryrefslogtreecommitdiff
path: root/Functions
diff options
context:
space:
mode:
Diffstat (limited to 'Functions')
-rw-r--r--Functions/MIME/zsh-mime-handler2
-rw-r--r--Functions/Misc/add-zle-hook-widget4
-rw-r--r--Functions/Misc/colors20
-rw-r--r--Functions/Misc/is-at-least8
-rw-r--r--Functions/Misc/mkshadow11
-rw-r--r--Functions/Misc/run-help12
-rw-r--r--Functions/Misc/run-help-docker9
-rw-r--r--Functions/Misc/run-help-ip2
-rw-r--r--Functions/Misc/run-help-openssl8
-rw-r--r--Functions/Misc/run-help-perf1
-rw-r--r--Functions/Misc/run-help-podman9
-rw-r--r--Functions/Misc/run-help-ssh6
-rw-r--r--Functions/Misc/run-help-svk1
-rw-r--r--Functions/Misc/run-help-svnadmin1
-rw-r--r--Functions/Misc/zargs40
-rw-r--r--Functions/Misc/zcalc4
-rw-r--r--Functions/Misc/zed14
-rw-r--r--Functions/Misc/zmv14
-rw-r--r--Functions/Misc/zslurp31
-rw-r--r--Functions/Prompts/prompt_restore_setup14
-rw-r--r--Functions/Prompts/prompt_sprint2_setup128
-rw-r--r--Functions/Prompts/promptinit2
-rw-r--r--Functions/VCS_Info/Backends/VCS_INFO_get_data_git44
-rw-r--r--Functions/Zle/edit-command-line23
-rw-r--r--Functions/Zle/incarg322
-rw-r--r--Functions/Zle/keeper3
26 files changed, 639 insertions, 94 deletions
diff --git a/Functions/MIME/zsh-mime-handler b/Functions/MIME/zsh-mime-handler
index 288a0796d..2feacf063 100644
--- a/Functions/MIME/zsh-mime-handler
+++ b/Functions/MIME/zsh-mime-handler
@@ -193,7 +193,7 @@ if ! zsh-mime-contexts -s $suffix flags flags; then
# Same again for flags.
s=$suffix
while true; do
- flags="${zsh_mime_flags[$suffix]}"
+ flags="${zsh_mime_flags[$s]}"
if [[ -n $flags ]]; then
break
fi
diff --git a/Functions/Misc/add-zle-hook-widget b/Functions/Misc/add-zle-hook-widget
index 4d8049083..4293a07dd 100644
--- a/Functions/Misc/add-zle-hook-widget
+++ b/Functions/Misc/add-zle-hook-widget
@@ -39,7 +39,7 @@ zstyle zle-hook types ${hooktypes#zle-}
# Relying on multifuncdef option here
function azhw:${^hooktypes} {
- local -a hook_widgets
+ local -a hook_widgets match mbegin mend
local hook
# Values of these styles look like number:name
# and we run them in number order
@@ -58,7 +58,7 @@ function azhw:${^hooktypes} {
# Redefine ourself with the setup left out
function add-zle-hook-widget {
- local -a hooktypes
+ local -a hooktypes match mbegin mend
zstyle -a zle-hook types hooktypes
# This part copied from add-zsh-hook
diff --git a/Functions/Misc/colors b/Functions/Misc/colors
index 5e9d77d10..8a0cec383 100644
--- a/Functions/Misc/colors
+++ b/Functions/Misc/colors
@@ -44,7 +44,7 @@ color=(
35 magenta 45 bg-magenta
36 cyan 46 bg-cyan
37 white 47 bg-white
-# 38 iso-8316-6 # 48 bg-iso-8316-6
+# 38 iso-8613-6 # 48 bg-iso-8613-6
39 default 49 bg-default
# Other codes:
@@ -63,6 +63,16 @@ color=(
# 63 double-overline-or-left
# 64 stress
# 65 no-ideogram-marking
+
+# Bright color codes (xterm extension)
+ 90 bright-gray 100 bg-bright-gray
+ 91 bright-red 101 bg-bright-red
+ 92 bright-green 102 bg-bright-green
+ 93 bright-yellow 103 bg-bright-yellow
+ 94 bright-blue 104 bg-bright-blue
+ 95 bright-magenta 105 bg-bright-magenta
+ 96 bright-cyan 106 bg-bright-cyan
+ 97 bright-white 107 bg-bright-white
)
# A word about black and white: The "normal" shade of white is really a
@@ -79,7 +89,7 @@ for k in ${(k)color}; do color[${color[$k]}]=$k; done
# Add "fg-" keys for all the text colors, for clarity.
-for k in ${color[(I)3?]}; do color[fg-${color[$k]}]=$k; done
+for k in ${color[(I)[39]?]}; do color[fg-${color[$k]}]=$k; done
# This is inaccurate, but the prompt theme system needs it.
@@ -89,7 +99,11 @@ for k in grey gray; do
color[bg-$k]=${color[bg-black]}
done
-# Assistance for the color-blind.
+# Assistance for the colo(u)r-blind.
+
+for k in '' fg- bg-; do
+ color[${k}bright-grey]=${color[${k}bright-gray]}
+done
colour=(${(kv)color}) # A case where ksh namerefs would be useful ...
diff --git a/Functions/Misc/is-at-least b/Functions/Misc/is-at-least
index d4ff3552a..5985684be 100644
--- a/Functions/Misc/is-at-least
+++ b/Functions/Misc/is-at-least
@@ -24,8 +24,14 @@ emulate -L zsh
local IFS=".-" min_cnt=0 ver_cnt=0 part min_ver version order
+: ${2=$ZSH_VERSION}
+
+# sort out the easy corner cases first
+[[ $1 = $2 ]] && return 0 # same version
+[[ -n $2 ]] || return 1 # no version
+
min_ver=(${=1})
-version=(${=2:-$ZSH_VERSION} 0)
+version=(${=2} 0)
while (( $min_cnt <= ${#min_ver} )); do
while [[ "$part" != <-> ]]; do
diff --git a/Functions/Misc/mkshadow b/Functions/Misc/mkshadow
new file mode 100644
index 000000000..2ae3a0f2c
--- /dev/null
+++ b/Functions/Misc/mkshadow
@@ -0,0 +1,11 @@
+#autoload
+# Front-end to the completion helper _shadow for use outside completion.
+# This just forces proper autoload of _shadow/_unshadow and calls them.
+
+autoload _shadow
+mkshadow() { unset REPLY; _shadow "$@" }
+rmshadow() { unset REPLY; _unshadow }
+
+# Bootstrap because of autoload special case
+unset REPLY
+_shadow "$@"
diff --git a/Functions/Misc/run-help b/Functions/Misc/run-help
index d52c1b032..462044b72 100644
--- a/Functions/Misc/run-help
+++ b/Functions/Misc/run-help
@@ -58,11 +58,11 @@ do
case $what in
(*( is an alias for (noglob|nocorrect))*)
[[ ${what[(w)7]:t} != ${what[(w)1]} ]] &&
- run_help_orig_cmd=${what[(w)1]} run-help ${what[(w)7]:t}
+ run_help_orig_cmd=${what[(w)1]} run-help ${what[(w)7]:t} ${(z)${what[(w)8,-1]}}
;;
(*( is an alias)*)
[[ ${what[(w)6]:t} != ${what[(w)1]} ]] &&
- run_help_orig_cmd=${what[(w)1]} run-help ${what[(w)6]:t}
+ run_help_orig_cmd=${what[(w)1]} run-help ${what[(w)6]:t} ${(z)${what[(w)7,-1]}}
;;
(*( is a * function))
case ${what[(w)1]} in
@@ -98,13 +98,13 @@ do
if whence "run-help-$1:t" >/dev/null
then
local cmd_args
- builtin getln cmd_args
+ builtin getln cmd_args &&
builtin print -z "$cmd_args"
- cmd_args=( ${(z)cmd_args} )
+ cmd_args=( ${(z)${cmd_args:-"$*"}} )
# Discard the command itself & everything before it.
- shift $cmd_args[(i)${run_help_orig_cmd:-$1}] cmd_args ||
- return
+ shift $cmd_args[(i)(${run_help_orig_cmd}|$1)] cmd_args 2>/dev/null ||
+ continue
# Discard options, parameter assignments & paths.
cmd_args=( ${cmd_args[@]:#([-+]*|*=*|*/*|\~*)} )
diff --git a/Functions/Misc/run-help-docker b/Functions/Misc/run-help-docker
new file mode 100644
index 000000000..09a8a221a
--- /dev/null
+++ b/Functions/Misc/run-help-docker
@@ -0,0 +1,9 @@
+if [[ $# == 0 ]]
+then
+ man docker
+elif [[ $# > 1 && $1 == (builder|checkpoint|config|container|context|image|manifest|network|node|plugin|secret|service|stack|swarm|system|trust|volume) ]]
+then
+ man docker-$1-$2
+else
+ man docker-$1
+fi
diff --git a/Functions/Misc/run-help-ip b/Functions/Misc/run-help-ip
index b811ce352..f635cce71 100644
--- a/Functions/Misc/run-help-ip
+++ b/Functions/Misc/run-help-ip
@@ -18,7 +18,7 @@ case $1 in
(addrl*) man ip-addrlabel ;;
(a*) man ip-address ;;
(l2*) man ip-l2tp ;;
- (li*) man ip-link ;;
+ (l*) man ip-link ;;
(ma*) man ip-maddress ;;
(mo*) man ip-monitor ;;
(mr*) man ip-mroute ;;
diff --git a/Functions/Misc/run-help-openssl b/Functions/Misc/run-help-openssl
index c528418c8..e4e45070e 100644
--- a/Functions/Misc/run-help-openssl
+++ b/Functions/Misc/run-help-openssl
@@ -1,7 +1 @@
-
-if [ $# -eq 0 ]; then
- man openssl
-else
- man $1
-fi
-
+man openssl${1:+-$1} || man ${1:-openssl}
diff --git a/Functions/Misc/run-help-perf b/Functions/Misc/run-help-perf
new file mode 100644
index 000000000..2e0695af2
--- /dev/null
+++ b/Functions/Misc/run-help-perf
@@ -0,0 +1 @@
+man perf${1:+-$1}
diff --git a/Functions/Misc/run-help-podman b/Functions/Misc/run-help-podman
new file mode 100644
index 000000000..64d9cd83f
--- /dev/null
+++ b/Functions/Misc/run-help-podman
@@ -0,0 +1,9 @@
+if [[ $# == 0 ]]
+then
+ man podman
+elif [[ $# > 1 && $1 == (container|generate|healthcheck|image|kube|machine|manifest|network|pod|secret|system|volume) ]]
+then
+ man podman-$1-$2
+else
+ man podman-$1
+fi
diff --git a/Functions/Misc/run-help-ssh b/Functions/Misc/run-help-ssh
new file mode 100644
index 000000000..9c48596ff
--- /dev/null
+++ b/Functions/Misc/run-help-ssh
@@ -0,0 +1,6 @@
+if [[ $# < 2 ]]
+then
+ man ssh
+else
+ run-help $2
+fi
diff --git a/Functions/Misc/run-help-svk b/Functions/Misc/run-help-svk
deleted file mode 100644
index 782538246..000000000
--- a/Functions/Misc/run-help-svk
+++ /dev/null
@@ -1 +0,0 @@
-svk help $1 | ${=PAGER:-more}
diff --git a/Functions/Misc/run-help-svnadmin b/Functions/Misc/run-help-svnadmin
new file mode 100644
index 000000000..dbddd6396
--- /dev/null
+++ b/Functions/Misc/run-help-svnadmin
@@ -0,0 +1 @@
+svnadmin help $1 | ${=PAGER:-more}
diff --git a/Functions/Misc/zargs b/Functions/Misc/zargs
index 81916a3ac..782d6811e 100644
--- a/Functions/Misc/zargs
+++ b/Functions/Misc/zargs
@@ -39,9 +39,14 @@
#
# "Killed by a signal" is determined by the usual shell rule that $? is
# the signal number plus 128, so zargs can be fooled by a command that
-# explicitly exits with 129+. Also, zsh prior to 4.1.x returns 1 rather
-# than 127 for "command not found" so this function incorrectly returns
-# 123 in that case if used with zsh 4.0.x.
+# explicitly exits with 129+. If the command passed to zargs is a shell
+# function which uses "exit" instead of "return", zsh interprets 129+ as
+# a signal sent to the process group and may terminate zargs with that
+# status. This is avoided when running zargs -P 2 or greater.
+#
+# ZARGS_VERSION 1.5 is the last to support zsh 4.x. Also, zsh prior to
+# 4.1.x returns 1 rather than 127 for "command not found" so zargs
+# incorrectly returned 123 in that case if used with zsh 4.0.x.
#
# Because of "wait" limitations, --max-procs spawns max-procs jobs, then
# waits for all of those, then spawns another batch, etc.
@@ -71,6 +76,10 @@
# * The use of SIGUSR1 and SIGUSR2 to change the number of parallel jobs
# is not supported.
+{ # Begin "always" block to reset locally defined functions
+
+local ZARGS_VERSION="1.8"
+
# First, capture the current setopts as "sticky emulation"
if zmodload zsh/parameter
then
@@ -84,11 +93,20 @@ else
emulate $(emulate -l) -c '_zarun() { eval "$@" }'
fi
+local _zaTRAPS="$(trap)"
+_zatraps() {
+ # In children, these traps may be reset to default behavior, even
+ # if the calling shell has traps. Restore to surrounding context,
+ # but assure that if zargs itself is signaled, children will exit.
+ [[ -o interactive ]] &&
+ function TRAP{HUP,INT,QUIT,TERM} { exit $((128 + $1)) }
+ [[ -n "$_zaTRAPS" ]] && eval "$_zaTRAPS"
+ unset _zaTRAPS
+}
+
emulate -L zsh || return 1
local -a opts eof n s l P i
-local ZARGS_VERSION="1.7"
-
if zparseopts -a opts -D -- \
-eof::=eof e::=eof \
-exit x \
@@ -193,14 +211,14 @@ then (( c = $#command - 1 ))
else command=( print -r -- )
fi
-local wait bg
-local execute='
+local bg execute='
if (( $opts[(I)-(-interactive|p)] ))
then read -q "?$call?..." || continue
elif (( $opts[(I)-(-verbose|t)] ))
then print -u2 -r -- "$call"
fi
_zarun "{
+ _zatraps
\"\${call[@]}\"
} $bg"'
local ret=0 analyze='
@@ -263,12 +281,10 @@ fi
if (( P != 1 && ARGC > 1 ))
then
- # These setopts are necessary for "wait" on multiple jobs to work.
- setopt nonotify nomonitor
+ setopt nonotify # Do not report each exiting job
local -a _zajobs
local j
bg='& _zajobs+=( $! )'
- wait='wait'
analyze='
for j in $_zajobs; do
wait $j
@@ -316,4 +332,8 @@ return $ret
)
+} always {
+ builtin unfunction _zarun _zatraps
+}
+
# }
diff --git a/Functions/Misc/zcalc b/Functions/Misc/zcalc
index 480373345..6cd2822c9 100644
--- a/Functions/Misc/zcalc
+++ b/Functions/Misc/zcalc
@@ -124,8 +124,10 @@ 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"
+history -ap "${ZCALC_HISTFILE:-${ZDOTDIR:-$HOME}/.zcalc_history}"
+
_forms=( '%2$g' '%.*g' '%.*f' '%.*E' '')
diff --git a/Functions/Misc/zed b/Functions/Misc/zed
index 7d0d590db..bb075512c 100644
--- a/Functions/Misc/zed
+++ b/Functions/Misc/zed
@@ -14,15 +14,17 @@ local var opts zed_file_name
integer TMOUT=0 okargs=1 fun hist bind
local -a expand
-zparseopts -D -A opts f h b x:
+zparseopts -D -A opts f h b x: || return 1
fun=$+opts[-f]
hist=$+opts[-h]
bind=$+opts[-b]
-if [[ $opts[-x] == <-> ]]; then
- expand=(-x $opts[-x])
-elif (( $+opts[-x] )); then
- print -r "Integer expected after -x: $opts[-x]" >&2
- return 1
+if (( $+opts[-x] )); then
+ if [[ $opts[-x] == <-> ]]; then
+ expand=(-x $opts[-x])
+ else
+ print -r "Integer expected after -x: $opts[-x]" >&2
+ return 1
+ fi
fi
[[ $0 = fned ]] && fun=1
diff --git a/Functions/Misc/zmv b/Functions/Misc/zmv
index 269fe5ba5..2002af5a6 100644
--- a/Functions/Misc/zmv
+++ b/Functions/Misc/zmv
@@ -236,20 +236,26 @@ if [[ $pat = (#b)(*)\((\*\*##/)\)(*) ]]; then
else
fpat=$pat
fi
-files=(${~fpat})
[[ -n $hasglobqual ]] && pat=$opat
errs=()
+() {
+ # (#qN) breaks bareglobqual -Q option, so:
+ setopt localoptions nullglob
+ files=(${~fpat})
+}
+(( ${#files} )) || errs=( "no files matched \`$fpat'" )
+
for f in $files; do
- if [[ $pat = (#b)(*)\(\*\*##/\)(*) ]]; then
+ if [[ $pat = (#b)(*)(\(\*\*##/\)|\*\*##/)(*) ]]; then
# This looks like a recursive glob. This isn't good enough,
- # because we should really enforce that $match[1] and $match[2]
+ # because we should really enforce that $match[1] and $match[3]
# don't match slashes unless they were explicitly given. But
# it's a start. It's fine for the classic case where (**/) is
# at the start of the pattern.
- pat="$match[1](*/|)$match[2]"
+ pat="$match[1](*/|)$match[3]"
fi
[[ -e $f && $f = (#b)${~pat} ]] || continue
set -- "$match[@]"
diff --git a/Functions/Misc/zslurp b/Functions/Misc/zslurp
new file mode 100644
index 000000000..84df0c948
--- /dev/null
+++ b/Functions/Misc/zslurp
@@ -0,0 +1,31 @@
+#!/bin/zsh -f
+
+# Read stdin verbatim and as efficiently as possible into $REPLY,
+# stopping without any change to $REPLY in the event of any error.
+# Benchmarked by Roman Perepelitsa in zsh-users/29472
+
+# Although this function faithfully records the input stream, later
+# references to $REPLY with the multibyte option back in effect will
+# (re-)interpret the content as multibyte characters. This may not be
+# what is desired.
+
+emulate -L zsh -o no_multibyte
+
+### Alternate formulation, faster on bigger files
+# # /dev/fd/0 is treated specially by -f so also check /dev/fd
+# if [[ -d /dev/fd && -f /dev/fd/0 ]] && zmodload zsh/mapfile
+# then
+# local +h -Ar mapfile
+# typeset -g REPLY="${mapfile[/dev/fd/0]}" && return
+# fi
+# # else fall through to read from pipe/socket
+
+zmodload zsh/system || return
+local -a content
+local -i i=0
+while true; do
+ sysread 'content[++i]' && continue
+ (( $? == 5 )) || return
+ break
+done
+typeset -g REPLY=${(j::)content}
diff --git a/Functions/Prompts/prompt_restore_setup b/Functions/Prompts/prompt_restore_setup
index b77dbe815..c1f9bfb7e 100644
--- a/Functions/Prompts/prompt_restore_setup
+++ b/Functions/Prompts/prompt_restore_setup
@@ -1,3 +1,11 @@
-# Damn that was easy
-zstyle -t :prompt-theme cleanup
-zstyle -t :prompt-theme restore
+prompt_restore_setup () {
+ # Damn that was easy
+ zstyle -t :prompt-theme cleanup
+ zstyle -t :prompt-theme restore
+}
+
+prompt_restore_preview () {
+ echo "The prompt command 'restore' is not a theme and cannot be previewed."
+}
+
+prompt_restore_setup "$@"
diff --git a/Functions/Prompts/prompt_sprint2_setup b/Functions/Prompts/prompt_sprint2_setup
new file mode 100644
index 000000000..0eaea4473
--- /dev/null
+++ b/Functions/Prompts/prompt_sprint2_setup
@@ -0,0 +1,128 @@
+# Created by Sebastian Gniazdowski
+
+prompt_sprint2_help () {
+ cat <<EOF
+This prompt is color themable. You can invoke it in following way:
+
+prompt sprint2 <time/line color> <braces clr.> <text clr.> <at/colon clr.> <prompt clr.>
+
+You can provide only N first arguments, N=1..5.
+
+The default colors are: 39 green blue green yellow
+EOF
+}
+
+prompt_sprint2_setup () {
+ local col_time_line=${1:-'39'}
+ local col_parens=${2:-'green'}
+ local col_text=${3:-'blue'}
+ local col_at_colon=${4:-'green'}
+ local col_prompt=${5:-'yellow'}
+
+ autoload -Uz vcs_info
+
+ typeset -gA _psvar
+
+ local cl_time_line="%B%F{$col_time_line}"
+ local cl_text="%b%F{$col_text}"
+ local cl_parens="%B%F{$col_parens}"
+ local cl_at_colon="%b%F{$col_at_colon}"
+ local cl_prompt="%B%F{$col_prompt}"
+ local cl_rst="%b%f"
+
+ local _lpar="${cl_parens}["
+ local _rpar="${cl_parens}]"
+
+ local _time="$cl_time_line%D{%H:%M}"
+ _psvar[user]='%n'
+ local _user="$cl_text"'${_psvar[user]}'
+ _psvar[at]="@"
+ _psvar[host]='%m'
+ local _at="$cl_at_colon"'${_psvar[at]}'"$cl_text"'${_psvar[host]}'
+ _psvar[colon]=':'
+ local _path="$cl_at_colon"'${_psvar[colon]}'"$cl_text%28<*<%/%<<"
+ local _line="$cl_time_line%i"
+ local _prompt="$cl_prompt# "
+
+ # You can instantly shorten the prompt by setting PSSHORT=1
+ if [[ "$COLUMNS" -le 94 || "$PSSHORT" = "1" ]]; then
+ _psvar=()
+ else
+ _psvar[user]='%n'
+ _psvar[at]="@"
+ _psvar[host]='%m'
+ _psvar[colon]=':'
+ fi
+
+ PS1="$_time$_lpar$_user$_at$_path$_rpar$_line$_prompt$cl_rst"
+
+ PS2="$cl_parens> $cl_rst"
+
+ RPS1='${vcs_info_msg_0_}'
+ prompt_opts=(cr subst percent)
+
+ zstyle ':vcs_info:*' enable git svn darcs bzr hg
+ zstyle ':vcs_info:*' stagedstr "%F{green}●$cl_rst"
+ zstyle ':vcs_info:*' unstagedstr "%F{yellow}●$cl_rst"
+ zstyle ':vcs_info:*' check-for-changes true
+ zstyle ':vcs_info:*' formats '(%s)-[%b%u%c]-'
+
+ add-zsh-hook precmd prompt_sprint2_precmd
+}
+
+prompt_sprint2_precmd () {
+ setopt localoptions noxtrace noksharrays
+
+ # You can instantly shorten the prompt by setting PSSHORT=1
+ if [[ "$COLUMNS" -le 94 || "$PSSHORT" = "1" ]]; then
+ _psvar=()
+ else
+ _psvar[user]='%n'
+ _psvar[at]="@"
+ _psvar[host]='%m'
+ _psvar[colon]=':'
+ fi
+
+ local -a changed_files
+ changed_files=( )
+ git diff --quiet 2>/dev/null || changed_files=( ${(f)"$( git diff --name-only 2>/dev/null )"} )
+ changed_files=( $^changed_files(N) )
+ if [[ "${#changed_files}" -gt 0 ]]; then
+ local basedir
+ basedir="$(git rev-parse --show-toplevel)/"
+ changed_files=( ${(f)"$( find "${basedir}${^changed_files[@]}" -mtime +2 )"} )
+ fi
+
+ if [[ "${#changed_files}" -eq 0 ]]; then
+ zstyle ':vcs_info:*' formats ' (%s)-[%b%u%c]'
+ else
+ zstyle ':vcs_info:*' formats ' (%s)-[%b%u%B%F{yellow}-OLD-%c%%b%f]'
+ fi
+
+ vcs_info
+}
+
+prompt_sprint2_preview () {
+ local -a colors_time_line colors_text
+ colors_time_line=(red yellow green blue magenta cyan)
+ colors_text=(red yellow green blue magenta cyan)
+
+ local ctime_line ctext i j
+
+ if (( ! $#* )); then
+ for (( i = 1; i <= ${#colors_time_line}; i++ )); do
+ ctime_line="${colors_time_line[$i]}"
+ for (( j = 1; j <= ${#colors_text}; j++ )); do
+ ctext="${colors_text[$j]}"
+ prompt_preview_theme sprint2 "$ctime_line" "red" "$ctext"
+ (( i != ${#colors_time_line} || j != ${#colors_text} )) && print
+ done
+ done
+ else
+ prompt_preview_theme sprint2 "$@"
+ fi
+}
+
+prompt_sprint2_setup "$@"
+
+# vim:ft=zsh
diff --git a/Functions/Prompts/promptinit b/Functions/Prompts/promptinit
index 0c06699e8..7383c6c68 100644
--- a/Functions/Prompts/promptinit
+++ b/Functions/Prompts/promptinit
@@ -246,7 +246,7 @@ prompt_preview_theme () {
# while the ZLE is not active.
[[ -o promptcr ]] && print -n $'\r'
- :; print -P -- "${PS1}command arg1 arg2 ... argn"
+ :; print -rP -- "${PS1}command arg1 arg2 ... argn"
[[ -n ${preexec_functions[(r)prompt_${1}_preexec]} ]] &&
prompt_${1}_preexec
diff --git a/Functions/VCS_Info/Backends/VCS_INFO_get_data_git b/Functions/VCS_Info/Backends/VCS_INFO_get_data_git
index e45eebc8e..9a608adab 100644
--- a/Functions/VCS_Info/Backends/VCS_INFO_get_data_git
+++ b/Functions/VCS_Info/Backends/VCS_INFO_get_data_git
@@ -184,15 +184,8 @@ fi
VCS_INFO_adjust
VCS_INFO_git_getaction ${gitdir}
-local patchdir=${gitdir}/patches/${gitbranch}
-if [[ -d $patchdir ]] && [[ -f $patchdir/applied ]] \
- && [[ -f $patchdir/unapplied ]]
-then
- # stgit
- git_patches_applied=(${(f)"$(< "${patchdir}/applied")"})
- git_patches_unapplied=(${(f)"$(< "${patchdir}/unapplied")"})
- VCS_INFO_git_handle_patches
-elif [[ -d "${gitdir}/rebase-merge" ]]; then
+local patchdir
+if [[ -d "${gitdir}/rebase-merge" ]]; then
# 'git rebase -i'
patchdir="${gitdir}/rebase-merge"
local p
@@ -251,7 +244,9 @@ elif [[ -d "${gitdir}/rebase-merge" ]]; then
(( $+REPLY )) && git_patches_applied+=( "$REPLY" )
done
fi
- if [[ -f "${patchdir}/git-rebase-todo" ]] ; then
+ if zstyle -t ":vcs_info:${vcs}:${usercontext}:${rrn}" get-unapplied &&
+ [[ -f "${patchdir}/git-rebase-todo" ]]
+ then
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" )
@@ -381,7 +376,9 @@ elif [[ -f "${gitdir}/CHERRY_PICK_HEAD" ]]; then
# TODO: maybe read up to the first blank line
IFS='' read -r subject < "${gitdir}/MERGE_MSG"
git_patches_applied=( "$(<${gitdir}/CHERRY_PICK_HEAD) ${subject}" )
- if [[ -f "${gitdir}/sequencer/todo" ]]; then
+ if zstyle -t ":vcs_info:${vcs}:${usercontext}:${rrn}" get-unapplied &&
+ [[ -f "${gitdir}/sequencer/todo" ]]
+ then
# Get the next patches, and remove the one that's in CHERRY_PICK_HEAD.
git_patches_unapplied=( ${${(M)${(f)"$(<"${gitdir}/sequencer/todo")"}:#pick *}#pick } )
git_patches_unapplied[1]=()
@@ -389,6 +386,31 @@ elif [[ -f "${gitdir}/CHERRY_PICK_HEAD" ]]; then
git_patches_unapplied=()
fi
VCS_INFO_git_handle_patches
+elif command -v stg >/dev/null &&
+ ${vcs_comm[cmd]} show-ref --quiet refs/stacks/${gitbranch} refs/heads/${gitbranch}.stgit 2>/dev/null &&
+ git_patches_applied=(${${(f)"$(stg series --noprefix --applied --description 2>/dev/null)"}/ #[#]})
+then
+ # Testing for StGit patches is done after testing for all git-proper
+ # patches/states. If a StGit user's repo is in one of those states, they
+ # will want to see that instead of the StGit patch info.
+
+ # Performance note: testing for the stg executable is done first because it
+ # is extremely cheap and there is nothing else to do if it isn't present.
+ # Using git to test whether a StGit stack is initialized is cheaper than
+ # running stg itself; especially for versions of StGit <= 2.0. Thus getting
+ # StGit patch info should only have a material runtime cost if StGit is
+ # installed and in-use for the current branch.
+
+ # In StGit >=1.2, the existence of refs/stacks/<branch> indicates StGit is
+ # initialized. In StGit >=0.15, it is refs/heads/<branch>.stgit.
+
+ # N.B. the "--noprefix" option is available in StGit 2.x as an alias for
+ # --no-prefix. The former is compatible with StGit versions going back to
+ # 2008.
+ if zstyle -t ":vcs_info:${vcs}:${usercontext}:${rrn}" get-unapplied; then
+ git_patches_unapplied=(${${(f)"$(stg series --noprefix --unapplied --description 2>/dev/null)"}/ #[#]})
+ fi
+ VCS_INFO_git_handle_patches
else
gitmisc=''
fi
diff --git a/Functions/Zle/edit-command-line b/Functions/Zle/edit-command-line
index 5f7ea321f..d4b405eaf 100644
--- a/Functions/Zle/edit-command-line
+++ b/Functions/Zle/edit-command-line
@@ -11,15 +11,30 @@ 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 (( REGION_ACTIVE == 1 )); then
if (( CURSOR < MARK )); then
left=$CURSOR right=$MARK
- lbuffer=
else
left=$MARK right=$CURSOR
- lbuffer[right-left,-1]=
fi
- (( left++ ))
+ lbuffer=$lbuffer[++left,-1]
+ buffer=$BUFFER[left,++right]
+elif (( REGION_ACTIVE == 2 )); then
+ local nl=$'\n'
+ if (( CURSOR < MARK )); then
+ left=${${BUFFER[1,CURSOR]}[(I)$nl]}
+ right=${${BUFFER[MARK+1,-1]}[(i)$nl]}
+ (( right += MARK ))
+ else
+ left=${${BUFFER[1,MARK]}[(I)$nl]}
+ right=${${BUFFER[CURSOR+1,-1]}[(i)$nl]}
+ (( right += CURSOR ))
+ fi
+ lbuffer=$lbuffer[++left,-1]
+ if [[ $BUFFER[right] = $nl ]]; then
+ # Keep the newline because "$(<$1)" below trims it
+ (( --right ))
+ fi
buffer=$BUFFER[left,right]
elif (( ! ZLE_RECURSIVE )); then
prebuffer=$PREBUFFER
diff --git a/Functions/Zle/incarg b/Functions/Zle/incarg
index cff0cfe4c..0cfaf9ff5 100644
--- a/Functions/Zle/incarg
+++ b/Functions/Zle/incarg
@@ -1,43 +1,303 @@
-# Shell function to increment an integer either under the cursor or just
-# to the left of it. Use
+emulate -L zsh
+
+# A ZLE widget to increment an integer.
+#
+# In addition to decimals, it can handle hexadecimals prefixed with "0x",
+# binaries with "0b", and octals with "0o".
+#
+# By default, the target integer will be incremented by one. With a numeric
+# argument, the integer is incremented by the amount of the argument. The shell
+# parameter "incarg" may be set to change the default increment to something
+# other than one.
+#
+# The behavior of this widget changes depending on how it is named.
+#
+# - incarg / decarg
+#
+# incarg will increment an integer either under the cursor or just to the left
+# of it. decarg, on the other hand, will decrement it.
+#
+# For example,
+#
+# echo 41
+# ^^^ cursor anywhere here
+#
+# with incarg gives
+#
+# echo 42
+# ^ cursor will move here
+#
+# - sync-incarg / sync-decarg
+#
+# The sync- variant is used for creating a sequence of numbers on split
+# terminals with synchronized key input. The first pane won't be incremented
+# at all, but each pane after that will have the number incremented once more
+# than the previous pane.
+#
+# Currently supports tmux and iTerm2.
+#
+# - vim-incarg / vim-decarg
+#
+# This behaves like Vim's CTRL-A / CTRL-X. It moves the cursor to the nearest
+# number after the cursor and increments or decrements it.
+#
+# - vim-backward-incarg / vim-backward-decarg
+#
+# This behaves like vim-incarg & vim-decarg, but it searches backwards for a
+# number.
+#
+# - vim-sync-incarg / vim-sync-decarg
+#
+# This combines the behavior of the vim- and sync- variants. It's inspired by
+# Vim's g_CTRL-A / g_CTRL-X.
+#
+# - vim-backward-sync-incarg / vim-backward-sync-decarg
+#
+# This combines the behavior of the vim-backward- and sync- variants.
+#
+# Example Usage:
+#
# autoload -Uz incarg
-# zle -N incarg
-# bindkey "..." incarg
-# to define it. For example,
-# echo 41
-# ^^^ cursor anywhere here
-# with incarg gives
-# echo 42
-# with the cursor in the same place.
-#
-# A numeric argument gives a number other than 1 to add (may be negative).
-# If you're going to do it a lot with one particular number, you can set
-# the parameter incarg to that number (a numeric argument still takes
-# precedence).
+# for widget in vim-{,sync-}{inc,dec}arg; do
+# zle -N "$widget" incarg
+# done
+# bindkey -a \
+# '^A' vim-incarg \
+# '^X' vim-decarg \
+# 'g^A' vim-sync-incarg \
+# 'g^X' vim-sync-decarg
-emulate -L zsh
-setopt extendedglob
+zle -f vichange
-local rrest lrest num
+setopt localoptions extended_glob
+local match mbegin mend MATCH MBEGIN MEND i
-rrest=${RBUFFER##[0-9]#}
-if [[ $RBUFFER = [0-9]* ]]; then
- if [[ -z $rrest ]]; then
- num=$RBUFFER
- else
- num=${RBUFFER[1,-$#rrest-1]}
+[[ -z "$BUFFER" ]] && return 1
+
+# find the number and determine the base
+integer pos=$(( CURSOR + 1 )) base=0
+
+# avoid miscalculating positions when cursor is at the end of the line
+while (( pos > 0 )) && [[ "$BUFFER[pos]" == '' ]]; do
+ (( pos-- ))
+done
+
+# check for a prefix (e.g., 0x) before the cursor
+for (( i = 0; i < 2; i++ )); do
+ case "$BUFFER[1,pos]" in
+ *0[xX][0-9a-fA-F]##) base=16 ;;
+ *0[oO][0-7]##) base=8 ;;
+ *0[bB][01]##) base=2 ;;
+ *[1-9]) base=10 ;;
+ *0) ;; # there may be a prefix right after the cursor
+ *)
+ # the non-Vim variant looks right before the cursor too, but not after it
+ if [[ "$WIDGET" != vi* ]]; then
+ if (( i == 0 )); then
+ (( pos-- ))
+ continue
+ else
+ return 1
+ fi
+ fi
+ ;;
+ esac
+
+ break
+done
+
+# check for a prefix on the cursor
+if (( base == 0 && pos < $#BUFFER )); then
+ case "$BUFFER[1,pos+1]" in
+ *0[xX][0-9a-fA-F]) base=16; (( pos++ )) ;;
+ *0[oO][0-7]) base=8; (( pos++ )) ;;
+ *0[bB][01]) base=2; (( pos++ )) ;;
+ esac
+fi
+
+if (( base == 0 )); then
+ if [[ "$WIDGET" == vi* ]]; then
+ if [[ "$WIDGET" == *backward-* ]]; then
+ # search backwards for a number
+ while true; do
+ case "$BUFFER[1,pos]" in
+ *0[xX][0-9a-fA-F]##) base=16 ;;
+ *0[oO][0-7]##) base=8 ;;
+ *0[bB][01]##) base=2 ;;
+ *[0-9]) base=10 ;;
+ *-)
+ case "$BUFFER[pos,-1]" in
+ -0[xX][0-9a-fA-F]*) ;;
+ -0[oO][0-7]*) ;;
+ -0[bB][01]*) ;;
+ -[0-9]*) base=10 ;;
+ esac
+ ;;
+ esac
+ (( base != 0 )) && break
+
+ (( pos-- ))
+ (( pos <= 0 )) && return 1
+ done
+ else
+ # jump to the nearest number after the cursor
+ while [[ "$BUFFER[pos]" == [^0-9] ]]; do
+ (( pos++ ))
+ (( pos > $#BUFFER )) && return 1
+ done
+ fi
+ fi
+
+ # check for a prefix right after the cursor and jump right after it, if any
+ if (( pos <= 1 )) || [[ "$BUFFER[pos-1]" == [^0-9] ]]; then
+ case "$BUFFER[pos,-1]" in
+ 0[xX][0-9a-fA-F]*) base=16; (( pos += 2 )) ;;
+ 0[oO][0-7]*) base=8; (( pos += 2 )) ;;
+ 0[bB][01]*) base=2; (( pos += 2 )) ;;
+ esac
fi
fi
-lrest=${LBUFFER%%[0-9]#}
-if [[ $LBUFFER = *[0-9] ]]; then
- if [[ -z $lrest ]]; then
- num="$LBUFFER$num"
+if (( base == 0 )); then
+ base=10
+fi
+
+# find the start of the number
+integer first="$pos"
+case "$base" in
+ 10)
+ while [[ "$BUFFER[first-1]" == [0-9] ]]; do
+ (( first-- ))
+ done
+ if [[ $BUFFER[first-1] = - ]]; then
+ (( first-- ))
+ fi
+ ;;
+ 2)
+ while [[ "$BUFFER[first-1]" == [01] ]]; do
+ (( first-- ))
+ done
+ ;;
+ 8)
+ while [[ "$BUFFER[first-1]" == [0-7] ]]; do
+ (( first-- ))
+ done
+ ;;
+ 16)
+ while [[ "$BUFFER[first-1]" == [0-9a-fA-F] ]]; do
+ (( first-- ))
+ done
+ ;;
+esac
+
+# find the end of the number
+integer last="$pos"
+case "$base" in
+ 10)
+ while [[ "$BUFFER[last+1]" == [0-9] ]]; do
+ (( last++ ))
+ done
+ ;;
+ 2)
+ while [[ "$BUFFER[last+1]" == [01] ]]; do
+ (( last++ ))
+ done
+ ;;
+ 8)
+ while [[ "$BUFFER[last+1]" == [0-7] ]]; do
+ (( last++ ))
+ done
+ ;;
+ 16)
+ while [[ "$BUFFER[last+1]" == [0-9a-fA-F] ]]; do
+ (( last++ ))
+ done
+ ;;
+esac
+
+# calculate the number of digits
+integer ndigits=0
+case "$BUFFER[first,first+1]" in
+ 0*|-0) ndigits=$(( last - first + 1 )) ;;
+esac
+
+# determine the amount to increment
+integer delta=${NUMERIC:-${incarg:-1}}
+if [[ "$WIDGET" = *decarg ]]; then
+ (( delta = -delta ))
+fi
+if [[ "$WIDGET" = *sync-* ]]; then
+ integer pane_index=0
+ if [[ -n "$TMUX_PANE" ]]; then
+ pane_index="$(tmux display-message -pt "$TMUX_PANE" '#{pane_index}')"
+ elif [[ "$ITERM_SESSION_ID" =~ '^w[0-9]+t[0-9]+p([0-9]+)' ]]; then
+ pane_index="$match[1]"
else
- num="${LBUFFER[$#lrest+1,-1]}$num"
+ zle -M "[$WIDGET] unsupported terminal"
+ return 1
fi
+ (( delta *= pane_index ))
fi
-[[ -n $num ]] && (( num += ${NUMERIC:-${incarg:-1}} ))
+local old="$BUFFER[first,last]"
+integer oldlen=$#BUFFER
+integer oldnum="$base#$old" 2> /dev/null
+
+# -00 should increment to 01 instead of 001
+if [[ "$BUFFER[first]" == '-' ]] && (( oldnum == 0 )); then
+ (( ndigits-- ))
+fi
+
+local fmt1 fmt2
+case "$base" in
+ 10) fmt1=d; fmt2='#10' ;;
+ 2) fmt1=s; fmt2='##2' ;;
+ 8) fmt1=s; fmt2='##8' ;;
+ 16) fmt1="$BUFFER[first-1]"; fmt2='#16' ;;
+esac
+
+local raw_result padded
+# $(( )) outputs an error message to stderr when integer truncation occurs
+printf -v raw_result "%0$ndigits$fmt1" $(( [$fmt2] "$base#$old" + delta )) 2> /dev/null
+padded="${raw_result// /0}"
+integer newnum="$base#$padded" 2> /dev/null
+
+# try to detect integer truncation
+if (( base != 10 && newnum < 0
+ || delta > 0 && newnum < oldnum
+ || delta < 0 && newnum > oldnum )); then
+ zle -M "[$WIDGET] The resulting number is either too big or too small."
+ return 1
+fi
+
+# adjust the number of leading zeros if the sign of the integer changed
+local new
+if (( base == 10 && ndigits == $#padded )); then
+ if (( oldnum < 0 && newnum >= 0 )); then
+ new="${padded#0}"
+ elif (( oldnum >= 0 && newnum < 0 )); then
+ new="-0${padded#-}"
+ fi
+fi
+if [[ -z "$new" ]]; then
+ new="$padded"
+fi
+
+if zstyle -t ":zle:$WIDGET" debug; then
+ zle -M "[$WIDGET] base: $base delta: $delta old: '$old' new: '$new'"
+fi
+
+if (( 0 < first && first <= last && last <= $#BUFFER )); then
+ BUFFER[first,last]="$new"
+else
+ zle -M "[$WIDGET] The detected location of the integer was invalid. [location=BUFFER[$first,$last]]"
+ return 1
+fi
+
+integer offset=0
+if [[ "$WIDGET" == vi* ]]; then
+ offset=-1
+fi
+(( CURSOR = last + $#BUFFER - oldlen + offset ))
-BUFFER="$lrest$num$rrest"
+return 0
diff --git a/Functions/Zle/keeper b/Functions/Zle/keeper
index a40125771..1570eb94a 100644
--- a/Functions/Zle/keeper
+++ b/Functions/Zle/keeper
@@ -73,6 +73,7 @@ zstyle ':completion:expand-kept-result:*' completer _insert_kept
_expand_word_and_keep() {
{
+ _shadow compadd
function compadd {
local -A args
zparseopts -E -A args J:
@@ -85,7 +86,7 @@ _expand_word_and_keep() {
}
_expand_word
} always {
- unfunction compadd
+ _unshadow compadd
}
}