Skip to content

Commit

Permalink
[#1880] improve negatable options doc
Browse files Browse the repository at this point in the history
Closes #1880
  • Loading branch information
remkop committed Dec 23, 2022
1 parent dde9259 commit 612e301
Show file tree
Hide file tree
Showing 4 changed files with 94 additions and 13 deletions.
3 changes: 3 additions & 0 deletions RELEASE-NOTES.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,9 @@ Artifacts in this release are signed by Remko Popma (6601 E5C0 8DCC BB96).
* [#1878][#1876] Bugfix: Annotation processor now avoids loading resource bundles at compile time. Thanks to [Ruud Senden](https://github.com/rsenden) for the discussion and the pull request.
* [#1881] DOC: Many documentation improvements. Thanks to [Andreas Deininger](https://github.com/deining) for the pull request.
* [#1855][#1857] DOC: Add new user manual section called [Rare Use Cases](https://picocli.info/#_rare_use_cases) detailing `System.exit` usage. Thanks to [Tadaya Tsuyukubo](https://github.com/ttddyy) for the pull request.
* [#1880] DOC: Improve documentation for negatable options that are true by default. Thanks to [Sebastian Hoß](https://github.com/sebhoss) for raising this.



## <a name="4.7.1-deprecated"></a> Deprecations
No features were deprecated in this release.
Expand Down
39 changes: 33 additions & 6 deletions docs/index.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -843,27 +843,54 @@ If the negated form of the option is found, for example `--no-verbose`, the valu
[TIP]
.Negatable options that are `true` by default
====
When a negatable option is `true` by default, give it the negative name. For example:
When a negatable option is `true` by default, give it both a `defaultValue` and a `fallbackValue` of `"true"`. For example:
.Java
[source,java,role="primary"]
----
@Option(names = "--no-backup", negatable = true,
@Option(names = "--backup", negatable = true,
defaultValue = "true", fallbackValue = "true",
description = "Make a backup. True by default.")
boolean backup = true;
boolean backup;
----
.Kotlin
[source,kotlin,role="secondary"]
----
@Option(names = ["--no-backup"], negatable = true,
@Option(names = ["--backup"], negatable = true,
defaultValue = "true", fallbackValue = "true",
description = ["Make a backup. True by default."])
var backup = true
----
When end users specify `--no-backup` on the command line, the value is set to `false`.
The table below shows the value assigned to the annotated option field for a number of possible user input strings:
//.Negatable option values for various user input strings
//[grid=cols,cols="10,10",options="header"]
//|===
//| End user input | Option value
//| (no args) | `true`
//| `--backup` | `true`
//| `--backup=true` | `true`
//| `--backup=false` | `false`
//| `--no-backup` | `false`
//| `--no-backup=true` | `false`
//| `--no-backup=false` | `true`
//|===
//
----
End user input Option value
-------------- ------------
(no args) true
--backup true
--backup=true true
--backup=false false
--no-backup false
--no-backup=true false
--no-backup=false true
----
The negated form of this option is `--backup`, and if that is specified, the default value is applied.
====

=== Positional Parameters
Expand Down
26 changes: 19 additions & 7 deletions docs/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -3214,29 +3214,41 @@ <h3 id="_negatable_options"><a class="anchor" href="#_negatable_options"></a>3.5
<td class="content">
<div class="title">Negatable options that are <code>true</code> by default</div>
<div class="paragraph">
<p>When a negatable option is <code>true</code> by default, give it the negative name. For example:</p>
<p>When a negatable option is <code>true</code> by default, give it both a <code>defaultValue</code> and a <code>fallbackValue</code> of <code>"true"</code>. For example:</p>
</div>
<div class="listingblock primary">
<div class="title">Java</div>
<div class="content">
<pre class="rouge highlight"><code data-lang="java"><span class="nd">@Option</span><span class="o">(</span><span class="n">names</span> <span class="o">=</span> <span class="s">"--no-backup"</span><span class="o">,</span> <span class="n">negatable</span> <span class="o">=</span> <span class="kc">true</span><span class="o">,</span>
<pre class="rouge highlight"><code data-lang="java"><span class="nd">@Option</span><span class="o">(</span><span class="n">names</span> <span class="o">=</span> <span class="s">"--backup"</span><span class="o">,</span> <span class="n">negatable</span> <span class="o">=</span> <span class="kc">true</span><span class="o">,</span>
<span class="n">defaultValue</span> <span class="o">=</span> <span class="s">"true"</span><span class="o">,</span> <span class="n">fallbackValue</span> <span class="o">=</span> <span class="s">"true"</span><span class="o">,</span>
<span class="n">description</span> <span class="o">=</span> <span class="s">"Make a backup. True by default."</span><span class="o">)</span>
<span class="kt">boolean</span> <span class="n">backup</span> <span class="o">=</span> <span class="kc">true</span><span class="o">;</span></code></pre>
<span class="kt">boolean</span> <span class="n">backup</span><span class="o">;</span></code></pre>
</div>
</div>
<div class="listingblock secondary">
<div class="title">Kotlin</div>
<div class="content">
<pre class="rouge highlight"><code data-lang="kotlin"><span class="nd">@Option</span><span class="p">(</span><span class="n">names</span> <span class="p">=</span> <span class="p">[</span><span class="s">"--no-backup"</span><span class="p">],</span> <span class="n">negatable</span> <span class="p">=</span> <span class="k">true</span><span class="p">,</span>
<pre class="rouge highlight"><code data-lang="kotlin"><span class="nd">@Option</span><span class="p">(</span><span class="n">names</span> <span class="p">=</span> <span class="p">[</span><span class="s">"--backup"</span><span class="p">],</span> <span class="n">negatable</span> <span class="p">=</span> <span class="k">true</span><span class="p">,</span>
<span class="n">defaultValue</span> <span class="p">=</span> <span class="s">"true"</span><span class="p">,</span> <span class="n">fallbackValue</span> <span class="p">=</span> <span class="s">"true"</span><span class="p">,</span>
<span class="n">description</span> <span class="p">=</span> <span class="p">[</span><span class="s">"Make a backup. True by default."</span><span class="p">])</span>
<span class="kd">var</span> <span class="py">backup</span> <span class="p">=</span> <span class="k">true</span></code></pre>
</div>
</div>
<div class="paragraph">
<p>When end users specify <code>--no-backup</code> on the command line, the value is set to <code>false</code>.</p>
<p>The table below shows the value assigned to the annotated option field for a number of possible user input strings:</p>
</div>
<div class="listingblock">
<div class="content">
<pre>End user input Option value
-------------- ------------
(no args) true
--backup true
--backup=true true
--backup=false false
--no-backup false
--no-backup=true false
--no-backup=false true</pre>
</div>
<div class="paragraph">
<p>The negated form of this option is <code>--backup</code>, and if that is specified, the default value is applied.</p>
</div>
</td>
</tr>
Expand Down
39 changes: 39 additions & 0 deletions src/test/java/picocli/NegatableOptionTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -587,4 +587,43 @@ class TestNegation {
assertFalse(obj.flag);
}

@CommandLine.Command
static class TestCommand1880 {

@CommandLine.Option(
names = {"--backup"}, defaultValue = "true",
fallbackValue = "true", // this is new
negatable = true
)
public boolean wanted;
}
// names = {"--no-wanted"}, defaultValue = "true",
// expected: true, was: true, (no args)
// expected: true, was: true, --wanted
// expected: true, was: false, --wanted=true
// expected: false, was: true, --wanted=false
// expected: false, was: false, --no-wanted
// expected: false, was: true, --no-wanted=true
// expected: true, was: false, --no-wanted=false

@Test
public void test1880() {
assertValue(true);
assertValue(true, "--backup");
assertValue(true, "--backup=true");
assertValue(false, "--backup=false");
assertValue(false, "--no-backup");
assertValue(false, "--no-backup=true");
assertValue(true, "--no-backup=false");
}

private void assertValue(boolean expected, String... args) {
final TestCommand1880 command = new TestCommand1880();
new CommandLine(command).parseArgs(args);

String label = args.length ==0 ? "(no args)" : args[0];
//System.out.printf("expected: %s, was: %s, %s%n", expected, command.wanted, label);
//System.out.printf("%-17s %s%n", label, command.wanted);
assertEquals(label, expected, command.wanted);
}
}

0 comments on commit 612e301

Please sign in to comment.