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

Re: Creating A Clean Environment For Autoloaded Functions

On Dec 30,  4:02pm, Russell Harmon wrote:
} On Sun, Dec 30, 2012 at 2:20 PM, Bart Schaefer
} <schaefer@xxxxxxxxxxxxxxxx> wrote:
} > This amounts to asking how to violate a basic tenet of shell function
} > behavior.  They're supposed to act like commands that are always at the
} > front of the search path, and the search path doesn't change based on
} > the order in which every other command was added to it.
} I guess that breaking with this particular shell idiom is what I want
} to do. Otherwise, how is one supposed to be able to create
} autoloadable functions with reliable and reproducible behavior?

As I said, you do it like this:

} > The way you avoid this is to write every function that explicitly does
} > not want this behavior so as to explicitly override it; for examply by
} > using "command ls" instead of "ls".

To be completely "reliable and reproducible" you also have to set up
the emulation mode very carefully, force a fixed value of $path, etc.
In practice is this is often more than either you or the caller of your
function actually want.

The alternative is to write scripts rather than autoloaded functions,
which run in their own process and have more complete control of their
context.  Part of the reason for using functions rather than scripts
is so that they operate in the context of the running shell, which
implies that the caller is permitted to screw around with that context.

} I'm thinking to add an option to autoload to undefine all functions
} much like how -U works with aliases.

The problem with that is that -U doesn't actually undefine the aliases,
it just prevents them from being expanded at parse time.  There is no
equivalent parse-time mechanism for distinguishing an external command
from a function.

In zsh (and probably only in zsh of all shells) there actually is a way
to remove all functions if you really want to.

    the_lonely_function() {
      builtin zmodload zsh/parameter
      builtin typeset +h functions
      builtin unfunction -m \*
      # There are now no functions but this function,
      # and even this function cannot call itself.
      # On return, the local parameter scope will end
      # and other function definitions will reappear.

There are a few obscure gotchas with this; for example, functions that
were previously autoload-able will instead become real functions that
use the "autoload -X" command to bootstrap.  That may not always have
the equivalent effect to the original autoload.
} Basically, I'm trying to follow what the best practices are when
} writing autoloadable functions so that they will be able to run
} reliably in the largest number of different environments possible.

I'd have to say that the *usual* practices are to worry about the
emulation mode and setopts, use globbing and parameter expansion
tricks to avoid reliance on external commands as much as possible,
and to presume "autoload -U" has eliminated parse-time surprises.
Beyond that and the judicious application of "builtin" or "command"
prefixes where necessary, you're putting in too much effort for the
incremental value.

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