# Match words by the style given below. The matching depends on the # cursor position. The matched_words array is set to the matched portions # separately. These look like: # # # # 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. # For example # foo bar rod stick # ^ # with the cursor where indicated will with typical settings produce the # elements `foo ', `bar', ` ', ` ', `rod', ` ' and `stick'. # # The style word-style can be set to indicate what a word is. # The three possibilities are: # # shell Words are shell words, i.e. elements of a command line. # whitespace Words are space delimited words; only space or tab characters # are considered to terminated a word. # normal (the default): the usual zle logic is applied, with all # alphanumeric characters plus any characters in $WORDCHARS # considered parts of a word. The style word-chars overrides # the parameter. (Any currently undefined value will be # treated as `normal', but this should not be relied upon.) # specified Similar to normal, except that only the words given # in the string (and not also alphanumeric characters) # are to be considered parts of words. # unspecified The negation of `specified': the characters given # are those that aren't to be considered parts of a word. # They should probably include white space. # # In the case of the `normal' or `(un)specified', more control on the # behaviour can be obtained by setting the style `word-chars' for the # current context. The value is used to override $WORDCHARS locally. # Hence, # zstyle ':zle:transpose-words*' word-style normal # zstyle ':zle:transpose-words*' word-chars '' # will force bash-style word recognition, i.e only alphanumeric characters # are considered parts of a word. It is up to the function which calls # match-words-by-style to set the context in the variable curcontext, # else a default context will be used (not recommended). # # You can override the use of word-chars with the style word-class. # This specifies the same information, but as a character class. # The surrounding square brackets shouldn't be given, but anything # which can appear inside is allowed. For example, # zstyle ':zle:*' word-class '-:[:alnum:]' # is valid. Note the usual care with `]' , `^' and `-' must be taken if # they need to appear as individual characters rather than for grouping. # # The final style is `skip-chars'. This is an integer; that many # characters counting the one under the cursor will be treated as # whitespace regardless and added to the front of the fourth element of # matched_words. The default is zero, i.e. the character under the cursor # will appear in if it is whitespace, else in # . This style is mostly useful for forcing # transposition to ignore the current character. emulate -L zsh setopt extendedglob local wordstyle spacepat wordpat1 wordpat2 opt charskip local match mbegin mend pat1 pat2 word1 word2 ws1 ws2 ws3 skip local MATCH MBEGIN MEND if [[ -z $curcontext ]]; then local curcontext=:zle:match-words-by-style fi zstyle -s $curcontext word-style wordstyle zstyle -s $curcontext skip-chars skip [[ -z $skip ]] && skip=0 case $wordstyle in (shell) local bufwords # This splits the line into words as the shell understands them. bufwords=(${(z)LBUFFER}) # Work around bug: if stripping quotes failed, a bogus # space is appended. Not a good test, since this may # be a quoted space, but it's hard to get right. wordpat1=${bufwords[-1]} if [[ ${wordpat1[-1]} = ' ' ]]; then wordpat1=${(q)wordpat1[1,-2]} else wordpat1="${(q)wordpat1}" fi # Take substring of RBUFFER to skip over $skip characters # from the cursor position. bufwords=(${(z)RBUFFER[1+$skip,-1]}) # Work around bug again. wordpat2=${bufwords[1]} if [[ ${wordpat2[-1]} = ' ' ]] then wordpat2=${(q)wordpat2[1,-2]} else wordpat2="${(q)wordpat2}" fi spacepat='[[:space:]]#' ;; (*space) spacepat='[[:space:]]#' wordpat1='[^[:space:]]##' wordpat2=$wordpat1 ;; (*) local wc # See if there is a character class. if zstyle -s $curcontext word-class wc; then # Treat as a character class: do minimal quoting. wc=${wc//(#m)[\'\"\`\$\(\)\^]/\\$MATCH} else # See if there is a local version of $WORDCHARS. zstyle -s $curcontext word-chars wc || wc=$WORDCHARS if [[ $wc = (#b)(?*)-(*) ]]; then # We need to bring any `-' to the front to avoid confusing # character classes... we get away with `]' since in zsh # this isn't a pattern character if it's quoted. wc=-$match[1]$match[2] fi wc="${(q)wc}" fi # Quote $wc where necessary, because we don't want those # characters to be considered as pattern characters later on. if [[ $wordstyle = *specified ]]; then if [[ $wordstyle != un* ]]; then # The given set of characters are the word characters, nothing else wordpat1="[${wc}]##" # anything else is a space. spacepat="[^${wc}]#" else # The other way round. wordpat1="[^${wc}]##" spacepat="[${wc}]#" fi else # Normal: similar, but add alphanumerics. wordpat1="[${wc}[:alnum:]]##" spacepat="[^${wc}[:alnum:]]#" fi wordpat2=$wordpat1 ;; esac # The eval makes any special characters in the parameters active. # In particular, we need the surrounding `[' s to be `real'. # This is why we quoted the wordpats in the `shell' option, where # they have to be treated as literal strings at this point. match=() eval pat1='${LBUFFER%%(#b)('${wordpat1}')('${spacepat}')}' word1=$match[1] ws1=$match[2] match=() charskip= repeat $skip charskip+=\? eval pat2='${RBUFFER##(#b)('${charskip}${spacepat}')('\ ${wordpat2}')('${spacepat}')}' ws2=$match[1] word2=$match[2] ws3=$match[3] matched_words=("$pat1" "$word1" "$ws1" "$ws2" "$word2" "$ws3" "$pat2")