Skip to content

Commit

Permalink
Compile command-line with custom pipes
Browse files Browse the repository at this point in the history
  • Loading branch information
mattirn committed Feb 8, 2020
1 parent ef3d00c commit 8c03cdf
Show file tree
Hide file tree
Showing 2 changed files with 102 additions and 35 deletions.
125 changes: 92 additions & 33 deletions builtins/src/main/java/org/jline/builtins/SystemRegistryImpl.java
Original file line number Diff line number Diff line change
Expand Up @@ -455,62 +455,111 @@ private List<CommandData> compileCommandLine(String commandLine) {
int first = 0;
int last = words.size();
String nextRawLine = commandLine;
Map<String,List<String>> customPipes = consoleId != null ? consoleEngine().getPipes() : new HashMap<>();
List<String> pipes = new ArrayList<>();
String pipeSource = null;
String rawLine = null;
String pipeResult = null;
do {
String variable = consoleId != null ? Parser.getVariable(words.get(first)) : null;
String command = ConsoleEngine.plainCommand(Parser.getCommand(words.get(first)));
if (consoleId != null && consoleEngine().hasAlias(command)) {
pl = parser.parse(nextRawLine.replaceFirst(command, consoleEngine().getAlias(command)), 0, ParseContext.ACCEPT_LINE);
command = ConsoleEngine.plainCommand(Parser.getCommand(pl.word()));
words = pl.words();
first = 0;
String variable = null;
String command = ConsoleEngine.plainCommand(Parser.getCommand(words.get(first)));
if (Parser.validCommandName(command) && consoleId != null) {
variable = Parser.getVariable(words.get(first));
if (consoleEngine().hasAlias(command)) {
pl = parser.parse(nextRawLine.replaceFirst(command, consoleEngine().getAlias(command)), 0, ParseContext.ACCEPT_LINE);
command = ConsoleEngine.plainCommand(Parser.getCommand(pl.word()));
words = pl.words();
first = 0;
}
}
last = words.size();
int lastarg = last;
File file = null;
boolean append = false;
boolean pipeStart = false;
for (int i = first + 1; i < last; i++) {
if (words.get(i).equals(">") || words.get(i).equals(">>")) {
pipes.add(words.get(i));
append = words.get(i).equals(">>");
if (i + 1 >= last) {
if (i + 2 != last) {
throw new IllegalArgumentException();
}
file = new File(words.get(i + 1));
last = i + 1;
lastarg = i;
break;
} else if (words.get(i).equals("|;")) {
if (variable != null || file != null || consoleId == null) {
if (variable != null || file != null || pipeResult != null || consoleId == null) {
throw new IllegalArgumentException();
}
pipes.add(words.get(i));
last = i;
lastarg = i;
variable = "_pipe" + (pipes.size() - 1);
break;
} else if (customPipes.containsKey(words.get(i))) {
pipes.add(words.get(i));
last = i;
lastarg = i;
if (pipeSource == null) {
pipeSource = "_pipe" + (pipes.size() - 1);
pipeResult = variable;
variable = pipeSource;
pipeStart = true;
}
}
}
if (last == words.size()) {
pipes.add("END");
}
String rawLine = last < words.size() || first > 0
String subLine = last < words.size() || first > 0
? words.subList(first, lastarg).stream().collect(Collectors.joining(" "))
: pl.line();
if (last + 1 < words.size()) {
nextRawLine = words.subList(last + 1, words.size()).stream().collect(Collectors.joining(" "));
}
boolean done = true;
boolean statement = false;
List<String> arglist = new ArrayList<>();
arglist.addAll(words.subList(first + 1, lastarg));
if (pipes.get(pipes.size() - 1).equals("|;")) {
rawLine = variable + "=" + rawLine;
if (rawLine != null || (pipes.size() > 1 && customPipes.containsKey(pipes.get(pipes.size() - 2)))) {
done = false;
if (rawLine == null) {
rawLine = pipeSource;
}
if (customPipes.containsKey(pipes.get(pipes.size() - 2))) {
List<String> fixes = customPipes.get(pipes.get(pipes.size() - 2));
rawLine += fixes.get(0) + subLine + fixes.get(1);
statement = true;
}
if (pipes.get(pipes.size() - 1).equals("|;")) {
done = true;
rawLine = variable + " = " + rawLine;
}
if (last + 1 >= words.size() || file != null) {
done = true;
if (pipeResult != null) {
rawLine = pipeResult + " = " + rawLine;
}
}

} else if (pipes.get(pipes.size() - 1).equals("|;") || pipeStart) {
if (pipeStart && pipeResult != null) {
subLine = subLine.substring(subLine.indexOf("=") + 1);
}
rawLine = variable + "=" + subLine;
} else if (pipes.size() > 1 && pipes.get(pipes.size() - 2).equals("|;")) {
String s = isCommandOrScript(command) ? "$" : "";
rawLine += " " + s + "_pipe" + (pipes.size() - 2);
rawLine = subLine + " " + s + "_pipe" + (pipes.size() - 2);
arglist.add(s + "_pipe" + (pipes.size() - 2));
} else {
rawLine = subLine;
}
if (done) {
String[] args = statement ? new String[] {} : arglist.toArray(new String[0]);
out.add(new CommandData(rawLine, statement ? "" : command, args, variable, file, append));
rawLine = null;
}
String[] args = arglist.toArray(new String[0]);
out.add(new CommandData(rawLine, command, args, variable, file, append));
first = last + 1;
} while (first < words.size());
return out;
Expand Down Expand Up @@ -603,26 +652,36 @@ public Object execute(String line) throws Exception {
}
outputStream.open();
}
if (isLocalCommand(cmd.command())) {
out = localExecute(cmd.command(), cmd.args());
} else {
int id = registryId(cmd.command());
if (id > -1) {
if (consoleId != null) {
out = commandRegistries[id].invoke(outputStream.getCommandSession(), cmd.command(),
consoleEngine().expandParameters(cmd.args()));
} else {
out = commandRegistries[id].execute(outputStream.getCommandSession(), cmd.command(),
cmd.args());
boolean consoleScript = false;
if (Parser.validCommandName(cmd.command())) {
if (isLocalCommand(cmd.command())) {
out = localExecute(cmd.command(), cmd.args());
} else {
int id = registryId(cmd.command());
if (id > -1) {
if (consoleId != null) {
out = commandRegistries[id].invoke(outputStream.getCommandSession(), cmd.command(),
consoleEngine().expandParameters(cmd.args()));
} else {
out = commandRegistries[id].execute(outputStream.getCommandSession(), cmd.command(),
cmd.args());
}
} else if (consoleId != null) {
consoleScript = true;
}
} else if (consoleId != null) {
if (outputStream.isByteStream() && !consoleEngine().scripts().contains(cmd.command())) {
outputStream.close();
outputStream.reset();
statement = true;
}
out = consoleEngine().execute(cmd.command(), cmd.rawLine(), cmd.args());
}
} else if (consoleId != null) {
consoleScript = true;
}
if (consoleScript) {
if (cmd.command().isEmpty() || !consoleEngine().scripts().contains(cmd.command())) {
statement = true;
}
if (statement && outputStream.isByteStream()) {
outputStream.close();
outputStream.reset();
}
out = consoleEngine().execute(cmd.command(), cmd.rawLine(), cmd.args());
}
} catch (HelpException e) {
trace(e);
Expand Down
12 changes: 10 additions & 2 deletions reader/src/main/java/org/jline/reader/Parser.java
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
import java.util.regex.Pattern;

public interface Parser {
static final String REGEX_VARIABLE = "[a-zA-Z_]{1,}[a-zA-Z0-9_-]*";
static final String REGEX_VARIABLE = "[a-zA-Z_]{1,}[a-zA-Z0-9_-]*((.|\\['|\\[\\\")[a-zA-Z0-9_-]*(|'\\]|\\\"\\])){0,1}";
static final String REGEX_COMMAND = "[:]{0,1}[a-zA-Z]{1,}[a-zA-Z0-9_-]*";

ParsedLine parse(String line, int cursor, ParseContext context) throws SyntaxError;
Expand All @@ -25,6 +25,10 @@ default boolean isEscapeChar(char ch) {
return ch == '\\';
}

public static boolean validCommandName(String name) {
return name.matches(REGEX_COMMAND);
}

static String getCommand(final String line) {
String out = null;
Pattern patternCommand = Pattern.compile("^\\s*" + REGEX_VARIABLE + "=(" + REGEX_COMMAND + ")(\\s+|$)");
Expand All @@ -33,13 +37,17 @@ static String getCommand(final String line) {
out = matcher.group(1);
} else {
out = line.trim().split("\\s+")[0];
int idx = out.indexOf("=");
if (idx > -1) {
out = out.substring(idx + 1);
}
}
return out;
}

static String getVariable(final String line) {
String out = null;
Pattern patternCommand = Pattern.compile("^\\s*(" + REGEX_VARIABLE + ")\\s*=[^=].*");
Pattern patternCommand = Pattern.compile("^\\s*(" + REGEX_VARIABLE + ")\\s*=[^=~].*");
Matcher matcher = patternCommand.matcher(line);
if (matcher.find()) {
out = matcher.group(1);
Expand Down

0 comments on commit 8c03cdf

Please sign in to comment.