From 76d2cee0cb0707c6db0132fa0423d47eeb593338 Mon Sep 17 00:00:00 2001 From: Koert Kuipers Date: Sat, 15 Jan 2022 17:45:23 -0500 Subject: [PATCH 1/2] indicate in help if arguments are optional or repeatable --- mainargs/src/Renderer.scala | 19 +++++++- mainargs/test/src-jvm-2/AmmoniteTests.scala | 50 +++++++++++---------- mainargs/test/src/CoreTests.scala | 6 +-- mainargs/test/src/RendererTests.scala | 45 +++++++++++++++++++ 4 files changed, 91 insertions(+), 29 deletions(-) create mode 100644 mainargs/test/src/RendererTests.scala diff --git a/mainargs/src/Renderer.scala b/mainargs/src/Renderer.scala index 9140c60..3297797 100644 --- a/mainargs/src/Renderer.scala +++ b/mainargs/src/Renderer.scala @@ -11,17 +11,32 @@ object Renderer { val newLine = System.lineSeparator() def normalizeNewlines(s: String) = s.replace("\r", "").replace("\n", newLine) + def makeOptional(s: String) = s"[$s]" + def makeRequired(s: String) = s" $s" + def makeVarargs(s: String) = s"[$s]*" + def makeOnePlus(s: String) = s"[$s]+" def renderArgShort(arg: ArgSig.Terminal[_, _]) = arg match{ case arg: ArgSig.Flag[_] => val shortPrefix = arg.shortName.map(c => s"-$c") val nameSuffix = arg.name.map(s => s"--$s") - (shortPrefix ++ nameSuffix).mkString(" ") + makeOptional((shortPrefix ++ nameSuffix).mkString(" ")) case arg: ArgSig.Simple[_, _] => val shortPrefix = arg.shortName.map(c => s"-$c") val typeSuffix = s"<${arg.typeString}>" val nameSuffix = if (arg.positional) arg.name else arg.name.map(s => s"--$s") - (shortPrefix ++ nameSuffix ++ Seq(typeSuffix)).mkString(" ") + val rendered = (shortPrefix ++ nameSuffix ++ Seq(typeSuffix)).mkString(" ") + arg match { + case ArgSig.Simple(_, _, _, _, tokensReader, _) if tokensReader.allowEmpty && tokensReader.alwaysRepeatable => + makeVarargs(rendered) + case ArgSig.Simple(_, _, _, _, tokensReader, _) if tokensReader.alwaysRepeatable => + makeOnePlus(rendered) + case ArgSig.Simple(_, _, _, _, tokensReader, _) if tokensReader.allowEmpty => + makeOptional(rendered) + case ArgSig.Simple(_, _, _, Some(_), _, _) => makeOptional(rendered) + case _ => + makeRequired(rendered) + } case arg: ArgSig.Leftover[_, _] => s"${arg.name0} <${arg.reader.shortName}>..." } diff --git a/mainargs/test/src-jvm-2/AmmoniteTests.scala b/mainargs/test/src-jvm-2/AmmoniteTests.scala index aaa9705..441e350 100644 --- a/mainargs/test/src-jvm-2/AmmoniteTests.scala +++ b/mainargs/test/src-jvm-2/AmmoniteTests.scala @@ -122,30 +122,32 @@ object AmmoniteTests extends TestSuite{ val expected = """Ammonite REPL & Script-Runner |usage: amm [ammonite-options] [script-file [script-options]] - | --no-default-predef Disable the default predef and run Ammonite with the minimal predef possible - | -s --silent Make ivy logs go silent instead of printing though failures will still throw - | exception - | -w --watch Watch and re-run your scripts when they change - | --bsp Run a BSP server against the passed scripts - | -c --code Pass in code to be run immediately in the REPL - | -h --home The home directory of the REPL; where it looks for config and caches - | -p --predef Lets you load your predef from a custom location, rather than the default - | location in your Ammonite home - | --color Enable or disable colored output; by default colors are enabled in both REPL - | and scripts if the console is interactive, and disabled otherwise - | --thin Hide parts of the core of Ammonite and some of its dependencies. By default, - | the core of Ammonite and all of its dependencies can be seen by users from - | the Ammonite session. This option mitigates that via class loader isolation. - | --help Print this message - | --predef-code Any commands you want to execute at the start of the REPL session - | --no-home-predef Disables the default behavior of loading predef files from your - | ~/.ammonite/predef.sc, predefScript.sc, or predefShared.sc. You can choose an - | additional predef to use using `--predef - | -b --banner Customize the welcome banner that gets shown when Ammonite starts - | --no-remote-logging (deprecated) Disable remote logging of the number of times a REPL starts and - | runs commands - | --classBased Wrap user code in classes rather than singletons, typically for Java - | serialization friendliness. + | [--no-default-predef] Disable the default predef and run Ammonite with the minimal predef + | possible + | [-s --silent] Make ivy logs go silent instead of printing though failures will still + | throw exception + | [-w --watch] Watch and re-run your scripts when they change + | [--bsp] Run a BSP server against the passed scripts + | [-c --code ] Pass in code to be run immediately in the REPL + | [-h --home ] The home directory of the REPL; where it looks for config and caches + | [-p --predef ] Lets you load your predef from a custom location, rather than the default + | location in your Ammonite home + | [--color ] Enable or disable colored output; by default colors are enabled in both + | REPL and scripts if the console is interactive, and disabled otherwise + | [--thin] Hide parts of the core of Ammonite and some of its dependencies. By + | default, the core of Ammonite and all of its dependencies can be seen by + | users from the Ammonite session. This option mitigates that via class + | loader isolation. + | [--help] Print this message + | [--predef-code ] Any commands you want to execute at the start of the REPL session + | [--no-home-predef] Disables the default behavior of loading predef files from your + | ~/.ammonite/predef.sc, predefScript.sc, or predefShared.sc. You can choose + | an additional predef to use using `--predef + | [-b --banner ] Customize the welcome banner that gets shown when Ammonite starts + | [--no-remote-logging] (deprecated) Disable remote logging of the number of times a REPL starts + | and runs commands + | [--classBased] Wrap user code in classes rather than singletons, typically for Java + | serialization friendliness. | rest ... |""".stripMargin.trim diff --git a/mainargs/test/src/CoreTests.scala b/mainargs/test/src/CoreTests.scala index 529b8d9..70ec126 100644 --- a/mainargs/test/src/CoreTests.scala +++ b/mainargs/test/src/CoreTests.scala @@ -39,12 +39,12 @@ class CoreTests(allowPositional: Boolean) extends TestSuite{ | foo | | bar - | -i + | -i | | qux | Qux is a function that does stuff - | -i - | -s Pass in a custom `s` to override it + | -i + | [-s ] Pass in a custom `s` to override it | | ex |""".stripMargin diff --git a/mainargs/test/src/RendererTests.scala b/mainargs/test/src/RendererTests.scala new file mode 100644 index 0000000..ff84058 --- /dev/null +++ b/mainargs/test/src/RendererTests.scala @@ -0,0 +1,45 @@ +package mainargs +import utest._ + + +object RenderedTests extends TestSuite{ + case class Config( + a: Int, + b: Int = 0, + c: Option[Int] = None, + d: Seq[Int], + e: Seq[Int] = Seq.empty, + @arg(doc = "this one has a doc") + a1: Int, + @arg(doc = "this one has a doc") + b1: Int = 0, + @arg(doc = "this one has a doc") + c1: Option[Int] = None, + @arg(doc = "this one has a doc") + d1: Seq[Int], + @arg(doc = "this one has a doc") + e1: Seq[Int] = Seq.empty + ) + val parser = ParserForClass[Config] + + val tests = Tests { + test("formatMainMethods"){ + val parsed = parser.helpText() + val expected = + """apply + | -a + | [-b ] + | [-c ] + | [-d ]* + | [-e ]* + | --a1 this one has a doc + | [--b1 ] this one has a doc + | [--c1 ] this one has a doc + | [--d1 ]* this one has a doc + | [--e1 ]* this one has a doc + |""".stripMargin + + parsed ==> expected + } + } +} From 77af1b7744e458ac3f318a9e70598371c8549810 Mon Sep 17 00:00:00 2001 From: Koert Kuipers Date: Sun, 9 Jul 2023 21:38:44 -0400 Subject: [PATCH 2/2] fix a few more tests for indications in help if arguments are optional or repeatable --- mainargs/test/src-jvm-2/AmmoniteTests.scala | 50 +++++++++-------- mainargs/test/src-jvm-2/MillTests.scala | 62 +++++++++++---------- mainargs/test/src/RendererTests.scala | 1 + 3 files changed, 60 insertions(+), 53 deletions(-) diff --git a/mainargs/test/src-jvm-2/AmmoniteTests.scala b/mainargs/test/src-jvm-2/AmmoniteTests.scala index f738000..5b7e199 100644 --- a/mainargs/test/src-jvm-2/AmmoniteTests.scala +++ b/mainargs/test/src-jvm-2/AmmoniteTests.scala @@ -186,30 +186,32 @@ object AmmoniteTests extends TestSuite { val expected = """Ammonite REPL & Script-Runner |usage: amm [ammonite-options] [script-file [script-options]] - | -b --banner Customize the welcome banner that gets shown when Ammonite starts - | --bsp Run a BSP server against the passed scripts - | -c --code Pass in code to be run immediately in the REPL - | --classBased Wrap user code in classes rather than singletons, typically for Java - | serialization friendliness. - | --color Enable or disable colored output; by default colors are enabled in both REPL - | and scripts if the console is interactive, and disabled otherwise - | -h --home The home directory of the REPL; where it looks for config and caches - | --help Print this message - | --no-default-predef Disable the default predef and run Ammonite with the minimal predef possible - | --no-home-predef Disables the default behavior of loading predef files from your - | ~/.ammonite/predef.sc, predefScript.sc, or predefShared.sc. You can choose an - | additional predef to use using `--predef - | --no-remote-logging (deprecated) Disable remote logging of the number of times a REPL starts and - | runs commands - | -p --predef Lets you load your predef from a custom location, rather than the default - | location in your Ammonite home - | --predef-code Any commands you want to execute at the start of the REPL session - | -s --silent Make ivy logs go silent instead of printing though failures will still throw - | exception - | --thin Hide parts of the core of Ammonite and some of its dependencies. By default, - | the core of Ammonite and all of its dependencies can be seen by users from - | the Ammonite session. This option mitigates that via class loader isolation. - | -w --watch Watch and re-run your scripts when they change + | [-b --banner ] Customize the welcome banner that gets shown when Ammonite starts + | [--bsp] Run a BSP server against the passed scripts + | [-c --code ] Pass in code to be run immediately in the REPL + | [--classBased] Wrap user code in classes rather than singletons, typically for Java + | serialization friendliness. + | [--color ] Enable or disable colored output; by default colors are enabled in both + | REPL and scripts if the console is interactive, and disabled otherwise + | [-h --home ] The home directory of the REPL; where it looks for config and caches + | [--help] Print this message + | [--no-default-predef] Disable the default predef and run Ammonite with the minimal predef + | possible + | [--no-home-predef] Disables the default behavior of loading predef files from your + | ~/.ammonite/predef.sc, predefScript.sc, or predefShared.sc. You can choose + | an additional predef to use using `--predef + | [--no-remote-logging] (deprecated) Disable remote logging of the number of times a REPL starts + | and runs commands + | [-p --predef ] Lets you load your predef from a custom location, rather than the default + | location in your Ammonite home + | [--predef-code ] Any commands you want to execute at the start of the REPL session + | [-s --silent] Make ivy logs go silent instead of printing though failures will still + | throw exception + | [--thin] Hide parts of the core of Ammonite and some of its dependencies. By + | default, the core of Ammonite and all of its dependencies can be seen by + | users from the Ammonite session. This option mitigates that via class + | loader isolation. + | [-w --watch] Watch and re-run your scripts when they change | rest ... |""".stripMargin.trim diff --git a/mainargs/test/src-jvm-2/MillTests.scala b/mainargs/test/src-jvm-2/MillTests.scala index c849fe9..1e8e324 100644 --- a/mainargs/test/src-jvm-2/MillTests.scala +++ b/mainargs/test/src-jvm-2/MillTests.scala @@ -95,35 +95,39 @@ object MillTests extends TestSuite { val expected = { """Mill Build Tool |usage: mill [mill-options] [target [target-options]] - | --repl Run Mill in interactive mode and start a build REPL. In this mode, no mill - | server will be used. Must be the first argument. - | --no-server Run Mill in interactive mode, suitable for opening REPLs and taking user - | input. In this mode, no mill server will be used. Must be the first argument. - | -i --interactive Run Mill in interactive mode, suitable for opening REPLs and taking user - | input. In this mode, no mill server will be used. Must be the first argument. - | -v --version Show mill version and exit. - | -b --bell Ring the bell once if the run completes successfully, twice if it fails. - | --disable-ticker Disable ticker log (e.g. short-lived prints of stages and progress bars) - | -d --debug Show debug output on STDOUT - | -k --keep-going Continue build, even after build failures - | -D --define Define (or overwrite) a system property - | -j --jobs Allow processing N targets in parallel. Use 1 to disable parallel and 0 to - | use as much threads as available processors. - | --no-default-predef Disable the default predef and run Ammonite with the minimal predef possible - | -s --silent Make ivy logs go silent instead of printing though failures will still throw - | exception - | -w --watch Watch and re-run your scripts when they change - | --bsp Run a BSP server against the passed scripts - | -c --code Pass in code to be run immediately in the REPL - | -h --home The home directory of the REPL; where it looks for config and caches - | -p --predef Lets you load your predef from a custom location, rather than the default - | location in your Ammonite home - | --color Enable or disable colored output; by default colors are enabled in both REPL - | and scripts if the console is interactive, and disabled otherwise - | --thin Hide parts of the core of Ammonite and some of its dependencies. By default, - | the core of Ammonite and all of its dependencies can be seen by users from - | the Ammonite session. This option mitigates that via class loader isolation. - | --help Print this message + | [--repl] Run Mill in interactive mode and start a build REPL. In this mode, no mill + | server will be used. Must be the first argument. + | [--no-server] Run Mill in interactive mode, suitable for opening REPLs and taking user + | input. In this mode, no mill server will be used. Must be the first + | argument. + | [-i --interactive] Run Mill in interactive mode, suitable for opening REPLs and taking user + | input. In this mode, no mill server will be used. Must be the first + | argument. + | [-v --version] Show mill version and exit. + | [-b --bell] Ring the bell once if the run completes successfully, twice if it fails. + | [--disable-ticker] Disable ticker log (e.g. short-lived prints of stages and progress bars) + | [-d --debug] Show debug output on STDOUT + | [-k --keep-going] Continue build, even after build failures + | [-D --define ]* Define (or overwrite) a system property + | [-j --jobs ] Allow processing N targets in parallel. Use 1 to disable parallel and 0 to + | use as much threads as available processors. + | [--no-default-predef] Disable the default predef and run Ammonite with the minimal predef + | possible + | [-s --silent] Make ivy logs go silent instead of printing though failures will still + | throw exception + | [-w --watch] Watch and re-run your scripts when they change + | [--bsp] Run a BSP server against the passed scripts + | [-c --code ] Pass in code to be run immediately in the REPL + | [-h --home ] The home directory of the REPL; where it looks for config and caches + | [-p --predef ] Lets you load your predef from a custom location, rather than the default + | location in your Ammonite home + | [--color ] Enable or disable colored output; by default colors are enabled in both + | REPL and scripts if the console is interactive, and disabled otherwise + | [--thin] Hide parts of the core of Ammonite and some of its dependencies. By + | default, the core of Ammonite and all of its dependencies can be seen by + | users from the Ammonite session. This option mitigates that via class + | loader isolation. + | [--help] Print this message |""".stripMargin } assert(rendered == expected) diff --git a/mainargs/test/src/RendererTests.scala b/mainargs/test/src/RendererTests.scala index 3cad7f6..bbfbe61 100644 --- a/mainargs/test/src/RendererTests.scala +++ b/mainargs/test/src/RendererTests.scala @@ -3,6 +3,7 @@ import utest._ object RenderedTests extends TestSuite{ + @main case class Config( a: Int, b: Int = 0,