Improve `gno run`
The gno run command is presently in a pre-alpha phase and may not perform reliably due to its specific requirements for package and function naming.
Its primary objective is to facilitate a smooth transition for developers from Go by allowing them to start with a basic main function. Additionally, it aims to provide utility tools for those who are forking or reviewing a package.
To enhance its usability and commence documentation in guides, two primary enhancements are urgently needed:
- The inclusion of argument passing support akin to
os.Args, enabling more dynamic results from a single main function based on various parameters. - Increased flexibility in the
package PKGPATHspecification, making it easier to add a main function and executegno runon a package without having to specify a file (related to issue #768).
Addresses #972
Starting with the implementation of the first enhancement (os.Args).
I refactored the RunMain() method to accept a slice of arguments. Apart from that, I added the os package into the stdlibs gnovm folder.
stdlib is loaded when using VMKeeper but RunMain() is on the Machine struct, so it looks a bit strange that to make Args work, you need to use the VM through the VMKeeper.
I'm having some problems injecting the Args into a var inside a package, waiting for https://github.com/gnolang/gno/pull/859 which should make the process simpler.
If someone has some insights about how to move forward, I'd be willing to chat with you about it.
Do you already have a PR for your work? can you share, the link?
@moul I don't. Because I wasn't able to make it work, I just discarded the changes. I can recreate and add them to a draft PR.
Yes please, a draft PR may be useful to help you.
@moul This is what I was trying to do: https://github.com/gnolang/gno/pull/982
I have a question how is the arguments will be parsed ? currently when you try to pass arguments after/before the file name it will be treated as a file, for example when i run
gno run main.gno hello
I get stat hello: no such file or directory
how do you want to handle this, do you want to handle this using a flag for example
gno run main.gno --args="Hello World"
or put the files under a flag
gno run --files="main.gno test.gno" Hello World
I discussed with @moul how to have os.Args in a "nice" way. Thanks for your contribution @salihdhaifullah, but actually direct access to os.Args is a non-goal.
Essentially we want main() as a way to access a realm / package from the GnoVM in an "interactive" way from the command line. There is already a way to have this - using gno run -expr, which allows to pass in an arbitrary expression to execute in place of main(); but we can "evolve" the usage of main to become a CLI "inspector" tool. Possibly in conjuction with https://github.com/gnolang/gno/issues/2989.
So, we're thinking of changing the functioning of gno run to be as follows:
gno run <PATH> [<ARGUMENT>...]
instead of supporting multiple file arguments.
Then, if arguments are passed, they are given in to the main function; in a fashion similar to what we have for maketx call. For example:
gno run . hello world
func main(arg1, arg2 string) {
println(arg1, arg2)
}
will print hello world.