Closed hyphenrf closed 3 years ago
I don't know what is the original reason, but it would increase pollution of the global namespace for no good reason and make it harder to opt-out of such behaviour. Currently you can make it behave the way you want simply by redefining %dispatch
hook in .esrc
or your script so I think this is a better default.
let (dispatch = $fn-%dispatch)
fn %dispatch { status = <={$dispatch $*} }
I'm not sure exactly what's happening, but it seems that because %dispatch
is dynamically bound, the $fn-%dispatch
we have on .esrc
is not the same one in the interactive shell, which seems to break this solution down.
when I try to echo $fn-%dispatch
within or outside of .esrc
, I get an empty definition, and when I try to print $status
on a new interactive shell, I get the return value of the last definition inside .esrc
and it doesn't change on every new "dispatch" which made me make those guesses.
Ah, you're right. The above would work in a script but %dispatch
is reset at the start of input, which is later than I thought and after the .esrc
finishes running. (It is also set separately for every .
sourced file to one of those according to the flags given.) So basically one would have to modify instead the functions it gets reset to.
fn %eval-noprint { status = <=$* }
fn %eval-print { echo $* >[1=2]; status = <=$* }
This should do the trick, but admittedly is less pretty than I hoped it be.
that did the trick :)
it's also worth noting that $status
is, with this solution, not reset between different evaluation contexts, probably because all vars that aren't let-scoped are exported by default(?)
so for example if I redefine %eval-*
in the middle of my .esrc
, then I open a new interactive shell, my $status
variable will contain the last return value of the last expression in .estc
. similarly, my $status
carries over to the first expression in any script I run.
I think redefining the loop prevents that? if only because the loop is run on every new session separately and at the head of that function, status is zeroed.
by that I mean:
let ( loop = $fn-%interactive-loop )
fn %interactive-loop { status = 0; $loop }
let ( loop = $fn-%batch-loop )
fn %batch-loop { status = 0; $loop }
Yes, that should do it, and putting it in .esrc
should work (you could of course put the whole loop modified as you initially proposed there too).
Dynamically scoped variables are indeed exported by default and I suppose it would be good to add noexport = $noexport status
to prevent that, but this affects only places where it's serialized to the environment. Values of global variables are always preserved between different contexts (including through fork
).
Thank you. until a modification like this is considered as the default, I feel like it's safe to close this issue for now.
It may be useful in many applications where you want to find a command's return status after the fact, not while executing it.
usually to get a command's status we wrap it in
<={ ... }
, but currently I know of no way to get a command's return status after it had executed. exposing$result
by not making its scope local to%interactive-loop
(and maybe renaming it to$status
so that there's less confusion with theresult
keyword) would allow for that.https://github.com/wryun/es-shell/blob/fe5e3a35c40d87bc0ef64ba3624767bccc270170/initial.es#L634-L635 https://github.com/wryun/es-shell/blob/fe5e3a35c40d87bc0ef64ba3624767bccc270170/initial.es#L652-L663