17384: new recursive-edit widget.

This commit is contained in:
Peter Stephenson 2002-07-01 09:54:47 +00:00
parent 053629183d
commit a18f020282
4 changed files with 164 additions and 95 deletions

View file

@ -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,

View file

@ -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.

View file

@ -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

View file

@ -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,108 +632,19 @@ getkey(int keytmout)
return ret;
}
/* Read a line. It is returned metafied. */
/**/
unsigned char *
zleread(char *lp, char *rp, int flags)
void
zlecore(void)
{
unsigned char *s;
int old_errno = errno;
int tmout = getiparam("TMOUT");
#if defined(HAVE_SELECT) || defined(HAVE_POLL)
long costmult;
# ifdef HAVE_POLL
# else
#if !defined(HAVE_POLL) && defined(HAVE_SELECT)
struct timeval tv;
fd_set foofd;
# endif
baud = getiparam("BAUD");
costmult = (baud) ? 3840000L / baud : 0;
#endif
/* ZLE doesn't currently work recursively. This is needed in case a *
* select loop is used in a function called from ZLE. vared handles *
* this differently itself. */
if(zleactive) {
char *pptbuf;
int pptlen;
pptbuf = unmetafy(promptexpand(lp, 0, NULL, NULL), &pptlen);
write(2, (WRITE_ARG_2_T)pptbuf, pptlen);
free(pptbuf);
return (unsigned char *)shingetline();
}
keytimeout = getiparam("KEYTIMEOUT");
if (!shout) {
if (SHTTY != -1)
init_shout();
if (!shout)
return NULL;
/* We could be smarter and default to a system read. */
/* If we just got a new shout, make sure the terminal is set up. */
if (termflags & TERM_UNKNOWN)
init_term();
}
fflush(shout);
fflush(stderr);
intr();
insmode = unset(OVERSTRIKE);
eofsent = 0;
resetneeded = 0;
lpromptbuf = promptexpand(lp, 1, NULL, NULL);
pmpt_attr = txtchange;
rpromptbuf = promptexpand(rp, 1, NULL, NULL);
rpmpt_attr = txtchange;
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;
vichgflag = 0;
viinsbegin = 0;
statusline = NULL;
selectkeymap("main", 1);
selectlocalmap(NULL);
fixsuffix();
if ((s = (unsigned char *)getlinknode(bufstack))) {
setline((char *)s);
zsfree((char *)s);
if (stackcs != -1) {
cs = stackcs;
stackcs = -1;
if (cs > ll)
cs = ll;
}
if (stackhist != -1) {
histline = stackhist;
stackhist = -1;
}
}
initundo();
if (isset(PROMPTCR))
putc('\r', shout);
if (tmout)
alarm(tmout);
zleactive = 1;
resetneeded = 1;
errflag = retflag = 0;
lastcol = -1;
initmodifier(&zmod);
prefixflag = 0;
zrefresh();
while (!done && !errflag) {
statusline = NULL;
@ -786,6 +698,100 @@ zleread(char *lp, char *rp, int flags)
if (!kungetct)
zrefresh();
}
}
/* Read a line. It is returned metafied. */
/**/
unsigned char *
zleread(char *lp, char *rp, int flags)
{
unsigned char *s;
int old_errno = errno;
int tmout = getiparam("TMOUT");
#if defined(HAVE_POLL) || defined(HAVE_SELECT)
baud = getiparam("BAUD");
costmult = (baud) ? 3840000L / baud : 0;
#endif
/* ZLE doesn't currently work recursively. This is needed in case a *
* select loop is used in a function called from ZLE. vared handles *
* this differently itself. */
if(zleactive) {
char *pptbuf;
int pptlen;
pptbuf = unmetafy(promptexpand(lp, 0, NULL, NULL), &pptlen);
write(2, (WRITE_ARG_2_T)pptbuf, pptlen);
free(pptbuf);
return (unsigned char *)shingetline();
}
keytimeout = getiparam("KEYTIMEOUT");
if (!shout) {
if (SHTTY != -1)
init_shout();
if (!shout)
return NULL;
/* We could be smarter and default to a system read. */
/* If we just got a new shout, make sure the terminal is set up. */
if (termflags & TERM_UNKNOWN)
init_term();
}
fflush(shout);
fflush(stderr);
intr();
insmode = unset(OVERSTRIKE);
eofsent = 0;
resetneeded = 0;
lpromptbuf = promptexpand(lp, 1, NULL, NULL);
pmpt_attr = txtchange;
rpromptbuf = promptexpand(rp, 1, NULL, NULL);
rpmpt_attr = txtchange;
zlereadflags = flags;
histline = curhist;
undoing = 1;
line = (unsigned char *)zalloc((linesz = 256) + 2);
virangeflag = lastcmd = done = cs = ll = mark = 0;
vichgflag = 0;
viinsbegin = 0;
statusline = NULL;
selectkeymap("main", 1);
selectlocalmap(NULL);
fixsuffix();
if ((s = (unsigned char *)getlinknode(bufstack))) {
setline((char *)s);
zsfree((char *)s);
if (stackcs != -1) {
cs = stackcs;
stackcs = -1;
if (cs > ll)
cs = ll;
}
if (stackhist != -1) {
histline = stackhist;
stackhist = -1;
}
}
initundo();
if (isset(PROMPTCR))
putc('\r', shout);
if (tmout)
alarm(tmout);
zleactive = 1;
resetneeded = 1;
errflag = retflag = 0;
lastcol = -1;
initmodifier(&zmod);
prefixflag = 0;
zlecore();
statusline = NULL;
invalidatelist();
trashzle();
@ -1233,6 +1239,20 @@ whereis(char **args)
return 0;
}
/**/
int
recursiveedit(char **args)
{
int locerror;
zlecore();
locerror = errflag;
errflag = done = 0;
return locerror;
}
/**/
mod_export void
trashzle(void)