zsh-workers
 help / color / mirror / code / Atom feed
* Tag functions with shell options?
@ 1996-07-02 12:05 Anthony Heading
  1996-07-02 13:36 ` Zefram
  1996-07-02 15:37 ` Peter Stephenson
  0 siblings, 2 replies; 10+ messages in thread
From: Anthony Heading @ 1996-07-02 12:05 UTC (permalink / raw)
  To: zsh-workers

I've hit a small shell-based problem, and I wonder if it's a common one...

My dearly beloved employers, or rather their technology guys, have come up with a
Unix application load/unload scheme.  And it works in a reasonably sensible way,
by defining shell functions which grub around in config files and then set
shell and environment variables appropriately.

The trouble is that these functions rely on sh-style word splitting, which I don't
have (or want) turned on by default. 

So I think I need some way of marking these functions to be interpreted with
SH_WORD_SPLIT turned on locally.  Or have I missed something simple?

Anthony



^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: Tag functions with shell options?
  1996-07-02 12:05 Tag functions with shell options? Anthony Heading
@ 1996-07-02 13:36 ` Zefram
  1996-07-02 14:12   ` Anthony Heading
  1996-07-02 15:37 ` Peter Stephenson
  1 sibling, 1 reply; 10+ messages in thread
From: Zefram @ 1996-07-02 13:36 UTC (permalink / raw)
  To: Anthony Heading; +Cc: zsh-workers

>So I think I need some way of marking these functions to be interpreted with
>SH_WORD_SPLIT turned on locally.  Or have I missed something simple?

awkward_func () {
  setopt local_options sh_word_split
  ...
}

This will set SH_WORD_SPLIT for the duration of the function, restoring
the state when it returns.

-zefram



^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: Tag functions with shell options?
  1996-07-02 13:36 ` Zefram
@ 1996-07-02 14:12   ` Anthony Heading
  1996-07-02 15:17     ` Zefram
  0 siblings, 1 reply; 10+ messages in thread
From: Anthony Heading @ 1996-07-02 14:12 UTC (permalink / raw)
  To: Zefram; +Cc: zsh-workers

Zefram wrote:
 
> >So I think I need some way of marking these functions to be interpreted with
> >SH_WORD_SPLIT turned on locally.  Or have I missed something simple?
> 
> awkward_func () {
>   setopt local_options sh_word_split
>   ...
> }
> 
> This will set SH_WORD_SPLIT for the duration of the function, restoring
> the state when it returns.

Thanks for the response.  The trouble is that I can't alter awkward_func. Effectively
I have a library of Bourne shell functions which I'd like to use from zsh, without
knowing about their internals, and I can't see how to do it. 

Anthony



^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: Tag functions with shell options?
  1996-07-02 14:12   ` Anthony Heading
@ 1996-07-02 15:17     ` Zefram
  0 siblings, 0 replies; 10+ messages in thread
From: Zefram @ 1996-07-02 15:17 UTC (permalink / raw)
  To: Anthony Heading; +Cc: A.Main, zsh-workers

>Thanks for the response.  The trouble is that I can't alter awkward_func. Effectively
>I have a library of Bourne shell functions which I'd like to use from zsh, without
>knowing about their internals, and I can't see how to do it. 

You could wrap the Bourne shell functions in zsh functions that do the
LOCAL_OPTIONS thing.

-zefram



^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: Tag functions with shell options?
  1996-07-02 12:05 Tag functions with shell options? Anthony Heading
  1996-07-02 13:36 ` Zefram
@ 1996-07-02 15:37 ` Peter Stephenson
  1996-07-02 16:57   ` Anthony Heading
  1 sibling, 1 reply; 10+ messages in thread
From: Peter Stephenson @ 1996-07-02 15:37 UTC (permalink / raw)
  To: Zsh hackers list

aheading@jpmorgan.com wrote:
> So I think I need some way of marking these functions to be interpreted with
> SH_WORD_SPLIT turned on locally.  Or have I missed something simple?

This is definitely a weak point in compatibility.  Perhaps in a future
version we do want special ways of doing things like this.  Some time
ago, people were suggesting having hooks you could call when a
function was called etc.; that would do the trick too.

However, for the time being... I take it the problem is within the
function, i.e. you don't actually have problems on the command line
yourself?  In that case it would be outside the scope of the function.

Another problem arises if the functions get defined at arbitrary
points during execution (err, like the sws_locate function below, in
fact).  In that case you're basically stuck without at the least a
smart script to convert all functions defined inside in the
appropriate manner.

If they are playing fair, however, try this function.  You need
to call it with the names of all the functions you want to have run
with sh_word_split turned on.  They can be either already in memory or
autoloadable: in the latter case, it assumes they are ksh-like
autoloadable functions, i.e. the entire function definition is there
including the `function foo { ... } bit.'

