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

[PATCH] Widget fallbacks (Re: Bad effect of error in zle-line-pre-redraw)



On Nov 12, 12:41pm, Bart Schaefer wrote:
}
} On Nov 12,  6:54pm, Mikael Magnusson wrote:
} }
} } There are many many more ways to break a shell session, surely.
} 
} Of course; e.g. just doing
} 
} zle -N self-insert this-does-not-exist

Seems to me that if we have immortal widgets backing the built-ins,
we should use them in cases like this?

IMO the only controversial bit of this patch is the final hunk.  As
there is no way to tell at what point the user-defined widget failed,
calling the immortal counterpart might duplicate something that was
already done.  In the other cases we know nothing else has happened.

An alternate approach for that final bit is to simply bail out of ZLE
entirely (opts[USEZLE] = 0).  That's a little tricky if we're a couple
of user-defined widgets down the call stack, as localoptions may end
up clobbering whatever we do here.


diff --git a/Src/Zle/zle_main.c b/Src/Zle/zle_main.c
index 96b631e..1652b7c 100644
--- a/Src/Zle/zle_main.c
+++ b/Src/Zle/zle_main.c
@@ -1368,6 +1368,16 @@ zleread(char **lp, char **rp, int flags, int context, char *init, char *finish)
     return s;
 }
 
+/**/
+static int
+execimmortal(Thingy func, char **args)
+{
+    Thingy immortal = rthingy_nocreate(dyncat(".", func->nam));
+    if (immortal)
+	return execzlefunc(immortal, args, 0);
+    return 1;
+}
+
 /*
  * Execute a widget.  The third argument indicates that the global
  * variable bindk should be set temporarily so that WIDGET etc.
@@ -1389,7 +1399,7 @@ execzlefunc(Thingy func, char **args, int set_bindk)
 	remetafy = 1;
     }
 
-    if(func->flags & DISABLED) {
+    if (func->flags & DISABLED) {
 	/* this thingy is not the name of a widget */
 	char *nm = nicedup(func->nam, 0);
 	char *msg = tricat("No such widget `", nm, "'");
@@ -1397,7 +1407,7 @@ execzlefunc(Thingy func, char **args, int set_bindk)
 	zsfree(nm);
 	showmsg(msg);
 	zsfree(msg);
-	ret = 1;
+	ret = execimmortal(func, args);
     } else if((w = func->widget)->flags & (WIDGET_INT|WIDGET_NCOMP)) {
 	int wflags = w->flags;
 
@@ -1461,7 +1471,7 @@ execzlefunc(Thingy func, char **args, int set_bindk)
 	    zsfree(nm);
 	    showmsg(msg);
 	    zsfree(msg);
-	    ret = 1;
+	    ret = execimmortal(func, args);
 	} else {
 	    int osc = sfcontext, osi = movefd(0);
 	    int oxt = isset(XTRACE);
@@ -1483,6 +1493,8 @@ execzlefunc(Thingy func, char **args, int set_bindk)
 	    opts[XTRACE] = oxt;
 	    sfcontext = osc;
 	    endparamscope();
+	    if (errflag == ERRFLAG_ERROR && !(ret = execimmortal(func, args)))
+		errflag &= ~ERRFLAG_ERROR;
 	    lastcmd = w->flags & ~(WIDGET_INUSE|WIDGET_FREE);
 	    if (inuse) {
 		w->flags &= WIDGET_INUSE|WIDGET_FREE;



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