Skip to content

Commit

Permalink
Highlight builtin commands help
Browse files Browse the repository at this point in the history
  • Loading branch information
mattirn committed Feb 23, 2019
1 parent 367a5bf commit 0b61777
Show file tree
Hide file tree
Showing 3 changed files with 163 additions and 8 deletions.
10 changes: 4 additions & 6 deletions builtins/src/main/java/org/jline/builtins/Commands.java
Original file line number Diff line number Diff line change
Expand Up @@ -58,11 +58,9 @@ public static void tmux(Terminal terminal, PrintStream out, PrintStream err,
"Usage: tmux [command]",
" -? --help Show help",
};
// Simplified parsing
if (argv.length == 1 && ("--help".equals(argv[0]) || "-?".equals(argv[0]))) {
for (String s : usage) {
err.println(s);
}
Options opt = Options.compile(usage).parse(argv);
if (opt.isSet("help")) {
opt.usage(err);
return;
}
// Tmux with no args
Expand Down Expand Up @@ -117,7 +115,7 @@ public static void less(Terminal terminal, InputStream in, PrintStream out, Prin
" -e --quit-at-eof Exit on second EOF",
" -E --QUIT-AT-EOF Exit on EOF",
" -q --quiet --silent Silent mode",
" -Q --QUIET --SILENT Completely silent",
" -Q --QUIET --SILENT Completely silent",
" -S --chop-long-lines Do not fold long lines",
" -i --ignore-case Search ignores lowercase case",
" -I --IGNORE-CASE Search ignores all case",
Expand Down
101 changes: 100 additions & 1 deletion builtins/src/main/java/org/jline/builtins/Options.java
Original file line number Diff line number Diff line change
Expand Up @@ -237,7 +237,7 @@ public void usage(PrintStream err) {

String msg = buf.toString();

err.print(msg);
HelpPrinter.getInstance().print(err, msg);
}

/**
Expand Down Expand Up @@ -505,4 +505,103 @@ public String toString() {
return "isSet" + optSet + "\nArg" + optArg + "\nargs" + xargs;
}

public static class HelpPrinter {
private static HelpPrinter instance = new HelpPrinter();

private final Pattern patternTitle = Pattern.compile("(Usage):\\b");
private final Pattern patternCommand = Pattern.compile("(^\\s*)([a-z]+){1}\\b");
private final Pattern patternArgument = Pattern.compile("(\\[|\\s|=)([A-Za-z]+[A-Za-z_-]*){1}\\b");
private final Pattern patternArgumentInComment = Pattern.compile("(\\s)([a-z]+[-]+[a-z]+){1}\\b");
private final Pattern patternOption = Pattern.compile("(\\s|\\[)(-\\?|[-]{1,2}[\\?A-Za-z-]+\\b){1}");
private final String title = "Usage";
private final String ansiReset = "\033[0m";
private String ansi4title = "\033[34;1m";
private String ansi4command = "\033[1m";
private String ansi4argument = "\033[3m";
private String ansi4option = "\033[33m";
private boolean color = false;

private HelpPrinter() {}

public static HelpPrinter getInstance() {
return instance;
}

public void setColor(boolean color) {
this.color = color;
}

public void setAnsi4title(String ansicode) {
this.ansi4title = ansicode;
}

public void setAnsi4command(String ansicode) {
this.ansi4command = ansicode;
}

public void setAnsi4argument(String ansicode) {
this.ansi4argument = ansicode;
}

public void setAnsi4option(String ansicode) {
this.ansi4option = ansicode;
}

public void print(PrintStream err, String msg) {
if (color) {
String[] p = msg.split(title + ":", 2);
if (p.length == 2) {
err.print(highlightCommand(p[0]));
err.print(ansi4title + title + ansiReset + ":");
for (String line: p[1].split("\n")) {
int ind = line.lastIndexOf(" ");
if (ind > 20) {
line = highlightSyntax(line.substring(0, ind)) + highlightComment(line.substring(ind + 1, line.length()));
} else {
line = highlightSyntax(line);
}
err.println(line);
}
} else {
err.print(msg);
}
} else {
err.print(msg);
}
}

private String highlightCommand(String command) {
Matcher matcher = patternCommand.matcher(command);
if (matcher.find()) {
command = matcher.replaceAll("$1" + ansi4command + "$2" + ansiReset);
}
return command;
}

private String highlightSyntax(String syntax) {
syntax = highlightCommand(syntax);
Matcher matcher = patternArgument.matcher(syntax);
if (matcher.find()) {
syntax = matcher.replaceAll("$1" + ansi4argument + "$2" + ansiReset);
}
matcher = patternOption.matcher(syntax);
if (matcher.find()) {
syntax = matcher.replaceAll("$1" + ansi4option + "$2" + ansiReset);
}
return syntax;
}

private String highlightComment(String comment) {
Matcher matcher = patternOption.matcher(comment);
if (matcher.find()) {
comment = matcher.replaceAll("$1" + ansi4option + "$2" + ansiReset);
}
matcher = patternArgumentInComment.matcher(comment);
if (matcher.find()) {
comment = matcher.replaceAll("$1" + ansi4argument + "$2" + ansiReset);
}
return comment;
}
}

}
60 changes: 59 additions & 1 deletion builtins/src/test/java/org/jline/example/Example.java
Original file line number Diff line number Diff line change
Expand Up @@ -9,16 +9,26 @@
package org.jline.example;

import java.io.IOException;
import java.io.InputStream;
import java.io.PrintStream;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.time.LocalDate;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeFormatterBuilder;
import java.util.*;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Supplier;

import org.jline.builtins.Commands;
import org.jline.builtins.Completers;
import org.jline.builtins.Completers.CompletionData;
import org.jline.builtins.Completers.TreeCompleter;
import org.jline.builtins.Options.HelpPrinter;
import org.jline.keymap.KeyMap;
import org.jline.reader.*;
import org.jline.reader.impl.DefaultParser;
Expand Down Expand Up @@ -230,6 +240,7 @@ public void complete(LineReader reader, ParsedLine line, List<Candidate> candida
}

Terminal terminal = builder.build();
HelpPrinter.getInstance().setColor(true);

LineReader reader = LineReaderBuilder.builder()
.terminal(terminal)
Expand Down Expand Up @@ -304,7 +315,8 @@ public void complete(LineReader reader, ParsedLine line, List<Candidate> candida
if (line.equalsIgnoreCase("quit") || line.equalsIgnoreCase("exit")) {
break;
}
ParsedLine pl = reader.getParser().parse(line, 0);
ParsedLine pl = reader.getParser().parse(line, 0);
String[] argv = pl.words().toArray(new String[0]);
if ("set".equals(pl.word())) {
if (pl.words().size() == 3) {
reader.setVariable(pl.words().get(1), pl.words().get(2));
Expand Down Expand Up @@ -380,6 +392,52 @@ else if ("cls".equals(pl.word())) {
else if ("sleep".equals(pl.word())) {
Thread.sleep(3000);
}
//
// builtin commands are added in order to test HelpPrinter class
//
else if ("tmux".equals(pl.word())) {
Commands.tmux(terminal, System.out, System.err,
null, //Supplier<Object> getter,
null, //Consumer<Object> setter,
null, //Consumer<Terminal> runner,
argv);
}
else if ("nano".equals(pl.word())) {
Commands.nano(terminal, System.out, System.err,
Paths.get(""),
argv);
}
else if ("less".equals(pl.word())) {
Commands.less(terminal, System.in, System.out, System.err,
Paths.get(""),
argv);
}
else if ("history".equals(pl.word())) {
Commands.history(reader, System.out, System.err,
argv);
}
else if ("complete".equals(pl.word())) {
Commands.complete(reader, System.out, System.err,
null, // Map<String, List<CompletionData>> completions,
argv);
}
else if ("widget".equals(pl.word())) {
Commands.widget(reader, System.out, System.err,
null, //Function<String, Widget> widgetCreator,
argv);
}
else if ("keymap".equals(pl.word())) {
Commands.keymap(reader, System.out, System.err,
argv);
}
else if ("setopt".equals(pl.word())) {
Commands.setopt(reader, System.out, System.err,
argv);
}
else if ("unsetopt".equals(pl.word())) {
Commands.unsetopt(reader, System.out, System.err,
argv);
}
}
}
catch (Throwable t) {
Expand Down

0 comments on commit 0b61777

Please sign in to comment.