diff options
Diffstat (limited to 'Functions')
27 files changed, 298 insertions, 36 deletions
diff --git a/Functions/Calendar/calendar_parse b/Functions/Calendar/calendar_parse index 1025a9a25..fabaf7413 100644 --- a/Functions/Calendar/calendar_parse +++ b/Functions/Calendar/calendar_parse @@ -1,7 +1,7 @@ # Parse the line passed down in the first argument as a calendar entry. # Sets the values parsed into the associative array reply, consisting of: # time The time as an integer (as per EPOCHSECONDS) of the (next) event. -# text1 The text from the the line not including the date/time, but +# text1 The text from the line not including the date/time, but # including any WARN or RPT text. This is useful for rescheduling # events, since the keywords need to be retained in this case. # warntime Any warning time (WARN keyword) as an integer, else an empty diff --git a/Functions/Chpwd/.distfiles b/Functions/Chpwd/.distfiles index 39ccd830c..89779a686 100644 --- a/Functions/Chpwd/.distfiles +++ b/Functions/Chpwd/.distfiles @@ -5,4 +5,5 @@ _cdr chpwd_recent_add chpwd_recent_dirs chpwd_recent_filehandler +zsh_directory_name_cdr ' diff --git a/Functions/Chpwd/cdr b/Functions/Chpwd/cdr index 3025a9d5c..4f399106b 100644 --- a/Functions/Chpwd/cdr +++ b/Functions/Chpwd/cdr @@ -15,7 +15,7 @@ # changing directory permanently, see below. # # The argument to cdr is a number corresponding to the Nth most recently -# changed-to directory starting at 1 for the immediately preceeding +# changed-to directory starting at 1 for the immediately preceding # directory (the current directory is remembered but is not offered as a # destination). You can use directory arguments if you set the # recent-dirs-default style, see below; however, it should be noted diff --git a/Functions/Chpwd/zsh_directory_name_cdr b/Functions/Chpwd/zsh_directory_name_cdr new file mode 100644 index 000000000..09aa35a93 --- /dev/null +++ b/Functions/Chpwd/zsh_directory_name_cdr @@ -0,0 +1,25 @@ +if [[ $1 = n ]]; then + if [[ $2 = <-> ]]; then + # Recent directory + typeset -ga reply + autoload -Uz cdr + cdr -r + if [[ -n ${reply[$2]} ]]; then + reply=(${reply[$2]}) + return 0 + else + reply=() + return 1 + fi + fi +elif [[ $1 = c ]]; then + if [[ $PREFIX = <-> || -z $PREFIX ]]; then + typeset -a keys values + values=(${${(f)"$(cdr -l)"}/ ##/:}) + keys=(${values%%:*}) + _describe -t dir-index 'recent directory index' \ + values keys -V unsorted -S']' + return + fi +fi +return 1 diff --git a/Functions/Misc/add-zsh-hook b/Functions/Misc/add-zsh-hook index aedc1e754..c49688643 100644 --- a/Functions/Misc/add-zsh-hook +++ b/Functions/Misc/add-zsh-hook @@ -1,6 +1,6 @@ # Add to HOOK the given FUNCTION. # HOOK is one of chpwd, precmd, preexec, periodic, zshaddhistory, -# zshexit (the _functions subscript is not required). +# zshexit, zsh_directory_name (the _functions subscript is not required). # # With -d, remove the function from the hook instead; delete the hook # variable if it is empty. @@ -15,7 +15,10 @@ emulate -L zsh local -a hooktypes -hooktypes=(chpwd precmd preexec periodic zshaddhistory zshexit) +hooktypes=( + chpwd precmd preexec periodic zshaddhistory zshexit + zsh_directory_name +) local opt local -a autoopts diff --git a/Functions/Misc/colors b/Functions/Misc/colors index bef93c8c3..027ca9a14 100644 --- a/Functions/Misc/colors +++ b/Functions/Misc/colors @@ -1,6 +1,8 @@ # Put standard ANSI color codes in shell parameters for easy use. # Note that some terminals do not support all combinations. +emulate -L zsh + typeset -Ag color colour color=( diff --git a/Functions/Misc/sticky-note b/Functions/Misc/sticky-note index cfe9ea684..efe5ec1eb 100644 --- a/Functions/Misc/sticky-note +++ b/Functions/Misc/sticky-note @@ -19,7 +19,7 @@ # # Otherwise, invoke the line editor with the previous notes available # as an editor history. Two quick taps on the return/enter key finish -# the note, or you can use use ^X^W as usual (ZZ in vicmd mode). +# the note, or you can use ^X^W as usual (ZZ in vicmd mode). # The application is configured by three zstyles, all using the context # ":sticky-note". The first two styles are "notefile" and "maxnotes" diff --git a/Functions/Prompts/prompt_bigfade_setup b/Functions/Prompts/prompt_bigfade_setup index 4e9aafdb1..2d95f3143 100644 --- a/Functions/Prompts/prompt_bigfade_setup +++ b/Functions/Prompts/prompt_bigfade_setup @@ -31,7 +31,7 @@ prompt_bigfade_setup () { autoload -Uz prompt_special_chars prompt_special_chars - PS1="%B%F{$fadebar}$schars[333]$schars[262]$schars[261]$schars[260]%B%F{$userhost}%K{$fadebar}%n@%m%b%k%f%F{$fadebar}%K{black}$schars[260]$schars[261]$schars[262]$schars[333]%b%f%k%F{$fadebar}%K{black}$schars[333]$schars[262]$schars[261]$schars[260]%B%F{$date}%K{black} %D{%a %b %d} %D{%I:%M:%S%P}$prompt_newline%B%F{$cwd}%K{black}$PWD>%b%f%k " + PS1="%B%F{$fadebar}$schars[333]$schars[262]$schars[261]$schars[260]%B%F{$userhost}%K{$fadebar}%n@%m%b%k%f%F{$fadebar}%K{black}$schars[260]$schars[261]$schars[262]$schars[333]%b%f%k%F{$fadebar}%K{black}$schars[333]$schars[262]$schars[261]$schars[260]%B%F{$date}%K{black} %D{%a %b %d} %D{%I:%M:%S%P}$prompt_newline%B%F{$cwd}%K{black}%d>%b%f%k " PS2="%B%F{$fadebar}$schars[333]$schars[262]$schars[261]$schars[260]%b%F{$fadebar}%K{black}$schars[260]$schars[261]$schars[262]$schars[333]%F{$fadebar}%K{black}$schars[333]$schars[262]$schars[261]$schars[260]%B%F{$fadebar}>%b%f%k " prompt_opts=(cr subst percent) diff --git a/Functions/TCP/tcp_read b/Functions/TCP/tcp_read index 7d8acf865..f880395dd 100644 --- a/Functions/TCP/tcp_read +++ b/Functions/TCP/tcp_read @@ -1,7 +1,7 @@ # Helper function for reading input from a TCP connection. # Actually, the input doesn't need to be a TCP connection at all, it # is simply an input file descriptor. However, it must be contained -# in ${tcp_by_fd[$TCP_SESS]}. This is set set by tcp_open, but may be +# in ${tcp_by_fd[$TCP_SESS]}. This is set by tcp_open, but may be # set by hand. (Note, however, the blocking/timeout behaviour is usually # not implemented for reading from regular files.) # diff --git a/Functions/VCS_Info/.distfiles b/Functions/VCS_Info/.distfiles index 988e7ada4..b6e55d2fc 100644 --- a/Functions/VCS_Info/.distfiles +++ b/Functions/VCS_Info/.distfiles @@ -1,6 +1,8 @@ DISTFILES_SRC=' .distfiles vcs_info +vcs_info_hookadd +vcs_info_hookdel VCS_INFO_adjust VCS_INFO_bydir_detect VCS_INFO_check_com diff --git a/Functions/VCS_Info/Backends/.distfiles b/Functions/VCS_Info/Backends/.distfiles index 46e9d6e67..67fb06cda 100644 --- a/Functions/VCS_Info/Backends/.distfiles +++ b/Functions/VCS_Info/Backends/.distfiles @@ -4,6 +4,7 @@ VCS_INFO_detect_bzr VCS_INFO_detect_cdv VCS_INFO_detect_cvs VCS_INFO_detect_darcs +VCS_INFO_detect_fossil VCS_INFO_detect_git VCS_INFO_detect_hg VCS_INFO_detect_mtn @@ -15,6 +16,7 @@ VCS_INFO_get_data_bzr VCS_INFO_get_data_cdv VCS_INFO_get_data_cvs VCS_INFO_get_data_darcs +VCS_INFO_get_data_fossil VCS_INFO_get_data_git VCS_INFO_get_data_hg VCS_INFO_get_data_mtn diff --git a/Functions/VCS_Info/Backends/VCS_INFO_detect_fossil b/Functions/VCS_Info/Backends/VCS_INFO_detect_fossil new file mode 100644 index 000000000..551528361 --- /dev/null +++ b/Functions/VCS_Info/Backends/VCS_INFO_detect_fossil @@ -0,0 +1,13 @@ +## vim:ft=zsh +## fossil support by: Mike Meyer <mwm@mired.org> +## Distributed under the same BSD-ish license as zsh itself. + +setopt localoptions NO_shwordsplit + +[[ $1 == '--flavours' ]] && return 1 + +VCS_INFO_check_com ${vcs_comm[cmd]} || return 1 +vcs_comm[detect_need_file]=_FOSSIL_ +VCS_INFO_bydir_detect . || return 1 + +return 0 diff --git a/Functions/VCS_Info/Backends/VCS_INFO_detect_hg b/Functions/VCS_Info/Backends/VCS_INFO_detect_hg index e2866afd5..a22c1ee0f 100644 --- a/Functions/VCS_Info/Backends/VCS_INFO_detect_hg +++ b/Functions/VCS_Info/Backends/VCS_INFO_detect_hg @@ -7,7 +7,7 @@ setopt localoptions NO_shwordsplit [[ $1 == '--flavours' ]] && { print -l hg-git hg-hgsubversion hg-hgsvn; return 0 } VCS_INFO_check_com ${vcs_comm[cmd]} || return 1 -vcs_comm[detect_need_file]=store +vcs_comm[detect_need_file]="store data" VCS_INFO_bydir_detect '.hg' || return 1 if [[ -d ${vcs_comm[basedir]}/.hg/svn ]] ; then diff --git a/Functions/VCS_Info/Backends/VCS_INFO_detect_svn b/Functions/VCS_Info/Backends/VCS_INFO_detect_svn index bb9d083ac..a777ecc43 100644 --- a/Functions/VCS_Info/Backends/VCS_INFO_detect_svn +++ b/Functions/VCS_Info/Backends/VCS_INFO_detect_svn @@ -7,5 +7,5 @@ setopt localoptions NO_shwordsplit [[ $1 == '--flavours' ]] && return 1 VCS_INFO_check_com ${vcs_comm[cmd]} || return 1 -[[ -d ".svn" ]] && return 0 +{ [[ -f ".svn/entries" ]] || [[ -f ".svn/format" ]] } && return 0 return 1 diff --git a/Functions/VCS_Info/Backends/VCS_INFO_get_data_fossil b/Functions/VCS_Info/Backends/VCS_INFO_get_data_fossil new file mode 100644 index 000000000..fd0f8389e --- /dev/null +++ b/Functions/VCS_Info/Backends/VCS_INFO_get_data_fossil @@ -0,0 +1,24 @@ +## vim:ft=zsh +## fossil support by: Mike Meyer (mwm@mired.org) +## Distributed under the same BSD-ish license as zsh itself. + +setopt localoptions extendedglob +local a b +local -A fsinfo +local fshash fsbranch changed merging action + +${vcs_comm[cmd]} status | + while IFS=: read a b; do + fsinfo[${a//-/_}]="${b## #}" + done + +fshash=${fsinfo[checkout]%% *} +fsbranch=${fsinfo[tags]%%, *} +changed=${(Mk)fsinfo:#(ADDED|EDITED|DELETED|UPDATED)*} +merging=${(Mk)fsinfo:#*_BY_MERGE*} +if [ -n "$merging" ]; then + action="merging" +fi + +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_hg b/Functions/VCS_Info/Backends/VCS_INFO_get_data_hg index 8e91d2651..a1b87f59e 100644 --- a/Functions/VCS_Info/Backends/VCS_INFO_get_data_hg +++ b/Functions/VCS_Info/Backends/VCS_INFO_get_data_hg @@ -50,7 +50,7 @@ if zstyle -t ":vcs_info:${vcs}:${usercontext}:${rrn}" get-revision ; then "check-for-changes" || hgid_args+=( -r. ) local HGRCPATH - HGRCPATH="/dev/null" ${vcs_comm[cmd]} ${(z)hgid_args} \ + HGRCPATH="/dev/null" ${vcs_comm[cmd]} ${(z)hgid_args} 2> /dev/null \ | read -r r_csetid r_lrev r_branch fi fi diff --git a/Functions/VCS_Info/VCS_INFO_bydir_detect b/Functions/VCS_Info/VCS_INFO_bydir_detect index 0b5996fd8..70b0fb6fa 100644 --- a/Functions/VCS_Info/VCS_INFO_bydir_detect +++ b/Functions/VCS_Info/VCS_INFO_bydir_detect @@ -4,15 +4,17 @@ setopt localoptions NO_shwordsplit local dirname=$1 -local basedir="." realbasedir +local basedir="." realbasedir file realbasedir="$(VCS_INFO_realpath ${basedir})" while [[ ${realbasedir} != '/' ]]; do [[ -r ${realbasedir} ]] || return 1 if [[ -n ${vcs_comm[detect_need_file]} ]] ; then - [[ -d ${basedir}/${dirname} ]] && \ - [[ -e ${basedir}/${dirname}/${vcs_comm[detect_need_file]} ]] && \ - break + [[ -d ${basedir}/${dirname} ]] && { + for file in ${(s: :)${vcs_comm[detect_need_file]}}; do + [[ -e ${basedir}/${dirname}/${file} ]] && break 2 + done + } else [[ -d ${basedir}/${dirname} ]] && break fi diff --git a/Functions/VCS_Info/VCS_INFO_hook b/Functions/VCS_Info/VCS_INFO_hook index 7274d726f..479f5968b 100644 --- a/Functions/VCS_Info/VCS_INFO_hook +++ b/Functions/VCS_Info/VCS_INFO_hook @@ -2,24 +2,36 @@ ## Written by Frank Terbeck <ft@bewatermyfriend.org> ## Distributed under the same BSD-ish license as zsh itself. -local hook func +local hook static func local -x context hook_name local -xi ret -local -a hooks +local -a hooks tmp local -i debug ret=0 hook_name="$1" shift context=":vcs_info:${vcs}+${hook_name}:${usercontext}:${rrn}" +static=":vcs_info-static_hooks:${hook_name}" zstyle -t "${context}" debug && debug=1 || debug=0 if (( debug )); then printf 'VCS_INFO_hook: running hook: "%s"\n' "${hook_name}" printf 'VCS_INFO_hook: current context: "%s"\n' "${context}" + printf 'VCS_INFO_hook: static context: "%s"\n' "${static}" fi -zstyle -a "${context}" hooks hooks || return 0 +zstyle -a "${static}" hooks hooks +if (( debug )); then + printf '+ static hooks: %s\n' "${(j:, :)hooks}" +fi +zstyle -a "${context}" hooks tmp +if (( debug )); then + printf '+ context hooks: %s\n' "${(j:, :)tmp}" +fi +hooks+=( "${tmp[@]}" ) +(( ${#hooks} == 0 )) && return 0 + # Protect some internal variables in hooks. The `-g' parameter to # typeset does *not* make the parameters global here (they are already # "*-local-export). It prevents typeset from creating *new* *local* diff --git a/Functions/VCS_Info/VCS_INFO_set b/Functions/VCS_Info/VCS_INFO_set index a2b838cdb..5087be43f 100644 --- a/Functions/VCS_Info/VCS_INFO_set +++ b/Functions/VCS_Info/VCS_INFO_set @@ -5,17 +5,13 @@ setopt localoptions noksharrays NO_shwordsplit local -i i j -if [[ $1 == '--clear' ]] ; then - for i in {0..9} ; do - unset vcs_info_msg_${i}_ - done -fi if [[ $1 == '--nvcs' ]] ; then [[ $2 == '-preinit-' ]] && (( maxexports == 0 )) && (( maxexports = 1 )) for i in {0..$((maxexports - 1))} ; do typeset -gx vcs_info_msg_${i}_= done VCS_INFO_nvcsformats $2 + [[ $2 != '-preinit-' ]] && VCS_INFO_hook "no-vcs" fi (( ${#msgs} - 1 < 0 )) && return 0 diff --git a/Functions/VCS_Info/vcs_info b/Functions/VCS_Info/vcs_info index 6ce1cd702..513489b70 100644 --- a/Functions/VCS_Info/vcs_info +++ b/Functions/VCS_Info/vcs_info @@ -26,6 +26,8 @@ static_functions=( VCS_INFO_reposub VCS_INFO_set + vcs_info_hookadd + vcs_info_hookdel vcs_info_lastmsg vcs_info_printsys vcs_info_setsys @@ -35,6 +37,7 @@ for func in ${static_functions} ; do autoload -Uz ${func} done +[[ -n ${(Mk)parameters:#vcs_info_msg_<->_} ]] && unset ${parameters[(I)vcs_info_msg_<->_]} VCS_INFO_set --nvcs '-preinit-' vcs_info_setsys @@ -75,7 +78,7 @@ vcs_info () { (( ${#enabled} == 0 )) && enabled=( all ) if [[ -n ${(M)enabled:#(#i)none} ]] ; then - [[ -n ${vcs_info_msg_0_} ]] && VCS_INFO_set --clear + [[ -n ${vcs_info_msg_0_} ]] && VCS_INFO_set --nvcs return 0 fi @@ -88,7 +91,7 @@ vcs_info () { for pat in ${dps} ; do if [[ ${PWD} == ${~pat} ]] ; then - [[ -n ${vcs_info_msg_0_} ]] && VCS_INFO_set --clear + [[ -n ${vcs_info_msg_0_} ]] && VCS_INFO_set --nvcs return 0 fi done diff --git a/Functions/VCS_Info/vcs_info_hookadd b/Functions/VCS_Info/vcs_info_hookadd new file mode 100644 index 000000000..867f7e271 --- /dev/null +++ b/Functions/VCS_Info/vcs_info_hookadd @@ -0,0 +1,22 @@ +## vim:ft=zsh +## Written by Frank Terbeck <ft@bewatermyfriend.org> +## Distributed under the same BSD-ish license as zsh itself. + +emulate -L zsh +setopt extendedglob + +if (( ${#argv} < 2 )); then + print 'usage: vcs_info_hookadd <HOOK> <FUNCTION(s)...>' + return 1 +fi + +local hook func context +local -a old + +hook=$1 +shift +context=":vcs_info-static_hooks:${hook}" + +zstyle -a "${context}" hooks old +zstyle "${context}" hooks "${old[@]}" "$@" +return $? diff --git a/Functions/VCS_Info/vcs_info_hookdel b/Functions/VCS_Info/vcs_info_hookdel new file mode 100644 index 000000000..e09a0575e --- /dev/null +++ b/Functions/VCS_Info/vcs_info_hookdel @@ -0,0 +1,45 @@ +## vim:ft=zsh +## Written by Frank Terbeck <ft@bewatermyfriend.org> +## Distributed under the same BSD-ish license as zsh itself. + +emulate -L zsh +setopt extendedglob + +local -i all + +if [[ "x$1" == 'x-a' ]]; then + all=1 + shift +else + all=0 +fi + +if (( ${#argv} < 2 )); then + print 'usage: vcs_info_hookdel [-a] <HOOK> <FUNCTION(s)...>' + return 1 +fi + +local hook func context +local -a old + +hook=$1 +shift +context=":vcs_info-static_hooks:${hook}" + +zstyle -a "${context}" hooks old || return 0 +for func in "$@"; do + if [[ -n ${(M)old:#$func} ]]; then + old[(Re)$func]=() + else + printf 'Not statically registered to `%s'\'': "%s"\n' \ + "${hook}" "${func}" + continue + fi + if (( all )); then + while [[ -n ${(M)old:#$func} ]]; do + old[(Re)$func]=() + done + fi +done +zstyle "${context}" hooks "${old[@]}" +return $? diff --git a/Functions/Zftp/zfcput b/Functions/Zftp/zfcput index d8a8a60a3..85141b68d 100644 --- a/Functions/Zftp/zfcput +++ b/Functions/Zftp/zfcput @@ -23,7 +23,7 @@ if [[ $(echo abcd | tail +2c) = bcd ]]; then elif [[ $(echo abcd | tail --bytes=+2) = bcd ]]; then tailtype=b else - print "I can't get your \`tail' to start from from arbitrary characters.\n" \ + print "I can't get your \`tail' to start from arbitrary characters.\n" \ "If you know how to do this, let me know." 2>&1 return 1 fi diff --git a/Functions/Zle/.distfiles b/Functions/Zle/.distfiles index 2ec4adc22..22eef1e6e 100644 --- a/Functions/Zle/.distfiles +++ b/Functions/Zle/.distfiles @@ -33,6 +33,7 @@ read-from-minibuffer replace-string replace-string-again select-word-style +send-invisible smart-insert-last-word split-shell-arguments transpose-lines diff --git a/Functions/Zle/modify-current-argument b/Functions/Zle/modify-current-argument index 92ca7bdab..92851d600 100644 --- a/Functions/Zle/modify-current-argument +++ b/Functions/Zle/modify-current-argument @@ -14,7 +14,7 @@ setopt localoptions noksharrays multibyte local -a reply -integer REPLY REPLY2 +integer REPLY REPLY2 fromend endoffset autoload -Uz split-shell-arguments split-shell-arguments @@ -30,6 +30,13 @@ if (( REPLY & 1 )); then (( REPLY2 = ${#reply[REPLY]} + 1 )) fi +# Work out offset from end of string +(( fromend = $REPLY2 - ${#reply[REPLY]} - 1 )) +if (( fromend >= -1 )); then + # Cursor is near the end of the word, we'll try to keep it there. + endoffset=1 +fi + # Length of all characters before current. # Force use of character (not index) counting and join without IFS. integer wordoff="${(cj..)#reply[1,REPLY-1]}" @@ -37,15 +44,32 @@ integer wordoff="${(cj..)#reply[1,REPLY-1]}" # Replacement for current word. This could do anything to ${reply[REPLY]}. local ARG="${reply[REPLY]}" repl eval repl=\"$1\" + +if (( !endoffset )) && [[ ${repl[fromend,-1]} = ${ARG[fromend,-1]} ]]; then + # If the part of the string from here to the end hasn't changed, + # leave the cursor this distance from the end instead of the beginning. + endoffset=1 +fi + # New line: all words before and after current word, with # no additional spaces since we've already got the whitespace # and the replacement word in the middle. -BUFFER="${(j..)reply[1,REPLY-1]}${repl}${(j..)reply[REPLY+1,-1]}" - -# Keep cursor at same position in replaced word. -# Redundant here, but useful if $repl changes the length. -# Limit to the next position after the end of the word. -integer repmax=$(( ${#repl} + 1 )) -# Remember CURSOR starts from offset 0 for some reason, so -# subtract 1 from positions. -(( CURSOR = wordoff + (REPLY2 > repmax ? repmax : REPLY2) - 1 )) +local left="${(j..)reply[1,REPLY-1]}${repl}" +local right="${(j..)reply[REPLY+1,-1]}" + +if [[ endoffset -ne 0 && ${#repl} -ne 0 ]]; then + # Place cursor relative to end. + LBUFFER="$left" + RBUFFER="$right" + (( CURSOR += fromend )) +else + BUFFER="$left$right" + + # Keep cursor at same position in replaced word. + # Redundant here, but useful if $repl changes the length. + # Limit to the next position after the end of the word. + integer repmax=$(( ${#repl} + 1 )) + # Remember CURSOR starts from offset 0 for some reason, so + # subtract 1 from positions. + (( CURSOR = wordoff + (REPLY2 > repmax ? repmax : REPLY2) - 1 )) +fi diff --git a/Functions/Zle/send-invisible b/Functions/Zle/send-invisible new file mode 100644 index 000000000..d31fc76ae --- /dev/null +++ b/Functions/Zle/send-invisible @@ -0,0 +1,85 @@ +#autoload + +# send-invisible reads a line from the terminal, displaying an +# asterisk for each character typed. It stores the line in the +# global variable INVISIBLE, and when finished reading, inserts +# the string ${INVISIBLE} into the original command buffer. + +# If one argument is given, it is the prompt. The default is +# "Non-echoed text: " + +# If two or three arguments are given, they form the prefix and +# suffix of the inserted INVISIBLE. Defaults are '${' and '}' +# but these can be replaced, for example with '"${' and '}"' to +# enclose the whole word in double quotes, or '${(z)' and '}' to +# split the value of $INVISIBLE like the shell parser. + +# To use: +# autoload -Uz send-invisible +# zle -N send-invisible +# bindkey '^X ' send-invisible +# Or more elaborately: +# hidden-command() { send-invisible '% ' '${(z)' '}' } +# zle -N hidden-command +# bindkey '^X%' hidden-command + +# Shamelessly cribbed from read-from-minibuffer. + +emulate -L zsh + +# Hide the value of INVISIBLE in any output of set and typeset +typeset -g -H INVISIBLE= + +local pretext="$PREDISPLAY$LBUFFER$RBUFFER$POSTDISPLAY"$'\n' + +# Can't directly make these locals because send-invisible is +# called as a widget, so these special variables are already +# local at the current level and wouldn't get restored +local save_lbuffer=$LBUFFER +local save_rbuffer=$RBUFFER +local save_predisplay=$PREDISPLAY +local save_postdisplay=$POSTDISPLAY +local -a save_region_highlight +save_region_highlight=("${region_highlight[@]}") + +{ + local lb rb opn=${2:-'${'} cls=${3:-'}'} + LBUFFER= + RBUFFER= + PREDISPLAY="$pretext${1:-Non-echoed text: }" + POSTDISPLAY= + region_highlight=("P${(m)#pretext} ${(m)#PREDISPLAY} bold") + + while zle -R && zle .read-command + do + # There are probably more commands that should go into + # the first clause here to harmlessly beep, because ... + case $REPLY in + (send-invisible|run-help|undefined-key|where-is|which-command) + zle .beep;; + (push-*|send-break) INVISIBLE=;& + (accept-*) break;; + (*) + LBUFFER=$lb + RBUFFER=$rb + zle $REPLY # ... this could expose something + lb=$LBUFFER + rb=$RBUFFER + INVISIBLE=$BUFFER + LBUFFER=${(l:$#LBUFFER::*:):-} + RBUFFER=${(l:$#RBUFFER::*:):-} + ;; + esac + done +} always { + LBUFFER=$save_lbuffer + RBUFFER=$save_rbuffer + PREDISPLAY=$save_predisplay + POSTDISPLAY=$save_postdisplay + region_highlight=("${save_region_highlight[@]}") + zle -R + + # Now that the highlight has been restored with all the old + # text and cursor positioning, insert the new text. + LBUFFER+=${INVISIBLE:+${opn}INVISIBLE${cls}} +} diff --git a/Functions/Zle/split-shell-arguments b/Functions/Zle/split-shell-arguments index ee737a067..32b04fcb5 100644 --- a/Functions/Zle/split-shell-arguments +++ b/Functions/Zle/split-shell-arguments @@ -15,7 +15,7 @@ local -a bufwords lbufwords local word integer pos=1 cpos=$((CURSOR+1)) opos iword ichar -bufwords=(${(z)BUFFER}) +bufwords=(${(Z+n+)BUFFER}) reply=() while [[ ${BUFFER[pos]} = [[:space:]] ]]; do |