diff options
authorPeter Stephenson <pws@users.sourceforge.net>2003-02-03 11:05:53 +0000
committerPeter Stephenson <pws@users.sourceforge.net>2003-02-03 11:05:53 +0000
commit06902e7f66be368975ca4c58607191cf36a68781 (patch)
parent980b437fcac06d47b37d36e7bbde0150f7d19ad2 (diff)
18174: New read-from-minibuffer and replace-string ZLE functions
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)
+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.
+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
+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.
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
+${1:-? }"
+zle recursive-edit
+integer stat=$?
+(( stat )) || REPLY=$BUFFER
+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
+read-from-minibuffer "$p1$src$p2" || return 1
+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}}
+ LBUFFER=${LBUFFER//$src/$rep}
+ RBUFFER=${RBUFFER//$src/$rep}