Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

move old JLine 3 example to wiki #1117

Merged
merged 1 commit into from
Jul 1, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
232 changes: 3 additions & 229 deletions picocli-shell-jline3/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,237 +49,11 @@ in the JLine `TailTipWidgets` terminal status bar.

JLine [Wiki](https://github.com/jline/jline3/wiki) and some more [Demos](https://github.com/jline/jline3/wiki/Demos).

## Example for JLine 3.13.2 and Picocli 4.1.2
## Example

The following example requires JLine 3.13.2 or higher.
The following example requires JJLine 3.14.1 and Picocli 4.3+.

```java
package picocli.shell.jline3.example;

import org.fusesource.jansi.AnsiConsole;
import org.jline.builtins.Builtins;
import org.jline.builtins.Completers.SystemCompleter;
import org.jline.builtins.Options.HelpException;
import org.jline.builtins.Widgets.CmdDesc;
import org.jline.builtins.Widgets.CmdLine;
import org.jline.builtins.Widgets.TailTipWidgets;
import org.jline.builtins.Widgets.TailTipWidgets.TipType;
import org.jline.reader.*;
import org.jline.reader.impl.DefaultParser;
import org.jline.reader.impl.LineReaderImpl;
import org.jline.terminal.Terminal;
import org.jline.terminal.TerminalBuilder;
import org.jline.utils.AttributedStringBuilder;
import org.jline.utils.AttributedStyle;
import picocli.CommandLine;
import picocli.CommandLine.ArgGroup;
import picocli.CommandLine.Command;
import picocli.CommandLine.Option;
import picocli.CommandLine.ParentCommand;
import picocli.shell.jline3.PicocliCommands;

import java.io.IOException;
import java.io.PrintWriter;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Arrays;
import java.util.concurrent.Callable;
import java.util.concurrent.TimeUnit;

/**
* Example that demonstrates how to build an interactive shell with JLine3 and picocli.
* @since 4.1.2
*/
public class Example {

/**
* Top-level command that just prints help.
*/
@Command(name = "",
description = {
"Example interactive shell with completion. " +
"Hit @|magenta <TAB>|@ to see available commands.",
"Type `@|bold,yellow keymap ^[s tailtip-toggle|@`, " +
"then hit @|magenta ALT-S|@ to toggle tailtips.",
""},
footer = {"", "Press Ctl-D to exit."},
subcommands = {
MyCommand.class, ClearScreen.class, CommandLine.HelpCommand.class})
static class CliCommands implements Runnable {
LineReaderImpl reader;
PrintWriter out;

CliCommands() {}

public void setReader(LineReader reader){
this.reader = (LineReaderImpl)reader;
out = reader.getTerminal().writer();
}

public void run() {
out.println(new CommandLine(this).getUsageMessage());
}
}

/**
* A command with some options to demonstrate completion.
*/
@Command(name = "cmd", mixinStandardHelpOptions = true, version = "1.0",
description = "Command with some options to demonstrate TAB-completion" +
" (note that enum values also get completed)",
subcommands = CommandLine.HelpCommand.class)
static class MyCommand implements Runnable {
@Option(names = {"-v", "--verbose"},
description = { "Specify multiple -v options to increase verbosity.",
"For example, `-v -v -v` or `-vvv`"})
private boolean[] verbosity = {};

@ArgGroup(exclusive = false)
private MyDuration myDuration = new MyDuration();

static class MyDuration {
@Option(names = {"-d", "--duration"},
description = "The duration quantity.",
required = true)
private int amount;

@Option(names = {"-u", "--timeUnit"},
description = "The duration time unit.",
required = true)
private TimeUnit unit;
}

@ParentCommand CliCommands parent;

public void run() {
if (verbosity.length > 0) {
parent.out.printf("Hi there. You asked for %d %s.%n",
myDuration.amount, myDuration.unit);
} else {
parent.out.println("hi!");
}
}
}

/**
* Command that clears the screen.
*/
@Command(name = "cls", aliases = "clear", mixinStandardHelpOptions = true,
description = "Clears the screen", version = "1.0")
static class ClearScreen implements Callable<Void> {

@ParentCommand CliCommands parent;

public Void call() throws IOException {
parent.reader.clearScreen();
return null;
}
}

/**
* Provide command descriptions for JLine TailTipWidgets
* to be displayed in the status bar.
*/
private static class DescriptionGenerator {
Builtins builtins;
PicocliCommands picocli;

public DescriptionGenerator(Builtins builtins, PicocliCommands picocli) {
this.builtins = builtins;
this.picocli = picocli;
}

CmdDesc commandDescription(CmdLine line) {
CmdDesc out = null;
switch (line.getDescriptionType()) {
case COMMAND:
String cmd = Parser.getCommand(line.getArgs().get(0));
if (builtins.hasCommand(cmd)) {
out = builtins.commandDescription(cmd);
} else if (picocli.hasCommand(cmd)) {
out = picocli.commandDescription(cmd);
}
break;
default:
break;
}
return out;
}
}

public static void main(String[] args) {
AnsiConsole.systemInstall();
try {
// set up JLine built-in commands
Path workDir = Paths.get("");
Builtins builtins = new Builtins(workDir, null, null);
builtins.rename(org.jline.builtins.Builtins.Command.TTOP, "top");
builtins.alias("zle", "widget");
builtins.alias("bindkey", "keymap");
SystemCompleter systemCompleter = builtins.compileCompleters();
// set up picocli commands
CliCommands commands = new CliCommands();
CommandLine cmd = new CommandLine(commands);
PicocliCommands picocliCommands = new PicocliCommands(workDir, cmd);
systemCompleter.add(picocliCommands.compileCompleters());
systemCompleter.compile();
Terminal terminal = TerminalBuilder.builder().build();
LineReader reader = LineReaderBuilder.builder()
.terminal(terminal)
.completer(systemCompleter)
.parser(new DefaultParser())
.variable(LineReader.LIST_MAX, 50) // max tab completion candidates
.build();
builtins.setLineReader(reader);
commands.setReader(reader);
DescriptionGenerator descriptionGenerator = new DescriptionGenerator(builtins, picocliCommands);
new TailTipWidgets(reader, descriptionGenerator::commandDescription, 5, TipType.COMPLETER);

String prompt = "prompt> ";
String rightPrompt = null;

// start the shell and process input until the user quits with Ctl-D
String line;
while (true) {
try {
line = reader.readLine(prompt, rightPrompt, (MaskingCallback) null, null);
if (line.matches("^\\s*#.*")) {
continue;
}
ParsedLine pl = reader.getParser().parse(line, 0);
String[] arguments = pl.words().toArray(new String[0]);
String command = Parser.getCommand(pl.word());
if (builtins.hasCommand(command)) {
builtins.execute(command, Arrays.copyOfRange(arguments, 1, arguments.length)
, System.in, System.out, System.err);
} else {
new CommandLine(commands).execute(arguments);
}
} catch (HelpException e) {
HelpException.highlight(e.getMessage(), HelpException.defaultStyle()).print(terminal);
} catch (UserInterruptException e) {
// Ignore
} catch (EndOfFileException e) {
return;
} catch (Exception e) {
AttributedStringBuilder asb = new AttributedStringBuilder();
asb.append(e.getMessage(), AttributedStyle.DEFAULT.foreground(AttributedStyle.RED));
asb.toAttributedString().println(terminal);
}
}
} catch (Throwable t) {
t.printStackTrace();
}
}
}
```

## Example for JLine 3.14.1 and Picocli 4.3+

Picocli 4.3.0 fixes an autocompletion issue with nested subcommands, thanks to a [pull request](https://github.com/remkop/picocli/pull/987) by one of the JLine authors.

This requires JLine 3.14.1, and things need to wired up differently with the new version of the `PicocliCommands` completer.
Here is the updated example:
See examples for older versions on the [wiki](https://github.com/remkop/picocli/wiki/JLine-3-Examples).

```java
package picocli.shell.jline3.example;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@

/**
* Example that demonstrates how to build an interactive shell with JLine3 and picocli.
* @since 4.1.2
* @since 4.3.2
*/
public class Example {

Expand Down