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

default command function



This is something I've been wondering about for a few weeks.  I
couldn't figure out an existing way to do it, so I changed the
source...  If there's already a way, well, it was good practice.
Otherwise, comments?  It's pretty hackish at this point.

Perl has an amusing feature whereby the sub named AUTOLOAD, if defined
in the current package, gets called in place of a "subroutine not
found" error.  The idea is that AUTOLOAD reads the sub definition from
somewhere, breathes life into it, and then calls it.  It basically allows
you to create default behavior for undefined subroutines.

I like it a lot, and wished that I could somehow trick zsh into acting
likewise, so I modified exec.c so that if a command is not found, it execs
(assuming it's defined) _default_cmd(), with the (failed) command line
as its args.

pretty mindless example: I use MH for reading my mail.  Defining
_default_cmd() thusly lets you use "25" for "show 25", etc.

  % _default_cmd() { show $* }

Is there a better way to do this?  My patch against 3.0.5 follows.

--
Greg Fast


--- zsh-3.0.5/Src/exec.c	Thu Sep 25 20:42:16 1997
+++ zsh-3.0.5-gdf/Src/exec.c	Mon Feb 23 01:38:56 1998
@@ -1,5 +1,5 @@
 /*
- * $Id: exec.c,v 2.93 1996/10/15 20:16:35 hzoli Exp $
+ * $Id: exec.c,v 1.7 1998/02/23 07:38:48 gdfast Exp gdfast $
  *
  * exec.c - command execution
  *
@@ -347,8 +347,44 @@
 	}
     if (eno)
 	zerr("%e: %s", arg0, eno);
-    else
-	zerr("command not found: %s", arg0, 0);
+#ifdef DEFAULT_CMD
+    else {
+      /* if cmd is unknown and function _default_cmd() is defined, 
+       * call _default_cmd() with the faulty cmdline as its args 
+       */
+      char *cmdarg = "_default_cmd";
+      HashNode f; /* Shfunc to execute */
+      LinkNode top; 
+      char * cxx;
+      Cmd fcmd = (Cmd) allocnode(N_CMD);
+
+      fcmd->args = newlinklist(); 
+      fcmd->redir = newlinklist();
+      fcmd->vars = newlinklist();
+      fcmd->type = FUNCDEF;
+      fcmd->lineno = 0; /*?*/
+      fcmd->u.generic = NULL; /*?*/
+      addlinknode(fcmd->args, (void *) cmdarg); /* make $0 "_default_cmd" */
+      /* args is global */
+      top = firstnode(args); /* keep track of where to stop rolling args */
+      do {
+	cxx = (char *) peekfirst(args);
+	addlinknode(fcmd->args, (void *) cxx);
+	if (args->first->next==NULL) {
+	  break; /* don't roll if there's nowhere to roll to */
+	}
+	rolllist(args, args->first->next);
+      } while (args->first!=top);
+      if ( (f=shfunctab->getnode(shfunctab, cmdarg)) ) {
+	execshfunc(fcmd, (Shfunc) f); 
+      } else {
+	zerr("command not found and no _default_cmd(): %s", arg0, 0);
+      }
+    }
+#else /* no DEFAULT_CMD */
+    else 
+      zerr("command not found: %s", arg0, 0);
+#endif /* DEFAULT_CMD */
     _exit(1);
 }
 



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