zsh-users
 help / color / mirror / code / Atom feed
* activate alias inside subshell
@ 2018-04-06 16:29 Ray Andrews
  2018-04-07 19:57 ` Ray Andrews
  0 siblings, 1 reply; 8+ messages in thread
From: Ray Andrews @ 2018-04-06 16:29 UTC (permalink / raw)
  To: Zsh Users

Sourcing this:

    mag=$'\e[35;1m'
    cyn=$'\e[36;1m'
    nrm=$'\e[0m'

    alias msg='echo $cyn alias outside $nrm'
    whence -v msg
    msg "called outside"

    function test1 ()
    {
    (
    msg "called inside"
    unalias msg
    alias msg='echo $mag alias inside $nrm'
    whence -v msg
    msg "called inside function"
    )
    }
    echo "\nnow test:\n"
    test1

    whence -v msg
    msg "called outside function"

    echo "\n==================================\n"

I get:

    15 /aWorking/Zsh/Source/Wk 7 $ . test1
    msg is an alias for echo $cyn alias outside $nrm << fine
      alias outside  called outside << fine

    now test:

      alias outside  called inside << fine
    msg is an alias for echo $mag alias inside $nrm << whence is correct
      alias outside  called inside function << but the old alias is used
    anyway.
    msg is an alias for echo $cyn alias outside $nrm << original alias
    undisturbed, good.
      alias outside  called outside function   << fine

    ==================================

... so I have an apparent localization of the alias as far as whence is 
concerned but it is not acted upon.  Can that be rectified?  I tried a 
few variations, one succeeds in having it exactly backwards, the 
external alias is used inside and the redefined alias is used 
externally, but a second run fixes that, it seems the alias must always 
be defined before the function is sourced.  Can we have instant 
gratification with an alias change inside a function?  I'd have thought 
that the subshell would make it easy.  In any case one would think that 
the alias that whence reports would be the alias in effect.

What I'm actually trying to do is reduce verbosity of a function by 
redefining various message printer functions as null.  It works fine 
with functions, but if the message printers are aliases (which seem to 
be the only way to get:  ${(%):-%x %I} ... line information printed, it 
seems that can't be done in a function) ... then it goes sour.  For example:

     [[ "$vverbose" < 3 ]] &&
     {
         warningmsg () { ; }
      }

... I kill the message by nullifying the function that prints it (it's 
nothing but a colorized line).  In the subshell it's all local, no 
damage outside the function.  But when debugging I like the line 
numbers, so 'warningmsg' becomes an alias:

     alias warningmsg=' echo -en "${(%):-%x %I}: " && magline ' # Just 
colorizes.  I wish we could do that in a function.

... but now, when I want to kill messages, as above, efforts to neuter 
the alias fail.  The whole thing is very suspect.  I had thought to 
redefine the alias like this:

         local alias warningmsg='#'

... which is probably outrageous, but the idea is that it would turn the 
text of the message into a comment.  I'm probably best to forget the 
whole thing, but I do love the line numbers and killing messages by 
nullifying message functions works like a charm ... but not with 
aliases.  Can I have my cake and eat it too?  Some elegant solution?





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

* Re: activate alias inside subshell
  2018-04-06 16:29 activate alias inside subshell Ray Andrews
@ 2018-04-07 19:57 ` Ray Andrews
  2018-04-08  7:39   ` Bart Schaefer
  0 siblings, 1 reply; 8+ messages in thread
From: Ray Andrews @ 2018-04-07 19:57 UTC (permalink / raw)
  To: zsh-users


> Some elegant solution?
>

>     " As a consequence, aliases defined in a function are not
>     available until after that function is executed. To be safe,
>     always put alias definitions on a separate line, and do not use
>     alias in compound commands.
>
> And another quote, this time from |zsh| manual:
>
>     There is a commonly encountered problem with aliases illustrated
>     by the following code:
>
>     |alias echobar='echo bar';echobar|
>
>     This prints a message that the command echobar could not be found."
>
Ok, that is clear.  Too bad whence seems to report the thing as active, 
that had me beating my head against the wall.  Something like a runtime 
expansion would be a nice option to have but it seems that unheard of.   
But another mystery:


    mag=$'\e[35;1m'
    cyn=$'\e[36;1m'
    nrm=$'\e[0m'

    yelline () { echo -e "$yel$@$nrm" }

    function msg () { echo -e "${grn}$@${nrm}" }
    alias msg='yelline ${(%):-%x %I}:'

    function test1 ()
    {
    (
    whence -va msg; declare -f msg
    msg one

    msg () { echo nulled }

    whence -va msg; declare -f msg
    msg where has the alias gone?
    echo "\n==========================\n"
    )
    }

Output:

     $ . test1; test1

    msg is an alias for yelline ${(%):-%x %I}: <<  fine
    msg is a shell function from test1                  << fine,
    function is right and alias is there
    msg () {
         echo -e "${grn}$@${nrm}"
    }
    test1 14: one <<  fine, the alias is  in effect.
    msg is an alias for yelline ${(%):-%x %I}:     << ok ..
    msg is a shell function from test1                 << ... but the
    function is not updated and ...
    msg () {
         echo -e "${grn}$@${nrm}"
    }
    nulled                                                  << ... the
    changed function now overrides the alias!

... in practice this is exactly what I need in the current situation -- 
to kill either function or alias, but it does seem strange that changing 
a function causes it to override an alias.  Is this documented somewhere?



>


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

* Re: activate alias inside subshell
  2018-04-07 19:57 ` Ray Andrews
