Skip to content

Commit

Permalink
1. Add javadocs and other comments
Browse files Browse the repository at this point in the history
2. Use LineReaderImpl instead of LineReader, and have the client/ caller do the cast
3. Add a constructor to allow factories to be chained
  • Loading branch information
sualeh authored and remkop committed Dec 14, 2020
1 parent 9ba72e6 commit ebb9cbc
Show file tree
Hide file tree
Showing 2 changed files with 59 additions and 9 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
import picocli.CommandLine;
import picocli.CommandLine.Command;
import picocli.CommandLine.Help;
import picocli.CommandLine.IFactory;
import picocli.CommandLine.Model.CommandSpec;
import picocli.CommandLine.Model.OptionSpec;

Expand All @@ -44,32 +45,81 @@ public class PicocliCommands implements CommandRegistry {

/**
* Command that clears the screen.
* <p>
* <b>WARNING:</b> This subcommand needs a JLine {@code LineReaderImpl} to clear the screen.
* To accomplish this, construct the {@code CommandLine} with a {@code PicocliCommandsFactory},
* and set the {@code LineReaderImpl} on that factory. For example:
* <pre>
* PicocliCommandsFactory factory = new PicocliCommandsFactory();
* CommandLine cmd = new CommandLine(new MyApp(), factory);
* LineReaderImpl readerImpl = ... // create reader
* factory.setLineReader(readerImpl);
* </pre>
*
* @since 4.6
*/
@Command(name = "cls", aliases = "clear", mixinStandardHelpOptions = true,
description = "Clears the screen", version = "1.0")
public static class ClearScreen implements Callable<Void> {

private final LineReaderImpl reader;

ClearScreen(LineReader reader) { this.reader = (LineReaderImpl) reader; }
ClearScreen(LineReaderImpl reader) { this.reader = reader; }

public Void call() throws IOException {
if (reader != null) { reader.clearScreen(); }
return null;
}
}


/**
* Command factory that is necessary for applications that want the use the {@code ClearScreen} subcommand.
* It allows chaining (or delegrating) to a custom factory.
* <p>
* <b>WARNING:</b> If the application uses the {@code ClearScreen} subcommand, construct the {@code CommandLine}
* with a {@code PicocliCommandsFactory}, and set the {@code LineReaderImpl} on that factory. Applications need
* to call the setLineReader method with a {@code LineReaderImpl}; this will be passed to the {@code ClearScreen}
* subcommand.
*
* For example:
* <pre>
* PicocliCommandsFactory factory = new PicocliCommandsFactory();
* CommandLine cmd = new CommandLine(new MyApp(), factory);
* LineReaderImpl readerImpl = ... // create reader
* factory.setLineReader(readerImpl);
* </pre>
*
* Custom factories can be chained by passing them in to the constructor like this:
* <pre>
* MyCustomFactory customFactory = createCustomFactory(); // your application custom factory
* PicocliCommandsFactory factory = new PicocliCommandsFactory(customFactory); // chain the factories
* </pre>
*
* @since 4.6
*/
public static class PicocliCommandsFactory implements CommandLine.IFactory {
private LineReader reader;

private CommandLine.IFactory nextFactory;
private LineReaderImpl reader;

public PicocliCommandsFactory() {
// nextFactory and line reader are null
}

public PicocliCommandsFactory(IFactory nextFactory) {
this.nextFactory = nextFactory;
// nextFactory is set (but may be null) and line reader is null
}

@SuppressWarnings("unchecked")
public <K> K create(Class<K> clazz) throws Exception {
if (ClearScreen.class == clazz) { return (K) new ClearScreen(reader); }
if (nextFactory != null) { return nextFactory.create(clazz); }
return CommandLine.defaultFactory().create(clazz);
}

public void setLineReader(LineReader reader) {
public void setLineReader(LineReaderImpl reader) {
this.reader = reader;
// reader may be null, so check before using it in ClearScreen command
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -137,12 +137,12 @@ public static void main(String[] args) {
builtins.alias("bindkey", "keymap");
// set up picocli commands
CliCommands commands = new CliCommands();

PicocliCommandsFactory factory = new PicocliCommandsFactory();
// Or, if you have your own factory, you can chain them like this:
// MyCustomFactory customFactory = createCustomFactory(); // your application custom factory
// PicocliCommands.Factory factory = new PicocliCommands.Factory(customFactory); // chain the factories
// PicocliCommandsFactory factory = new PicocliCommandsFactory(customFactory); // chain the factories

CommandLine cmd = new CommandLine(commands, factory);
PicocliCommands picocliCommands = new PicocliCommands(Example::workDir, cmd);

Expand All @@ -159,7 +159,7 @@ public static void main(String[] args) {
.variable(LineReader.LIST_MAX, 50) // max tab completion candidates
.build();
builtins.setLineReader(reader);
factory.setLineReader(reader);
factory.setLineReader((LineReaderImpl) reader);
TailTipWidgets widgets = new TailTipWidgets(reader, systemRegistry::commandDescription, 5, TailTipWidgets.TipType.COMPLETER);
widgets.enable();
KeyMap<Binding> keyMap = reader.getKeyMaps().get("main");
Expand Down

0 comments on commit ebb9cbc

Please sign in to comment.