Skip to content

Commit

Permalink
added automatic insertion of closing bracket
Browse files Browse the repository at this point in the history
  • Loading branch information
mattirn committed Oct 2, 2019
1 parent 24b622d commit 9fb7822
Show file tree
Hide file tree
Showing 5 changed files with 79 additions and 45 deletions.
4 changes: 3 additions & 1 deletion builtins/src/test/java/org/jline/example/Example.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2002-2017, the original author or authors.
* Copyright (c) 2002-2019, the original author or authors.
*
* This software is distributable under the BSD license. See the terms of the
* BSD license in the documentation provided with this software.
Expand All @@ -22,6 +22,7 @@
import org.jline.builtins.Completers.TreeCompleter;
import org.jline.keymap.KeyMap;
import org.jline.reader.*;
import org.jline.reader.LineReader.Option;
import org.jline.reader.impl.DefaultParser;
import org.jline.reader.impl.DefaultParser.Bracket;
import org.jline.reader.impl.LineReaderImpl;
Expand Down Expand Up @@ -238,6 +239,7 @@ public void complete(LineReader reader, ParsedLine line, List<Candidate> candida
.parser(parser)
.variable(LineReader.SECONDARY_PROMPT_PATTERN, "%M%P > ")
.variable(LineReader.INDENTATION, 2)
.option(Option.INSERT_BRACKET, true)
.build();

if (timer) {
Expand Down
16 changes: 11 additions & 5 deletions reader/src/main/java/org/jline/reader/EOFError.java
Original file line number Diff line number Diff line change
Expand Up @@ -22,28 +22,34 @@ public class EOFError extends SyntaxError {

private static final long serialVersionUID = 1L;

private final String missing;
private final String missing;
private final int openBrackets;
private final String nextClosingBracket;

public EOFError(int line, int column, String message) {
this(line, column, message, null);
}

public EOFError(int line, int column, String message, String missing) {
this(line, column, message, missing, 0);
this(line, column, message, missing, 0, null);
}

public EOFError(int line, int column, String message, String missing, int openBrackets) {
public EOFError(int line, int column, String message, String missing, int openBrackets, String nextClosingBracket) {
super(line, column, message);
this.missing = missing;
this.openBrackets = openBrackets;
this.nextClosingBracket = nextClosingBracket;
}

public String getMissing() {
return missing;
}

public int getOpenBrackets(){
return openBrackets;
return openBrackets;
}

public String getNextClosingBracket() {
return nextClosingBracket;
}
}
7 changes: 5 additions & 2 deletions reader/src/main/java/org/jline/reader/LineReader.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2002-2018, the original author or authors.
* Copyright (c) 2002-2019, the original author or authors.
*
* This software is distributable under the BSD license. See the terms of the
* BSD license in the documentation provided with this software.
Expand Down Expand Up @@ -353,7 +353,7 @@ public interface LineReader {
* Number of history items to keep in the history file.
*/
String HISTORY_FILE_SIZE = "history-file-size";

/**
* New line automatic indentation after opening/closing bracket.
*/
Expand Down Expand Up @@ -420,6 +420,9 @@ enum Option {

/** if history search is fully case insensitive */
CASE_INSENSITIVE_SEARCH,

/** Automatic insertion of closing bracket */
INSERT_BRACKET,
;

private final boolean def;
Expand Down
63 changes: 38 additions & 25 deletions reader/src/main/java/org/jline/reader/impl/DefaultParser.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2002-2018, the original author or authors.
* Copyright (c) 2002-2019, the original author or authors.
*
* This software is distributable under the BSD license. See the terms of the
* BSD license in the documentation provided with this software.
Expand All @@ -17,8 +17,8 @@
import org.jline.reader.Parser;

public class DefaultParser implements Parser {
public enum Bracket {

public enum Bracket {
ROUND, // ()
CURLY, // {}
SQUARE, // []
Expand All @@ -32,11 +32,11 @@ public enum Bracket {
private boolean eofOnUnclosedQuote;

private boolean eofOnEscapedNewLine;

private char[] openingBrackets = null;

private char[] closingBrackets = null;

//
// Chainable setters
//
Expand All @@ -60,7 +60,7 @@ public DefaultParser eofOnUnclosedBracket(Bracket... brackets){
setEofOnUnclosedBracket(brackets);
return this;
}

public DefaultParser eofOnEscapedNewLine(boolean eofOnEscapedNewLine) {
this.eofOnEscapedNewLine = eofOnEscapedNewLine;
return this;
Expand Down Expand Up @@ -134,7 +134,7 @@ public void setEofOnUnclosedBracket(Bracket... brackets){
}
}
}

public ParsedLine parse(final String line, final int cursor, ParseContext context) {
List<String> words = new LinkedList<>();
StringBuilder current = new StringBuilder();
Expand Down Expand Up @@ -174,7 +174,7 @@ public ParsedLine parse(final String line, final int cursor, ParseContext contex
rawWordLength = i - rawWordStart + 1;
}
quoteStart = -1;
quotedWord = false;
quotedWord = false;
} else if (quoteStart < 0 && isDelimiter(line, i)) {
// Delimiter
if (current.length() > 0) {
Expand All @@ -188,7 +188,7 @@ public ParsedLine parse(final String line, final int cursor, ParseContext contex
} else {
if (!isEscapeChar(line, i)) {
current.append(line.charAt(i));
if (quoteStart < 0) {
if (quoteStart < 0) {
bracketChecker.check(line, i);
}
}
Expand Down Expand Up @@ -217,13 +217,18 @@ public ParsedLine parse(final String line, final int cursor, ParseContext contex
throw new EOFError(-1, -1, "Missing closing quote", line.charAt(quoteStart) == '\''
? "quote" : "dquote");
}
if (bracketChecker.isOpeningBracketMissing()) {
throw new EOFError(-1, -1, "Missing opening bracket", "missing: " + bracketChecker.getMissingOpeningBracket());
}
if (bracketChecker.isClosingBracketMissing()) {
throw new EOFError(-1, -1,
"Missing closing brackets", "add: " + bracketChecker.getMissingClosingBrackets(),
bracketChecker.getOpenBrackets());
if (bracketChecker.isClosingBracketMissing() || bracketChecker.isOpeningBracketMissing()) {
String message = null;
String missing = null;
if(bracketChecker.isClosingBracketMissing()) {
message = "Missing closing brackets";
missing = "add: " + bracketChecker.getMissingClosingBrackets();
} else {
message = "Missing opening bracket";
missing = "missing: " + bracketChecker.getMissingOpeningBracket();
}
throw new EOFError(-1, -1, message, missing,
bracketChecker.getOpenBrackets(), bracketChecker.getNextClosingBracket());
}
}

Expand Down Expand Up @@ -351,11 +356,12 @@ private class BracketChecker {
private List<Integer> nested = new ArrayList<>();
private int openBrackets = 0;
private int cursor;

private String nextClosingBracket;

public BracketChecker(int cursor){
this.cursor = cursor;
}

public void check(final CharSequence buffer, final int pos){
if (openingBrackets == null || pos < 0) {
return;
Expand All @@ -372,16 +378,19 @@ public void check(final CharSequence buffer, final int pos){
missingOpeningBracket = bid;
}
}
}
}
if (cursor > pos) {
openBrackets = nested.size();
if (nested.size() > 0) {
nextClosingBracket = String.valueOf(closingBrackets[nested.get(nested.size() - 1)]);
}
}
}

public boolean isOpeningBracketMissing(){
return missingOpeningBracket != -1;
}

public String getMissingOpeningBracket(){
if (!isOpeningBracketMissing()) {
return null;
Expand All @@ -403,19 +412,23 @@ public String getMissingClosingBrackets(){
}
return out.toString();
}

public int getOpenBrackets(){
return openBrackets;
}


public String getNextClosingBracket() {
return nested.size() > 1 ? nextClosingBracket : null;
}

private int bracketId(final char[] brackets, final CharSequence buffer, final int pos){
for (int i=0; i < brackets.length; i++) {
if (buffer.charAt(pos) == brackets[i]) {
return i;
}
}
return -1;
}
return -1;
}
}

/**
Expand Down
34 changes: 22 additions & 12 deletions reader/src/main/java/org/jline/reader/impl/LineReaderImpl.java
Original file line number Diff line number Diff line change
Expand Up @@ -2013,9 +2013,9 @@ protected boolean insertClose(String s) {
redisplay();

peekCharacter(blink);
int blinkPosition = buf.cursor();
int blinkPosition = buf.cursor();
buf.cursor(closePosition);

if (blinkPosition != closePosition - 1) {
removeIndentation();
}
Expand Down Expand Up @@ -2770,22 +2770,23 @@ protected boolean acceptLineAndDownHistory() {
}
return nextCommandFromHistory;
}

protected boolean acceptAndInferNextHistory() {
nextCommandFromHistory = false;
acceptLine();
if (!buf.toString().isEmpty()) {
nextHistoryId = searchBackwards(buf.toString(), history.last());
if (nextHistoryId >= 0 && history.size() > nextHistoryId + 1) {
nextHistoryId++;
nextCommandFromHistory = true;
nextCommandFromHistory = true;
}
}
return nextCommandFromHistory;
}

protected boolean acceptLine() {
parsedLine = null;
int curPos = 0;
if (!isSet(Option.DISABLE_EVENT_EXPANSION)) {
try {
String str = buf.toString();
Expand All @@ -2802,16 +2803,19 @@ protected boolean acceptLine() {
}
}
try {
curPos = buf.cursor();
parsedLine = parser.parse(buf.toString(), buf.cursor(), ParseContext.ACCEPT_LINE);
} catch (EOFError e) {
int indent = getInt(INDENTATION, DEFAULT_INDENTATION)*e.getOpenBrackets();
StringBuilder sb = new StringBuilder("\n");
if (indent > 0) {
for (int i = 0; i < indent; i++) {
sb.append(' ');
}
indention(e.getOpenBrackets(), sb);
int curMove = sb.length();
if (isSet(Option.INSERT_BRACKET) && e.getOpenBrackets() > 1 && e.getNextClosingBracket() != null) {
sb.append('\n');
indention(e.getOpenBrackets() - 1, sb);
sb.append(e.getNextClosingBracket());
}
buf.write(sb.toString());
buf.cursor(curPos + curMove);
return true;
} catch (SyntaxError e) {
// do nothing
Expand All @@ -2821,6 +2825,13 @@ protected boolean acceptLine() {
return true;
}

void indention(int nb, StringBuilder sb) {
int indent = getInt(INDENTATION, DEFAULT_INDENTATION)*nb;
for (int i = 0; i < indent; i++) {
sb.append(' ');
}
}

protected boolean selfInsert() {
for (int count = this.count; count > 0; count--) {
putString(getLastBinding());
Expand Down Expand Up @@ -3572,7 +3583,7 @@ protected Map<String, Widget> builtinWidgets() {
addBuiltinWidget(widgets, FOCUS_OUT, this::focusOut);
return widgets;
}

private void addBuiltinWidget(Map<String, Widget> widgets, String name, Widget widget) {
widgets.put(name, namedWidget(name, widget));
}
Expand Down Expand Up @@ -3619,7 +3630,6 @@ protected synchronized void redisplay(boolean flush) {
if(maskingCallback != null) {
line = maskingCallback.display(line);
}

concat(new AttributedString(line).columnSplitLength(Integer.MAX_VALUE), sb);
AttributedString toCursor = sb.toAttributedString();

Expand Down Expand Up @@ -3729,7 +3739,7 @@ public AttributedString getDisplayedBufferWithPrompts(List<AttributedString> sec
private AttributedString getHighlightedBuffer(String buffer) {
if (maskingCallback != null) {
buffer = maskingCallback.display(buffer);
}
}
if (highlighter != null && !isSet(Option.DISABLE_HIGHLIGHTER)) {
return highlighter.highlight(this, buffer);
}
Expand Down

0 comments on commit 9fb7822

Please sign in to comment.