* Detect if a script is being sourced vs executed @ 2014-09-12 17:57 Daniel Hahler 2014-09-12 19:05 ` Peter Stephenson 2014-09-12 20:09 ` Kurtis Rader 0 siblings, 2 replies; 6+ messages in thread From: Daniel Hahler @ 2014-09-12 17:57 UTC (permalink / raw) To: zsh-users I want to detect if a script is being sourced instead of being called. This is meant for pyenv, which uses shims to delegate execution to the selected Python version. Currently it always uses "exec" to do so, but there is a pull request to add support for scripts that are meant to be sourced (like virtualenvwrapper.sh), and then would use "source" instead of "exec" in the shim. The PR provides this functionality for Bash, which provides a way to detect this via $BASH_SOURCE/$BASH_LINENO: https://github.com/yyuu/pyenv/pull/100/files My current approach so far is the following, which requires Zsh 5.0.5 (for POSIX_ARGZERO) and does not work for "zsh test_source.sh" yet (a patch has been posted to zsh-workers to fix this). I would like to do this for older Zsh versions, and in a simpler / more elegant way. Script to be sourced (test_source.sh): #!/usr/bin/zsh echo "\$0: $0" sourced=0 if [ -n "$ZSH_VERSION" ]; then # Use prompt expansion to get the current file. cur_file=${(%):-%x} # Fix $0: if (( ${+options[posixargzero]} )); then # added in zsh 5.0.5 (2014-06-01) if [[ $options[posixargzero] != "on" ]]; then setopt posixargzero [ "$0" = "$cur_file" ] || sourced=1 setopt noposixargzero else [ "$0" = "$cur_file" ] || sourced=1 fi else echo "TODO" fi elif [ -n "$BASH_VERSION" ]; then [ "$0" = "$BASH_SOURCE" ] || sourced=1 fi echo "sourced: $sourced" Test script (test.sh): #!/usr/bin/zsh echo "== CALL" ./test_source.sh echo "== SOURCE" . ./test_source.sh echo "== CALL: bash" bash ./test_source.sh echo "== CALL: zsh" zsh ./test_source.sh echo "== EXEC" exec ./test_source.sh There must be an easier way!? It would be really useful, if Zsh would provide a mechanism like Bash to simplify this. Regards, Daniel. ^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: Detect if a script is being sourced vs executed 2014-09-12 17:57 Detect if a script is being sourced vs executed Daniel Hahler @ 2014-09-12 19:05 ` Peter Stephenson 2014-09-12 23:21 ` Bart Schaefer 2014-09-12 20:09 ` Kurtis Rader 1 sibling, 1 reply; 6+ messages in thread From: Peter Stephenson @ 2014-09-12 19:05 UTC (permalink / raw) To: zsh-users On Fri, 12 Sep 2014 19:57:19 +0200 Daniel Hahler <dhahler@gmail.com> wrote: > I want to detect if a script is being sourced instead of being called. I think this is difficult for older versions of zsh, but Bart will probably come up with something. I was surprised to find the zsh/parameter modules series of array parameters that allow you to trace back the functions, sourced files, etc. being executed don't give this information, which is present internally. This adds $functypestack to do this. So you need to see if $functypestack[1] is "source". diff --git a/Doc/Zsh/mod_parameter.yo b/Doc/Zsh/mod_parameter.yo index 32d4796..0dde813 100644 --- a/Doc/Zsh/mod_parameter.yo +++ b/Doc/Zsh/mod_parameter.yo @@ -201,7 +201,10 @@ The format of each element is var(filename)tt(:)var(lineno). For functions autoloaded from a file in native zsh format, where only the body of the function occurs in the file, or for files that have been executed by the tt(source) or `tt(.)' builtins, the trace information is -shown as var(filename)tt(:)var(0), since the entire file is the definition. +shown as var(filename)tt(:)var(0), since the entire file is the +definition. + +The most recent call is the first element in the array. Most users will be interested in the information in the tt(funcfiletrace) array instead. @@ -221,4 +224,13 @@ The format of each element is var(name)tt(:)var(lineno). Callers are also shown for sourced files; the caller is the point where the tt(source) or `tt(.)' command was executed. ) +vindex(functypestack) +item(tt(functrace))( +This array corresponds element by element with tt(funcstack) and +prints out `tt(source)' for a sourced file, `tt(function)' for a +function and `tt(eval)' for an eval'd expression. At the top +level of execution of a series of commands, tt($functypestack[1]) is +empty if the commands are being executed as a script, or one of the +strings above if the commands are being executed as that type. +) enditem() diff --git a/Src/Modules/parameter.c b/Src/Modules/parameter.c index 0385a70..02a642b 100644 --- a/Src/Modules/parameter.c +++ b/Src/Modules/parameter.c @@ -640,6 +640,41 @@ funcfiletracegetfn(UNUSED(Param pm)) return ret; } +/* Functions for the functypestack special parameter. */ + +static char ** +functypestackgetfn(UNUSED(Param pm)) +{ + Funcstack f; + int num; + char **ret, **p; + + for (f = funcstack, num = 0; f; f = f->prev, num++); + + ret = (char **) zhalloc((num + 1) * sizeof(char *)); + + for (f = funcstack, p = ret; f; f = f->prev, p++) + { + switch (f->tp) + { + case FS_SOURCE: + *p = "source"; + break; + + case FS_FUNC: + *p = "function"; + break; + + case FS_EVAL: + *p = "eval"; + break; + } + } + *p = NULL; + + return ret; +} + /* Functions for the builtins special parameter. */ /**/ @@ -2046,6 +2081,8 @@ static const struct gsu_array funcsourcetrace_gsu = { funcsourcetracegetfn, arrsetfn, stdunsetfn }; static const struct gsu_array funcfiletrace_gsu = { funcfiletracegetfn, arrsetfn, stdunsetfn }; +static const struct gsu_array functypestack_gsu = +{ functypestackgetfn, arrsetfn, stdunsetfn }; static const struct gsu_array reswords_gsu = { reswordsgetfn, arrsetfn, stdunsetfn }; static const struct gsu_array disreswords_gsu = @@ -2090,6 +2127,8 @@ static struct paramdef partab[] = { scanpmfunctions), SPECIALPMDEF("functrace", PM_ARRAY|PM_READONLY, &functrace_gsu, NULL, NULL), + SPECIALPMDEF("functypestack", PM_ARRAY|PM_READONLY, + &functypestack_gsu, NULL, NULL), SPECIALPMDEF("galiases", 0, &pmgaliases_gsu, getpmgalias, scanpmgaliases), SPECIALPMDEF("history", PM_READONLY, -- Peter Stephenson <p.w.stephenson@ntlworld.com> Web page now at http://homepage.ntlworld.com/p.w.stephenson/ ^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: Detect if a script is being sourced vs executed 2014-09-12 19:05 ` Peter Stephenson @ 2014-09-12 23:21 ` Bart Schaefer 2014-09-13 8:01 ` Peter Stephenson 0 siblings, 1 reply; 6+ messages in thread From: Bart Schaefer @ 2014-09-12 23:21 UTC (permalink / raw) To: zsh-users On Sep 12, 8:05pm, Peter Stephenson wrote: } } I was surprised to find the zsh/parameter modules series of array } parameters that allow you to trace back the functions, sourced files, } etc. being executed don't give this information, which is present } internally. This adds $functypestack to do this. Is this in some way NOT redundant with $zsh_eval_context ? Other than apparently being in the reverse order? torch% source =(<<<'() { print $zsh_eval_context }') toplevel file shfunc torch% source =(<<<'() { zmodload zsh/parameter; print $functypestack }') function source ^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: Detect if a script is being sourced vs executed 2014-09-12 23:21 ` Bart Schaefer @ 2014-09-13 8:01 ` Peter Stephenson 2014-09-16 19:14 ` Peter Stephenson 0 siblings, 1 reply; 6+ messages in thread From: Peter Stephenson @ 2014-09-13 8:01 UTC (permalink / raw) To: zsh-users On 13/09/2014, Bart Schaefer <schaefer@brasslantern.com> wrote: > On Sep 12, 8:05pm, Peter Stephenson wrote: > } > } I was surprised to find the zsh/parameter modules series of array > } parameters that allow you to trace back the functions, sourced files, > } etc. being executed don't give this information, which is present > } internally. This adds $functypestack to do this. > > Is this in some way NOT redundant with $zsh_eval_context ? Other than > apparently being in the reverse order? You'rr right, I was looking in the wrong place. It can be replacef simply by a cross-reference. pws ^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: Detect if a script is being sourced vs executed 2014-09-13 8:01 ` Peter Stephenson @ 2014-09-16 19:14 ` Peter Stephenson 0 siblings, 0 replies; 6+ messages in thread From: Peter Stephenson @ 2014-09-16 19:14 UTC (permalink / raw) To: zsh-users On Sat, 13 Sep 2014 09:01:21 +0100 Peter Stephenson <p.w.stephenson@ntlworld.com> wrote: > On 13/09/2014, Bart Schaefer <schaefer@brasslantern.com> wrote: > > On Sep 12, 8:05pm, Peter Stephenson wrote: > > } > > } I was surprised to find the zsh/parameter modules series of array > > } parameters that allow you to trace back the functions, sourced files, > > } etc. being executed don't give this information, which is present > > } internally. This adds $functypestack to do this. > > > > Is this in some way NOT redundant with $zsh_eval_context ? Other than > > apparently being in the reverse order? > > You're right, I was looking in the wrong place. It can > be replaced simply by a cross-reference. They also don't actually quite correspond -- you can get extra entries in zsh_eval_context since it intercepts the lowest level of code execution while the funcstack stuff is done for each applicable layer separately. So there's potentially some use for functypestack --- however, it's not needed for the purpose here, where $zsh_eval_context[-1] is good enough (it'll be either "toplevel" or "file"). diff --git a/Doc/Zsh/mod_parameter.yo b/Doc/Zsh/mod_parameter.yo index c157160..7886d0e 100644 --- a/Doc/Zsh/mod_parameter.yo +++ b/Doc/Zsh/mod_parameter.yo @@ -201,10 +201,7 @@ The format of each element is var(filename)tt(:)var(lineno). For functions autoloaded from a file in native zsh format, where only the body of the function occurs in the file, or for files that have been executed by the tt(source) or `tt(.)' builtins, the trace information is -shown as var(filename)tt(:)var(0), since the entire file is the -definition. - -The most recent call is the first element in the array. +shown as var(filename)tt(:)var(0), since the entire file is the definition. Most users will be interested in the information in the tt(funcfiletrace) array instead. @@ -215,6 +212,14 @@ This array contains the names of the functions, sourced files, and (if tt(EVAL_LINENO) is set) tt(eval) commands. currently being executed. The first element is the name of the function using the parameter. + +The standard shell array tt(zsh_eval_context) can be used to +determine the type of shell construct being executed at each depth: +note, however, that is in the opposite order, with the most recent +item last, and it is more detailed, for example including an +entry for tt(toplevel), the main shell code being executed +either interactively or from a script, which is not present +in tt($funcstack). ) vindex(functrace) item(tt(functrace))( @@ -224,13 +229,4 @@ The format of each element is var(name)tt(:)var(lineno). Callers are also shown for sourced files; the caller is the point where the tt(source) or `tt(.)' command was executed. ) -vindex(functypestack) -item(tt(functypestack))( -This array corresponds element by element with tt(funcstack). -Each element contains `tt(source)' for a sourced file, `tt(function)' -for a function and `tt(eval)' for an tt(eval)'d expression. At the top -level of execution of a series of commands, tt($functypestack[1]) is -empty if the commands are being executed as a script, or one of the -previous strings if the commands are being executed as that type. -) enditem() diff --git a/Src/Modules/parameter.c b/Src/Modules/parameter.c index 02a642b..0385a70 100644 --- a/Src/Modules/parameter.c +++ b/Src/Modules/parameter.c @@ -640,41 +640,6 @@ funcfiletracegetfn(UNUSED(Param pm)) return ret; } -/* Functions for the functypestack special parameter. */ - -static char ** -functypestackgetfn(UNUSED(Param pm)) -{ - Funcstack f; - int num; - char **ret, **p; - - for (f = funcstack, num = 0; f; f = f->prev, num++); - - ret = (char **) zhalloc((num + 1) * sizeof(char *)); - - for (f = funcstack, p = ret; f; f = f->prev, p++) - { - switch (f->tp) - { - case FS_SOURCE: - *p = "source"; - break; - - case FS_FUNC: - *p = "function"; - break; - - case FS_EVAL: - *p = "eval"; - break; - } - } - *p = NULL; - - return ret; -} - /* Functions for the builtins special parameter. */ /**/ @@ -2081,8 +2046,6 @@ static const struct gsu_array funcsourcetrace_gsu = { funcsourcetracegetfn, arrsetfn, stdunsetfn }; static const struct gsu_array funcfiletrace_gsu = { funcfiletracegetfn, arrsetfn, stdunsetfn }; -static const struct gsu_array functypestack_gsu = -{ functypestackgetfn, arrsetfn, stdunsetfn }; static const struct gsu_array reswords_gsu = { reswordsgetfn, arrsetfn, stdunsetfn }; static const struct gsu_array disreswords_gsu = @@ -2127,8 +2090,6 @@ static struct paramdef partab[] = { scanpmfunctions), SPECIALPMDEF("functrace", PM_ARRAY|PM_READONLY, &functrace_gsu, NULL, NULL), - SPECIALPMDEF("functypestack", PM_ARRAY|PM_READONLY, - &functypestack_gsu, NULL, NULL), SPECIALPMDEF("galiases", 0, &pmgaliases_gsu, getpmgalias, scanpmgaliases), SPECIALPMDEF("history", PM_READONLY, -- Peter Stephenson <p.w.stephenson@ntlworld.com> Web page now at http://homepage.ntlworld.com/p.w.stephenson/ ^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: Detect if a script is being sourced vs executed 2014-09-12 17:57 Detect if a script is being sourced vs executed Daniel Hahler 2014-09-12 19:05 ` Peter Stephenson @ 2014-09-12 20:09 ` Kurtis Rader 1 sibling, 0 replies; 6+ messages in thread From: Kurtis Rader @ 2014-09-12 20:09 UTC (permalink / raw) To: Daniel Hahler; +Cc: Zsh Users [-- Attachment #1: Type: text/plain, Size: 2506 bytes --] Here's an example of what I use in my scripts (zsh 5.0.2): if [[ $ZSH_EVAL_CONTEXT == 'toplevel' ]]; then # We're not being sourced so run the colors command which in turn sources # this script and uses its content to produce representative output. colors fi On Fri, Sep 12, 2014 at 10:57 AM, Daniel Hahler <dhahler@gmail.com> wrote: > I want to detect if a script is being sourced instead of being called. > > This is meant for pyenv, which uses shims to delegate execution to the > selected Python version. > > Currently it always uses "exec" to do so, but there is a pull request to > add support for scripts that are meant to be sourced (like > virtualenvwrapper.sh), and then would use "source" instead of "exec" in the > shim. > > The PR provides this functionality for Bash, which provides a way to > detect this via $BASH_SOURCE/$BASH_LINENO: > https://github.com/yyuu/pyenv/pull/100/files > > > My current approach so far is the following, which requires Zsh 5.0.5 (for > POSIX_ARGZERO) and does not work for "zsh test_source.sh" yet (a patch has > been posted to zsh-workers to fix this). > > I would like to do this for older Zsh versions, and in a simpler / more > elegant way. > > > Script to be sourced (test_source.sh): > > #!/usr/bin/zsh > > echo "\$0: $0" > > sourced=0 > if [ -n "$ZSH_VERSION" ]; then > # Use prompt expansion to get the current file. > cur_file=${(%):-%x} > > # Fix $0: > if (( ${+options[posixargzero]} )); then # added in zsh 5.0.5 > (2014-06-01) > if [[ $options[posixargzero] != "on" ]]; then > setopt posixargzero > [ "$0" = "$cur_file" ] || sourced=1 > setopt noposixargzero > else > [ "$0" = "$cur_file" ] || sourced=1 > fi > else > echo "TODO" > fi > > elif [ -n "$BASH_VERSION" ]; then > [ "$0" = "$BASH_SOURCE" ] || sourced=1 > fi > > echo "sourced: $sourced" > > > Test script (test.sh): > > #!/usr/bin/zsh > > echo "== CALL" > ./test_source.sh > > echo "== SOURCE" > . ./test_source.sh > > echo "== CALL: bash" > bash ./test_source.sh > > echo "== CALL: zsh" > zsh ./test_source.sh > > echo "== EXEC" > exec ./test_source.sh > > > There must be an easier way!? > > It would be really useful, if Zsh would provide a mechanism like Bash to > simplify this. > > > Regards, > Daniel. > -- Kurtis Rader Caretaker of the exceptional canines Junior and Hank ^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2014-09-16 19:20 UTC | newest] Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2014-09-12 17:57 Detect if a script is being sourced vs executed Daniel Hahler 2014-09-12 19:05 ` Peter Stephenson 2014-09-12 23:21 ` Bart Schaefer 2014-09-13 8:01 ` Peter Stephenson 2014-09-16 19:14 ` Peter Stephenson 2014-09-12 20:09 ` Kurtis Rader
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).