-
Notifications
You must be signed in to change notification settings - Fork 446
Closed
Labels
Milestone
Description
Picocli reuse command object when used in interactive mode. While reusing it clears all the instance variable annotated with @Option/@Paramters, but does not reset the options specified at method level. It looks like Picocli does not invokes method annotated with @option unless the matching option is specified in command line. Due to this, when the command is executed with the option, then instance variable is initialized and next the command is executed without the option, then same value gets visible.
We thought of using default value attribute to get it reset, but unfortunately, in our application, we cannot predefine the default value, thus could not take this approach. Kindly check it.
Example code
package example;
import org.jline.console.SystemRegistry;
import org.jline.console.impl.Builtins;
import org.jline.console.impl.SystemRegistryImpl;
import org.jline.reader.LineReader;
import org.jline.reader.LineReaderBuilder;
import org.jline.reader.MaskingCallback;
import org.jline.reader.Parser;
import org.jline.reader.impl.DefaultParser;
import org.jline.terminal.Terminal;
import org.jline.terminal.TerminalBuilder;
import picocli.CommandLine;
import picocli.CommandLine.Command;
import picocli.CommandLine.Option;
import picocli.shell.jline3.PicocliCommands;
import picocli.shell.jline3.PicocliCommands.PicocliCommandsFactory;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.List;
import java.util.function.Supplier;
/**
* Example.
*/
public class Example {
/**
* Top-level command that just prints help.
*/
@Command(name = "", description = "Example root command.", subcommands = {MyCommand.class})
static class CliCommands implements Runnable {
public void run() {
System.out.println(new CommandLine(this).getUsageMessage());
}
}
/**
* A command with some options to demonstrate issue.
*/
@Command(name = "cmd", mixinStandardHelpOptions = true, description = "Example test command.")
static class MyCommand implements Runnable {
private List<String> modules;
@Option(names = "-c", description = "comps", split = ",")
private List<String> comps;
public List<String> getModules() {
return modules;
}
@Option(names = "-m", description = "modules", split = ",")
public void setModules(final List<String> modules) {
this.modules = modules;
}
public void run() {
System.out.println("Modules = " + modules);
System.out.println("Comps = " + comps);
}
}
/**
* Main method.
* @param args arguments.
* @throws Exception exception.
*/
public static void main(final String[] args) throws Exception {
Supplier<Path> workDir = () -> Paths.get(System.getProperty("user.dir"));
// set up JLine built-in commands
Builtins builtins = new Builtins(workDir, null, null);
// set up picocli commands
CliCommands commands = new CliCommands();
PicocliCommandsFactory factory = new PicocliCommandsFactory();
CommandLine cmd = new CommandLine(commands, factory);
PicocliCommands picocliCommands = new PicocliCommands(cmd);
Parser parser = new DefaultParser();
Terminal terminal = TerminalBuilder.builder().build();
SystemRegistry systemRegistry = new SystemRegistryImpl(parser, terminal, workDir, null);
systemRegistry.setCommandRegistries(builtins, picocliCommands);
LineReader reader = LineReaderBuilder.builder().terminal(terminal).completer(systemRegistry.completer())
.parser(parser).variable(LineReader.LIST_MAX, 50).build();
builtins.setLineReader(reader);
factory.setTerminal(terminal);
String prompt = "prompt> ";
String rightPrompt = null;
// start the shell and process input until the user quits with Ctrl-D
String line;
while (true) {
systemRegistry.cleanUp();
line = reader.readLine(prompt, rightPrompt, (MaskingCallback) null, null);
systemRegistry.execute(line);
}
}
}
Execution
prompt> cmd
Modules = null
Comps = null
prompt> cmd -c c1 -m m1
Modules = [m1]
Comps = [c1]
prompt> cmd
Modules = [m1]
Comps = null
prompt>