It relies on the fact that `functions foo' returns an accurate
representation of foo.  I've been trying to ensure this over the
years, but there almost certainly some things we've all missed.


sws_fn () {
  # Convert a sh or ksh function to run under zsh by the addition of
  # some set of options.  The function may already be defined, or be in
  # some autoload directory.

  # This is the text we\'d like added at the top of the function.
  local optline="setopt shwordsplit localoptions"

  local func body dir fnfile

  sws_locate() {
    # Find an autoload file.
    local dir
    for dir in $fpath; do
      if [[ -f $dir/$1 ]]; then
	fnfile=$dir/$1
	return 0
      fi
    done
    return 1
  }

  for func; do
    if [[ "$(functions $func | head -1)" = *undefined* ]] &&
      sws_locate $func; then
      # We're assuming these are ksh-like autoload functions,
      # i.e. they contain the full function include definition lines.
      . $fnfile
    fi
    body="$(functions $func 2>&1 | sed -e 1d -e '$d')"
    [[ -z $body ]] && print "No such function: $func" >&2 && continue
    eval "function $func {
      $optline
      $body
    }"
  done
}

-- 
Peter Stephenson <pws@ifh.de>       Tel: +49 33762 77366
WWW:  http://www.ifh.de/~pws/       Fax: +49 33762 77330
Deutches Electronen-Synchrotron --- Institut fuer Hochenergiephysik Zeuthen
DESY-IfH, 15735 Zeuthen, Germany.



^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: Tag functions with shell options?
  1996-07-02 15:37 ` Peter Stephenson
@ 1996-07-02 16:57   ` Anthony Heading
  1996-07-02 19:07     ` Bart Schaefer
  0 siblings, 1 reply; 10+ messages in thread
From: Anthony Heading @ 1996-07-02 16:57 UTC (permalink / raw)
  To: Peter Stephenson; +Cc: zsh-workers

Peter wrote:
> If they are playing fair, however, try this function.

Thanks.  That's a bit cleaner than the hack I was resorting
to - viz . <( sed /blaa/ foo.sh) trying to edit the functions
on the way in.

On a longer term, perhaps lexical closures are possibility?
It would be pleasingly complicated.

Anthony



