malxau / yori

Yori is a CMD replacement shell that supports backquotes, job control, and improves tab completion, file matching, aliases, command history, and more.
http://www.malsmith.net/yori/
MIT License
1.24k stars 31 forks source link

Yori script execution #70

Closed aleaksunder closed 3 years ago

aleaksunder commented 3 years ago

Hi!

There is something with "yori.exe" arguments interpretation... The thing is that there is four parameters on "yori.exe" and when I am trying to combine it something weird going on:

  1. If I try to launch yori script with command line something like that:

    yori.exe -nouser -c "C:\path\script.ys1"

    than nothing happens... it simply starts new yori executable

  2. When I try to do otherwise:

    yori.exe -c "C:\path\script.ys1" -nouser 

    that yori start the script and "-nouser" will be the %1% parameter in this script during execution.

I guess this is due to that code: https://github.com/malxau/yori/blob/24024b6b412847b6f2fe6d2f5382d07bebda9faf/sh/main.c#L387-L405

malxau commented 3 years ago

I think the bug here was the handling of -nouser in that it used break to terminate parsing. Most of these arguments are expected to terminate parsing to allow all future arguments to go to the script (as happened in the second example. The bug is that the first example is expected to work, but -nouser caused parsing to terminate, which is why it ignored the rest and launched a new shell.

aleaksunder commented 3 years ago

Thanks a lot!!! And there is another issue with script execution. EXIT command simply ignored, this script file will ECHO:

{ any code }
EXIT
ECHO 123

Is there a way to terminate script execution without "GOTO :EOF" statement? Simply just want to make EXIT raising errorlevel, just as CMD does: EXIT /B 1 for example

I can create another issue for this or we may continue here

malxau commented 3 years ago

I tried the script you mention and exit terminated the shell process, so the echo never ran.

I pushed two commits related to this, but I'm not really happy about these behaviors; it seems like there are three different concepts and I'm using two commands to express them:

Previously, Yori had the exit command for the first concept and the return command for the third concept. The second concept could be expressed with goto :eof but as you point out, that makes specifying the error code impossible. I extended the return command to allow for returning from a script, which should be compatible because previously the return statement was undefined when not running from a subroutine. However, this still leaves exiting a script from within a subroutine as inexpressible, and the behavior of return is very different depending on whether a subroutine is active or not. Within a subroutine this will provide isolation (restoring environment and current directory) but from the global scope in a script no isolation is provided.

So what I'd really like is to split return into a second command, but I'm not sure what word to use to express it.

Anyway, commit 2f8ca8dd508eb3fe2d131c511c9298fbbe8dddca allows exit to specify an exit code and commit ec8e3adaef01f3d0b85157a65532dfa9e830ff0d allows return to do something from the global scope of a script.

aleaksunder commented 3 years ago

Recompiled yori with current source... It is more simple to see with that code:

ECHO First
EXIT
ECHO Second
PAUSE

Yes, it exists the script but only after all commands are executed.

For the rest... I think in a nutshell script is nothing more than subroutine for the shell, or maybe just routine, that may have subroutine and RETURN for the script is a very good idea, since it can not only specify exit code but export environment variables in global scope! So if EXIT means to terminate the shell, RETURN means to return something to the shell, it is clear and obvious, and the problem with RETURN for subroutine and RETURN for the script can be solved with for example '-g' switch:

So within subroutine: RETURN 123 var1 var2 var3 means end subroutine returing exit code 123 and saving vars RETURN -G 123 var1 var2 var3 means end global routine saving vars But there is a dillemma... what vars subroutine must save: it's own or var of global routine ( script ) However this is just a variant.

Another variant is new QUIT command for the script, which has identical functionality as RETURN but operates only in script scope.

  1. EXIT exits the shell
  2. QUIT ends the script
  3. RETURN ends the subroutine

Not so bad at first glance, but you're right... there are many variants, it needs more time to decide which is better

malxau commented 3 years ago

I pushed commit 731b03637f54eeea93e3351a424371007d7c6049 to ensure that exit from partway through a script terminates script parsing.

What's frustrating about returning from the global scope in a script is it's just so common for CMD scripts to expect their effects to be public, which is why the global scope doesn't (by default) isolate state. This can be done with setlocal and endlocal . I'd agree that isolating state and forcing scripts to declare their intended effects is technically cleaner, but it's very different.

aleaksunder commented 3 years ago

Thanks for quick responses!

P.S. As for me right now feature described in (https://github.com/malxau/yori/issues/58) is most desireble. Good luck!