Zsh Mailing List Archive
Messages sorted by: Reverse Date, Date, Thread, Author

PATCH: Re: The `zle' command and traps



Bart Schaefer wrote:

> On Mar 9,  1:21pm, Sven Wischnowsky wrote:
> } Subject: Re: The `zle' command and traps
> }
> } Bart Schaefer wrote:
> } 
> } > 	TMOUT=2 ; TRAPALRM() { zle -R "Hi there, I'm a trap." }
> } > 
> } > Of course if the signal arrives when ZLE is not active, this generates an
> } > ugly warning message.
> } 
> } I was about to add a/some test(s) for sfcontext in bin_zle()
> } but... this is quite cool, isn't it? ;-)
> 
> Yes, I confess I thought so too ... but some things don't work so well.
> For example, try using "zle -M ..." instead of -R in that trap.
> 
> Or try
> 
> 	TRAPINT() { zle push-input }
> 
> and then type ctrl-C.  Note that the line gets pushed onto the buffer
> stack, but the display is not refreshed so you can't tell.  You need an
> explicit refresh:
> 
> 	TRAPINT() { zle push-input ; zle -R }
> 
> (An explicit refresh makes the "zle -M" trap work as well.)
> 
> I'm also concerned about what happens if a zle widget is invoked from a
> trap in the middle of some interactive thing like menu-selection.  That
> could get messy quickly, especially if it's something that alters the
> buffer.
>  
> } So, should we disallow it completely?
> 
> I can't decide.  The message modes and refresh seem harmless enough, but
> perhaps we should refuse to execute widgets from within traps?

The patch does that. And it adds the automatic re-display for -M.

> } Or make the zle builtin be quiet if zle isn't active?
> 
> That isn't strictly necessary as one can redirect stdout to hide the
> warning.  However, it'd be nice if zle returned a non-zero status when
> it fails; try typing
> 
> 	zle -R "not echoed" || echo zle failed
> 
> and you'll get
> 
> 	zle: can only be called from widget function
> 
> but not "zle failed".

Argh! That's a much more general problem: try `continue || echo foo'. And
3.0.8 does the same, too.

And it's connected to my patch for `zcompile' (10106). I have to check 
that again.

Hm. Some builtins sometimes reset errflag and sometimes not. execbuiltin()
resets errflag if it was set before the call to the function
implementing the builtin and after that only uses zwarnnam(), not
zerrnam(). Is it correct to reset errflag in execbuiltin() after the
call to the function? Or do we have to find all the places where we
have to reset errflag? Or just replace some calls to zerrnam() with
calls to zwarnnam(). No patch for that yet.

> } Make the zle special parameters accessible (read-only) in traps if zle
> } is active?
> 
> If we allow widgets to be called, you can cause the special parameters
> to become available by using "zle widgetname".  So instead of writing
> 
> 	TRAPINT() { .... something with $BUFFER .... }
> 
> One writes
> 
> 	widgetname() { .... something with $BUFFER .... }
> 	zle -N widgetname
> 	TRAPINT() { zle widgetname }
> 
> Can you extend read-only-ness of the parameters to the point that widgets
> are restricted as well?  I.e., if you call from a trap a builtin widget
> that moves the cursor or inserts/deletes characters, it would fail?

Well, there are the functions in zle_utils.c that modify the line and
most zle functions use them, but they are still free to do with the
line whatever they want. And many functions like spaceinline() don't
return anything yet (we could return a boolean saying if we are
allowed to modify the line). And many functions happily alter cs...

So, I think it would be quite a bit of work to implement that.

> If we can restrict widgets to those that do "safe" things, then we can
> allow "zle widgetname" and there's no need for the special parameters to
> be visible directly to the trap function.  If instead we must prohibit
> widget-calling entirely, then perhaps the parameters should be available
> to the trap function.

No patch for that yet, either. The problem is that traps are called
from the core (of course) and the zle module might not be there. Maybe 
calling a hook in dotrapargs() so that zle can install its own hook
function when it is loaded to make the parameters available read-only
when zle is active. Or does this sound too complicated to anyone?

> } Add a way to detect if zle is active?
> 
> That would be nice.  "zle" with no arguments silently returning 0 or 1
> would be sufficient (it now says "zle: widgets can only be called ...").

