summaryrefslogtreecommitdiff
path: root/Functions/Zle/match-words-by-style
diff options
context:
space:
mode:
authorPeter Stephenson <pws@users.sourceforge.net>2003-03-28 11:34:07 +0000
committerPeter Stephenson <pws@users.sourceforge.net>2003-03-28 11:34:07 +0000
commit1e57c42f470bdd2ab6179ec44dae96fd3377a1dd (patch)
tree5f9c38c21bcbbcba7b7524f9df7e4f99b8344424 /Functions/Zle/match-words-by-style
parent2941469f616202f51da7ba9ceafa3f419f34573b (diff)
downloadzsh-1e57c42f470bdd2ab6179ec44dae96fd3377a1dd.tar.gz
zsh-1e57c42f470bdd2ab6179ec44dae96fd3377a1dd.zip
18394: New word movement and editing widgets.
Diffstat (limited to 'Functions/Zle/match-words-by-style')
-rw-r--r--Functions/Zle/match-words-by-style167
1 files changed, 167 insertions, 0 deletions
diff --git a/Functions/Zle/match-words-by-style b/Functions/Zle/match-words-by-style
new file mode 100644
index 000000000..9dcc165a9
--- /dev/null
+++ b/Functions/Zle/match-words-by-style
@@ -0,0 +1,167 @@
+# 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:
+# <stuff-at-start> <word-before-cursor> <whitespace-before-cursor>
+# <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.
+# For example
+# foo bar rod stick
+# ^
+# with the cursor where indicated whill 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 considerd 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 considerd 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 <whitespace-after-cursor> if it is whitespace, else in
+# <word-after-cursor>. 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")