-
Notifications
You must be signed in to change notification settings - Fork 1.1k
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
Generalize main annotations #13727
Generalize main annotations #13727
Conversation
81ebb1e
to
46188c9
Compare
This comment has been minimized.
This comment has been minimized.
c85f94f
to
8ba453e
Compare
8ba453e
to
3a566ff
Compare
cmdName, | ||
TypeTree(), | ||
Apply( | ||
Select(instanciateAnnotation(mainAnnot), defn.MainAnnot_command.name), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Select(instanciateAnnotation(mainAnnot), defn.MainAnnot_command.name), | |
Select(instanciateAnnotation(mainAnnot), nme.main), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That won't work, nme.main
is "main" whereas defn.MainAnnot_command
is "command"
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Then we should add command
to StdNames
.
report.error(s"main can only annotate a method", pos) | ||
} | ||
|
||
val run = Apply(Select(Ident(cmdName), defn.MainAnnotCommand_run.name), mainCall) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
val run = Apply(Select(Ident(cmdName), defn.MainAnnotCommand_run.name), mainCall) | |
val run = Apply(Select(Ident(cmdName), nme.run), mainCall) |
Important points from LAMP meeting, 03/02/2022:
|
Continuing the discussion from @abgruszecki's mail here:
That seems confusing. A convention I've seen in some cli programs like ripgrep (https://github.com/BurntSushi/ripgrep) is that for every boolean flag --foo there is a complimentary flag --no-foo, and if a combination of these flags is passed, the last one win (this is very convenient since it lets you define an alias with some flags but then override them on the command line). |
There's another thread about making sure option processing is uniform. Consensus isn't easy. |
Hm, these seem like orthogonal problems. What I mean is only that:
In general, if an argument is not repeated, then what I would expect is that if I pass multiple instances of it, the last one wins, no matter if the flag is boolean or not. We can do that later on though, if in the first version passing a flag multiple times will be an error (which is now the case, IIRC). |
- Pass ParameterInfos for parameters in the command method instead of the getter functions. This way, we know about all of them beforehand, and parsing can be done more efficiently.
- Merge Name and ShortName into Alias - Make Alias take a variable number of arguments - Distinguish between long and short names by string length
- --help and -h display usage and help - if an argument or an alias is the same as either help or h, disable help printing for that argument
1b60681
to
4ce8911
Compare
There is a slight issue with this: as much as I think it could provide something good for scripting, it makes testing significantly harder, as the test harness does not seem to have a nice way of handling return codes. Should I implement it anyway, and remove tests that expect an error to occur? Or leave it for the experimental version to implement? |
Wait, what is the exact problem? Is it difficult to check the exact error code returned, or is the test harness not detecting that some non-zero exit codes are an error? The latter is a bug to be fixed; if it's the earlier, I think not having tests that check for the exact error code returned is not great, but acceptable. |
If you wish to test the exact exit code you could write a test in the following shell script which is part of our CI: https://github.com/lampepfl/dotty/blob/main/project/scripts/bootstrapCmdTests
That's the part I find confusing, imo if we have: @main def run(color: Boolean = true, verbose: Boolean = false) = ... Then we should generate four flags: |
Ah, that's just simpler than what I had in mind, I agree this is the better way. |
trait Command[ArgumentParser[_], MainResultType]: | ||
|
||
/** The getter for the next argument of type `T` */ | ||
def argGetter[T](name: String, optDefaultGetter: Option[() => T])(using fromString: ArgumentParser[T]): () => T |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This name
is redundant because we already have it in parameterInfoss
. I would pass the parameter index to argGetter
instead. This way we can access the name with parameterInfoss[idx].name
but also can access any of the other ParameterInfos
in a simple way.
def argGetter[T](name: String, optDefaultGetter: Option[() => T])(using fromString: ArgumentParser[T]): () => T | |
def argGetter[T](idx: Int, optDefaultGetter: Option[() => T])(using fromString: ArgumentParser[T]): () => T |
type MainResultType | ||
|
||
/** A new command with arguments from `args` */ | ||
def command(args: Array[String], commandName: String, documentation: String, parameterInfoss: MainAnnotation.ParameterInfos*): MainAnnotation.Command[ArgumentParser, MainResultType] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The double s
in parameterInfoss
is a bit confusing because we usually use it for List[List[T]]
. I would propose dropping the second s
from parameterInfoss
and the s
of ParameterInfos
def command(args: Array[String], commandName: String, documentation: String, parameterInfoss: MainAnnotation.ParameterInfos*): MainAnnotation.Command[ArgumentParser, MainResultType] | |
def command(args: Array[String], commandName: String, documentation: String, parameterInfos: MainAnnotation.ParameterInfo*): MainAnnotation.Command[ArgumentParser, MainResultType] |
Actually, it should be in https://github.com/lampepfl/dotty/blob/main/project/scripts/cmdTests but we need the fix of #14428 to make the CI run it on PRs. We will need to rebase on |
Extracted |
As defined in scala#13727 adapted to new API.
As defined in scala#13727 adapted to new API.
Based on prototype in scala#13727
Based on prototype in scala#13727 Co-authored-by: Timothée Loyck Andres <timothee.andres@epfl.ch>
Based on prototype in scala#13727 Co-authored-by: Timothée Loyck Andres <timothee.andres@epfl.ch>
Based on prototype in scala#13727 Co-authored-by: Timothée Loyck Andres <timothee.andres@epfl.ch>
Based on prototype in scala#13727 Co-authored-by: Timothée Loyck Andres <timothee.andres@epfl.ch>
Based on prototype in scala#13727 Co-authored-by: Timothée Loyck Andres <timothee.andres@epfl.ch>
Based on prototype in scala#13727 Co-authored-by: Timothée Loyck Andres <timothee.andres@epfl.ch>
Based on prototype in scala#13727 Co-authored-by: Timothée Loyck Andres <timothee.andres@epfl.ch>
Work in progress
Working on abstracting
@main
annotations in Scala3