@ 2018-04-08  7:39   ` Bart Schaefer
  2018-04-08 14:56     ` Ray Andrews
  0 siblings, 1 reply; 8+ messages in thread
From: Bart Schaefer @ 2018-04-08  7:39 UTC (permalink / raw)
  To: Zsh Users

I'm not going to try to respond blow-by-blow to your messages, because
there still seem to be some concepts about aliasing that we've
discussed in past threads that you don't appear to be applying.

Firstly, though, there's something that doesn't add up about your
"test1" example; as you quoted it, "yelline" references a variable
$yel that's never assigned, and if I attempt to replicate verbatim in
a freshly-started shell what you say you've done, I get exactly the
errors I expected:

% . test1; test1
test1:10: defining function based on alias `msg'
test1:14: parse error near `()'
zsh: command not found: test1

I suspect you're using a shell in which you've been running other
tests and something from an earlier experiment is spilling over to
confuse you.  Either that, or you haven't actually shown us the full
contents of the "test1" file.

The fundamental thing you're forgetting is that aliases act by text
replacement.  "whence" will tell you whether an alias WILL replace
text the NEXT time the lexer is invoked, but that has no meaning for
text that has previously been parsed.  Function definitions are always
fully lexed+parsed before they are executed, so once a function is
defined any aliases it may have used have been replaced by the
expanded text of the alias and can never expand again.

We explained this several threads ago when you were shown the "eval"
example.  "eval" runs the parser again so aliases have a chance to
expand.

Thus:

% alias msg='echo this is an alias'
% test1() { msg in test1 }
% functions test1
test1 () {
    echo this is an alias in test1
}
%

See how the use of the alias is no longer present in the stored
definition of test1?  Note that it's important that the alias and the
function were defined separately (in this example at separate PS1
prompts), so that the parser was run a second time AFTER the alias was
defined.

