diff options
author | Axel Beckert <abe@deuxchevaux.org> | 2016-12-04 04:32:03 +0100 |
---|---|---|
committer | Axel Beckert <abe@deuxchevaux.org> | 2016-12-04 04:32:03 +0100 |
commit | 3e439c3863f14c82f70666804c8570a13b3732e6 (patch) | |
tree | 07036c43e0f3f9242bb6dd42cd2a849ec8ea8aca /Functions/Zle | |
parent | 2aedc4b88fd0e87b89583983951b04b96f48efd3 (diff) | |
parent | 7b7e84f0815ed22a0ee348a217776529035dccf3 (diff) | |
download | zsh-3e439c3863f14c82f70666804c8570a13b3732e6.tar.gz zsh-3e439c3863f14c82f70666804c8570a13b3732e6.zip |
Merge tag 'zsh-5.2-test-1' into debian
Diffstat (limited to 'Functions/Zle')
-rw-r--r-- | Functions/Zle/bracketed-paste-magic | 54 | ||||
-rw-r--r-- | Functions/Zle/bracketed-paste-url-magic | 4 | ||||
-rw-r--r-- | Functions/Zle/delete-whole-word-match | 15 | ||||
-rw-r--r-- | Functions/Zle/expand-absolute-path | 2 | ||||
-rw-r--r-- | Functions/Zle/history-beginning-search-menu | 2 | ||||
-rw-r--r-- | Functions/Zle/match-words-by-style | 53 | ||||
-rw-r--r-- | Functions/Zle/select-bracketed | 2 | ||||
-rw-r--r-- | Functions/Zle/select-word-match | 120 | ||||
-rw-r--r-- | Functions/Zle/surround | 7 | ||||
-rw-r--r-- | Functions/Zle/vi-pipe | 39 | ||||
-rw-r--r-- | Functions/Zle/zcalc-auto-insert | 3 |
11 files changed, 249 insertions, 52 deletions
diff --git a/Functions/Zle/bracketed-paste-magic b/Functions/Zle/bracketed-paste-magic index 2b2bc630d..fb584d595 100644 --- a/Functions/Zle/bracketed-paste-magic +++ b/Functions/Zle/bracketed-paste-magic @@ -20,7 +20,7 @@ # 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. +# paste. All other key sequences are processed as "zle .self-insert". # 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 @@ -31,7 +31,7 @@ # # 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. +# always use "zle .self-insert" 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. # @@ -145,27 +145,26 @@ bracketed-paste-magic() { 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 - + # Save context, create a clean slate for the paste + integer bpm_mark=$MARK bpm_region=$REGION_ACTIVE + integer bpm_numeric=${NUMERIC:-1} + integer bpm_limit=$UNDO_LIMIT_NO bpm_undo=$UNDO_CHANGE_NO + BUFFER= + CURSOR=1 + zle .split-undo + UNDO_LIMIT_NO=$UNDO_CHANGE_NO + fc -p -a /dev/null 0 0 if [[ $bmp_keymap = vicmd ]]; then zle -K viins fi + # There are active widgets. Reprocess $PASTED as keystrokes. + NUMERIC=1 + zle -U - "$PASTED" + # Just in case there are active undo widgets - zle .split-undo - integer bpm_limit=$UNDO_LIMIT_NO bpm_undo=$UNDO_CHANGE_NO - UNDO_LIMIT_NO=$UNDO_CHANGE_NO while [[ -n $PASTED ]] && zle .read-command; do PASTED=${PASTED#$KEYS} @@ -175,7 +174,7 @@ bracketed-paste-magic() { case $REPLY in (${~bpm_active}) function () { emulate -L $bpm_emulate; set -$bpm_opts - zle $REPLY + zle $REPLY -w };; (*) zle .self-insert;; esac @@ -183,21 +182,16 @@ bracketed-paste-magic() { done PASTED=$BUFFER - # Reset the undo state - zle undo $bpm_undo - UNDO_LIMIT_NO=$bpm_limit - + # Restore state zle -K $bpm_keymap + fc -P + MARK=$bpm_mark + REGION_ACTIVE=$bpm_region + NUMERIC=$bpm_numeric + zle .undo $bpm_undo + UNDO_LIMIT_NO=$bpm_limit 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 @@ -212,7 +206,7 @@ bracketed-paste-magic() { # Reprocess $PASTED as an actual paste this time zle -U - $PASTED$'\e[201~' # append paste-end marker - zle .bracketed-paste + zle .bracketed-paste -- "$@" zle .split-undo # Arrange to display highlighting if necessary diff --git a/Functions/Zle/bracketed-paste-url-magic b/Functions/Zle/bracketed-paste-url-magic index 06dee2657..b894696bb 100644 --- a/Functions/Zle/bracketed-paste-url-magic +++ b/Functions/Zle/bracketed-paste-url-magic @@ -19,7 +19,7 @@ # 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) +zstyle -a :bracketed-paste-url-magic schema schema || schema=(http:// https:// ftp:// ftps:// file:// ssh:// sftp:// magnet:) local wantquote=${NUMERIC:-0} local content @@ -28,7 +28,7 @@ local start=$#LBUFFER zle .$WIDGET -N content if (( $wantquote == 0 )); then - if [[ $content = (${(~j:|:)schema})://* ]]; then + if [[ $content = (${(~j:|:)schema})* ]]; then wantquote=1 fi fi diff --git a/Functions/Zle/delete-whole-word-match b/Functions/Zle/delete-whole-word-match index aece86065..3d52dd3d7 100644 --- a/Functions/Zle/delete-whole-word-match +++ b/Functions/Zle/delete-whole-word-match @@ -12,30 +12,29 @@ emulate -L zsh setopt extendedglob local curcontext=:zle:$WIDGET -local -a matched_words +local -A matched_words # Start and end of range of characters to remove. integer pos1 pos2 autoload -Uz match-words-by-style match-words-by-style -if [[ -n "${matched_words[3]}" ]]; then - # There's whitespace before the cursor, so the word we are deleting - # starts at the cursor position. +if (( ${matched_words[is-word-start]} )); then + # The word we are deleting starts at the cursor position. pos1=$CURSOR else - # No whitespace before us, so delete any wordcharacters there. - pos1="${#matched_words[1]}" + # Not, so delete any wordcharacters before, too + pos1="${#matched_words[start]}" fi -if [[ -n "${matched_words[4]}" ]]; then +if [[ -n "${matched_words[ws-after-cursor]}" ]]; then # There's whitespace at the cursor position, so only delete # up to the cursor position. (( pos2 = CURSOR + 1 )) else # No whitespace at the cursor position, so delete the # current character and any following wordcharacters. - (( pos2 = CURSOR + ${#matched_words[5]} + 1 )) + (( pos2 = CURSOR + ${#matched_words[word-after-cursor]} + 1 )) fi # Move the cursor then delete the block in one go for the diff --git a/Functions/Zle/expand-absolute-path b/Functions/Zle/expand-absolute-path index b85757600..4887f3c60 100644 --- a/Functions/Zle/expand-absolute-path +++ b/Functions/Zle/expand-absolute-path @@ -10,7 +10,7 @@ autoload -Uz modify-current-argument if (( ! ${+functions[glob-expand-absolute-path]} )); then glob-expand-absolute-path() { local -a files - files=(${~1}(N:A)) + files=(${~1}(N:P)) (( ${#files} )) || return REPLY=${(D)files[1]} } diff --git a/Functions/Zle/history-beginning-search-menu b/Functions/Zle/history-beginning-search-menu index 105518102..0e1bbc734 100644 --- a/Functions/Zle/history-beginning-search-menu +++ b/Functions/Zle/history-beginning-search-menu @@ -112,7 +112,7 @@ fi # go to the last one. This allows accept-line-and-down-history etc. # to work. local -a lines -local matchq=${matches[$chars]//(#m)[\][()\\*?#<>~^]/\\$MATCH} +local matchq=${matches[$chars]//(#m)[\][|()\\*?#<>~^]/\\$MATCH} lines=(${(kon)history[(R)$matchq]}) HISTNO=$lines[-1] diff --git a/Functions/Zle/match-words-by-style b/Functions/Zle/match-words-by-style index 54e019d23..fc59c2764 100644 --- a/Functions/Zle/match-words-by-style +++ b/Functions/Zle/match-words-by-style @@ -5,8 +5,16 @@ # <whitespace-after-cursor> <word-after-cursor> <whitespace-after-word> # <stuff-at-end> # where the cursor position is always after the third item and `after' -# is to be interpreted as `after or on'. Some -# of the array elements will be empty; this depends on the style. +# is to be interpreted as `after or on'. +# +# matched_words may be an associative array, in which case the +# values above are now given by the elements named start, word-before-cursor, +# ws-before-cursor, ws-after-cursor, word-after-cursor, ws-after-word, +# end. In addition, the element is-word-start is 1 if the cursor +# is on the start of a word; this is non-trivial in the case of subword +# (camel case) matching as there may be no white space to test. +# +# Some of the array elements will be empty; this depends on the style. # For example # foo bar rod stick # ^ @@ -202,7 +210,7 @@ if [[ $wordstyle = *subword* ]]; then # followed by a lower case letter, or an upper case letter at # the start of a group of upper case letters. To make # it easier to be consistent, we just use anything that - # isn't an upper case characer instead of a lower case + # isn't an upper case character instead of a lower case # character. # Here the initial "*" will match greedily, so we get the # last such match, as we want. @@ -224,11 +232,18 @@ charskip=${(l:skip::?:)} eval pat2='${RBUFFER##(#b)('${charskip}${spacepat}')('\ ${wordpat2}')('${spacepat}')}' +if [[ -n $match[2] ]]; then + ws2=$match[1] + word2=$match[2] + ws3=$match[3] +else + # No more words, so anything left is white space after cursor. + ws2=$RBUFFER + pat2= +fi -ws2=$match[1] -word2=$match[2] -ws3=$match[3] - +integer wordstart +[[ ( -n $ws1 || -n $ws2 ) && -n $word2 ]] && wordstart=1 if [[ $wordstyle = *subword* ]]; then # Do we have a group of upper case characters at the start # of word2 (that don't form the entire word)? @@ -237,12 +252,19 @@ if [[ $wordstyle = *subword* ]]; then -n $match[2] ]]; then # Yes, so the last one is new word boundary. (( epos = ${#match[1]} - 1 )) + # Otherwise, are we in the middle of a word? + # In other, er, words, we've got something on the left with no + # white space following and something that doesn't start a word here. + elif [[ -n $word1 && -z $ws1 && -z $ws2 && \ + $word2 = (#b)([^${~subwordrange}]##)* ]]; then + (( epos = ${#match[1]} )) # Otherwise, do we have upper followed by non-upper not # at the start? Ignore the initial character, we already # know it's a word boundary so it can be an upper case character # if it wants. elif [[ $word2 = (#b)(?[^${~subwordrange}]##)[${~subwordrange}]* ]]; then (( epos = ${#match[1]} )) + (( wordstart = 1 )) else (( epos = 0 )) fi @@ -256,4 +278,19 @@ if [[ $wordstyle = *subword* ]]; then fi fi -matched_words=("$pat1" "$word1" "$ws1" "$ws2" "$word2" "$ws3" "$pat2") +# matched_words should be local to caller. +# Just fix type here. +if [[ ${(t)matched_words} = *association* ]]; then + matched_words=( + start "$pat1" + word-before-cursor "$word1" + ws-before-cursor "$ws1" + ws-after-cursor "$ws2" + word-after-cursor "$word2" + ws-after-word "$ws3" + end "$pat2" + is-word-start $wordstart + ) +else + matched_words=("$pat1" "$word1" "$ws1" "$ws2" "$word2" "$ws3" "$pat2") +fi diff --git a/Functions/Zle/select-bracketed b/Functions/Zle/select-bracketed index 00f51be2c..d467bb804 100644 --- a/Functions/Zle/select-bracketed +++ b/Functions/Zle/select-bracketed @@ -12,6 +12,8 @@ # done # done +setopt localoptions noksharrays + local style=${${1:-$KEYS}[1]} matching="(){}[]<>bbBB" local -i find=${NUMERIC:-1} idx=${matching[(I)[${${1:-$KEYS}[2]}]]}%9 (( idx )) || return 1 # no corresponding closing bracket diff --git a/Functions/Zle/select-word-match b/Functions/Zle/select-word-match new file mode 100644 index 000000000..8440852ab --- /dev/null +++ b/Functions/Zle/select-word-match @@ -0,0 +1,120 @@ +# Select the entire word around the cursor. Intended for use as +# a vim-style text object in vi mode but with customisable +# word boundaries. +# +# For example: +# autoload -U select-word-match +# zle -N select-in-camel select-word-match +# bindkey -M viopp ic select-in-camel +# zstyle ':zle:*-camel' word-style normal-subword + +emulate -L zsh +setopt extendedglob + +local curcontext=:zle:$WIDGET +local -A matched_words +# Start and end of range of characters +integer pos1 pos2 num=${NUMERIC:-1} +local style word + +# choose between inner word or a word style of widget +for style in $1 ${${WIDGET#*-}[1]} $KEYS[1] "i"; do + [[ $style = [ai] ]] && break +done + +autoload -Uz match-words-by-style + +while (( num-- )); do + if (( MARK > CURSOR )); then + # if cursor is at the start of the selection, just move back a word + match-words-by-style + if [[ $style = i && -n $matched_words[ws-before-cursor] ]]; then + word=$matched_words[ws-before-cursor] + else + word=$matched_words[word-before-cursor]$matched_words[ws-before-cursor] + fi + if [[ -n $word ]]; then + (( CURSOR -= ${#word} )) + else + return 1 + fi + elif (( MARK >= 0 && MARK < CURSOR )); then + # cursor at the end, move forward a word + (( CURSOR+1 == $#BUFFER )) && return 1 + (( CURSOR++ )) + match-words-by-style + if [[ -n $matched_words[ws-after-cursor] ]]; then + if [[ $style = i ]]; then + # just skip the whitespace + word=$matched_words[ws-after-cursor] + else + # skip the whitespace plus word + word=$matched_words[ws-after-cursor]$matched_words[word-after-cursor] + fi + else + if [[ $style = i ]]; then + # skip the word + word=$matched_words[word-after-cursor] + else + # skip word and following whitespace + word=$matched_words[word-after-cursor]$matched_words[ws-after-word] + fi + fi + (( CURSOR += ${#word} - 1 )) + else + match-words-by-style + + if (( ${matched_words[is-word-start]} )); then + # The word we are selecting starts at the cursor position. + pos1=$CURSOR + else + # No whitespace before us, so select any wordcharacters there. + pos1="${#matched_words[start]}" + fi + + if [[ -n "${matched_words[ws-after-cursor]}" ]]; then + if [[ -n "${matched_words[ws-before-cursor]}" ]] || (( CURSOR == 0 )); then + # whitespace either side, select it + (( pos1 = CURSOR - ${#matched_words[ws-before-cursor]} )) + (( pos2 = CURSOR + ${#matched_words[ws-after-cursor]} )) + else + # There's whitespace at the cursor position, so only select + # up to the cursor position. + (( pos2 = CURSOR + 1 )) + fi + else + # No whitespace at the cursor position, so select the + # current character and any following wordcharacters. + (( pos2 = CURSOR + ${#matched_words[word-after-cursor]} )) + fi + + if [[ $style = a ]]; then + if [[ -n "${matched_words[ws-after-cursor]}" && ( -n "${matched_words[ws-before-cursor]}" || CURSOR -eq 0 ) ]]; then + # in the middle of whitespace so grab a word + if [[ -n "${matched_words[word-after-cursor]}" ]]; then + (( pos2 += ${#matched_words[word-after-cursor]} )) # preferably the one after + else + (( pos1 -= ${#matched_words[word-before-cursor]} )) # otherwise the one before + fi + elif [[ -n "${matched_words[ws-after-word]}" ]]; then + (( pos2 += ${#matched_words[ws-after-word]} )) + elif [[ -n "${matched_words[ws-before-cursor]}" ]]; then + # couldn't grab whitespace forwards so try backwards + (( pos1 -= ${#matched_words[ws-before-cursor]} )) + elif (( pos1 > 0 )); then + # There might have been whitespace before the word + (( CURSOR = pos1 )) + match-words-by-style + if [[ -n "${matched_words[ws-before-cursor]}" ]]; then + (( pos1 -= ${#matched_words[ws-before-cursor]} )) + fi + fi + fi + + (( MARK = pos1, CURSOR = pos2-1 )) + fi +done + +if [[ $KEYMAP == vicmd ]] && (( !REGION_ACTIVE )); then + (( CURSOR++ )) # Need to include cursor position for operators +fi diff --git a/Functions/Zle/surround b/Functions/Zle/surround index b7be30b75..b51b77c04 100644 --- a/Functions/Zle/surround +++ b/Functions/Zle/surround @@ -19,6 +19,7 @@ local before after local -A matching matching=( \( \) \{ \} \< \> \[ \] ) +zle -f vichange case $WIDGET in change-*) local MARK="$MARK" CURSOR="$CURSOR" call @@ -69,7 +70,11 @@ case $WIDGET in before="${(k)matching[(r)[$before:q]]}" fi CUTBUFFER="$before$CUTBUFFER$after" - zle .vi-put-after -n 1 + if [[ CURSOR -eq 0 || $BUFFER[CURSOR] = $'\n' ]]; then + zle .vi-put-before -n 1 + else + zle .vi-put-after -n 1 + fi CUTBUFFER="$save_cut" CURSOR="$save_cur" ;; esac diff --git a/Functions/Zle/vi-pipe b/Functions/Zle/vi-pipe new file mode 100644 index 000000000..1729cb6e1 --- /dev/null +++ b/Functions/Zle/vi-pipe @@ -0,0 +1,39 @@ +# Example of a widget that takes a vi motion + +# Filter part of buffer corresponding to a vi motion through an external +# program. + +# To enable with vi compatible bindings use: +# autoload -Uz vi-pipe +# bindkey -a '!' vi-pipe + +setopt localoptions noksharrays + +autoload -Uz read-from-minibuffer +local _save_cut="$CUTBUFFER" REPLY + +# mark this widget as a vi change so it can be repeated as a whole +zle -f vichange + +# force movement to default to line mode +(( REGION_ACTIVE )) || zle -U V +# Use the standard vi-change to accept a vi motion. +zle .vi-change || return +read-from-minibuffer "!" +zle .vi-cmd-mode +local _save_cur=$CURSOR + +# cut buffer contains the deleted text and can be modified +CUTBUFFER=$(eval "$REPLY" <<<"$CUTBUFFER") + +# put the modified text back in position. +if [[ CURSOR -eq 0 || $BUFFER[CURSOR] = $'\n' ]]; then + # at the beginning of a line, vi-delete won't have moved the cursor + # back to a previous line + zle .vi-put-before -n 1 +else + zle .vi-put-after -n 1 +fi + +# restore cut buffer and cursor to the start of the range +CUTBUFFER="$_save_cut" CURSOR="$_save_cur" diff --git a/Functions/Zle/zcalc-auto-insert b/Functions/Zle/zcalc-auto-insert index c9a5c8867..e1affd1c3 100644 --- a/Functions/Zle/zcalc-auto-insert +++ b/Functions/Zle/zcalc-auto-insert @@ -1,6 +1,7 @@ # Bind to a binary operator keystroke for use with zcalc +# Not useful in RPN mode. -if [[ -n $ZCALC_ACTIVE ]]; then +if [[ -n $ZCALC_ACTIVE && $ZCALC_ACTIVE != rpn ]]; then if [[ $CURSOR -eq 0 || $LBUFFER[-1] = "(" ]]; then LBUFFER+=${ZCALC_AUTO_INSERT_PREFIX:-"ans "} fi |