diff options
Diffstat (limited to 'Functions')
25 files changed, 359 insertions, 80 deletions
diff --git a/Functions/Misc/nslookup b/Functions/Misc/nslookup index 150bd035c..8c11909d5 100644 --- a/Functions/Misc/nslookup +++ b/Functions/Misc/nslookup @@ -26,8 +26,7 @@ zstyle -s ':nslookup' pager tmp && zpty nslookup command nslookup "${(q)@}" -zpty -r nslookup line '* -> ' +zpty -r nslookup line '*> ' print -nr "$line" while line=''; vared -he "$pmpt[@]" line; do diff --git a/Functions/Misc/zargs b/Functions/Misc/zargs index 71fd42835..28ebca78f 100644 --- a/Functions/Misc/zargs +++ b/Functions/Misc/zargs @@ -73,7 +73,7 @@ emulate -L zsh || return 1 local -a opts eof n s l P i -local ZARGS_VERSION="1.4" +local ZARGS_VERSION="1.5" if zparseopts -a opts -D -- \ -eof::=eof e::=eof \ @@ -254,7 +254,7 @@ then bg='&' if zmodload -i zsh/parameter 2>/dev/null then - wait='wait %${(k)^jobstates[(R)running:*]}' + wait='wait ${${jobstates[(R)running:*]/#*:/}/%=*/}' else wait='wait' fi diff --git a/Functions/Misc/zed b/Functions/Misc/zed index c2caaf3f5..010b69bee 100644 --- a/Functions/Misc/zed +++ b/Functions/Misc/zed @@ -9,8 +9,9 @@ local var opt zed_file_name # We do not want timeout while we are editing a file integer TMOUT=0 okargs=1 fun bind +local -a expand -while getopts "fb" opt; do +while getopts "fbx:" opt; do case $opt in (f) fun=1 @@ -19,6 +20,14 @@ while getopts "fb" opt; do (b) bind=1 ;; + + (x) + if [[ $OPTARG != <-> ]]; then + print -r "Integer expected after -x: $OPTARG" >&2 + return 1 + fi + expand=(-x $OPTARG) + ;; esac done shift $(( OPTIND - 1 )) @@ -29,8 +38,8 @@ shift $(( OPTIND - 1 )) if (( $# != okargs )); then echo 'Usage: zed filename -zed -f function -zed -b' +zed -f [ -x N ] function +zed -b' >&2 return 1 fi @@ -71,7 +80,7 @@ fi setopt localoptions nobanghist if ((fun)) then - var="$(functions $1)" + var="$(functions $expand $1)" # If function is undefined but autoloadable, load it if [[ $var = *\#\ undefined* ]] then var="$(autoload +X $1; functions $1)" diff --git a/Functions/Prompts/prompt_adam1_setup b/Functions/Prompts/prompt_adam1_setup index 034641fb8..aca0e59f1 100644 --- a/Functions/Prompts/prompt_adam1_setup +++ b/Functions/Prompts/prompt_adam1_setup @@ -14,8 +14,6 @@ This theme works best with a dark background. Recommended fonts for this theme: nexus or vga or similar. If you don't have any of these, then specify the `plain' option to use 7-bit replacements for the 8-bit characters. - -And you probably thought adam1 was overkill. EOF } @@ -27,8 +25,9 @@ prompt_adam1_setup () { base_prompt="%K{$prompt_adam1_color1}%n@%m%k " post_prompt="%b%f%k" - base_prompt_no_color=$(echo "$base_prompt" | perl -pe "s/%(K{.*?}|k)//g") - post_prompt_no_color=$(echo "$post_prompt" | perl -pe "s/%(K{.*?}|k)//g") + setopt localoptions extendedglob + base_prompt_no_color="${base_prompt//(%K{[^\\\}]#\}|%k)/}" + post_prompt_no_color="${post_prompt//(%K{[^\\\}]#\}|%k)/}" add-zsh-hook precmd prompt_adam1_precmd } diff --git a/Functions/Prompts/prompt_bart_setup b/Functions/Prompts/prompt_bart_setup index 6cbbb71c7..45fcffed4 100644 --- a/Functions/Prompts/prompt_bart_setup +++ b/Functions/Prompts/prompt_bart_setup @@ -48,9 +48,13 @@ prompt_bart_help () { When RPS1 (RPROMPT) is set before this prompt is selected and a fifth color is specified, that color is turned on before RPS1 is displayed and reset after it. Other color changes within RPS1, if - any, remain in effect. + any, remain in effect. This also applies to RPS2 (RPROMPT2). + If a fifth color is specified and there is no RPS2, PS2 (PROMPT2) + is colored and moved to RPS2. Changes to RPS1/RPS2 are currently + not reverted when the theme is switched off. These work best with + the TRANSIENT_RPROMPT option, which must be set separately. - This prompt hijacks psvar[7] through [9] to avoid having to reset + This theme hijacks psvar[7] through [9] to avoid having to reset the entire PS1 string on every command. It uses TRAPWINCH to set the position of the upper right prompt on a window resize, so the prompt may not match the window width until the next command. @@ -107,9 +111,9 @@ prompt_bart_precmd () { ((PSCOL == 1)) || { PSCOL=1 ; prompt_bart_ps1 } if [[ -o promptcr ]] then - # Emulate the 4.3.x promptsp option if it isn't available - eval '[[ -o promptsp ]] 2>/dev/null' || - print -nP "${(l.COLUMNS.. .)}\e[s${(pl.COLUMNS..\b.)}%E\e[u" >$TTY + # Emulate the 4.3.x promptsp option if it isn't available + eval '[[ -o promptsp ]] 2>/dev/null' || + print -nP "${(l.COLUMNS.. .)}\e[s${(pl.COLUMNS..\b.)}%E\e[u" >$TTY else IFS='[;' read -s -d R escape\?$'\e[6n' lineno PSCOL <$TTY fi ((PSCOL == 1)) || prompt_bart_ps1 @@ -146,7 +150,7 @@ prompt_bart_ps1 () { # Assemble the new prompt ps1=( ${(f)PS1} ) # Split the existing prompt at newlines ps1=( - "%$[COLUMNS-PSCOL]>..>" # Begin truncation (upper left prompt) + "%$[COLUMNS-PSCOL]>..>" # Begin truncation (upper left prompt) "$host" "$hist1" # Empty when too wide for one line "$dir" @@ -176,8 +180,8 @@ prompt_bart_setup () { # A few extra niceties ... repeat 1 case "$1:l" in (off|disable) - add-zsh-hook -D precmd "prompt_*_precmd" - add-zsh-hook -D preexec "prompt_*_preexec" + add-zsh-hook -D precmd "prompt_*_precmd" + add-zsh-hook -D preexec "prompt_*_preexec" functions[TRAPWINCH]="${functions[TRAPWINCH]//prompt_bart_winch}" [[ $prompt_theme[1] = bart ]] && PS1=${${(f)PS1}[-1]} return 1 @@ -201,9 +205,22 @@ prompt_bart_setup () { prompt_bart_ps1 - # No RPS1 by default because prompt_off_setup doesn't fix it. - (($#RPS1 && $# > 4)) && RPS1="%F{$5}$RPS1%f" - + if (($# > 4)) + then + # No RPS1 by default because prompt_off_setup doesn't fix it. + if (($#RPS1)) + then + RPS1="%F{$5}$RPS1%f" + fi + # RPS2 is less obvious so don't mind that it's not restored. + if (($#RPS2)) + then + RPS2="%F{$5}$RPS2%f" + else + RPS2="%F{$5}<${${PS2//\%_/%^}%> }%f" + PS2='' + fi + fi # Paste our special commands into precmd and TRAPWINCH add-zsh-hook precmd prompt_bart_precmd diff --git a/Functions/VCS_Info/Backends/VCS_INFO_get_data_bzr b/Functions/VCS_Info/Backends/VCS_INFO_get_data_bzr index cae1a3b08..e8c8e81de 100644 --- a/Functions/VCS_Info/Backends/VCS_INFO_get_data_bzr +++ b/Functions/VCS_Info/Backends/VCS_INFO_get_data_bzr @@ -6,7 +6,7 @@ setopt localoptions noksharrays extendedglob NO_shwordsplit local bzrbase bzrbr bzr_changes bzr_type local -a bzrinfo -local -xA hook_com bzr_info +local -A hook_com bzr_info VCS_INFO_bzr_get_info() { bzrinfo=( ${(s.:.)$( ${vcs_comm[cmd]} version-info --custom \ diff --git a/Functions/VCS_Info/Backends/VCS_INFO_get_data_git b/Functions/VCS_Info/Backends/VCS_INFO_get_data_git index c348da2a7..3fc861eeb 100644 --- a/Functions/VCS_Info/Backends/VCS_INFO_get_data_git +++ b/Functions/VCS_Info/Backends/VCS_INFO_get_data_git @@ -210,7 +210,9 @@ elif [[ -d "${gitdir}/rebase-merge" ]]; then # remove action git_patches_applied+=("${${(s: :)p}[2,-1]}") done - git_patches_unapplied=(${(f)"$(grep -v '^$' "${patchdir}/git-rebase-todo" | grep -v '^#')"}) + if [[ -f "${patchdir}/git-rebase-todo" ]] ; then + git_patches_unapplied=(${(f)"$(grep -v '^$' "${patchdir}/git-rebase-todo" | grep -v '^#')"}) + fi VCS_INFO_git_handle_patches elif [[ -d "${gitdir}/rebase-apply" ]]; then # Fake patch names for all but current patch diff --git a/Functions/VCS_Info/Backends/VCS_INFO_get_data_hg b/Functions/VCS_Info/Backends/VCS_INFO_get_data_hg index 1274ca337..f35ad5965 100644 --- a/Functions/VCS_Info/Backends/VCS_INFO_get_data_hg +++ b/Functions/VCS_Info/Backends/VCS_INFO_get_data_hg @@ -16,7 +16,7 @@ local -a hgid_args defrevformat defbranchformat \ hgbmarks mqpatches mqseries mqguards mqunapplied hgmisc \ i_patchguards i_negguards i_posguards -local -xA hook_com +local -A hook_com hgbase=${vcs_comm[basedir]} rrn=${hgbase:t} diff --git a/Functions/VCS_Info/Backends/VCS_INFO_get_data_p4 b/Functions/VCS_Info/Backends/VCS_INFO_get_data_p4 index 430cfa6f0..329884982 100644 --- a/Functions/VCS_Info/Backends/VCS_INFO_get_data_p4 +++ b/Functions/VCS_Info/Backends/VCS_INFO_get_data_p4 @@ -6,7 +6,7 @@ setopt localoptions extendedglob local p4base a b local -A p4info -local -xA hook_com +local -A hook_com ${vcs_comm[cmd]} info | while IFS=: read a b; do p4info[${a// /_}]="${b## #}"; done p4base=${vcs_comm[basedir]} diff --git a/Functions/VCS_Info/Backends/VCS_INFO_get_data_svk b/Functions/VCS_Info/Backends/VCS_INFO_get_data_svk index 6107a14f3..1d2d22ffb 100644 --- a/Functions/VCS_Info/Backends/VCS_INFO_get_data_svk +++ b/Functions/VCS_Info/Backends/VCS_INFO_get_data_svk @@ -4,7 +4,7 @@ setopt localoptions NO_shwordsplit local svkbranch svkbase -local -xA hook_com +local -A hook_com svkbase=${vcs_comm[basedir]} rrn=${svkbase:t} diff --git a/Functions/VCS_Info/Backends/VCS_INFO_get_data_svn b/Functions/VCS_Info/Backends/VCS_INFO_get_data_svn index e56afee02..e1334f661 100644 --- a/Functions/VCS_Info/Backends/VCS_INFO_get_data_svn +++ b/Functions/VCS_Info/Backends/VCS_INFO_get_data_svn @@ -8,7 +8,7 @@ setopt localoptions noksharrays extendedglob NO_shwordsplit local svnbase svnbranch a b rrn local -i rc local -A svninfo parentinfo cwdinfo -local -xA hook_com +local -A hook_com svnbase="."; svninfo=() diff --git a/Functions/VCS_Info/VCS_INFO_formats b/Functions/VCS_Info/VCS_INFO_formats index 138091944..4d0dd75c2 100644 --- a/Functions/VCS_Info/VCS_INFO_formats +++ b/Functions/VCS_Info/VCS_INFO_formats @@ -5,7 +5,7 @@ setopt localoptions noksharrays NO_shwordsplit local msg tmp local -i i -local -xA hook_com +local -A hook_com # The _origs are needed because hooks can change values and there would # be no way to get the originals back for later hooks (a hook is run for # each message, that's being created). @@ -68,7 +68,7 @@ if [[ -n ${hook_com[unstaged]} ]] ; then fi if [[ ${quiltmode} != 'standalone' ]] && VCS_INFO_hook "pre-addon-quilt"; then - local -x REPLY + local REPLY VCS_INFO_quilt addon hook_com[quilt]="${REPLY}" unset REPLY diff --git a/Functions/VCS_Info/VCS_INFO_hook b/Functions/VCS_Info/VCS_INFO_hook index 479f5968b..94ae63017 100644 --- a/Functions/VCS_Info/VCS_INFO_hook +++ b/Functions/VCS_Info/VCS_INFO_hook @@ -3,8 +3,8 @@ ## Distributed under the same BSD-ish license as zsh itself. local hook static func -local -x context hook_name -local -xi ret +local context hook_name +local -i ret local -a hooks tmp local -i debug diff --git a/Functions/VCS_Info/VCS_INFO_quilt b/Functions/VCS_Info/VCS_INFO_quilt index 34ff1edbf..bc71cfb7d 100644 --- a/Functions/VCS_Info/VCS_INFO_quilt +++ b/Functions/VCS_Info/VCS_INFO_quilt @@ -86,9 +86,9 @@ function VCS_INFO_quilt() { local mode="$1" local patches pc tmp qstring root local -i ret - local -x context + local context local -a applied unapplied all applied_string unapplied_string quiltcommand quilt_env - local -Ax hook_com + local -A hook_com context=":vcs_info:${vcs}.quilt-${mode}:${usercontext}:${rrn}" zstyle -t "${context}" use-quilt || return 1 @@ -183,7 +183,7 @@ function VCS_INFO_quilt() { VCS_INFO_set ;; (addon) - # When VCS_INFO_quilt() is called with "addon" a "local -x REPLY" variable + # When VCS_INFO_quilt() is called with "addon" a "local REPLY" variable # should be in place. That variable can be unset after it's being used. REPLY="${qstring}" ;; diff --git a/Functions/VCS_Info/VCS_INFO_set b/Functions/VCS_Info/VCS_INFO_set index 5087be43f..484c7937d 100644 --- a/Functions/VCS_Info/VCS_INFO_set +++ b/Functions/VCS_Info/VCS_INFO_set @@ -8,7 +8,7 @@ local -i i j if [[ $1 == '--nvcs' ]] ; then [[ $2 == '-preinit-' ]] && (( maxexports == 0 )) && (( maxexports = 1 )) for i in {0..$((maxexports - 1))} ; do - typeset -gx vcs_info_msg_${i}_= + typeset -g vcs_info_msg_${i}_= done VCS_INFO_nvcsformats $2 [[ $2 != '-preinit-' ]] && VCS_INFO_hook "no-vcs" @@ -17,12 +17,12 @@ fi (( ${#msgs} - 1 < 0 )) && return 0 for i in {0..$(( ${#msgs} - 1 ))} ; do (( j = i + 1 )) - typeset -gx vcs_info_msg_${i}_=${msgs[$j]} + typeset -g vcs_info_msg_${i}_=${msgs[$j]} done if (( i < maxexports )) ; then for j in {$(( i + 1 ))..${maxexports}} ; do - [[ -n ${(P)${:-vcs_info_msg_${j}_}} ]] && typeset -gx vcs_info_msg_${j}_= + [[ -n ${(P)${:-vcs_info_msg_${j}_}} ]] && typeset -g vcs_info_msg_${j}_= done fi return 0 diff --git a/Functions/VCS_Info/vcs_info b/Functions/VCS_Info/vcs_info index 46938691d..350b189e9 100644 --- a/Functions/VCS_Info/vcs_info +++ b/Functions/VCS_Info/vcs_info @@ -51,10 +51,11 @@ vcs_info () { local pat local -i found retval local -a enabled disabled dps - local -x usercontext vcs rrn quiltmode LC_MESSAGES - local -ix maxexports - local -ax msgs - local -Ax vcs_comm hook_com backend_misc user_data + local usercontext vcs rrn quiltmode + local -x LC_MESSAGES + local -i maxexports + local -a msgs + local -A vcs_comm hook_com backend_misc user_data LC_MESSAGES=C if [[ -n ${LC_ALL} ]]; then diff --git a/Functions/VCS_Info/vcs_info_lastmsg b/Functions/VCS_Info/vcs_info_lastmsg index ddfaaf88b..438567cef 100644 --- a/Functions/VCS_Info/vcs_info_lastmsg +++ b/Functions/VCS_Info/vcs_info_lastmsg @@ -5,7 +5,7 @@ emulate -L zsh local -i i -local -ix maxexports +local -i maxexports VCS_INFO_maxexports for i in {0..$((maxexports - 1))} ; do diff --git a/Functions/VCS_Info/vcs_info_printsys b/Functions/VCS_Info/vcs_info_printsys index f29061463..b44b9c9b4 100644 --- a/Functions/VCS_Info/vcs_info_printsys +++ b/Functions/VCS_Info/vcs_info_printsys @@ -7,7 +7,7 @@ setopt extendedglob local sys local -a disabled enabled -local -Ax vcs_comm +local -A vcs_comm zstyle -a ":vcs_info:-init-:${1:-default}:-all-" "enable" enabled (( ${#enabled} == 0 )) && enabled=( all ) diff --git a/Functions/Zle/bracketed-paste-magic b/Functions/Zle/bracketed-paste-magic new file mode 100644 index 000000000..da106d1ac --- /dev/null +++ b/Functions/Zle/bracketed-paste-magic @@ -0,0 +1,192 @@ +# Starting with zsh-5.0.9, ZLE began to recognize the "bracketed paste" +# capability of terminal emulators, that is, the sequences $'\e[200~' to +# start a paste and $'\e[201~' to indicate the end of the pasted text. +# Pastes are handled by the bracketed-paste widget and insert literally +# into the editor buffer rather than being interpreted as keystrokes. +# +# This disables some common usages where the self-insert widget has been +# replaced in order to accomplish some extra processing. An example is +# the contributed url-quote-magic widget. The bracketed-paste-magic +# widget replaces bracketed-paste with a wrapper that re-enables these +# self-insert actions, and other actions as selected by the zstyles +# described below. +# +# Setup: +# autoload -Uz bracketed-paste-magic +# zle -N bracketed-paste bracketed-paste-magic + +# The following zstyles may be set to control processing of pasted text. +# +# active-widgets +# Looked up in the context :bracketed-paste-magic to obtain a list of +# patterns that match widget names that should be activated during the +# paste. All other key sequences are processed as self-insert-unmeta. +# The default is 'self-*' so any user-defined widgets named with that +# prefix are active along with the builtin self-insert. If this style is +# not set (note: it must be explicitly deleted after loading this +# function, otherwise it becomes set by default) or has no value, no +# widgets are active and the pasted text is inserted literally. If the +# value includes undefined-key, any unknown sequences are discarded from +# the pasted text. +# +# inactive-keys +# This is the inverse of active-widgets, it lists key sequences that +# always use self-insert-unmeta even when bound to an active-widget. +# Note that this is a list of literal key sequences, not patterns. +# This style is in context :bracketed-paste-magic and has no default. +# +# paste-init +# paste-finish +# Also looked up in the context :bracketed-paste-magic, these styles +# each are a list of function names. They are executed in widget +# context but are called as functions (NOT as widgets with "zle name"). +# They also run in zsh emulation context set by bracketed-paste-magic. +# As with hooks, the functions are called in order until one of them +# returns a nonzero exit status. The parameter PASTED contains the +# current state of the pasted text, other ZLE parameters are as usual. +# Although a nonzero status stops each list of functions, it does NOT +# abort the entire paste operation; use "zle send-break" for that. + +# IMPORTANT: During processing of the paste (after paste-init and +# before paste-finish), BUFFER starts empty and history is restricted, +# so cursor motions etc. may not pass outside of the pasted content. +# However, the paste-init functions have access to the full history and +# the original BUFFER, so they may for example move words from BUFFER +# into PASTED to make those words visible to the active-widgets. + +# Establish default values for styles, but only if not already set +zstyle -m :bracketed-paste-magic active-widgets '*' || + zstyle ':bracketed-paste-magic' active-widgets 'self-*' + +# Helper/example paste-init for exposing a word prefix inside PASTED. +# Useful with url-quote-magic if you have http://... on the line and +# are pasting additional text on the end of the URL. +# +# Usage: +# zstyle :bracketed-paste-magic paste-init backward-extend-paste +# +# TODO: rewrite this using match-words-by-style +# +backward-extend-paste() { + : emulate -LR zsh # Already set by bracketed-paste-magic + integer bep_mark=$MARK bep_region=$REGION_ACTIVE + if (( REGION_ACTIVE && MARK < CURSOR )); then + zle .exchange-point-and-mark + fi + if (( CURSOR )); then + local -a bep_words=( ${(z)LBUFFER} ) + if [[ -n $bep_words[-1] && $LBUFFER = *$bep_words[-1] ]]; then + PASTED=$bep_words[-1]$PASTED + LBUFFER=${LBUFFER%${bep_words[-1]}} + fi + fi + if (( MARK > bep_mark )); then + zle .exchange-point-and-mark + fi + REGION_ACTIVE=$bep_region +} + +# Example paste-finish for quoting the pasted text. +# +# Usage e.g.: +# zstyle :bracketed-paste-magic paste-finish quote-paste +# zstyle :bracketed-paste-magic:finish quote-style qqq +# +# Using "zstyle -e" to examine $PASTED lets you choose different quotes +# depending on context. +# +# To forcibly turn off numeric prefix quoting, use e.g.: +# zstyle :bracketed-paste-magic:finish quote-style none +# +quote-paste() { + : emulate -LR zsh # Already set by bracketed-paste-magic + local qstyle + # If there's a quoting style, be sure .bracketed-paste leaves it alone + zstyle -s :bracketed-paste-magic:finish quote-style qstyle && NUMERIC=1 + case $qstyle in + (b) PASTED=${(b)PASTED};; + (q-) PASTED=${(q-)PASTED};; + (\\|q) PASTED=${(q)PASTED};; + (\'|qq) PASTED=${(qq)PASTED};; + (\"|qqq) PASTED=${(qqq)PASTED};; + (\$|qqqq) PASTED=${(qqqq)PASTED};; + (Q) PASTED=${(Q)PASTED};; + esac +} + +# Now the actual function + +bracketed-paste-magic() { + emulate -LR zsh + local -a bpm_hooks bpm_inactive + local PASTED bpm_func bpm_active + + # Set PASTED and run the paste-init functions + zle .bracketed-paste PASTED + if zstyle -a :bracketed-paste-magic paste-init bpm_hooks; then + for bpm_func in $bpm_hooks; do + if (( $+functions[$bpm_func] )); then + $bpm_func || break + fi + done + fi + + # Save context, create a clean slate for the paste + integer bpm_mark=$MARK bpm_cursor=$CURSOR bpm_region=$REGION_ACTIVE + integer bpm_numeric=${NUMERIC:-1} + local bpm_buffer=$BUFFER + fc -p -a /dev/null 0 0 + BUFFER= + + zstyle -a :bracketed-paste-magic inactive-keys bpm_inactive + if zstyle -s :bracketed-paste-magic active-widgets bpm_active '|'; then + # There are active widgets. Reprocess $PASTED as keystrokes. + NUMERIC=1 + zle -U - $PASTED + while [[ -n $PASTED ]] && zle .read-command; do + PASTED=${PASTED#$KEYS} + if [[ $KEYS = ${(~j:|:)${(b)bpm_inactive}} ]]; then + zle .self-insert-unmeta + else + case $REPLY in + (${~bpm_active}) zle $REPLY;; + (*) zle .self-insert-unmeta;; + esac + fi + done + PASTED=$BUFFER + fi + + # Restore state + BUFFER=$bpm_buffer + MARK=$bpm_mark + CURSOR=$bpm_cursor + REGION_ACTIVE=$bpm_region + NUMERIC=$bpm_numeric + fc -P + + # PASTED has been updated, run the paste-finish functions + if zstyle -a :bracketed-paste-magic paste-finish bpm_hooks; then + for bpm_func in $bpm_hooks; do + if (( $+functions[$bpm_func] )); then + $bpm_func || break + fi + done + fi + + # Reprocess $PASTED as an actual paste this time + zle -U - $PASTED$'\e[201~' # append paste-end marker + zle .bracketed-paste + zle .split-undo + + # Arrange to display highlighting if necessary + if [[ -n ${(M)zle_highlight:#paste:*} ]]; then + zle -R + zle .read-command && zle -U - $KEYS + fi +} + +# Handle zsh autoloading conventions +if [[ $zsh_eval_context = *loadautofunc && ! -o kshautoload ]]; then + bracketed-paste-magic "$@" +fi diff --git a/Functions/Zle/edit-command-line b/Functions/Zle/edit-command-line index 100af9601..2c7f34b8b 100644 --- a/Functions/Zle/edit-command-line +++ b/Functions/Zle/edit-command-line @@ -8,7 +8,20 @@ () { exec </dev/tty - ${=${VISUAL:-${EDITOR:-vi}}} $1 + + # Compute the cursor's position in bytes, not characters. + setopt localoptions nomultibyte + integer byteoffset=$(( $#PREBUFFER + $#LBUFFER + 1 )) + + # Open the editor, placing the cursor at the right place if we know how. + local editor=${${VISUAL:-${EDITOR:-vi}}} + case $editor in + (*vim*) ${=editor} -c "normal! ${byteoffset}go" -- $1;; + (*emacs*) ${=editor} $1 -eval "(goto-char ${byteoffset})";; + (*) ${=editor} $1;; + esac + + # Replace the buffer with the editor output. print -Rz - "$(<$1)" } =(<<<"$PREBUFFER$BUFFER") diff --git a/Functions/Zle/incremental-complete-word b/Functions/Zle/incremental-complete-word index 67a9d4744..ccc007543 100644 --- a/Functions/Zle/incremental-complete-word +++ b/Functions/Zle/incremental-complete-word @@ -69,7 +69,7 @@ incremental-complete-word() { '#key' -ne '#\\C-g' ]]; do twid=$wid if [[ "$key" = ${~stop} ]]; then - zle -U "$key" + zle -U - "$key" return elif [[ "$key" = ${~brk} ]]; then return diff --git a/Functions/Zle/narrow-to-region b/Functions/Zle/narrow-to-region index 86fd7ac13..261d821a9 100644 --- a/Functions/Zle/narrow-to-region +++ b/Functions/Zle/narrow-to-region @@ -5,39 +5,52 @@ # Optionally accepts exactly two arguments, which are used instead of # $CURSOR and $MARK as limits to the range. # +# Upon exit, $MARK is always the start of the edited range and $CURSOR +# the end of the range, even if they began in the opposite order. +# # Other options: -# -p pretext show `pretext' instead of the buffer text before the region. -# -P posttext show `posttext' instead of the buffer text after the region. -# Either or both may be empty. +# -p pretext show "pretext" instead of the buffer text before the region. +# -P posttext show "posttext" instead of the buffer text after the region. +# Either or both may be empty. # -n Only replace the text before or after the region with # the -p or -P options if the text was not empty. +# -l lbufvar $lbufvar is assigned the value of $LBUFFER and +# -r rbufvar $rbufvar is assigned the value of $RBUFFER +# from any recursive edit (i.e. not with -S or -R). Neither +# lbufvar nor rbufvar may begin with the prefix "_ntr_". # -S statevar # -R statevar -# Save or restore the state in/from the parameter named statevar. In -# either case no recursive editing takes place; this will typically be -# done within the calling function between calls with -S and -R. The -# statevar may not begin with the prefix _ntr_ which is reserved for -# parameters within narrow-to-region. +# Save or restore the state in/from the parameter named statevar. In +# either case no recursive editing takes place; this will typically be +# done within the calling function between calls with -S and -R. The +# statevar may not begin with the prefix "_ntr_" which is reserved for +# parameters within narrow-to-region. -emulate -L zsh -setopt extendedglob +# set the minimum of options to avoid changing behaviour away from +# user preferences from within recursive-edit +setopt localoptions noshwordsplit noksharrays -local _ntr_lbuffer _ntr_rbuffer +local _ntr_newbuf _ntr_lbuf_return _ntr_rbuf_return local _ntr_predisplay=$PREDISPLAY _ntr_postdisplay=$POSTDISPLAY +integer _ntr_savelim=UNDO_LIMIT_NO _ntr_changeno _ntr_histno=HISTNO integer _ntr_start _ntr_end _ntr_swap _ntr_cursor=$CURSOR _ntr_mark=$MARK integer _ntr_stat local _ntr_opt _ntr_pretext _ntr_posttext _ntr_usepretext _ntr_useposttext -local _ntr_nonempty _ntr_save _ntr_restore +local _ntr_nonempty _ntr_save _ntr_restore _ntr_lbuffer _ntr_rbuffer -while getopts "np:P:R:S:" _ntr_opt; do +while getopts "l:np:P:r:R:S:" _ntr_opt; do case $_ntr_opt in + (l) _ntr_lbuf_return=$OPTARG + ;; (n) _ntr_nonempty=1 ;; (p) _ntr_pretext=$OPTARG _ntr_usepretext=1 ;; (P) _ntr_posttext=$OPTARG _ntr_useposttext=1 ;; + (r) _ntr_rbuf_return=$OPTARG + ;; (R) _ntr_restore=$OPTARG ;; (S) _ntr_save=$OPTARG @@ -49,7 +62,8 @@ while getopts "np:P:R:S:" _ntr_opt; do done (( OPTIND > 1 )) && shift $(( OPTIND - 1 )) -if [[ $_ntr_restore = _ntr_* || $_ntr_save = _ntr_* ]]; then +if [[ $_ntr_restore = _ntr_* || $_ntr_save = _ntr_* || + $_ntr_lbuf_return = _ntr_* || $_ntr_rbuf_return = _ntr_* ]]; then zle -M "$0: _ntr_ prefix is reserved" >&2 return 1 fi @@ -58,7 +72,7 @@ if [[ -n $_ntr_save || -z $_ntr_restore ]]; then if (( $# )); then if (( $# != 2 )); then - zle -M "$0: supply zero or two arguments" + zle -M "$0: supply zero or two arguments" >&2 return 1 fi _ntr_start=$1 @@ -74,50 +88,68 @@ if [[ -n $_ntr_save || -z $_ntr_restore ]]; then _ntr_end=_ntr_swap fi - (( _ntr_end++, _ntr_cursor -= _ntr_start, _ntr_mark -= _ntr_start )) + (( _ntr_cursor -= _ntr_start, _ntr_mark -= _ntr_start )) _ntr_lbuffer=${BUFFER[1,_ntr_start]} if [[ -z $_ntr_usepretext || ( -n $_ntr_nonempty && -z $_ntr_lbuffer ) ]] then _ntr_pretext=$_ntr_lbuffer fi - _ntr_rbuffer=${BUFFER[_ntr_end,-1]} + _ntr_rbuffer=${BUFFER[_ntr_end+1,-1]} if [[ -z $_ntr_useposttext || ( -n $_ntr_nonempty && -z $_ntr_rbuffer ) ]] then _ntr_posttext=$_ntr_rbuffer fi + _ntr_changeno=$UNDO_CHANGE_NO PREDISPLAY="$_ntr_predisplay$_ntr_pretext" POSTDISPLAY="$_ntr_posttext$_ntr_postdisplay" - BUFFER=${BUFFER[_ntr_start+1,_ntr_end-1]} - CURSOR=$_ntr_cursor - MARK=$_ntr_mark if [[ -n $_ntr_save ]]; then - eval "$_ntr_save=(${(qq)_ntr_predisplay} ${(qq)_ntr_postdisplay} -${(qq)_ntr_lbuffer} ${(qq)_ntr_rbuffer})" || return 1 + builtin typeset -ga $_ntr_save + set -A $_ntr_save "${_ntr_predisplay}" "${_ntr_postdisplay}" \ + "${_ntr_savelim}" "${_ntr_changeno}" \ + "${_ntr_start}" "${_ntr_end}" "${_ntr_histno}" || return 1 fi + + BUFFER=${BUFFER[_ntr_start+1,_ntr_end]} + CURSOR=$_ntr_cursor + MARK=$_ntr_mark + zle split-undo + UNDO_LIMIT_NO=$UNDO_CHANGE_NO fi if [[ -z $_ntr_save && -z $_ntr_restore ]]; then zle recursive-edit _ntr_stat=$? + + [[ -n $_ntr_lbuf_return ]] && + builtin typeset -g ${_ntr_lbuf_return}="${LBUFFER}" + [[ -n $_ntr_rbuf_return ]] && + builtin typeset -g ${_ntr_rbuf_return}="${RBUFFER}" fi if [[ -n $_ntr_restore || -z $_ntr_save ]]; then if [[ -n $_ntr_restore ]]; then - if ! eval "_ntr_predisplay=\${${_ntr_restore}[1]} -_ntr_postdisplay=\${${_ntr_restore}[2]} -_ntr_lbuffer=\${${_ntr_restore}[3]} -_ntr_rbuffer=\${${_ntr_restore}[4]}"; then - zle -M Failed. + if ! { _ntr_predisplay="${${(@P)_ntr_restore}[1]}" + _ntr_postdisplay="${${(@P)_ntr_restore}[2]}" + _ntr_savelim="${${(@P)_ntr_restore}[3]}" + _ntr_changeno="${${(@P)_ntr_restore}[4]}" + _ntr_start="${${(@P)_ntr_restore}[5]}" + _ntr_end="${${(@P)_ntr_restore}[6]}" + _ntr_histno="${${(@P)_ntr_restore}[7]}" }; then + zle -M Failed. >&2 return 1 fi fi + _ntr_newbuf="$BUFFER" + HISTNO=_ntr_histno + zle undo $_ntr_changeno PREDISPLAY=$_ntr_predisplay POSTDISPLAY=$_ntr_postdisplay - LBUFFER="$_ntr_lbuffer$LBUFFER" - RBUFFER="$RBUFFER$_ntr_rbuffer" + BUFFER[_ntr_start+1,_ntr_end]="$_ntr_newbuf" + (( MARK = _ntr_start, CURSOR = _ntr_start + ${#_ntr_newbuf} )) + UNDO_LIMIT_NO=_ntr_savelim fi return $_ntr_stat diff --git a/Functions/Zle/read-from-minibuffer b/Functions/Zle/read-from-minibuffer index 8fec1105e..09dc68f97 100644 --- a/Functions/Zle/read-from-minibuffer +++ b/Functions/Zle/read-from-minibuffer @@ -20,7 +20,7 @@ done (( OPTIND > 1 )) && shift $(( OPTIND - 1 )) local readprompt="$1" lbuf_init="$2" rbuf_init="$3" -integer changeno=$UNDO_CHANGE_NO +integer savelim=$UNDO_LIMIT_NO changeno=$UNDO_CHANGE_NO { # Use anonymous function to make sure special values get restored, @@ -43,6 +43,8 @@ integer changeno=$UNDO_CHANGE_NO else local NUMERIC unset NUMERIC + zle split-undo + UNDO_LIMIT_NO=$UNDO_CHANGE_NO zle recursive-edit -K main stat=$? (( stat )) || REPLY=$BUFFER @@ -52,6 +54,7 @@ integer changeno=$UNDO_CHANGE_NO # This removes the edits relating to the read from the undo history. # These aren't useful once we get back to the main editing buffer. zle undo $changeno + UNDO_LIMIT_NO=savelim } return $stat diff --git a/Functions/Zle/smart-insert-last-word b/Functions/Zle/smart-insert-last-word index 27b0849ee..67adea760 100644 --- a/Functions/Zle/smart-insert-last-word +++ b/Functions/Zle/smart-insert-last-word @@ -47,13 +47,15 @@ setopt extendedglob nohistignoredups zle auto-suffix-retain # Not strictly necessary: -# (($+_ilw_hist)) || integer -g _ilw_hist _ilw_count _ilw_cursor _ilw_lcursor +# (($+_ilw_hist)) || integer -g _ilw_hist _ilw_count _ilw_cursor _ilw_lcursor _ilw_changeno integer cursor=$CURSOR lcursor=$CURSOR local lastcmd pattern numeric=$NUMERIC # Save state for repeated calls -if (( HISTNO == _ilw_hist && cursor == _ilw_cursor )); then +if (( HISTNO == _ilw_hist && cursor == _ilw_cursor && + UNDO_CHANGE_NO == _ilw_changeno )) +then NUMERIC=$[_ilw_count+1] lcursor=$_ilw_lcursor else @@ -61,7 +63,8 @@ else _ilw_lcursor=$lcursor fi # Handle the up to three arguments of .insert-last-word -if (( $+1 )); then +if (( $+1 )) +then if (( $+3 )); then ((NUMERIC = -($1))) else @@ -117,3 +120,6 @@ fi LBUFFER[lcursor+1,cursor+1]=$lastcmd[-NUMERIC] _ilw_cursor=$CURSOR + +# This is necessary to update UNDO_CHANGE_NO immediately +zle split-undo && _ilw_changeno=$UNDO_CHANGE_NO diff --git a/Functions/Zle/url-quote-magic b/Functions/Zle/url-quote-magic index fbcc7c19c..362d15c44 100644 --- a/Functions/Zle/url-quote-magic +++ b/Functions/Zle/url-quote-magic @@ -8,6 +8,12 @@ # autoload -Uz url-quote-magic # zle -N self-insert url-quote-magic +# As of zsh-5.0.9, the following may also be necessary in order to apply +# quoting to copy-pasted URLs: +# autload -Uz bracketed-paste-magic +# zle -N bracketed-paste bracketed-paste-magic +# See also backward-extend-paste in bracketed-paste-magic source file. + # A number of zstyles may be set to control the quoting behavior. # # url-metas |