Compare running the parser only once, by using a multi-line construct
(I have started a fresh "zsh -f" for each of these examples even
though I've changed the function names to differentiate them):

% {
cursh> alias msg='echo this is an alias'
cursh> test2() { msg in test2 }
cursh> }
% functions test2
test2 () {
    msg in test2
}
% test2
test2: command not found: msg
%

Here test2 was parsed at the same time as the alias command, so the
alias was not yet "active" when the body of test2 was read, and thus
the alias definition is both not expanded in test2 and also irrelevant
at the time the function is executed.

However, that has no bearing on what "whence" will say about the
current state of the alias at the time the function is executed:

% {
cursh> alias msg='echo this is an alias'
cursh> test3() { whence -v msg; msg }
cursh> }
% test3
msg is an alias for echo this is an alias
test3: command not found: msg
%

Something like this must be involved in producing the "nulled" output
from the example you posted.


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

* Re: activate alias inside subshell
  2018-04-08  7:39   ` Bart Schaefer
@ 2018-04-08 14:56     ` Ray Andrews
  2018-04-08 20:18       ` Bart Schaefer
  2018-04-08 22:38       ` Ray Andrews
  0 siblings, 2 replies; 8+ messages in thread
From: Ray Andrews @ 2018-04-08 14:56 UTC (permalink / raw)
  To: zsh-users

On 08/04/18 12:39 AM, Bart Schaefer wrote:
> I'm not going to try to respond blow-by-blow to your messages, because
> there still seem to be some concepts about aliasing that we've
> discussed in past threads that you don't appear to be applying.

It does take a while for some things to stick, but they do stick 
eventually.  There are so many things assumed to be understood in the 
culture.  Misunderstood, answers don't really gel, the mind hunts for a 
'get it' but the 'get it' is false.  Like only recently do I finally 
really get it as to bleeding newlines in arrays -- not there!
> Firstly, though, there's something that doesn't add up about your
> "test1" example; as you quoted it, "yelline" references a variable
> $yel that's never assigned,
Pardon, I try to copy in all the relevant bits and pieces from my 
environment.  That's just the code for 'yellow' of course.  What's the 
best way to run something as a test for fitness to export it, as to 
here, for example?  I mean a way of ensuring that it's entirely 
self-contained as to things like that and nothing has been left out or 
assumed?
> I suspect you're using a shell in which you've been running other
> tests and something from an earlier experiment is spilling over to
> confuse you.  Either that, or you haven't actually shown us the full
> contents of the "test1" file.
Sure.  As above, I'm always worried that there's some local setting or 
glitch that makes my code invalid as far as other people pasting it from 
an email and getting the same results.  I need a sort of 'virgin' test 
before sending these things on.  Should have got that squared away years 
ago.
> The fundamental thing you're forgetting is that aliases act by text
> replacement.  "whence" will tell you whether an alias WILL replace
> text the NEXT time the lexer is invoked, but that has no meaning for
> text that has previously been parsed.  Function definitions are always
> fully lexed+parsed before they are executed, so once a function is
> defined any aliases it may have used have been replaced by the
> expanded text of the alias and can never expand again.
Ok, so whence is simply obeying the 'not active till next time' rule.  
Not very friendly but it is consistent with the law of aliases.
> % alias msg='echo this is an alias'
> % test1() { msg in test1 }
> % functions test1
> test1 () {
>      echo this is an alias in test1
> }
> %
>
> See how the use of the alias is no longer present in the stored
> definition of test1?

That at least is exactly as I expect, it's a macro.

> Note that it's important that the alias and the
> function were defined separately (in this example at separate PS1
> prompts), so that the parser was run a second time AFTER the alias was
> defined.
>
> Compare running the parser only once, by using a multi-line construct
> (I have started a fresh "zsh -f" for each of these examples even
> though I've changed the function names to differentiate them):

Is 'zsh -f' the answer to the above -- a truly clean test of something?

> Here test2 was parsed at the same time as the alias command, so the
> alias was not yet "active" when the body of test2 was read, and thus
> the alias definition is both not expanded in test2 and also irrelevant
> at the time the function is executed.

So:

$ alias msg ... ; test2 () { msg }

and:

$ alias msg ...
$ test2 () { msg }

... are very different!  In the former the alias is 'pending' in the 
latter, it is active, yes?  That's easy not to know.

> Something like this must be involved in producing the "nulled" output
> from the example you posted.

Ok, let me hack away at it a bit more.  Nevermind whence, the only 
serious issue is the way the redefined function seems to kill the alias 
within the subshell within the calling function.  Again, it turns out 
that this is exactly what I want, but not something I understand.  It is 
as if the fact that the redefined function has the same name as the 
alias overwrites the namespace within the subshell so the alias 
vanishes.  If so, that could be seen as a feature not a bug.

BTW, results are hugely different if the redefined message function is 
redefined with or without 'function' prepended: " function msg () ... " 
vs. " msg () ... ".  Most comments found on the internet suggest there 
should be no difference but that is not so, one changes things 
externally, the other does not.  It added to the confusion.



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

* Re: activate alias inside subshell
  2018-04-08 14:56     ` Ray Andrews
@ 2018-04-08 20:18       ` Bart Schaefer
  2018-04-08 20:54         ` Ray Andrews
  2018-04-08 22:38       ` Ray Andrews
  1 sibling, 1 reply; 8+ messages in thread
From: Bart Schaefer @ 2018-04-08 20:18 UTC (permalink / raw)
  To: zsh-users

On Apr 8,  7:56am, Ray Andrews wrote:
}
} Is 'zsh -f' the answer to the above -- a truly clean test of something?

The first thing asked following most bug reports is "can you reproduce
this from zsh -f?"  So yes.  Start from -f and then load the minimum
number of changes to try what you want to try (e.g., add extendedglob
if necessary, zmodload zsh/parameter or other required modules, etc.).
 
} So:
} 
} $ alias msg ... ; test2 () { msg }
} 
} and:
} 
} $ alias msg ...
} $ test2 () { msg }
} 
} ... are very different!  In the former the alias is 'pending' in the 
} latter, it is active, yes?  That's easy not to know.

Yes, that's correct.  "alias" is really intended only to make interactive
shells easier (reduce typing), not to abbreviate scripts (even if the
script is going to be used interactively later).

} BTW, results are hugely different if the redefined message function is 
} redefined with or without 'function' prepended: " function msg () ... " 
} vs. " msg () ... ".  Most comments found on the internet suggest there 
} should be no difference

There's no difference when "msg" is not an alias.  But in
    msg() ...
the word "msg" is in command position and therefore subject to alias
expansion, whereas in
    function msg () ...
it is *not* in command position and will not be alias-expanded.


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

* Re: activate alias inside subshell
  2018-04-08 20:18       ` Bart Schaefer
@ 2018-04-08 20:54         ` Ray Andrews
  0 siblings, 0 replies; 8+ messages in thread
