From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 27676 invoked by alias); 30 Dec 2012 21:29:33 -0000 Mailing-List: contact zsh-users-help@zsh.org; run by ezmlm Precedence: bulk X-No-Archive: yes List-Id: Zsh Users List List-Post: List-Help: X-Seq: 17511 Received: (qmail 285 invoked from network); 30 Dec 2012 21:29:29 -0000 X-Spam-Checker-Version: SpamAssassin 3.3.2 (2011-06-06) on f.primenet.com.au X-Spam-Level: X-Spam-Status: No, score=-2.5 required=5.0 tests=BAYES_00,DKIM_SIGNED, RCVD_IN_DNSWL_LOW,T_DKIM_INVALID autolearn=ham version=3.3.2 Received-SPF: pass (ns1.primenet.com.au: SPF record at _netblocks.google.com designates 209.85.220.172 as permitted sender) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=mime-version:sender:in-reply-to:references:from:date :x-google-sender-auth:message-id:subject:to:cc:content-type; bh=ZPToQW6iY4mbPOq4VqKua71HNX4ISPLoRHxJu6RhIyE=; b=ps1MWc3LdeEmfbOsR48UXJVewXyAluYqU4EED+YWws7FaZ3ZtYkDNnyRLIUDH1wj3e kMQ4Ko8A0wmYpKinE4S4ywgJMpE3IAHsl8T5QI5M5Su1ydjhfSZEmFrujvfNnnRtsdKm Jjdcr5IE1Roo61kU34CapZ39fs+twO4M7Gg2Y3VOWUqjnVwN7Upk3xGpri10WwZR6Wq3 DkKOPbyoxw/tK5yQ8k7/OfMRsPBuXKrux1QODCF6NsoDr5WSyHDirg3aj5UDLunyA+0D VEoeg1HhoDi4YOiE8JPykrCI0PgsNuNQN7qgYTClp8e6EDQGm8LGJI2M+IOw9/Xqszc2 cusQ== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=eatnumber1.com; s=google; h=mime-version:sender:in-reply-to:references:from:date :x-google-sender-auth:message-id:subject:to:cc:content-type; bh=ZPToQW6iY4mbPOq4VqKua71HNX4ISPLoRHxJu6RhIyE=; b=hZoMdniopmsql+eD2V2xf9NvOx6Je7x8NZhu2tNtnpwbXYEORdlk3E0dF5KBwscMdX T467CAd6uEf6CYXKAb/ZLlJZK5M8YociHuLXzUByJpe+/E6EbkyQ3EDURgflUlcz6Xde oTiwTCRkou2nYPMWh/T345S+c/LAzmzAkaOIk= MIME-Version: 1.0 Sender: eatnumber1@gmail.com In-Reply-To: <121230112044.ZM879@torch.brasslantern.com> References: <121230112044.ZM879@torch.brasslantern.com> From: Russell Harmon Date: Sun, 30 Dec 2012 16:02:02 -0500 X-Google-Sender-Auth: B82FPj5BIatZoL6gfiwgqs-Bm1E Message-ID: Subject: Re: Creating A Clean Environment For Autoloaded Functions To: Bart Schaefer Cc: zsh-users@zsh.org Content-Type: text/plain; charset=UTF-8 On Sun, Dec 30, 2012 at 2:20 PM, Bart Schaefer wrote: > On Dec 30, 4:44am, Russell Harmon wrote: >> >> If I want to write a function which can be autoloaded, how can I >> prevent functions defined outside of my function from being accessible >> from within my function? For example, I have a function ls { gls "$@" >> }, and I know of no way to prevent that function from leaking into the >> definition of all the functions I've autoloaded which use ls. > > 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. > > 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". > > However, you could do something like this, assuming zsh/parameter is > loaded: > > ls() { > if (( $#funcstack > 1 )) > then command ls "$@" > else gls "$@" > fi > } > > This will prevent gls from being run inside any other function, although > it won't bypass the ls wrapper function entirely. 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? I'm thinking to add an option to autoload to undefine all functions much like how -U works with aliases. 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. > >> Additionally, is it possible to zmodload a module which is >> automatically unloaded from the environment after my function >> completes _only if_ that module was not already loaded? > > There isn't a property of modules that supports this, but you can do it > yourself explicitly with something like this: > > { > zmodload -e zsh/mathfunc # for example > local unload_mathfunc=$? > zmodload zsh/mathfunc > > : do what you need to with math functions > > } always { > (( unload_mathfunc )) && zmodload -u zsh/mathfunc > } > > If the zsh/parameter module is not itself one of the ones you care about > unloading in this way, you can be more generic: > > { > zmodload zsh/parameter > local -a existing_modules > existing_modules=( ${(k)modules[(R)loaded]} ) > > : do whatever zmodloads you want ... > > } always { > # Requires zsh 5.0, otherwise you need a loop > zmodload -u ${(k)modules[(R)loaded]:|existing_modules} > } > > I'm not sure that zmodload is clever enough to notice that inter-module > dependencies have been satisfied by the list provided to -u and thus > unload the modules in the correct order to be sure it succeeds, so a > bit of tweaking to the above may be required for full generality. Hmm, I think I'm realizing that loading & unloading of dependent modules every time a function is called might not be exactly what I want. I think what I'm looking for is more like zsh modules where you have hook functions for when the function is loaded & unloaded so that you can unload relevant modules when no longer needed. That has it's own difficulties however because it'd be hard to tell if some other function loaded after you were loaded needs a module which you are about to unload.