about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog6
-rw-r--r--Doc/Zsh/contrib.yo52
-rw-r--r--Functions/Zle/read-from-minibuffer20
-rw-r--r--Functions/Zle/replace-string45
4 files changed, 123 insertions, 0 deletions
diff --git a/ChangeLog b/ChangeLog
index 174ca2c9d..b1313e12d 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,9 @@
+2003-02-03  Peter Stephenson  <pws@csr.com>
+
+	* 18174: Doc/Zsh/contrib.yo, Functions/Zle/read-from-minibuffer,
+	Functions/Zle/replace-string:  New widgets for reading values
+	during editing and for performing string and pattern replacements.
+
 2003-01-30  Clint Adams  <clint@zsh.org>
 
 	* unposted: config.guess, config.sub: update to 2003-01-10 and
diff --git a/Doc/Zsh/contrib.yo b/Doc/Zsh/contrib.yo
index 4f1995f6d..3dd398634 100644
--- a/Doc/Zsh/contrib.yo
+++ b/Doc/Zsh/contrib.yo
@@ -588,6 +588,58 @@ zle -N predict-off
 bindkey '^X^Z' predict-on
 bindkey '^Z' predict-off)
 )
+tindex(read-from-minibuffer)
+item(tt(read-from-minibuffer))(
+This is most useful when called as a function from inside a widget, but will
+work correctly as a widget in its own right.  It prompts for a value
+below the current command line; a value may be input using all of the
+standard zle operations (and not merely the restricted set available
+when executing, for example, tt(execute-named-cmd)).  The value is then
+returned to the calling function in the parameter tt($REPLY) and the
+editing buffer restored to its previous state.  If the read was aborted
+by a keyboard break (typically tt(^G)), the function returns status 1
+and tt($REPLY) is not set.  If an argument is supplied to the function
+it is taken as a prompt, otherwise `tt(? )' is used.
+
+The name is a slight misnomer, as in fact the shell's own minibuffer is
+not used.  Hence it is still possible to call tt(executed-named-cmd) and
+similar functions while reading a value.
+)
+tindex(replace-string)
+tindex(replace-pattern)
+item(tt(replace-string), tt(replace-pattern))(
+The function tt(replace-string) implements two widgets.
+If defined under the same name as the function, it prompts for two
+strings; the first (source) string will be replaced by the second
+everywhere it occurs in the line editing buffer.
+
+If the widget name contains the word `tt(pattern)', for example by
+defining the widget using the command `tt(zle -N replace-pattern
+replace-string)', then the replacement is done by pattern matching.  All
+zsh extended globbing patterns can be used in the source string; note
+that unlike filename generation the pattern does not need to match an
+entire word, nor do glob qualifiers have any effect.  In addition, the
+replacement string can contain parameter or command substitutions.
+Furthermore, a `tt(&)' in the replacement string will be replaced with
+the matched source string, and a backquoted digit `tt(\)var(N)' will be
+replaced by the var(N)th parenthesised expression matched.  The form
+`tt(\{)var(N)tt(})' may be used to protect the digit from following
+digits.
+
+For example, starting from the line:
+
+example(print This line contains fan and fond)
+
+and invoking tt(replace-pattern) with the source string `tt(f(?)n)' and
+the replacment string `tt(c\1r)' produces the not very useful line:
+
+example(print This line contains car and cord)
+
+The range of the replacement string can be limited by using the
+tt(narrow-to-region-invisible) widget.  One limitation of the current
+version is that tt(undo) will cycle through changes to the replacement
+and source strings before undoing the replacement itself.
+)
 tindex(smart-insert-last-word)
 item(tt(smart-insert-last-word))(
 This function may replace the tt(insert-last-word) widget, like so:
diff --git a/Functions/Zle/read-from-minibuffer b/Functions/Zle/read-from-minibuffer
new file mode 100644
index 000000000..93eec42a5
--- /dev/null
+++ b/Functions/Zle/read-from-minibuffer
@@ -0,0 +1,20 @@
+local savelbuffer=$LBUFFER saverbuffer=$RBUFFER
+local savepredisplay=$PREDISPLAY savepostdisplay=$POSTDISPLAY
+
+LBUFFER=
+RBUFFER=
+PREDISPLAY="$PREDISPLAY$savelbuffer$saverbuffer$POSTDISPLAY
+${1:-? }"
+POSTDISPLAY=
+
+zle recursive-edit
+integer stat=$?
+
+(( stat )) || REPLY=$BUFFER
+
+LBUFFER=$savelbuffer
+RBUFFER=$saverbuffer
+PREDISPLAY=$savepredisplay
+POSTDISPLAY=$savepostdisplay
+
+return $stat
diff --git a/Functions/Zle/replace-string b/Functions/Zle/replace-string
new file mode 100644
index 000000000..2fe0da901
--- /dev/null
+++ b/Functions/Zle/replace-string
@@ -0,0 +1,45 @@
+emulate -L zsh
+setopt extendedglob
+
+autoload read-from-minibuffer
+
+local p1="Replace: " p2="   with: "
+local src rep REPLY MATCH MBEGIN MEND curwidget=$WIDGET
+local -a match mbegin mend
+
+read-from-minibuffer $p1 || return 1
+src=$REPLY
+
+read-from-minibuffer "$p1$src$p2" || return 1
+rep=$REPLY
+
+if [[ $curwidget = *pattern* ]]; then
+    local rep2
+    # The following horror is so that an & preceded by an even
+    # number of backslashes is active, without stripping backslashes,
+    # while preceded by an odd number of backslashes is inactive,
+    # with one backslash being stripped.  A similar logic applies
+    # to \digit.
+    while [[ $rep = (#b)([^\\]#)(\\\\)#(\\|)(\&|\\<->|\\\{<->\})(*) ]]; do
+	if [[ -n $match[3] ]]; then
+	    # Expression is quoted, strip quotes
+	    rep2="${match[1]}${match[2]}${match[4]}"
+	else
+	    rep2+="${match[1]}${match[2]}"
+	    if [[ $match[4] = \& ]]; then
+		rep2+='${MATCH}'
+	    elif [[ $match[4] = \\\{* ]]; then
+		rep2+='${match['${match[4][3,-2]}']}'
+	    else
+		rep2+='${match['${match[4][2,-1]}']}'
+	    fi
+	fi
+	rep=${match[5]}
+    done
+    rep2+=$rep
+    LBUFFER=${LBUFFER//(#bm)$~src/${(e)rep2}}
+    RBUFFER=${RBUFFER//(#bm)$~src/${(e)rep2}}
+else
+    LBUFFER=${LBUFFER//$src/$rep}
+    RBUFFER=${RBUFFER//$src/$rep}
+fi