Skip to content

Commit

Permalink
Finished docs on case sensitivity (#9), and add some examples.
Browse files Browse the repository at this point in the history
  • Loading branch information
jerrylususu authored and remkop committed May 4, 2020
1 parent 8dd32f5 commit ad406a6
Show file tree
Hide file tree
Showing 4 changed files with 182 additions and 0 deletions.
62 changes: 62 additions & 0 deletions docs/index.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -2577,6 +2577,68 @@ class ExecParameterConsumer implements IParameterConsumer {
}
```

=== Case Sensitivity
By deafult, all options and subcommands are case senstive. Case Sensitivity can be toggled globally, with `CommandLine.setSubcommandsCaseInsensitive` and `CommandLine.setOptionsCaseInsensitive`.

The following example shows setting a case insensitive parse config. With such settings, `help`, `HELP`, `HElp` will all be resolved to `helpCommand`. Similarly, `-h` and `-H` will both be resolved to `helpmessage`.
[source,java]
----
@Command
class App {
@Command(name = "help")
public void helpCommand() {}
@Option(names = "-h")
public boolean helpMessage;
}
CommandLine commandLine = new CommandLine(new App());
commandLine.setSubcommandsCaseInsensitive(true);
commandLine.setOptionsCaseInsensitive(true);
----

Finer controls of case sensitivity in the scope of a given `CommandSpec` is also possible. This enables some SubCommands to exhibit different case sensitivty to others.

The following example shows setting the `strict` subcommand to case sensitive, while leaving others case insensitive.
[source,java]
----
// From examples.casesensitivity.ScopedCaseSensitivityDemo
CommandLine commandLine = new CommandLine(new ScopedCaseSensitivityDemo());
commandLine.addSubcommand("strict", new StrictGreet());
// globally case insensitive
commandLine.setOptionsCaseInsensitive(true);
commandLine.setSubcommandsCaseInsensitive(true);
// specifically case sensitive
// accepts `strict GrEET`
// rejects `strict greet`, `strict GREET`...
commandLine.getSubcommands().get("strict").setSubcommandsCaseInsensitive(false);
commandLine.execute(args);
----

With case-insensitive enabled, Subcommands and Options having the same letters but with different cases can not be used at the same time, and will throw exception with messages indicting duplicate keys. Other operations that might lead to ambiguity will also throw exceptions.

The following example shows a failure of adding two options with the same letter `h` but differnt cases.

[source,java]
----
class App {
@Option(names = "-h")
boolean helpMessage;
@Option(names = "-H")
boolean highlight;
}
CommandLine commandLine = new CommandLine(new App());
commandLine.setCaseInsensitiveOptions(true); // won't work
// IllegalStateException: Duplicated keys: -h and -H
----

[WARNING]
====
Combination of POSIX options might resemble a long option. In such cases, Picocli will prioritize the long option. For example, if there are POSIX options `-a`, `-b`, `-c` and `-d`, and a long option `-abcd`, and user specifies `-abcd`, Picocli will recognize it as the long option `-abcd`, not any of the POSIX options. `examples.casesensitivity.POSIXOptionResembleDemo` illustrates such a problem.
====


== Help

=== Help Options
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package picocli.examples.casesensitivity;

import picocli.CommandLine;
import picocli.CommandLine.Command;
import picocli.CommandLine.Option;

@Command(name = "Case Insensitive Demo")
public class CaseInsensitiveDemo implements Runnable {

@Option(names = {"-n", "--name"}, required = false, defaultValue = "User")
String name;

@Command(name = "greet")
public int greet() {
System.out.println("Have a nice day!");
return 0;
}

@Override
public void run() {
System.out.println("Hi, Your name is " + name);
}

public static void main(String... args){
new CommandLine(new CaseInsensitiveDemo())
.setOptionsCaseInsensitive(true) // accepts `-H`, `--nAmE`
.setSubcommandsCaseInsensitive(true) // accepts `gREET`, `GREET`
.execute(args);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package picocli.examples.casesensitivity;

import picocli.CommandLine;
import picocli.CommandLine.Command;
import picocli.CommandLine.Option;

@Command(name = "POSIX Option Resemble Demo",
description = "This shows what will happen if multiple POSIX options resemble a long option")
public class POSIXOptionResembleDemo implements Runnable {

@Option(names = "-a", required = false)
boolean a;

@Option(names = "-b", required = false)
boolean b;

@Option(names = "-c", required = false)
boolean c;

@Option(names = "-abc", required = false)
boolean abc;

@Override
public void run() {
System.out.println("a is " + a + "\n" +
"b is " + b + "\n" +
"c is " + c + "\n" +
"abc is " + abc);
}

public static void main(String... args){
new CommandLine(new POSIXOptionResembleDemo())
.setOptionsCaseInsensitive(true)
.execute(args);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
package picocli.examples.casesensitivity;

import picocli.CommandLine;
import picocli.CommandLine.Command;
import picocli.CommandLine.Option;

import java.util.concurrent.Callable;

@Command(name = "Scoped Case Sensitivity Demo")
public class ScopedCaseSensitivityDemo implements Runnable {

@Option(names = {"-n", "--name"}, required = false, defaultValue = "User")
String name;

@Command(name = "greet")
public int greet() {
System.out.println("Have a nice day!");
return 0;
}

@Override
public void run() {
System.out.println("Hi, Your name is " + name);
}

public static void main(String... args){
CommandLine commandLine = new CommandLine(new ScopedCaseSensitivityDemo());
commandLine.addSubcommand("strict", new StrictGreet());
// globally case insensitive
commandLine.setOptionsCaseInsensitive(true);
commandLine.setSubcommandsCaseInsensitive(true);
// specifically case sensitive
// accepts `strict GrEET`
// rejects `strict greet`, `strict GREET`...
commandLine.getSubcommands().get("strict").setSubcommandsCaseInsensitive(false);
commandLine.execute(args);
}
}

@Command(name = "Strict Greet")
class StrictGreet implements Callable<Integer>{

@Command(name = "GrEET")
public int greet() {
System.out.println("I will only GrEET if the case is correct!");
return 0;
}

@Override
public Integer call() {
System.out.println("Entering strict zone...");
return 0;
}
}

0 comments on commit ad406a6

Please sign in to comment.