about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog6
-rw-r--r--Doc/Zsh/contrib.yo31
-rw-r--r--Functions/Zle/delete-whole-word-match56
3 files changed, 93 insertions, 0 deletions
diff --git a/ChangeLog b/ChangeLog
index 12c13cebb..e5a37217a 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,9 @@
+2003-10-13  Peter Stephenson  <pws@csr.com>
+
+	* 19183: Doc/Zsh/contrib.yo,
+	Functions/Zle/delete-whole-word-match:  New word-matching function
+	to delete entire word around cursor.
+
 2003-10-09  Oliver Kiddle  <opk@zsh.org>
 
 	* unposted: Completion/Unix/Command/_nmap: update for nmap 3.48
diff --git a/Doc/Zsh/contrib.yo b/Doc/Zsh/contrib.yo
index 82ed6da12..2648fd6c8 100644
--- a/Doc/Zsh/contrib.yo
+++ b/Doc/Zsh/contrib.yo
@@ -484,6 +484,21 @@ has been set, and tt(transpose-words-match) is called with the cursor on
 the var(X) of tt(foo)var(X)tt(bar), where var(X) can be any character, then
 the resulting expression is tt(bar)var(X)tt(foo).
 
+Here are some examples of use of the styles, actually taken from the
+simplified interface in tt(select-word-style):
+
+example(zstyle ':zle:*' word-style standard
+zstyle ':zle:*' word-chars '')
+
+Implements bash-style word handling for all widgets, i.e. only
+alphanumerics are word characters; equivalent to setting
+the parameter tt(WORDCHARS) empty for the given context.
+
+example(style ':zle:*kill*' word-style space)
+
+Uses space-delimited words for widgets with the word `kill' in the name.
+Neither of the styles tt(word-chars) nor tt(word-class) is used in this case.
+
 The word matching and all the handling of tt(zstyle) settings is actually
 implemented by the function tt(match-words-by-style).  This can be used to
 create new user-defined widgets.  The calling function should set the local
@@ -499,6 +514,22 @@ non-word characters following that word (7) the remainder of the line.  Any
 of the elements may be an empty string; the calling function should test
 for this to decide whether it can perform its function.
 )
+tindex(delete-whole-word-match)
+item(tt(delete-whole-word-match))(
+This is another function which works like the tt(-match) functions
+described immediately above, i.e. using styles to decide the word
+boundaries.  However, it is not a replacement for any existing function.
+
+The basic behaviour is to delete the word around the cursor.  There is no
+numeric prefix handling; only the single word around the cursor is
+considered.  If the widget contains the string tt(kill), the removed text
+will be placed in the cutbuffer for future yanking.  This can be obtained
+by defining tt(kill-whole-word-match) as follows:
+
+example(zle -N kill-whole-word-match delete-whole-word-match)
+
+and then binding the widget tt(kill-whole-word-match).
+)
 tindex(copy-earlier-word)
 item(tt(copy-earlier-word))(
 This widget works like a combination of tt(insert-last-word) and
diff --git a/Functions/Zle/delete-whole-word-match b/Functions/Zle/delete-whole-word-match
new file mode 100644
index 000000000..9f7b29128
--- /dev/null
+++ b/Functions/Zle/delete-whole-word-match
@@ -0,0 +1,56 @@
+# Delete the entire word around the cursor.  Does not handle
+# a prefix argument; either the cursor is in the word or it isn't.
+# The word may be just before the cursor, e.g.
+#   print this is a line
+#             ^ here
+# and then the word before (i.e. `this') will be deleted.
+#
+# If the widget has the name `kill' in, the text deleted will be
+# saved for future yanking in the normal way.
+
+emulate -L zsh
+setopt extendedglob
+
+local curcontext=:zle:delete-whole-word
+local -a matched_words
+# Start and end of range of characters to remove.
+integer pos1 pos2
+
+autoload -U 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.
+    pos1=$CURSOR
+else
+    # No whitespace before us, so delete any wordcharacters there.
+    pos1="${#matched_words[1]}"
+fi
+
+if [[ -n "${matched_words[4]}" ]]; then
+    # There's whitespace at the cursor position, so only delete
+    # up to the cursor position.
+    pos2=$CURSOR
+else
+    # No whitespace at the cursor position, so delete the
+    # current character and any following wordcharacters.
+    (( pos2 = CURSOR + ${#matched_words[5]} + 1 ))
+fi
+
+# Move the cursor then delete the block in one go for the
+# purpose of undoing (and yanking, if appropriate).
+(( CURSOR = pos1 ))
+
+# If the widget name includes the word `kill', the removed
+# text goes into the cutbuffer in the standard way.
+if [[ $WIDGET = *kill* ]]; then
+  local word="${BUFFER[pos1+1,pos2-1]}"
+  if [[ $LASTWIDGET = *kill* ]]; then
+    CUTBUFFER="$CUTBUFFER$word"
+  else
+    killring=("$CUTBUFFER" "${(@)killring[1,-2]}")
+    CUTBUFFER=$word
+  fi
+fi
+BUFFER="${BUFFER[1,pos1]}${BUFFER[pos2,-1]}"