Skip to content

Commit

Permalink
Parser: added SPLIT_LINE context
Browse files Browse the repository at this point in the history
  • Loading branch information
mattirn committed Feb 15, 2020
1 parent 8b28847 commit 9b0c987
Show file tree
Hide file tree
Showing 4 changed files with 38 additions and 40 deletions.
54 changes: 15 additions & 39 deletions builtins/src/main/java/org/jline/builtins/SystemRegistryImpl.java
Original file line number Diff line number Diff line change
Expand Up @@ -490,11 +490,10 @@ private boolean isPipe(String arg, Set<String> pipes) {

private List<CommandData> compileCommandLine(String commandLine) {
List<CommandData> out = new ArrayList<>();
ParsedLine pl = parser.parse(commandLine, 0, ParseContext.ACCEPT_LINE);
ParsedLine pl = parser.parse(commandLine, 0, ParseContext.SPLIT_LINE);
List<String> ws = pl.words();
List<String> words = new ArrayList<>();
String nextRawLine = "";
ArgsParser argsParser = new ArgsParser();
Map<String,List<String>> customPipes = consoleId != null ? consoleEngine().getPipes() : new HashMap<>();
if (consoleId != null && pl.words().contains(pipeName.get(Pipe.NAMED))) {
StringBuilder sb = new StringBuilder();
Expand Down Expand Up @@ -524,15 +523,15 @@ private List<CommandData> compileCommandLine(String commandLine) {
}
sb.append(pipeAlias);
} else {
sb.append(argsParser.arg2Line(ws.get(i)));
sb.append(ws.get(i));
}
} else {
sb.append(argsParser.arg2Line(ws.get(i)));
sb.append(ws.get(i));
}
sb.append(" ");
}
nextRawLine = sb.toString();
pl = parser.parse(nextRawLine, 0, ParseContext.ACCEPT_LINE);
pl = parser.parse(nextRawLine, 0, ParseContext.SPLIT_LINE);
words = pl.words();
if (trace) {
consoleEngine().trace(nextRawLine);
Expand All @@ -553,7 +552,7 @@ private List<CommandData> compileCommandLine(String commandLine) {
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);
pl = parser.parse(nextRawLine.replaceFirst(command, consoleEngine().getAlias(command)), 0, ParseContext.SPLIT_LINE);
command = ConsoleEngine.plainCommand(parser.getCommand(pl.word()));
words = pl.words();
first = 0;
Expand All @@ -563,7 +562,7 @@ private List<CommandData> compileCommandLine(String commandLine) {
File file = null;
boolean append = false;
boolean pipeStart = false;
argsParser = new ArgsParser();
ArgsParser argsParser = new ArgsParser();
List<String> _words = new ArrayList<>();
for (int i = first; i < last; i++) {
argsParser.next(words.get(i));
Expand Down Expand Up @@ -634,12 +633,11 @@ private List<CommandData> compileCommandLine(String commandLine) {
if (last == words.size()) {
pipes.add("END_PIPE");
}
argsParser = new ArgsParser();
String subLine = last < words.size() || first > 0
? argsParser.join(_words)
? _words.stream().collect(Collectors.joining(" "))
: pl.line();
if (last + 1 < words.size()) {
nextRawLine = argsParser.join(words.subList(last + 1, words.size()));
nextRawLine = words.subList(last + 1, words.size()).stream().collect(Collectors.joining(" "));
}
boolean done = true;
boolean statement = false;
Expand Down Expand Up @@ -687,7 +685,13 @@ private List<CommandData> compileCommandLine(String commandLine) {
rawLine = flipArgument(command, subLine, pipes, arglist);
}
if (done) {
String[] args = statement ? new String[] {} : arglist.toArray(new String[0]);
String[] args = new String[] {};
if (!statement) {
ParsedLine plf = parser.parse(rawLine, 0, ParseContext.ACCEPT_LINE);
if (plf.words().size() > 1) {
args = plf.words().subList(1, plf.words().size()).toArray(new String[0]);
}
}
out.add(new CommandData(rawLine, statement ? "" : command, args, variable, file, append, pipes.get(pipes.size() - 1)));
rawLine = null;
}
Expand All @@ -702,14 +706,10 @@ private static class ArgsParser {
private int square = 0;
private boolean quoted;
private boolean doubleQuoted;
private boolean unquotedSpace;
private boolean hasQuote;

public ArgsParser() {}

public void next(String arg) {
unquotedSpace = false;
hasQuote = false;
char prevChar = ' ';
for (int i = 0; i < arg.length(); i++) {
char c = arg.charAt(i);
Expand All @@ -731,9 +731,6 @@ public void next(String arg) {
doubleQuoted = true;
} else if (c == '\'') {
quoted = true;
hasQuote = true;
} else if (c == ' ') {
unquotedSpace = true;
}
} else if (quoted && c == '\'') {
quoted = false;
Expand All @@ -749,27 +746,6 @@ public boolean isEnclosed() {
return round != 0 || curly != 0 || square != 0 || quoted || doubleQuoted;
}

public String join(List<String> words) {
StringBuilder sb = new StringBuilder();
boolean first = true;
for (String w : words) {
if (!first) {
sb.append(" ");
}
sb.append(arg2Line(w));
first = false;
}
return sb.toString();
}

public String arg2Line(String arg) {
String out = arg;
next(arg);
if (unquotedSpace) {
out = hasQuote ? "\"" + out + "\"" : "'" + out + "'";
}
return out;
}
}

private String flipArgument(final String command, final String subLine, final List<String> pipes, List<String> arglist) {
Expand Down
6 changes: 6 additions & 0 deletions reader/src/main/java/org/jline/reader/Parser.java
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,12 @@ enum ParseContext {
*/
ACCEPT_LINE,

/** Parsed words will have all characters present in input line
* including quotes and escape chars.
* May throw EOFError in which case we have incomplete input.
*/
SPLIT_LINE,

/** Parse to find completions (typically after a Tab).
* We should tolerate and ignore errors.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -238,12 +238,15 @@ public ParsedLine parse(final String line, final int cursor, ParseContext contex
quoteStart = i;
if (current.length()==0) {
quotedWord = true;
if (context == ParseContext.SPLIT_LINE) {
current.append(line.charAt(i));
}
} else {
current.append(line.charAt(i));
}
} else if (quoteStart >= 0 && line.charAt(quoteStart) == line.charAt(i) && !isEscaped(line, i)) {
// End quote block
if (!quotedWord) {
if (!quotedWord || context == ParseContext.SPLIT_LINE) {
current.append(line.charAt(i));
} else if (rawWordCursor >= 0 && rawWordLength < 0) {
rawWordLength = i - rawWordStart + 1;
Expand All @@ -266,6 +269,8 @@ public ParsedLine parse(final String line, final int cursor, ParseContext contex
if (quoteStart < 0) {
bracketChecker.check(line, i);
}
} else if (context == ParseContext.SPLIT_LINE) {
current.append(line.charAt(i));
}
}
}
Expand Down
11 changes: 11 additions & 0 deletions reader/src/test/java/org/jline/reader/impl/DefaultParserTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@

import org.jline.reader.CompletingParsedLine;
import org.jline.reader.ParsedLine;
import org.jline.reader.Parser.ParseContext;
import org.junit.Test;

import static org.junit.Assert.assertEquals;
Expand Down Expand Up @@ -66,4 +67,14 @@ public void testVariable() {
assertEquals("variable['key']", parser.getVariable("variable['key'] = statement"));
}

@Test
public void testSplitLine() {
DefaultParser parser = new DefaultParser();
CompletingParsedLine line = (CompletingParsedLine) parser.parse("foo second\\ param \"quoted param\"", 0, ParseContext.SPLIT_LINE);
assertNotNull(line);
assertNotNull(line.words());
assertEquals("foo", line.words().get(0));
assertEquals("second\\ param", line.words().get(1));
assertEquals("\"quoted param\"", line.words().get(2));
}
}

0 comments on commit 9b0c987

Please sign in to comment.