...
- Interactive shell:
- commands should feature argument completion
- commands should allow interactive prompts
- Bndtools UI
- arguments should be grouped
- interactive prompts should be converted into multiple pages of a wizard
- Scripts
- commands should be able to run without interaction (so all optional arguments should be supplied)
- slightly related, if commands retain some kind of state, that state should be CommandSession scoped (note that this is not script specific, but will become an issue once scripts are being executed)
Metatype interfaces with Java code for conditional parameters
In this approach the arguments are grouped in interfaces.
Code Block |
---|
// Simple case: one set of parameters, no interactivity
@Meta.OCD interface NameAndType {
enum TYPE { CLASS, INTERFACE };
@Meta.AD(name="FQN", description="The fully qualified name of the class.") FQN name();
@Meta.AD(description="The type (class or interface)") TYPE type();
}
@Command()
public void cmd(String... args) {
NameAndType nat = m_prompt.ask(NameAndType.class, args);
// arguments are available as nat.name():String and nat.type():FQN |
Code Block |
---|
// Complex case: multiple sets of parameters, with interactivity
@Meta.OCD interface NameAndType {
enum TYPE { CLASS, INTERFACE };
@Meta.AD(name="FQN", description="The fully qualified name of the class.") FQN name();
@Meta.AD(description="The type (class or interface)") TYPE type();
}
@Meta.OCD interface DefaultMethods {
@Meta.AD(description="generate toString method?") boolean string();
@Meta.AD(description="generate equals method?") boolean equals();
@Meta.AD(description="generate hashCode method?") boolean hashcode();
}
@Command()
public void cmd(String... args) {
NameAndType nat = m_prompt.ask(NameAndType.class, args);
if (nat.type().equals(CLASS)) {
DefaultMethods methods = m_prompt.ask(DefaultMethods.class, args);
} |
Scripting can be implemented by recording arguments before executing the command.
Upsides:
- Questions are grouped, this is ideal for generating wizards in Bndtools
- Don't need multiple methods for commands that have optional parameters.
- No special things required for scripting, script can just provide all parameters.
Downsides:
- The questions are "disconnected" from the command implementations. This is less obvious to program.
- Difficult to support command completion
Annotated arguments
Code Block |
---|
// Simple case: one set of parameters, no interactivity @Command() public void cmd(@Argument(name="name", description="The fully qualified name of the class.") String name, @Argument(description="The type (class or interface)") FQN type) { // arguments are available as name:String and type:FQN |
Code Block |
---|
// Complex case: multiple sets of parameters, with interactivity
@Command()
public void cmd(@Argument(name="name", description="The fully qualified name of the class.") String name, @Argument(description="The type (class or interface)") FQN type) {
if (type.equals(CLASS)) {
boolean genString = m_prompt.ask("generate toString method?", Boolean.class, "string");
boolean genEquals = m_prompt.ask("generate equals method?", Boolean.class, "equals");
boolean genHashcode = m_prompt.ask("generate hashCode method?", Boolean.class, "hashcode"); |
Scripting can be implemented by recording arguments before executing the command.
Upsides:
- Obvious to implement.
- Relatively easy to support both passing arguments immediately, and asking the user for answers during execution of the command, you just write different implementations of your method.
- Easy to implement argument completion for the initial set of arguments and the interactive prompts separately, hard to do completion on a single command line for all possible arguments.
...
- No way to group questions, besides just showing all of them in the same wizard. Note that this is only a problem when multiple wizard pages are required in Bndtools (the complex case).
- No argument completion for the total set of options.
- Needs multiple methods for optional arguments.
- Scripting needs extra recorder, which adds state somewhere that can't be transferred through the arguments of the command/method.
Metatype interfaces with DSL
...
for conditional parameters
Code Block |
---|
// Simple case: one set of parameters, no interactivity
@Meta.OCD interface NameAndType {
@Meta.AD(name="FQN", description="The fully qualified name of the class.") FQN name();
@Meta.AD(description="The type (class or interface)") TYPE type();
}
@Command()
public void cmd(@Prompt(NameAndType.class) String... args) {
NameAndType nat = m_prompt.ask(NameAndType.class, args);
|
Code Block |
---|
// Complex case: multiple sets of parameters, with interactivity @Meta.OCD interface Q1NameAndType { String first@Meta.AD(name="FQN", description="The fully qualified name of the class.") FQN name(); String last@Meta.AD(description="The type (class or interface)") TYPE type(); @Condition("lasttype=BakkerCLASS") Q2DefaultMethods emailmethods(); } @Meta.OCD interface Q2DefaultMethods { @Meta.AD(description="generate toString method?") String email(); } @Commandboolean string(); @Meta.AD(description="generate equals method?") boolean equals(); @Meta.AD(description="generate hashCode method?") boolean hashcode(); } @Command() public void cmd(@Prompt(Q1NameAndType.class) String... args) { Q1 q NameAndType nat = m_prompt.ask(Q1NameAndType.class, args); // Q1 and Q2 are available for processing |
(have to go now, more later...)
...
|
Upsides:
- Questions are grouped, this is ideal for generating wizards in Bndtools.
- Argument completion for all parameters of all parts of the interaction.
- In a UI, all wizard pages can be generated in one go.
- Don't need multiple methods for commands that have optional parameters.
- No special things required for scripting, script can just provide all parameters.
Downsides:
- The questions are "disconnected" from the command implementations. This is less obvious to program.
- The "DSL" that describes the "@Condition" is a more limited than Java code.