Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use custom argument parser with ammonite #423

Closed
benwbooth opened this Issue Aug 1, 2016 · 12 comments

Comments

Projects
None yet
2 participants
@benwbooth
Copy link

benwbooth commented Aug 1, 2016

I would like to be able to use a custom argument parser with ammonite instead of the built in one. How can I achieve this? Is there some way to access the command line arguments directly from the script without needing to use the @main annotation? It would be nice if there were an annotation like this:

@args val args: Seq[String] = null

or maybe:

val args: Seq[String] = ammonite.main.Scripts.args

which automatically filled in the command line arguments to a variable. This would also enable users to not have to provide a @main function in their scripts. Is this possible to achieve?
Thanks!

@lihaoyi

This comment has been minimized.

Copy link
Owner

lihaoyi commented Aug 2, 2016

Ideally

@main def main(args: String*) = {
  ...
}

Should work. It currently doesn't, but that can be fixed.

We could expose the arguments as a global, which is what Python does, but I'd like to avoid that if possible. Exposing the command-line arguments as, well, arguments should in theory push people in the direction of dealing with them at the entry-point rather than grabbing them randomly throughout their scripts, which I think is the right thing to do

@benwbooth

This comment has been minimized.

Copy link
Author

benwbooth commented Aug 2, 2016

Fair enough. The one reason I like having the arguments as a "global" or being able to get them from a global function, is that it allows me to write the entire script at the top-level instead of within the main() function, which to me feels more script-y.

But if the syntax you posted worked, that would be a big improvement.

@lihaoyi lihaoyi added the enhancement label Aug 2, 2016

@benwbooth

This comment has been minimized.

Copy link
Author

benwbooth commented Aug 4, 2016

What about setting this.args to be the full command-line arguments in the script top-level? That way, the arguments are visible only to the script, and are not global.

@lihaoyi

This comment has been minimized.

Copy link
Owner

lihaoyi commented Aug 10, 2016

Discussed with @coderabhishek in gitter, we will try first to make String* work fine with the generateRoutes macro and scopt. If that doesn't work, we'll fall back to having it available as a global.

@lihaoyi

This comment has been minimized.

Copy link
Owner

lihaoyi commented Aug 17, 2016

Fixed by 7608d6f; this allows you to take String* arguments in your @main methods, which will then take in all kinds of sets of arguments un-changed that you can then feed into whatever argument parser you want

@lihaoyi lihaoyi closed this Aug 17, 2016

@benwbooth

This comment has been minimized.

Copy link
Author

benwbooth commented Aug 19, 2016

I noticed a problem, with the following script I'm not getting the right command line arguments:

#!/usr/bin/env amm

@main def main(args: String*) = {
  println(args)
}

If I run that script using a --:

$ ./test.sc a b c -- d e
Vector(d, e, a, b, c)

The -- is removed, and everything after the -- is moved before the first set of arguments. This bug will prevent users from being able to correctly use custom argument parsers.

@benwbooth

This comment has been minimized.

Copy link
Author

benwbooth commented Aug 19, 2016

Also, is there any chance that the full arguments could also be exposed as a read-only global? It's the programming style a lot of people coming from other scripting languages (including myself) would prefer. I don't like having to indent my entire script in order to access the command-line arguments. Thanks!

@lihaoyi

This comment has been minimized.

Copy link
Owner

lihaoyi commented Aug 19, 2016

The -- is removed, and everything after the -- is moved before the first set of arguments. This bug will prevent users from being able to correctly use custom argument parsers.

Ahh yeah that is a result of a hack I put in to distinguish script args from Ammonite's args; I hadn't realized it would result in this poor interaction. That will need to be fixed.

Also, is there any chance that the full arguments could also be exposed as a read-only global?

sure I can do that

@lihaoyi lihaoyi reopened this Aug 19, 2016

@lihaoyi

This comment has been minimized.

Copy link
Owner

lihaoyi commented Aug 19, 2016

sure I can do that

Actually, @benwbooth would you like to do the honors of making a change and sending a PR? Concretely you'll need to add a def scriptArgs: Vector[String] onto our abstract trait InterpAPI and then from Main.scala, plumb the arguments down into wherever we end up instantiating our InterpAPI

@benwbooth

This comment has been minimized.

Copy link
Author

benwbooth commented Aug 19, 2016

Sure, no problem: #440

I had a question about whether passThroughArgs actually contains all the unprocessed arguments, or just the non-keyword positional arguments. Hopefully it contains all the arguments, since that's what I'm passing into the InterpAPI.args field.

Thanks!

@lihaoyi

This comment has been minimized.

Copy link
Owner

lihaoyi commented May 19, 2017

Fixed in c605d86#diff-d624941e18d4c528c725d4c3c0bd0517R1089

This lets @main methods with varargs properly slurp in everything, allowing you to then use your own custom argument parser. The only caveat is you cannot use -- in your own argument list, since that is reserved to separate Ammonite's arguments from your script's arguments.

Please take a look at the changelog entry which describes this and let me know if this satisfies your requirements

@lihaoyi lihaoyi closed this May 19, 2017

@lihaoyi

This comment has been minimized.

Copy link
Owner

lihaoyi commented May 21, 2017

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.