diff options
Diffstat (limited to 'Functions')
-rw-r--r-- | Functions/Calendar/age | 2 | ||||
-rw-r--r-- | Functions/Chpwd/cdr | 37 | ||||
-rw-r--r-- | Functions/Chpwd/zsh_directory_name_generic | 151 | ||||
-rw-r--r-- | Functions/MIME/zsh-mime-setup | 2 | ||||
-rw-r--r-- | Functions/Misc/add-zsh-hook | 2 | ||||
-rw-r--r-- | Functions/Misc/zcalc | 4 | ||||
-rw-r--r-- | Functions/Misc/zed | 35 | ||||
-rw-r--r-- | Functions/Misc/zrecompile | 2 | ||||
-rw-r--r-- | Functions/TCP/tcp_open | 2 | ||||
-rw-r--r-- | Functions/TCP/tcp_read | 2 | ||||
-rw-r--r-- | Functions/TCP/tcp_send | 2 | ||||
-rw-r--r-- | Functions/TCP/tcp_shoot | 4 | ||||
-rw-r--r-- | Functions/VCS_Info/Backends/VCS_INFO_get_data_git | 65 | ||||
-rw-r--r-- | Functions/VCS_Info/VCS_INFO_quilt | 31 | ||||
-rw-r--r-- | Functions/VCS_Info/vcs_info | 2 | ||||
-rw-r--r-- | Functions/Zle/bracketed-paste-magic | 29 | ||||
-rw-r--r-- | Functions/Zle/bracketed-paste-url-magic | 44 | ||||
-rw-r--r-- | Functions/Zle/edit-command-line | 9 | ||||
-rw-r--r-- | Functions/Zle/match-word-context | 9 | ||||
-rw-r--r-- | Functions/Zle/smart-insert-last-word | 10 |
20 files changed, 368 insertions, 76 deletions
diff --git a/Functions/Calendar/age b/Functions/Calendar/age index 17cf4d13e..50755d610 100644 --- a/Functions/Calendar/age +++ b/Functions/Calendar/age @@ -1,4 +1,4 @@ -# Match the age of a file, for use as a glob qualifer. Can +# Match the age of a file, for use as a glob qualifier. Can # take one or two arguments, which can be supplied by one of two # ways (always the same for both arguments): # diff --git a/Functions/Chpwd/cdr b/Functions/Chpwd/cdr index 4f399106b..4bed88b13 100644 --- a/Functions/Chpwd/cdr +++ b/Functions/Chpwd/cdr @@ -51,6 +51,13 @@ # (and only /). Usually the first entry should be left as the current # directory. # +# "cdr -p 'pattern'" prunes anything matching the given extended glob +# 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 +# skipped by giving -P instead of -p. +# # Details of directory handling # ============================= # @@ -217,11 +224,11 @@ setopt extendedglob autoload -Uz chpwd_recent_filehandler chpwd_recent_add -integer list set_reply i bad edit -local opt dir +integer list set_reply i bad edit force_prune +local opt dir prune local -aU dirs -while getopts "elr" opt; do +while getopts "elp:P:r" opt; do case $opt in (e) edit=1 @@ -231,6 +238,12 @@ while getopts "elr" opt; do list=1 ;; + ([pP]) + prune=$OPTARG + edit=1 + [[ $opt = P ]] && force_prune=1 + ;; + (r) set_reply=1 ;; @@ -278,10 +291,22 @@ if [[ $PWD != $reply[1] ]]; then fi if (( edit )); then - local compcontext='directories:directory:_path_files -/' -IFS=' + if [[ -n $prune ]]; then + reply=(${reply:#$~prune}) + if [[ force_prune -eq 0 && -t 1 ]]; then + print -nrl "New list:" $reply 'Accept? ' + if ! read -q; then + print + return 1 + fi + print + fi + else + local compcontext='directories:directory:_path_files -/' + IFS=' ' vared reply || return 1 -chpwd_recent_filehandler $reply + fi + chpwd_recent_filehandler $reply fi # Skip current directory if present (may have been pruned). diff --git a/Functions/Chpwd/zsh_directory_name_generic b/Functions/Chpwd/zsh_directory_name_generic new file mode 100644 index 000000000..9430c95e4 --- /dev/null +++ b/Functions/Chpwd/zsh_directory_name_generic @@ -0,0 +1,151 @@ +## zsh_directory_name_generic +# +# This function is useful as a hook function for the zsh_directory_name +# facility. +# +# See the zsh-contrib manual page for more. + +emulate -L zsh +setopt extendedglob +local -a match mbegin mend + +# The variable containing the top level mapping. +local _zdn_topvar + +zmodload -i zsh/parameter +zstyle -s ":zdn:${funcstack[2]}:" mapping _zdn_topvar || _zdn_topvar=zdn_top + +if (( ! ${(P)#_zdn_topvar} )); then + print -r -- "$0: $_zdn_topver is not set" >&2 + return 1 +fi + +local _zdn_var=$_zdn_topvar +local -A _zdn_assoc + +if [[ $1 = n ]]; then + # Turning a name into a directory. + local _zdn_name=$2 + local -a _zdn_words + local _zdn_dir _zdn_cpt + + _zdn_words=(${(s.:.)_zdn_name}) + while (( ${#_zdn_words} )); do + if [[ -z ${_zdn_var} ]]; then + print -r -- "$0: too many components in directory name \`$_zdn_name'" >&2 + return 1 + fi + + # Subscripting (P)_zdn_var directly seems not to work. + _zdn_assoc=(${(Pkv)_zdn_var}) + _zdn_cpt=${_zdn_assoc[${_zdn_words[1]}]} + shift _zdn_words + + if [[ -z $_zdn_cpt ]]; then + # If top level component, just try another expansion + if [[ $_zdn_var != $_zdn_top ]]; then + # Committed to this expansion, so report failure. + print -r -- "$0: no expansion for directory name \`$_zdn_name'" >&2 + fi + return 1 + fi + if [[ $_zdn_cpt = (#b)(*)/:([[:IDENT:]]##) ]]; then + _zdn_cpt=$match[1] + _zdn_var=$match[2] + else + # may be empty + _zdn_var=${${_zdn_assoc[:default:]}##*/:} + fi + _zdn_dir=${_zdn_dir:+$_zdn_dir/}$_zdn_cpt + done + if (( ${#_zdn_dir} )); then + typeset -ag reply + reply=($_zdn_dir) + return 0 + fi +elif [[ $1 = d ]]; then + # Turning a directory into a name. + local _zdn_dir=$2 + local _zdn_rest=$_zdn_dir + local -a _zdn_cpts + local _zdn_pref _zdn_pref_raw _zdn_matched _zdn_cpt _zdn_name + + while [[ -n $_zdn_var && -n $_zdn_rest ]]; do + _zdn_assoc=(${(Pkv)_zdn_var}) + # Sorting in descending order will ensure prefixes + # come after longer strings with that perfix, so + # we match more specific directory names preferentially. + _zdn_cpts=(${(Ov)_zdn_assoc}) + _zdn_cpt='' + for _zdn_pref_raw in $_zdn_cpts; do + _zdn_pref=${_zdn_pref_raw%/:*} + [[ -z $_zdn_pref ]] && continue + if [[ $_zdn_rest = $_zdn_pref(#b)(/|)(*) ]]; then + _zdn_cpt=${(k)_zdn_assoc[(r)$_zdn_pref_raw]} + # if we matched a /, too, add it... + _zdn_matched+=$_zdn_pref$match[1] + _zdn_rest=$match[2] + break + fi + done + if [[ -n $_zdn_cpt ]]; then + _zdn_name+=${_zdn_name:+${_zdh_name}:}$_zdn_cpt + if [[ ${_zdn_assoc[$_zdn_cpt]} = (#b)*/:([[:IDENT:]]##) ]]; then + _zdn_var=$match[1] + else + _zdn_var=${${_zdn_assoc[:default:]}##*/:} + fi + else + break + fi + done + if [[ -n $_zdn_name ]]; then + # matched something, so report that. + integer _zdn_len=${#_zdn_matched} + [[ $_zdn_matched[-1] = / ]] && (( _zdn_len-- )) + typeset -ag reply + reply=($_zdn_name $_zdn_len) + return 0 + fi + # else let someone else have a go. +elif [[ $1 = c ]]; then + # Completion + + if [[ -n $SUFFIX ]]; then + _message "Can't complete in the middle of a dynamic directory name" + else + local -a _zdn_cpts + local _zdn_word _zdn_cpt _zdn_desc _zdn_sofar expl + + while [[ -n ${_zdn_var} && ${PREFIX} = (#b)([^:]##):* ]]; do + _zdn_word=$match[1] + compset -P '[^:]##:' + _zdn_assoc=(${(Pkv)_zdn_var}) + _zdn_cpt=${_zdn_assoc[$_zdn_word]} + # We only complete at the end so must match here + [[ -z $_zdn_cpt ]] && return 1 + if [[ $_zdn_cpt = (#b)(*)/:([[:IDENT:]]##) ]]; then + _zdn_cpt=$match[1] + _zdn_var=$match[2] + else + _zdn_var=${${_zdn_assoc[:default:]}##*/:} + fi + _zdn_sofar+=${_zdn_sofar:+${_zdn_sofar}/}$_zdn_cpt + done + if [[ -n $_zdn_var ]]; then + _zdn_assoc=(${(Pkv)_zdn_var}) + local -a _zdn_cpts + for _zdn_cpt _zdn_desc in ${(kv)_zdn_assoc}; do + [[ $_zdn_cpt = :* ]] && continue + _zdn_cpts+=(${_zdn_cpt}:${_zdn_desc%/:[[:IDENT:]]##}) + done + _describe -t dirnames "directory name under ${_zdn_sofar%%/}" \ + _zdn_cpts -S: -r ':]' + return + fi + fi +fi + +# Failed +return 1 +## end diff --git a/Functions/MIME/zsh-mime-setup b/Functions/MIME/zsh-mime-setup index 23e44fdc0..35f6e6b6b 100644 --- a/Functions/MIME/zsh-mime-setup +++ b/Functions/MIME/zsh-mime-setup @@ -1,7 +1,7 @@ emulate -L zsh setopt extendedglob cbases -local opt o_verbose o_list +local opt o_verbose o_list i autoload -Uz zsh-mime-handler diff --git a/Functions/Misc/add-zsh-hook b/Functions/Misc/add-zsh-hook index ee37d674d..fc39659ae 100644 --- a/Functions/Misc/add-zsh-hook +++ b/Functions/Misc/add-zsh-hook @@ -82,9 +82,11 @@ if (( del )); then else if (( ${(P)+hook} )); then if (( ${${(P)hook}[(I)$fn]} == 0 )); then + typeset -ga $hook set -A $hook ${(P)hook} $fn fi else + typeset -ga $hook set -A $hook $fn fi autoload $autoopts -- $fn diff --git a/Functions/Misc/zcalc b/Functions/Misc/zcalc index 63f67adb0..17700e48b 100644 --- a/Functions/Misc/zcalc +++ b/Functions/Misc/zcalc @@ -120,6 +120,10 @@ autoload -Uz zmathfuncdef float PI E (( PI = 4 * atan(1), E = exp(1) )) +if [[ -f "${ZDOTDIR:-$HOME}/.zcalcrc" ]]; then + . "${ZDOTDIR:-$HOME}/.zcalcrc" || return 1 +fi + # Process command line while [[ -n $1 && $1 = -(|[#-]*|f|e) ]]; do optlist=${1[2,-1]} diff --git a/Functions/Misc/zed b/Functions/Misc/zed index 010b69bee..eb8f557ea 100644 --- a/Functions/Misc/zed +++ b/Functions/Misc/zed @@ -6,31 +6,20 @@ # Use ^X^W to save, ^C to abort. # Option -f: edit shell functions. (Also if called as fned.) -local var opt zed_file_name +local var opts 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 "fbx:" opt; do - case $opt in - (f) - fun=1 - ;; - - (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 )) +zparseopts -D -A opts f b x: +fun=$+opts[-f] +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 +fi [[ $0 = fned ]] && fun=1 (( bind )) && okargs=0 @@ -80,10 +69,10 @@ 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="$1() { }" diff --git a/Functions/Misc/zrecompile b/Functions/Misc/zrecompile index 8fe990086..d9fc55020 100644 --- a/Functions/Misc/zrecompile +++ b/Functions/Misc/zrecompile @@ -52,7 +52,7 @@ while getopts ":tqp" opt; do fi esac done -shift OPTIND-${#tmp:-1} +shift OPTIND-${#tmp}-1 if [[ -n $check ]]; then ret=1 diff --git a/Functions/TCP/tcp_open b/Functions/TCP/tcp_open index 091217788..a04403c76 100644 --- a/Functions/TCP/tcp_open +++ b/Functions/TCP/tcp_open @@ -152,7 +152,7 @@ fi if (( $# )); then print "Usage: $0 [-z] [-a fd | -f fd | host port [ session ] ] - $0 [-z] [ -s session | -l sesslist ] ..." >&2 + $0 [-z] [ -s session | -l sesslist ] ..." >&2 return 1 fi diff --git a/Functions/TCP/tcp_read b/Functions/TCP/tcp_read index f880395dd..ba9185ed5 100644 --- a/Functions/TCP/tcp_read +++ b/Functions/TCP/tcp_read @@ -116,7 +116,7 @@ while getopts "abdl:qs:t:T:u:" opt; do read_fds[$((read_fd))]=1 done ;; - (*) [[ $opt != \? ]] && print Unhandled option, complain: $opt >&2 + (*) [[ $opt != \? ]] && print "Unhandled option, complain: $opt" >&2 return 1 ;; esac diff --git a/Functions/TCP/tcp_send b/Functions/TCP/tcp_send index c976a2fb7..86dda6403 100644 --- a/Functions/TCP/tcp_send +++ b/Functions/TCP/tcp_send @@ -29,7 +29,7 @@ while getopts "acl:nqs:" opt; do fi sessions+=($OPTARG) ;; - (*) [[ $opt != '?' ]] && print Unhandled option, complain: $opt >&2 + (*) [[ $opt != '?' ]] && print "Unhandled option, complain: $opt" >&2 return 1 ;; esac diff --git a/Functions/TCP/tcp_shoot b/Functions/TCP/tcp_shoot index 8ff9866ba..c485c140a 100644 --- a/Functions/TCP/tcp_shoot +++ b/Functions/TCP/tcp_shoot @@ -4,8 +4,8 @@ setopt extendedglob local REPLY tfd if [[ $# -ne 2 ]]; then - print "Usage: tcp_dump host port -Connect to the given host and port; send standard input.">&2 + print "Usage: $0 host port +Connect to the given host and port; send standard input." >&2 return 1 fi diff --git a/Functions/VCS_Info/Backends/VCS_INFO_get_data_git b/Functions/VCS_Info/Backends/VCS_INFO_get_data_git index 638ea4572..704c1890e 100644 --- a/Functions/VCS_Info/Backends/VCS_INFO_get_data_git +++ b/Functions/VCS_Info/Backends/VCS_INFO_get_data_git @@ -87,13 +87,18 @@ VCS_INFO_git_getbranch () { gitbranch="$(${(z)gitsymref} 2> /dev/null)" [[ -z ${gitbranch} ]] && [[ -r ${actiondir}/head-name ]] \ && gitbranch="$(< ${actiondir}/head-name)" + [[ -z ${gitbranch} ]] && gitbranch="$(< ${gitdir}/ORIG_HEAD)" elif [[ -f "${gitdir}/MERGE_HEAD" ]] ; then gitbranch="$(${(z)gitsymref} 2> /dev/null)" - [[ -z ${gitbranch} ]] && gitbranch="$(< ${gitdir}/MERGE_HEAD)" + [[ -z ${gitbranch} ]] && gitbranch="$(< ${gitdir}/ORIG_HEAD)" elif [[ -d "${gitdir}/rebase-merge" ]] ; then gitbranch="$(< ${gitdir}/rebase-merge/head-name)" + if [[ $gitbranch == 'detached HEAD' ]]; then + # get a sha1 + gitbranch="$(< ${gitdir}/rebase-merge/orig-head)" + fi elif [[ -d "${gitdir}/.dotest-merge" ]] ; then gitbranch="$(< ${gitdir}/.dotest-merge/head-name)" @@ -217,18 +222,32 @@ elif [[ -d "${gitdir}/rebase-merge" ]]; then elif [[ -d "${gitdir}/rebase-apply" ]]; then # Fake patch names for all but current patch patchdir="${gitdir}/rebase-apply" - local cur=$(< "${patchdir}/next") - local p subject - for p in $(seq $(($cur - 1))); do - git_patches_applied+=("$(printf "%04d" $p) ?") - done - subject="${$(< "${patchdir}/msg-clean")[(f)1]}" - if [[ -f "${patchdir}/original-commit" ]]; then - git_patches_applied+=("$(< ${patchdir}/original-commit) $subject") - else - git_patches_applied+=("? $subject") + local next="${patchdir}/next" + if [[ -f $next ]]; then + local cur=$(< $next) + local p subject + for ((p = 1; p < cur; p++)); do + git_patches_applied+=("$(printf "%04d" $p) ?") + done + if [[ -f "${patchdir}/msg-clean" ]]; then + subject="${$(< "${patchdir}/msg-clean")[(f)1]}" + fi + if [[ -f "${patchdir}/original-commit" ]]; then + if [[ -n $subject ]]; then + git_patches_applied+=("$(< ${patchdir}/original-commit) $subject") + else + git_patches_applied+=("$(< ${patchdir}/original-commit)") + fi + else + if [[ -n $subject ]]; then + git_patches_applied+=("? $subject") + else + git_patches_applied+=("?") + fi + fi + local last="$(< "${patchdir}/last")" + git_patches_unapplied=( {$cur..$last} ) fi - git_patches_unapplied=($(seq $cur $(< "${patchdir}/last"))) VCS_INFO_git_handle_patches elif [[ -f "${gitdir}/MERGE_HEAD" ]]; then @@ -248,6 +267,28 @@ elif [[ -f "${gitdir}/MERGE_HEAD" ]]; then # Not touching git_patches_unapplied VCS_INFO_git_handle_patches +elif [[ -f "${gitdir}/CHERRY_PICK_HEAD" ]]; then + # 'git cherry-pick' without -n, that conflicted. (With -n, git doesn't + # record the CHERRY_PICK_HEAD information anywhere, as of git 2.6.2.) + # + # ### 'git cherry-pick foo bar baz' only records the "remaining" part of + # ### the queue in the .git dir: if 'bar' has a conflict, the .git dir + # ### has a record of 'baz' being queued, but no record of 'foo' having been + # ### part of the queue as well. Therefore, the %n/%c applied/unapplied + # ### expandos will be memoryless: the "applied" counter will always + # ### be "1". The %u/%c tuple will assume the values [(1,2), (1,1), (1,0)], + # ### whereas the correct sequence would be [(1,2), (2,1), (3,0)]. + local subject + IFS='' read -r subject < "${gitdir}/MERGE_MSG" + git_patches_applied=( "$(<${gitdir}/CHERRY_PICK_HEAD) ${subject}" ) + if [[ -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]=() + else + git_patches_unapplied=() + fi + VCS_INFO_git_handle_patches else gitmisc='' fi diff --git a/Functions/VCS_Info/VCS_INFO_quilt b/Functions/VCS_Info/VCS_INFO_quilt index bc71cfb7d..c3c3d864d 100644 --- a/Functions/VCS_Info/VCS_INFO_quilt +++ b/Functions/VCS_Info/VCS_INFO_quilt @@ -119,6 +119,7 @@ function VCS_INFO_quilt() { applied=() fi patches=$(<$pc/.quilt_patches) + patches=`builtin cd -q "${pc:h}" && print -r - ${patches:A}` fi if zstyle -t "${context}" get-unapplied; then # This zstyle call needs to be moved further up if `quilt' needs @@ -144,6 +145,36 @@ function VCS_INFO_quilt() { unapplied=() fi + if [[ -n $patches ]]; then + () { + local i line + for ((i=1; i<=$#applied; i++)); do + if [[ -f "$patches/$applied[$i]" ]] && + read -r line < "$patches/$applied[$i]" && + [[ $line != (#b)(---|Index:)* ]] && + true + ; + then + applied[$i]+=" $line" + else + applied[$i]+=" ?" + fi + done + for ((i=1; i<=$#unapplied; i++)); do + if [[ -f "$patches/$unapplied[$i]" ]] && + read -r line < "$patches/$unapplied[$i]" && + [[ $line != (#b)(---|Index:)* ]] && + true + ; + then + unapplied[$i]+=" $line" + else + unapplied[$i]+=" ?" + fi + done + } + fi + all=( ${(Oa)applied} ${unapplied} ) if VCS_INFO_hook 'gen-applied-string' "${applied[@]}"; then diff --git a/Functions/VCS_Info/vcs_info b/Functions/VCS_Info/vcs_info index 350b189e9..628dde9b1 100644 --- a/Functions/VCS_Info/vcs_info +++ b/Functions/VCS_Info/vcs_info @@ -11,6 +11,7 @@ setopt localoptions noksharrays extendedglob NO_shwordsplit local file func sys local -a static_functions +local -i maxexports static_functions=( VCS_INFO_adjust @@ -38,6 +39,7 @@ for func in ${static_functions} ; do done [[ -n ${(Mk)parameters:#vcs_info_msg_<->_} ]] && unset ${parameters[(I)vcs_info_msg_<->_]} +VCS_INFO_maxexports VCS_INFO_set --nvcs '-preinit-' vcs_info_setsys diff --git a/Functions/Zle/bracketed-paste-magic b/Functions/Zle/bracketed-paste-magic index 464c6b339..2b2bc630d 100644 --- a/Functions/Zle/bracketed-paste-magic +++ b/Functions/Zle/bracketed-paste-magic @@ -116,10 +116,14 @@ quote-paste() { # Now the actual function bracketed-paste-magic() { - # Fast exit in the vi-mode cut-buffer context if [[ "$LASTWIDGET" = *vi-set-buffer ]]; then + # Fast exit in the vi-mode cut-buffer context zle .bracketed-paste return + else + # Capture the pasted text in $PASTED + local PASTED REPLY + zle .bracketed-paste PASTED fi # Really necessary to go to this much effort? @@ -127,10 +131,9 @@ bracketed-paste-magic() { emulate -L zsh local -a bpm_hooks bpm_inactive - local PASTED bpm_func bpm_active bpm_keymap=$KEYMAP + local bpm_func bpm_active bpm_keymap=$KEYMAP - # Set PASTED and run the paste-init functions - zle .bracketed-paste PASTED + # Run the paste-init functions if zstyle -a :bracketed-paste-magic paste-init bpm_hooks; then for bpm_func in $bpm_hooks; do if (( $+functions[$bpm_func] )); then @@ -164,25 +167,17 @@ bracketed-paste-magic() { integer bpm_limit=$UNDO_LIMIT_NO bpm_undo=$UNDO_CHANGE_NO UNDO_LIMIT_NO=$UNDO_CHANGE_NO - local mbchar - integer ismb while [[ -n $PASTED ]] && zle .read-command; do - mbchar=$KEYS - ismb=0 - while [[ $mbchar = [[:INCOMPLETE:]]* ]] && zle .read-command; do - mbchar+=$KEYS - ismb=1 - done - PASTED=${PASTED#$mbchar} - if [[ ismb -ne 0 || $mbchar = ${(~j:|:)${(b)bpm_inactive}} ]]; then - LBUFFER+=$mbchar + PASTED=${PASTED#$KEYS} + if [[ $KEYS = ${(~j:|:)${(b)bpm_inactive}} ]]; then + zle .self-insert else case $REPLY in (${~bpm_active}) function () { emulate -L $bpm_emulate; set -$bpm_opts zle $REPLY };; - (*) LBUFFER+=$mbchar; + (*) zle .self-insert;; esac fi done @@ -221,7 +216,7 @@ bracketed-paste-magic() { zle .split-undo # Arrange to display highlighting if necessary - if [[ -n ${(M)zle_highlight:#paste:*} ]]; then + if [[ -z $zle_highlight || -n ${(M)zle_highlight:#paste:*} ]]; then zle -R zle .read-command && zle -U - $KEYS fi diff --git a/Functions/Zle/bracketed-paste-url-magic b/Functions/Zle/bracketed-paste-url-magic new file mode 100644 index 000000000..06dee2657 --- /dev/null +++ b/Functions/Zle/bracketed-paste-url-magic @@ -0,0 +1,44 @@ +# bracketed-paste-url-magic quotes pasted urls automatically, if the +# paste exactly starts with a url, eg no spaces or other characters precede it +# +# If the numeric argument is provided (eg, pressing alt-0 or alt-1 in emacs mode, +# or just the number by itself in vi command mode), then +# 0 is the default and means auto detect urls +# 1 means always quote +# any other value means never quote +# +# To use this widget, put this in your startup files (eg, .zshrc) +# +# autoload -Uz bracketed-paste-url-magic +# zle -N bracketed-paste bracketed-paste-url-magic +# +# You can customize which schemas are to be quoted by using +# +# zstyle :bracketed-paste-url-magic schema http https ftp +# +# The default can be seen just below. + +local -a schema +zstyle -a :bracketed-paste-url-magic schema schema || schema=(http https ftp ftps file ssh sftp) + +local wantquote=${NUMERIC:-0} +local content +local start=$#LBUFFER + +zle .$WIDGET -N content + +if (( $wantquote == 0 )); then + if [[ $content = (${(~j:|:)schema})://* ]]; then + wantquote=1 + fi +fi + +if (( $wantquote == 1 )); then + content=${(q-)content} +fi + +LBUFFER+=$content + +YANK_START=$start +YANK_END=$#LBUFFER +zle -f yank diff --git a/Functions/Zle/edit-command-line b/Functions/Zle/edit-command-line index 2c7f34b8b..103a1c1a5 100644 --- a/Functions/Zle/edit-command-line +++ b/Functions/Zle/edit-command-line @@ -11,13 +11,16 @@ # 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})";; + (*vim*) + integer byteoffset=$(( $#PREBUFFER + $#LBUFFER + 1 )) + ${=editor} -c "normal! ${byteoffset}go" -- $1;; + (*emacs*) + local lines=( ${(f):-"$PREBUFFER$LBUFFER"} ) + ${=editor} +${#lines}:$((${#lines[-1]} + 1)) $1;; (*) ${=editor} $1;; esac diff --git a/Functions/Zle/match-word-context b/Functions/Zle/match-word-context index 7f1154498..8793483f4 100644 --- a/Functions/Zle/match-word-context +++ b/Functions/Zle/match-word-context @@ -7,7 +7,7 @@ setopt extendedglob local -a worcon bufwords local pat tag lastword word backword forword -integer iword +integer iword between zstyle -a $curcontext word-context worcon || return 0 @@ -25,13 +25,18 @@ if [[ $lastword = ${bufwords[iword]} ]]; then # If the word immediately left of the cursor is complete, # we're not on it for forward operations. forword=${bufwords[iword+1]} + # If, furthermore, we're on whitespace, then we're between words. + # It can't be significant whitespace because the previous word is complete. + [[ $RBUFFER[1] = [[:space:]] ]] && between=1 else # We're on a word. forword=${bufwords[iword]} fi backword=${bufwords[iword]} -if [[ $curcontext = *back* ]]; then +if [[ between -ne 0 && $curcontext = *between* ]]; then + word=' ' +elif [[ $curcontext = *back* ]]; then word=$backword else word=$forword diff --git a/Functions/Zle/smart-insert-last-word b/Functions/Zle/smart-insert-last-word index 67adea760..cf8715dfe 100644 --- a/Functions/Zle/smart-insert-last-word +++ b/Functions/Zle/smart-insert-last-word @@ -60,7 +60,7 @@ then lcursor=$_ilw_lcursor else NUMERIC=1 - _ilw_lcursor=$lcursor + typeset -g _ilw_lcursor=$lcursor fi # Handle the up to three arguments of .insert-last-word if (( $+1 )) @@ -73,8 +73,8 @@ then (( NUMERIC )) || LBUFFER[lcursor+1,cursor+1]='' numeric=$((-(${2:--numeric}))) fi -_ilw_hist=$HISTNO -_ilw_count=$NUMERIC +typeset -g _ilw_hist=$HISTNO +typeset -g _ilw_count=$NUMERIC if [[ -z "$numeric" ]] then @@ -119,7 +119,7 @@ fi (( NUMERIC > $#lastcmd )) && return 1 LBUFFER[lcursor+1,cursor+1]=$lastcmd[-NUMERIC] -_ilw_cursor=$CURSOR +typeset -g _ilw_cursor=$CURSOR # This is necessary to update UNDO_CHANGE_NO immediately -zle split-undo && _ilw_changeno=$UNDO_CHANGE_NO +zle split-undo && typeset -g _ilw_changeno=$UNDO_CHANGE_NO |