execline: pushing and popping the environment
Keywords: execline environment push pop el_pushenv el_popenv

execline
Software
skarnet.org

# Pushing and popping the environment

The execlineb launcher can store positional parameters, i.e. arguments given to your script, into the environment. The `#` variable contains the number of arguments; the `0` variable contains the name of your execline script; the `1` variable contains the first argument; and so on.

Up to execline-1.04, this could create problems with nested scripts: the inner script would overwrite the outer script's parameters, and there was no way to get them back. In particular, writing execline commands in the execline language via the runblock command was impossible.

To solve that issue
, execline now implements a kind of environment stack. When execlineb reads the arguments, it does not overwrite the positional parameters, but pushes them on a stack:

- `#` will be set to the current number of arguments
- but if a variable named `#` existed before, it is renamed `#:1`
- and if a variable named `#:1` also existed, it is renamed `#:2`
- ... and so on until `#:n+1` doesn't exist.

Same goes for the other positional parameters.

The script then runs; and commands such as elgetpositionals use the current frame of positional parameters, without paying attention to the deeper levels.

When you are done with the arguments
, it is advisable to drop the current frame, and pop the environment stack to get it back to its previous state:

- `#` will be unset
- but if `#:1` exists, it will be renamed `#`
- and if `#:2` exists, it will be renamed `#:1`
- ... and so on until `#:n+1` doesn't exist.

Again, same goes for the other positional parameters.
The runblock command will perform that pop operation automatically; the standard "manual" way to perform it is to use the emptyenv -P command.

## A pop example

Suppose you want to run the long-lived program prog after printing the list of its arguments.

     #!/command/execlineb
     elgetpositionals
     foreground { echo $0 $@ }
     prog $@

will work, but will pollute prog's environment with a set of positional parameters that have no meaning to it. A better script is:

     #!/command/execlineb
     elgetpositionals
     foreground { echo $0 $@ }
     emptyenv -P
     prog $@

which will run prog with the same environment as the script's caller.

## Substituting positional parameters without touching the environment

Most of the time, you just need to substitute the positional parameters in your execline script, and don't need to go through the whole elgetpositionals and emptyenv chain. execline comes with an integrated substitution mechanism, that does not touch the environment at all: the `-S n` option.

Scripts beginning with:

    #!/command/execlineb -Sn
    foobar...

are equivalent to:

    #!/command/execlineb
    elgetpositionals -Pn
    emptyenv -P
    foobar...

So, to summarize, from most efficient (but less flexible) to least efficient (but more flexible):

- Use `execlineb -P` if you don't need positional parameters at all; for instance, in s6 or runit run scripts.
- Use `execlineb -Sn` if you need only simple positional parameter substitution in your script - no shift or elgetopt, no `importas 1 1`.
- Use `execlineb -p`, then `elgetpositionals` if you don't mind overwriting the current stack of positional parameters.
- Use `execlineb`, then `elgetpositionals`, then `emptyenv -P` if you need the full power of positional parameter handling.