^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: Tag functions with shell options?
  1996-07-02 16:57   ` Anthony Heading
@ 1996-07-02 19:07     ` Bart Schaefer
  1996-07-02 19:53       ` Anthony Heading
  0 siblings, 1 reply; 10+ messages in thread
From: Bart Schaefer @ 1996-07-02 19:07 UTC (permalink / raw)
  To: Anthony Heading, Peter Stephenson, Zefram, zsh-workers

On Jul 2,  5:37pm, Peter Stephenson wrote:
} Subject: Re: Tag functions with shell options?
}
} aheading@jpmorgan.com wrote:
} > So I think I need some way of marking these functions to be interpreted
} > with SH_WORD_SPLIT turned on locally. Or have I missed something simple?
} 
} This is definitely a weak point in compatibility.  Perhaps in a future
} version we do want special ways of doing things like this.  Some time
} ago, people were suggesting having hooks you could call when a
} function was called etc.; that would do the trick too.

I like the hook idea, but I think something simpler would be sufficient
in this case.

On Jul 2,  4:17pm, Zefram wrote:
} You could wrap the Bourne shell functions in zsh functions that do the
} LOCAL_OPTIONS thing.

That's how I'd approach it, and that's mostly what Peter's sws_fn does.
I've been using this trick in my .zshrc for years:

if typeset -f precmd >& /dev/null
then
    let n=1
    while typeset -f x${n}precmd >& /dev/null; do let n++; done
    eval x${n}"`typeset -f precmd`"
    if [[ "$TERM" = screen ]]
    then
        eval "precmd() { title ; x${n}precmd }"
    else
        eval "precmd() { TMOUT=600 ; title ; x${n}precmd }"
    fi
fi

What that does is rename precmd to a new name that doesn't exist, and
then creates a new precmd which sets the title bar and calls the new
name.  Unfortunately, that doesn't work on autoloaded functions, which
is what most of the work in sws_fn is fixing.

What would be nice is if one of the zsh builtins permitted forcing load
of an autoload function without running the function, and if a builtin
permtitted a function's name to be changed without redefining it.

[Back to PWS again:]
} Another problem arises if the functions get defined at arbitrary
} points during execution (err, like the sws_locate function below, in
} fact).  In that case you're basically stuck without at the least a
} smart script to convert all functions defined inside in the
} appropriate manner.

Right; it doesn't seem that Anthony has given us enough context.  Do
the functions get defined and then executed all within /etc/profile,
for example?  Or do they act as wrappers around actual applications,
so they don't run until you execute them "manually"?  (Sounds like the
latter, but ...)

Are you explicitly sourcing the script that defines those functions,
or are they in a startup script that zsh reads automatically?

If you know the names of all the functions that need to be wrapped,
it seems to me that a much simpler implementation of sws_fn is:

    sws_fn () {
	# \\${1} below is in case of multiple calls to `sws_fn foo`
	# for the same 'foo', to be sure an alias isn't referenced.
	eval "SWS_${1} () { setopt localoptions shwordsplit; \\${1} }"
	alias ${1}=SWS_${1}
    }

The only drawback to this is that other functions that may already have
been defined won't see the alias -- but presumably those functions will
themselves be given the sws_fn treatment, so it's moot.

BTW, does it bother anyone else that, for textually-identical definitions
of `foo':

    foo() {
	bar
    }
    alias bar=baz

Is not equivalent to:

    autoload foo
    alias bar=baz

??

-- 
Bart Schaefer                             Brass Lantern Enterprises
http://www.well.com/user/barts            http://www.nbn.com/people/lantern

New male in /home/schaefer:
>N  2 Justin William Schaefer  Sat May 11 03:43  53/4040  "Happy Birthday"



^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: Tag functions with shell options?
  1996-07-02 19:07     ` Bart Schaefer
@ 1996-07-02 19:53       ` Anthony Heading
  1996-07-02 21:31         ` Bart Schaefer
  0 siblings, 1 reply; 10+ messages in thread
From: Anthony Heading @ 1996-07-02 19:53 UTC (permalink / raw)
  To: schaefer; +Cc: aheading, pws, A.Main, zsh-workers

> Right; it doesn't seem that Anthony has given us enough context.  Do
> the functions get defined and then executed all within /etc/profile,
> for example?  Or do they act as wrappers around actual applications,
> so they don't run until you execute them "manually"?  (Sounds like the
> latter, but ...)

Yes, the latter. The lack of context was sort-of deliberate, since I
suspected any interest would be in the wider picture, rather than my
particular petty problems.  It seemed simply an example of something
it would be nice to support elegantly.

> it seems to me that a much simpler implementation of sws_fn is:
[wrapping the function, and then aliasing the wrapper to the original]

> The only drawback to this is that other functions that may already have
> been defined won't see the alias -- but presumably those functions will
> themselves be given the sws_fn treatment, so it's moot.

Hmm. Don't understand the first point, but I'll experiment.

Thanks

Anthony



^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: Tag functions with shell options?
  1996-07-02 19:53       ` Anthony Heading
@ 1996-07-02 21:31         ` Bart Schaefer
  1996-07-02 22:27           ` Anthony Heading
  0 siblings, 1 reply; 10+ messages in thread
From: Bart Schaefer @ 1996-07-02 21:31 UTC (permalink / raw)
  To: Anthony Heading; +Cc: zsh-workers

On Jul 2,  8:53pm, Anthony Heading wrote:
} Subject: Re: Tag functions with shell options?
}
} The lack of context was sort-of deliberate, since I
} suspected any interest would be in the wider picture, rather than my
} particular petty problems.  It seemed simply an example of something
} it would be nice to support elegantly.

