summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog6
-rw-r--r--Doc/Zsh/zle.yo42
-rw-r--r--Src/Zle/iwidgets.list1
-rw-r--r--Src/Zle/zle_main.c152
4 files changed, 135 insertions, 66 deletions
diff --git a/ChangeLog b/ChangeLog
index d4d213167..b90f8cef6 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,9 @@
+2002-07-01 Peter Stephenson <pws@csr.com>
+
+ * 17384: Src/Zle/zle_main.c, Src/Zle/iwidgets.list,
+ Doc/Zsh/zle.yo: new `recursive-edit' widget allows a user-defined
+ widget to pass control back to zle as a subcommand.
+
2002-07-01 Sven Wischnowsky <wischnow@zsh.org>
* 17387: Completion/Zsh/Context/.distfiles,
diff --git a/Doc/Zsh/zle.yo b/Doc/Zsh/zle.yo
index f7210e7a6..0cc1b52df 100644
--- a/Doc/Zsh/zle.yo
+++ b/Doc/Zsh/zle.yo
@@ -1620,6 +1620,48 @@ At a secondary (tt(PS2)) prompt, move the entire current multiline
construct into the editor buffer.
The latter is equivalent to tt(push-input) followed by tt(get-line).
)
+tindex(recursive-edit)
+item(tt(recursive-edit))(
+Only useful from a user-defined widget. At this point in the function,
+the editor regains control until one of the standard widgets which would
+normally cause zle to exit (typically an tt(accept-line) caused by
+hitting the return key) is executed. Instead, control returns to the
+user-defined widget. The status returned is non-zero if the return was
+caused by an error, but the function still continues executing and hence
+may tidy up. This makes it safe for the user-defined widget to alter
+the command line or key bindings temporarily.
+
+
+The following widget, tt(caps-lock), serves as an example.
+example(self-insert-ucase() {
+ LBUFFER+=${(U)KEYS[-1]}
+}
+
+integer stat
+
+zle -N self-insert self-insert-ucase
+zle -A caps-lock save-caps-lock
+zle -A accept-line caps-lock
+
+zle recursive-edit
+stat=$?
+
+zle -A .self-insert self-insert
+zle -A save-caps-lock caps-lock
+zle -D save-caps-lock
+
+(( stat )) && zle send-break
+
+return $stat
+)
+This causes typed letters to be inserted capitalised until either
+tt(accept-line) (i.e. typically the return key) is typed or the
+tt(caps-lock) widget is invoked again; the later is handled by saving
+the old definition of tt(caps-lock) as tt(save-caps-lock) and then
+rebinding it to invoke tt(accept-line). Note that an error from the
+recursive edit is detected as a non-zero return status and propagated by
+using the tt(send-break) widget.
+)
tindex(redisplay)
item(tt(redisplay) (unbound) (^R) (^R))(
Redisplays the edit buffer.
diff --git a/Src/Zle/iwidgets.list b/Src/Zle/iwidgets.list
index da5bcc531..fbd45dacc 100644
--- a/Src/Zle/iwidgets.list
+++ b/Src/Zle/iwidgets.list
@@ -85,6 +85,7 @@
"quoted-insert", quotedinsert, ZLE_MENUCMP | ZLE_KEEPSUFFIX
"quote-line", quoteline, 0
"quote-region", quoteregion, 0
+"recursive-edit", recursiveedit, ZLE_MENUCMP | ZLE_KEEPSUFFIX | ZLE_LASTCOL
"redisplay", redisplay, ZLE_MENUCMP | ZLE_KEEPSUFFIX | ZLE_LASTCOL
"redo", redo, ZLE_KEEPSUFFIX
"reverse-menu-complete", reversemenucomplete, ZLE_MENUCMP | ZLE_KEEPSUFFIX | ZLE_ISCOMP
diff --git a/Src/Zle/zle_main.c b/Src/Zle/zle_main.c
index 782bd472c..9332b509d 100644
--- a/Src/Zle/zle_main.c
+++ b/Src/Zle/zle_main.c
@@ -89,10 +89,11 @@ mod_export int eofchar;
static int eofsent;
static long keytimeout;
-#ifdef HAVE_SELECT
+#if defined(HAVE_SELECT) || defined(HAVE_POLL)
/* Terminal baud rate */
static int baud;
+static long costmult;
#endif
/* flags associated with last command */
@@ -631,6 +632,74 @@ getkey(int keytmout)
return ret;
}
+/**/
+void
+zlecore(void)
+{
+#if !defined(HAVE_POLL) && defined(HAVE_SELECT)
+ struct timeval tv;
+ fd_set foofd;
+
+ FD_ZERO(&foofd);
+#endif
+
+ zrefresh();
+
+ while (!done && !errflag) {
+
+ statusline = NULL;
+ vilinerange = 0;
+ reselectkeymap();
+ selectlocalmap(NULL);
+ bindk = getkeycmd();
+ if (!ll && isfirstln && unset(IGNOREEOF) && c == eofchar) {
+ eofsent = 1;
+ break;
+ }
+ if (bindk) {
+ if (execzlefunc(bindk, zlenoargs))
+ handlefeep(zlenoargs);
+ handleprefixes();
+ /* for vi mode, make sure the cursor isn't somewhere illegal */
+ if (invicmdmode() && cs > findbol() &&
+ (cs == ll || line[cs] == '\n'))
+ cs--;
+ if (undoing)
+ handleundo();
+ } else {
+ errflag = 1;
+ break;
+ }
+#ifdef HAVE_POLL
+ if (baud && !(lastcmd & ZLE_MENUCMP)) {
+ struct pollfd pfd;
+ int to = cost * costmult / 1000; /* milliseconds */
+
+ if (to > 500)
+ to = 500;
+ pfd.fd = SHTTY;
+ pfd.events = POLLIN;
+ if (!kungetct && poll(&pfd, 1, to) <= 0)
+ zrefresh();
+ } else
+#else
+# ifdef HAVE_SELECT
+ if (baud && !(lastcmd & ZLE_MENUCMP)) {
+ FD_SET(SHTTY, &foofd);
+ tv.tv_sec = 0;
+ if ((tv.tv_usec = cost * costmult) > 500000)
+ tv.tv_usec = 500000;
+ if (!kungetct && select(SHTTY+1, (SELECT_ARG_2_T) & foofd,
+ NULL, NULL, &tv) <= 0)
+ zrefresh();
+ } else
+# endif
+#endif
+ if (!kungetct)
+ zrefresh();
+ }
+}
+
/* Read a line. It is returned metafied. */
/**/
@@ -641,14 +710,7 @@ zleread(char *lp, char *rp, int flags)
int old_errno = errno;
int tmout = getiparam("TMOUT");
-#if defined(HAVE_SELECT) || defined(HAVE_POLL)
- long costmult;
-# ifdef HAVE_POLL
-# else
- struct timeval tv;
- fd_set foofd;
-# endif
-
+#if defined(HAVE_POLL) || defined(HAVE_SELECT)
baud = getiparam("BAUD");
costmult = (baud) ? 3840000L / baud : 0;
#endif
@@ -693,11 +755,6 @@ zleread(char *lp, char *rp, int flags)
zlereadflags = flags;
histline = curhist;
-#ifndef HAVE_POLL
-# ifdef HAVE_SELECT
- FD_ZERO(&foofd);
-# endif
-#endif
undoing = 1;
line = (unsigned char *)zalloc((linesz = 256) + 2);
virangeflag = lastcmd = done = cs = ll = mark = 0;
@@ -732,60 +789,9 @@ zleread(char *lp, char *rp, int flags)
lastcol = -1;
initmodifier(&zmod);
prefixflag = 0;
- zrefresh();
- while (!done && !errflag) {
- statusline = NULL;
- vilinerange = 0;
- reselectkeymap();
- selectlocalmap(NULL);
- bindk = getkeycmd();
- if (!ll && isfirstln && unset(IGNOREEOF) && c == eofchar) {
- eofsent = 1;
- break;
- }
- if (bindk) {
- if (execzlefunc(bindk, zlenoargs))
- handlefeep(zlenoargs);
- handleprefixes();
- /* for vi mode, make sure the cursor isn't somewhere illegal */
- if (invicmdmode() && cs > findbol() &&
- (cs == ll || line[cs] == '\n'))
- cs--;
- if (undoing)
- handleundo();
- } else {
- errflag = 1;
- break;
- }
-#ifdef HAVE_POLL
- if (baud && !(lastcmd & ZLE_MENUCMP)) {
- struct pollfd pfd;
- int to = cost * costmult / 1000; /* milliseconds */
+ zlecore();
- if (to > 500)
- to = 500;
- pfd.fd = SHTTY;
- pfd.events = POLLIN;
- if (!kungetct && poll(&pfd, 1, to) <= 0)
- zrefresh();
- } else
-#else
-# ifdef HAVE_SELECT
- if (baud && !(lastcmd & ZLE_MENUCMP)) {
- FD_SET(SHTTY, &foofd);
- tv.tv_sec = 0;
- if ((tv.tv_usec = cost * costmult) > 500000)
- tv.tv_usec = 500000;
- if (!kungetct && select(SHTTY+1, (SELECT_ARG_2_T) & foofd,
- NULL, NULL, &tv) <= 0)
- zrefresh();
- } else
-# endif
-#endif
- if (!kungetct)
- zrefresh();
- }
statusline = NULL;
invalidatelist();
trashzle();
@@ -1234,6 +1240,20 @@ whereis(char **args)
}
/**/
+int
+recursiveedit(char **args)
+{
+ int locerror;
+
+ zlecore();
+
+ locerror = errflag;
+ errflag = done = 0;
+
+ return locerror;
+}
+
+/**/
mod_export void
trashzle(void)
{