Good idea. The patch does that. But... currently this is done in a way 
that allows to find out if one can call widgets. It does not say
anything about the possibility to call `zle -R'. Hm.

> While we're on the subject ... CURSOR is almost equivalent to emacs'
> (point).  Why is there no MARK variable? [...]

Yes, why not. The patch adds it.

> } Add a way to detect if (the shell thinks that) there is a
> } completion list displayed below the prompt? Etc, etc?
> 
> Hrm.  That may be getting too esoteric.  Hard to say.
> 
> While we're on the subject of zle behavior:
> 
> 	zle -U frob
> 
> This results in "brof" being inserted onto the command line.  The docs
> refer to the "input queue" not the "input stack" -- why is it LIFO?

Oops. Fixed.

Bye
 Sven

diff -ru ../z.old/Doc/Zsh/mod_zle.yo Doc/Zsh/mod_zle.yo
--- ../z.old/Doc/Zsh/mod_zle.yo	Mon Mar 13 14:15:04 2000
+++ Doc/Zsh/mod_zle.yo	Mon Mar 13 15:21:01 2000
@@ -184,7 +184,8 @@
 xitem(tt(zle) tt(-R) [ tt(-c) ] [ var(display-string) ] [ var(string) ... ])
 xitem(tt(zle) tt(-M) var(string))
 xitem(tt(zle) tt(-U) var(string))
-item(tt(zle) var(widget) tt([ -n) var(num) tt(]) tt([ -N ]) var(args) ...)(
+xitem(tt(zle) var(widget) tt([ -n) var(num) tt(]) tt([ -N ]) var(args) ...)
+item(tt(zle))(
 The tt(zle) builtin performs a number of different actions concerning
 ZLE.  Which operation it performs depends on its options:
 
@@ -289,5 +290,9 @@
 it should call the tt(beep) widget directly.
 )
 enditem()
+
+With no options and no arguments, only the returns status will be
+set. It is zero if ZLE is currently active and widgets could be
+invoked using this builtin command and non-zero if ZLE is not active.
 )
 enditem()
diff -ru ../z.old/Src/Zle/zle_params.c Src/Zle/zle_params.c
--- ../z.old/Src/Zle/zle_params.c	Mon Mar 13 14:14:54 2000
+++ Src/Zle/zle_params.c	Mon Mar 13 15:12:26 2000
@@ -57,6 +57,8 @@
 	zleunsetfn, NULL },
     { "CURSOR",  PM_INTEGER, FN(set_cursor),  FN(get_cursor),
 	zleunsetfn, NULL },
+    { "MARK",  PM_INTEGER, FN(set_mark),  FN(get_mark),
+	zleunsetfn, NULL },
     { "LBUFFER", PM_SCALAR,  FN(set_lbuffer), FN(get_lbuffer),
 	zleunsetfn, NULL },
     { "RBUFFER", PM_SCALAR,  FN(set_rbuffer), FN(get_rbuffer),
@@ -169,6 +171,25 @@
 get_cursor(Param pm)
 {
     return cs;
+}
+
+/**/
+static void
+set_mark(Param pm, zlong x)
+{
+    if (x < 0)
+	mark = 0;
+    else if (x > ll)
+	mark = ll;
+    else
+	mark = x;
+}
+
+/**/
+static zlong
+get_mark(Param pm)
+{
+    return mark;
 }
 
 /**/
diff -ru ../z.old/Src/Zle/zle_thingy.c Src/Zle/zle_thingy.c
--- ../z.old/Src/Zle/zle_thingy.c	Mon Mar 13 14:14:54 2000
+++ Src/Zle/zle_thingy.c	Mon Mar 13 15:35:02 2000
@@ -434,7 +434,13 @@
 static int
 bin_zle_mesg(char *name, char **args, char *ops, char func)
 {
+    if (!zleactive) {
+	zerrnam(name, "can only be called from widget function", NULL, 0);
+	return 1;
+    }
     showmsg(*args);
+    if (sfcontext != SFC_WIDGET)
+	zrefresh();
     return 0;
 }
 
@@ -442,14 +448,14 @@
 static int
 bin_zle_unget(char *name, char **args, char *ops, char func)
 {
-    char *p = *args;
+    char *b = *args, *p = b + strlen(b);
 
     if (!zleactive) {
 	zerrnam(name, "can only be called from widget function", NULL, 0);
 	return 1;
     }
-    while (*p)
-	ungetkey((int) *p++);
+    while (p > b)
+	ungetkey((int) *--p);
     return 0;
 }
 
@@ -589,18 +595,18 @@
     int ret, saveflag = 0;
     char *wname = *args++;
 
-    if(!zleactive || incompctlfunc || incompfunc) {
-	zerrnam(name, "widgets can only be called when ZLE is active",
-	    NULL, 0);
-	return 1;
-    }
-
     if (!wname) {
-	zwarnnam(name, "wrong number of arguments", NULL, 0);
 	if (saveflag)
 	    zmod = modsave;
+	return (!zleactive || incompctlfunc || incompfunc ||
+		sfcontext != SFC_WIDGET);
+    }
+    if(!zleactive || incompctlfunc || incompfunc || sfcontext != SFC_WIDGET) {
+	zerrnam(name, "widgets can only be called when ZLE is active",
+	    NULL, 0);
 	return 1;
     }
+
     while (*args && **args == '-') {
 	char *num;
 	if (!args[0][1] || args[0][1] == '-') {

--
Sven Wischnowsky                         wischnow@xxxxxxxxxxxxxxxxxxxxxxx



Messages sorted by: Reverse Date, Date, Thread, Author