From: Ray Andrews @ 2018-04-08 20:54 UTC (permalink / raw)
  To: zsh-users

On 08/04/18 01:18 PM, Bart Schaefer wrote:
> On Apr 8,  7:56am, Ray Andrews wrote:
> }
> } Is 'zsh -f' the answer to the above -- a truly clean test of something?
>
> The first thing asked following most bug reports is "can you reproduce
> this from zsh -f?"  So yes.  Start from -f and then load the minimum
> number of changes to try what you want to try (e.g., add extendedglob
> if necessary, zmodload zsh/parameter or other required modules, etc.).

Thanks, I hate wasting everyone's time over really elementary issues 
like that.
> } ... are very different!  In the former the alias is 'pending' in the
> } latter, it is active, yes?  That's easy not to know.
>
> Yes, that's correct.  "alias" is really intended only to make interactive
> shells easier (reduce typing), not to abbreviate scripts (even if the
> script is going to be used interactively later).

I've always distrusted any sort of macro and I use aliases only in the 
most limited way possible.  The anomaly is with that 'print function and 
line' code which seems to be impossible to put inside a function via 
another function except via an alias IF you want to be able to turn it 
on and off, thus the can of worms is opened and after that it becomes a 
matter more of education.  I do understand that  " ${(%):-%x %I} " is a 
parse time thing which is why that string can't be in a function called 
by another function and report anything other than its position in the 
immediate function, so the alias seems inevitable.   If there was such a 
thing as a runtime expansion of an alias, sorta an automatic 'eval',  
that would be cool but I can believe that such a thing is just not on.
>
> } BTW, results are hugely different if the redefined message function is
> } redefined with or without 'function' prepended: " function msg () ... "
> } vs. " msg () ... ".  Most comments found on the internet suggest there
> } should be no difference
>
> There's no difference when "msg" is not an alias.  But in
>      msg() ...
> the word "msg" is in command position and therefore subject to alias
> expansion, whereas in
>      function msg () ...
> it is *not* in command position and will not be alias-expanded.
>
Ah!!  Nuts ... I'm unconsciously thinking that a function definition is 
somehow immune to alias substitution.  Why would it be?  And yes, the 
'command position' thing is easy to forget about.  I know it in theory 
but in practice ...

Ok, I'll bet that's everything I need to understand my issue.



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

* Re: activate alias inside subshell
  2018-04-08 14:56     ` Ray Andrews
  2018-04-08 20:18       ` Bart Schaefer
@ 2018-04-08 22:38       ` Ray Andrews
  2018-04-09  4:11         ` Ray Andrews
  1 sibling, 1 reply; 8+ messages in thread
From: Ray Andrews @ 2018-04-08 22:38 UTC (permalink / raw)
  To: zsh-users


> BTW, results are hugely different if the redefined message function is 
> redefined with or without 'function' prepended: " function msg () ... 
> " vs. " msg () ... ".  Most comments found on the internet suggest 
> there should be no difference but that is not so, one changes things 
> externally, the other does not.  It added to the confusion.
>
Well zsh-5.5 behaves quite differently with or without '-f':

# . test1; test1
test1:6: defining function based on alias `msg'
test1:16: parse error near `()'
zsh: permission denied: test1

... so it seems that I'm not going to get away with my previous 
anymore.   Is there a new strategy that might work?  Nullify the 
function and/or the alias?  Really, just some way of stopping messages 
from printing at all?
>
>


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

* Re: activate alias inside subshell
  2018-04-08 22:38       ` Ray Andrews
@ 2018-04-09  4:11         ` Ray Andrews
  0 siblings, 0 replies; 8+ messages in thread
From: Ray Andrews @ 2018-04-09  4:11 UTC (permalink / raw)
  To: zsh-users

On 08/04/18 03:38 PM, Ray Andrews wrote:
>
>
> ... so it seems that I'm not going to get away with my previous 
> anymore.   Is there a new strategy that might work?  Nullify the 
> function and/or the alias?  Really, just some way of stopping messages 
> from printing at all?
>>
Heck it's easy, and no need for anything sick and twisted.  Case closed. 
Thanks for your patience Bart.
>>
>
>


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

end of thread, other threads:[~2018-04-09  4:11 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-04-06 16:29 activate alias inside subshell Ray Andrews
2018-04-07 19:57 ` Ray Andrews
2018-04-08  7:39   ` Bart Schaefer
2018-04-08 14:56     ` Ray Andrews
2018-04-08 20:18       ` Bart Schaefer
2018-04-08 20:54         ` Ray Andrews
2018-04-08 22:38       ` Ray Andrews
2018-04-09  4:11         ` Ray Andrews

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).