This introduces a whole class of problems, which is most obvious in the
case when you *do not* know the names of the functions that should have
their local options (or whatever) changed.  In that case you almost end
up needing something like Perl's "package", so that you can do e.g.:

    package admin
    . /etc/profile
    for f in $(whence -FP admin)
    do
	typeset -fo ${f}=(shwordsplit globassign bsdecho nobgnice);;
    done

Where I'm assuming a slew of new features:
1.  `package foo' groups all functions, aliases, etc. in the package
    named `foo' until the next `package' is executed
2.  `whence -F' lists the names (but NOT definitions) of functions
    [Aside:  Why doesn't `typeset +f' do that already?]
3.  `whence -P foo' lists from the package `foo'
4.  `typeset -o' is equivalent to `setopt' (and `+o' to `unsetopt')
5.  `typeset -fo foo=(options...)' sets local options for `foo', as
    if `foo' began with `setopt localoptions options...'
6.  Zoltan's (or was it Zefram's?) change to make `setopt nofoo' be
    equivalent to `unsetopt foo'

} > it seems to me that a much simpler implementation of sws_fn is:
} [wrapping the function, and then aliasing the wrapper to the original]
} 
} > The only drawback to this is that other functions that may already have
} > been defined won't see the alias -- but presumably those functions will
} > themselves be given the sws_fn treatment, so it's moot.
} 
} Hmm. Don't understand the first point, but I'll experiment.

Example:

    yfn () {
	echo Y
    }
    zfn () {
	echo Z
    }

    xfn1 () {
	yfn
    }

    alias yfn=zfn

    xfn2 () {
	yfn
    }

Now:

    zsh% xfn1
    Y
    zsh% xfn2
    Z

Because the alias for yfn was introduced *after* xfn1 was defined, xfn1
still references the "real" yfn, rather than the alias.  The presumption
is that if you're going to use

    sws_fn yfn

Then you are also going to use

    sws_fn xfn1
    sws_fn xfn2

So that it doesn't matter what "yfn" means inside of xfn*.

-- 
Bart Schaefer                             Brass Lantern Enterprises
http://www.well.com/user/barts            http://www.nbn.com/people/lantern

New male in /home/schaefer:
>N  2 Justin William Schaefer  Sat May 11 03:43  53/4040  "Happy Birthday"



^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: Tag functions with shell options?
  1996-07-02 21:31         ` Bart Schaefer
@ 1996-07-02 22:27           ` Anthony Heading
  0 siblings, 0 replies; 10+ messages in thread
From: Anthony Heading @ 1996-07-02 22:27 UTC (permalink / raw)
  To: schaefer; +Cc: aheading, zsh-workers

Bart wrote:
> 
> } The lack of context was sort-of deliberate, since I
> } suspected any interest would be in the wider picture, rather than my
> } particular petty problems.  It seemed simply an example of something
> } it would be nice to support elegantly.
> 
> This introduces a whole class of problems, which is most obvious in the
> case when you *do not* know the names of the functions that should have
> their local options (or whatever) changed.  In that case you almost end
> up needing something like Perl's "package".

Right. I guess this is like what I would have thought of doing as a sort of
closure.  So a function, when defined, would snapshot its option-environment.

function setup() {
  setopt local_options closure_options sh_word_split
  . /someone/elses/setup/file.sh
}


> Because the alias for yfn was introduced *after* xfn1 was defined, xfn1
> still references the "real" yfn, rather than the alias.  The presumption
> is that if you're going to use

OK. As if aliases are resolved at parse-time. Or something. Perhaps they are.
I should RTFS. But I understand now. 

Thank-you all.

A



^ permalink raw reply	[flat|nested] 10+ messages in thread

end of thread, other threads:[~1996-07-02 22:35 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
1996-07-02 12:05 Tag functions with shell options? Anthony Heading
1996-07-02 13:36 ` Zefram
1996-07-02 14:12   ` Anthony Heading
1996-07-02 15:17     ` Zefram
1996-07-02 15:37 ` Peter Stephenson
1996-07-02 16:57   ` Anthony Heading
1996-07-02 19:07     ` Bart Schaefer
1996-07-02 19:53       ` Anthony Heading
1996-07-02 21:31         ` Bart Schaefer
1996-07-02 22:27           ` Anthony Heading

Code repositories for project(s) associated with this public inbox

	https://git.vuxu.org/mirror/zsh/

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).