--- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/keymap/BindingReader.java Mon Nov 04 14:26:18 2019 +0800
+++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/keymap/BindingReader.java Mon Nov 04 09:40:35 2019 +0100
@@ -4,7 +4,7 @@
* This software is distributable under the BSD license. See the terms of the
* BSD license in the documentation provided with this software.
*
- * http://www.opensource.org/licenses/bsd-license.php
+ * https://opensource.org/licenses/BSD-3-Clause
*/
package jdk.internal.org.jline.keymap;
--- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/keymap/KeyMap.java Mon Nov 04 14:26:18 2019 +0800
+++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/keymap/KeyMap.java Mon Nov 04 09:40:35 2019 +0100
@@ -4,7 +4,7 @@
* This software is distributable under the BSD license. See the terms of the
* BSD license in the documentation provided with this software.
*
- * http://www.opensource.org/licenses/bsd-license.php
+ * https://opensource.org/licenses/BSD-3-Clause
*/
package jdk.internal.org.jline.keymap;
--- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/Binding.java Mon Nov 04 14:26:18 2019 +0800
+++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/Binding.java Mon Nov 04 09:40:35 2019 +0100
@@ -4,7 +4,7 @@
* This software is distributable under the BSD license. See the terms of the
* BSD license in the documentation provided with this software.
*
- * http://www.opensource.org/licenses/bsd-license.php
+ * https://opensource.org/licenses/BSD-3-Clause
*/
package jdk.internal.org.jline.reader;
--- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/Buffer.java Mon Nov 04 14:26:18 2019 +0800
+++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/Buffer.java Mon Nov 04 09:40:35 2019 +0100
@@ -4,7 +4,7 @@
* This software is distributable under the BSD license. See the terms of the
* BSD license in the documentation provided with this software.
*
- * http://www.opensource.org/licenses/bsd-license.php
+ * https://opensource.org/licenses/BSD-3-Clause
*/
package jdk.internal.org.jline.reader;
--- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/Candidate.java Mon Nov 04 14:26:18 2019 +0800
+++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/Candidate.java Mon Nov 04 09:40:35 2019 +0100
@@ -4,7 +4,7 @@
* This software is distributable under the BSD license. See the terms of the
* BSD license in the documentation provided with this software.
*
- * http://www.opensource.org/licenses/bsd-license.php
+ * https://opensource.org/licenses/BSD-3-Clause
*/
package jdk.internal.org.jline.reader;
--- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/Completer.java Mon Nov 04 14:26:18 2019 +0800
+++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/Completer.java Mon Nov 04 09:40:35 2019 +0100
@@ -4,7 +4,7 @@
* This software is distributable under the BSD license. See the terms of the
* BSD license in the documentation provided with this software.
*
- * http://www.opensource.org/licenses/bsd-license.php
+ * https://opensource.org/licenses/BSD-3-Clause
*/
package jdk.internal.org.jline.reader;
--- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/CompletingParsedLine.java Mon Nov 04 14:26:18 2019 +0800
+++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/CompletingParsedLine.java Mon Nov 04 09:40:35 2019 +0100
@@ -4,7 +4,7 @@
* This software is distributable under the BSD license. See the terms of the
* BSD license in the documentation provided with this software.
*
- * http://www.opensource.org/licenses/bsd-license.php
+ * https://opensource.org/licenses/BSD-3-Clause
*/
package jdk.internal.org.jline.reader;
--- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/EndOfFileException.java Mon Nov 04 14:26:18 2019 +0800
+++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/EndOfFileException.java Mon Nov 04 09:40:35 2019 +0100
@@ -4,7 +4,7 @@
* This software is distributable under the BSD license. See the terms of the
* BSD license in the documentation provided with this software.
*
- * http://www.opensource.org/licenses/bsd-license.php
+ * https://opensource.org/licenses/BSD-3-Clause
*/
package jdk.internal.org.jline.reader;
--- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/Expander.java Mon Nov 04 14:26:18 2019 +0800
+++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/Expander.java Mon Nov 04 09:40:35 2019 +0100
@@ -4,7 +4,7 @@
* This software is distributable under the BSD license. See the terms of the
* BSD license in the documentation provided with this software.
*
- * http://www.opensource.org/licenses/bsd-license.php
+ * https://opensource.org/licenses/BSD-3-Clause
*/
package jdk.internal.org.jline.reader;
--- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/Highlighter.java Mon Nov 04 14:26:18 2019 +0800
+++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/Highlighter.java Mon Nov 04 09:40:35 2019 +0100
@@ -4,7 +4,7 @@
* This software is distributable under the BSD license. See the terms of the
* BSD license in the documentation provided with this software.
*
- * http://www.opensource.org/licenses/bsd-license.php
+ * https://opensource.org/licenses/BSD-3-Clause
*/
package jdk.internal.org.jline.reader;
--- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/History.java Mon Nov 04 14:26:18 2019 +0800
+++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/History.java Mon Nov 04 09:40:35 2019 +0100
@@ -4,11 +4,12 @@
* This software is distributable under the BSD license. See the terms of the
* BSD license in the documentation provided with this software.
*
- * http://www.opensource.org/licenses/bsd-license.php
+ * https://opensource.org/licenses/BSD-3-Clause
*/
package jdk.internal.org.jline.reader;
import java.io.IOException;
+import java.nio.file.Path;
import java.time.Instant;
import java.util.Iterator;
import java.util.ListIterator;
@@ -42,6 +43,26 @@
void save() throws IOException;
/**
+ * Write history to the file. If incremental only the events that are new since the last incremental operation to
+ * the file are added.
+ * @throws IOException if a problem occurs
+ */
+ void write(Path file, boolean incremental) throws IOException;
+
+ /**
+ * Append history to the file. If incremental only the events that are new since the last incremental operation to
+ * the file are added.
+ * @throws IOException if a problem occurs
+ */
+ void append(Path file, boolean incremental) throws IOException;
+
+ /**
+ * Read history from the file. If incremental only the events that are not contained within the internal list are added.
+ * @throws IOException if a problem occurs
+ */
+ void read(Path file, boolean incremental) throws IOException;
+
+ /**
* Purge history.
* @throws IOException if a problem occurs
*/
--- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/LineReader.java Mon Nov 04 14:26:18 2019 +0800
+++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/LineReader.java Mon Nov 04 09:40:35 2019 +0100
@@ -4,7 +4,7 @@
* This software is distributable under the BSD license. See the terms of the
* BSD license in the documentation provided with this software.
*
- * http://www.opensource.org/licenses/bsd-license.php
+ * https://opensource.org/licenses/BSD-3-Clause
*/
package jdk.internal.org.jline.reader;
@@ -95,7 +95,10 @@
String CALLBACK_FINISH = "callback-finish";
String CALLBACK_KEYMAP = "callback-keymap";
+ String ACCEPT_AND_INFER_NEXT_HISTORY = "accept-and-infer-next-history";
+ String ACCEPT_AND_HOLD = "accept-and-hold";
String ACCEPT_LINE = "accept-line";
+ String ACCEPT_LINE_AND_DOWN_HISTORY = "accept-line-and-down-history";
String ARGUMENT_BASE = "argument-base";
String BACKWARD_CHAR = "backward-char";
String BACKWARD_DELETE_CHAR = "backward-delete-char";
--- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/LineReaderBuilder.java Mon Nov 04 14:26:18 2019 +0800
+++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/LineReaderBuilder.java Mon Nov 04 09:40:35 2019 +0100
@@ -4,7 +4,7 @@
* This software is distributable under the BSD license. See the terms of the
* BSD license in the documentation provided with this software.
*
- * http://www.opensource.org/licenses/bsd-license.php
+ * https://opensource.org/licenses/BSD-3-Clause
*/
package jdk.internal.org.jline.reader;
@@ -85,7 +85,7 @@
public LineReaderBuilder parser(Parser parser) {
if (parser != null) {
try {
- if (!Boolean.parseBoolean(LineReader.PROP_SUPPORT_PARSEDLINE)
+ if (!Boolean.getBoolean(LineReader.PROP_SUPPORT_PARSEDLINE)
&& !(parser.parse("", 0) instanceof CompletingParsedLine)) {
Log.warn("The Parser of class " + parser.getClass().getName() + " does not support the CompletingParsedLine interface. " +
"Completion with escaped or quoted words won't work correctly.");
--- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/Macro.java Mon Nov 04 14:26:18 2019 +0800
+++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/Macro.java Mon Nov 04 09:40:35 2019 +0100
@@ -4,7 +4,7 @@
* This software is distributable under the BSD license. See the terms of the
* BSD license in the documentation provided with this software.
*
- * http://www.opensource.org/licenses/bsd-license.php
+ * https://opensource.org/licenses/BSD-3-Clause
*/
package jdk.internal.org.jline.reader;
--- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/MaskingCallback.java Mon Nov 04 14:26:18 2019 +0800
+++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/MaskingCallback.java Mon Nov 04 09:40:35 2019 +0100
@@ -4,7 +4,7 @@
* This software is distributable under the BSD license. See the terms of the
* BSD license in the documentation provided with this software.
*
- * http://www.opensource.org/licenses/bsd-license.php
+ * https://opensource.org/licenses/BSD-3-Clause
*/
package jdk.internal.org.jline.reader;
--- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/ParsedLine.java Mon Nov 04 14:26:18 2019 +0800
+++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/ParsedLine.java Mon Nov 04 09:40:35 2019 +0100
@@ -4,7 +4,7 @@
* This software is distributable under the BSD license. See the terms of the
* BSD license in the documentation provided with this software.
*
- * http://www.opensource.org/licenses/bsd-license.php
+ * https://opensource.org/licenses/BSD-3-Clause
*/
package jdk.internal.org.jline.reader;
--- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/Parser.java Mon Nov 04 14:26:18 2019 +0800
+++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/Parser.java Mon Nov 04 09:40:35 2019 +0100
@@ -4,7 +4,7 @@
* This software is distributable under the BSD license. See the terms of the
* BSD license in the documentation provided with this software.
*
- * http://www.opensource.org/licenses/bsd-license.php
+ * https://opensource.org/licenses/BSD-3-Clause
*/
package jdk.internal.org.jline.reader;
@@ -16,6 +16,10 @@
return parse(line, cursor, ParseContext.UNSPECIFIED);
}
+ default boolean isEscapeChar(char ch) {
+ return ch == '\\';
+ }
+
enum ParseContext {
UNSPECIFIED,
--- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/Reference.java Mon Nov 04 14:26:18 2019 +0800
+++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/Reference.java Mon Nov 04 09:40:35 2019 +0100
@@ -4,7 +4,7 @@
* This software is distributable under the BSD license. See the terms of the
* BSD license in the documentation provided with this software.
*
- * http://www.opensource.org/licenses/bsd-license.php
+ * https://opensource.org/licenses/BSD-3-Clause
*/
package jdk.internal.org.jline.reader;
--- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/UserInterruptException.java Mon Nov 04 14:26:18 2019 +0800
+++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/UserInterruptException.java Mon Nov 04 09:40:35 2019 +0100
@@ -4,7 +4,7 @@
* This software is distributable under the BSD license. See the terms of the
* BSD license in the documentation provided with this software.
*
- * http://www.opensource.org/licenses/bsd-license.php
+ * https://opensource.org/licenses/BSD-3-Clause
*/
package jdk.internal.org.jline.reader;
--- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/Widget.java Mon Nov 04 14:26:18 2019 +0800
+++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/Widget.java Mon Nov 04 09:40:35 2019 +0100
@@ -4,7 +4,7 @@
* This software is distributable under the BSD license. See the terms of the
* BSD license in the documentation provided with this software.
*
- * http://www.opensource.org/licenses/bsd-license.php
+ * https://opensource.org/licenses/BSD-3-Clause
*/
package jdk.internal.org.jline.reader;
--- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/BufferImpl.java Mon Nov 04 14:26:18 2019 +0800
+++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/BufferImpl.java Mon Nov 04 09:40:35 2019 +0100
@@ -4,7 +4,7 @@
* This software is distributable under the BSD license. See the terms of the
* BSD license in the documentation provided with this software.
*
- * http://www.opensource.org/licenses/bsd-license.php
+ * https://opensource.org/licenses/BSD-3-Clause
*/
package jdk.internal.org.jline.reader.impl;
--- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/DefaultExpander.java Mon Nov 04 14:26:18 2019 +0800
+++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/DefaultExpander.java Mon Nov 04 09:40:35 2019 +0100
@@ -4,7 +4,7 @@
* This software is distributable under the BSD license. See the terms of the
* BSD license in the documentation provided with this software.
*
- * http://www.opensource.org/licenses/bsd-license.php
+ * https://opensource.org/licenses/BSD-3-Clause
*/
package jdk.internal.org.jline.reader.impl;
--- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/DefaultHighlighter.java Mon Nov 04 14:26:18 2019 +0800
+++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/DefaultHighlighter.java Mon Nov 04 09:40:35 2019 +0100
@@ -4,7 +4,7 @@
* This software is distributable under the BSD license. See the terms of the
* BSD license in the documentation provided with this software.
*
- * http://www.opensource.org/licenses/bsd-license.php
+ * https://opensource.org/licenses/BSD-3-Clause
*/
package jdk.internal.org.jline.reader.impl;
--- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/DefaultParser.java Mon Nov 04 14:26:18 2019 +0800
+++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/DefaultParser.java Mon Nov 04 09:40:35 2019 +0100
@@ -4,7 +4,7 @@
* This software is distributable under the BSD license. See the terms of the
* BSD license in the documentation provided with this software.
*
- * http://www.opensource.org/licenses/bsd-license.php
+ * https://opensource.org/licenses/BSD-3-Clause
*/
package jdk.internal.org.jline.reader.impl;
@@ -18,6 +18,13 @@
public class DefaultParser implements Parser {
+ public enum Bracket {
+ ROUND, // ()
+ CURLY, // {}
+ SQUARE, // []
+ ANGLE; // <>
+ }
+
private char[] quoteChars = {'\'', '"'};
private char[] escapeChars = {'\\'};
@@ -26,6 +33,10 @@
private boolean eofOnEscapedNewLine;
+ private char[] openingBrackets = null;
+
+ private char[] closingBrackets = null;
+
//
// Chainable setters
//
@@ -45,6 +56,11 @@
return this;
}
+ public DefaultParser eofOnUnclosedBracket(Bracket... brackets){
+ setEofOnUnclosedBracket(brackets);
+ return this;
+ }
+
public DefaultParser eofOnEscapedNewLine(boolean eofOnEscapedNewLine) {
this.eofOnEscapedNewLine = eofOnEscapedNewLine;
return this;
@@ -86,6 +102,39 @@
return eofOnEscapedNewLine;
}
+ public void setEofOnUnclosedBracket(Bracket... brackets){
+ if (brackets == null) {
+ openingBrackets = null;
+ closingBrackets = null;
+ } else {
+ Set<Bracket> bs = new HashSet<>(Arrays.asList(brackets));
+ openingBrackets = new char[bs.size()];
+ closingBrackets = new char[bs.size()];
+ int i = 0;
+ for (Bracket b : bs) {
+ switch (b) {
+ case ROUND:
+ openingBrackets[i] = '(';
+ closingBrackets[i] = ')';
+ break;
+ case CURLY:
+ openingBrackets[i] = '{';
+ closingBrackets[i] = '}';
+ break;
+ case SQUARE:
+ openingBrackets[i] = '[';
+ closingBrackets[i] = ']';
+ break;
+ case ANGLE:
+ openingBrackets[i] = '<';
+ closingBrackets[i] = '>';
+ break;
+ }
+ i++;
+ }
+ }
+ }
+
public ParsedLine parse(final String line, final int cursor, ParseContext context) {
List<String> words = new LinkedList<>();
StringBuilder current = new StringBuilder();
@@ -95,6 +144,8 @@
int rawWordCursor = -1;
int rawWordLength = -1;
int rawWordStart = 0;
+ BracketChecker bracketChecker = new BracketChecker();
+ boolean quotedWord = false;
for (int i = 0; (line != null) && (i < line.length()); i++) {
// once we reach the cursor, set the
@@ -110,36 +161,35 @@
if (quoteStart < 0 && isQuoteChar(line, i)) {
// Start a quote block
quoteStart = i;
- } else if (quoteStart >= 0) {
- // In a quote block
- if (line.charAt(quoteStart) == line.charAt(i) && !isEscaped(line, i)) {
- // End the block; arg could be empty, but that's fine
+ if (current.length()==0) {
+ quotedWord = true;
+ } else {
+ current.append(line.charAt(i));
+ }
+ } else if (quoteStart >= 0 && line.charAt(quoteStart) == line.charAt(i) && !isEscaped(line, i)) {
+ // End quote block
+ if (!quotedWord) {
+ current.append(line.charAt(i));
+ } else if (rawWordCursor >= 0 && rawWordLength < 0) {
+ rawWordLength = i - rawWordStart + 1;
+ }
+ quoteStart = -1;
+ quotedWord = false;
+ } else if (quoteStart < 0 && isDelimiter(line, i)) {
+ // Delimiter
+ if (current.length() > 0) {
words.add(current.toString());
- current.setLength(0);
- quoteStart = -1;
+ current.setLength(0); // reset the arg
if (rawWordCursor >= 0 && rawWordLength < 0) {
- rawWordLength = i - rawWordStart + 1;
- }
- } else {
- if (!isEscapeChar(line, i)) {
- // Take the next character
- current.append(line.charAt(i));
+ rawWordLength = i - rawWordStart;
}
}
+ rawWordStart = i + 1;
} else {
- // Not in a quote block
- if (isDelimiter(line, i)) {
- if (current.length() > 0) {
- words.add(current.toString());
- current.setLength(0); // reset the arg
- if (rawWordCursor >= 0 && rawWordLength < 0) {
- rawWordLength = i - rawWordStart;
- }
- }
- rawWordStart = i + 1;
- } else {
- if (!isEscapeChar(line, i)) {
- current.append(line.charAt(i));
+ if (!isEscapeChar(line, i)) {
+ current.append(line.charAt(i));
+ if (quoteStart < 0) {
+ bracketChecker.check(line, i);
}
}
}
@@ -159,21 +209,29 @@
rawWordLength = rawWordCursor;
}
- if (eofOnEscapedNewLine && isEscapeChar(line, line.length() - 1)) {
- throw new EOFError(-1, -1, "Escaped new line", "newline");
- }
- if (eofOnUnclosedQuote && quoteStart >= 0 && context != ParseContext.COMPLETE) {
- throw new EOFError(-1, -1, "Missing closing quote", line.charAt(quoteStart) == '\''
- ? "quote" : "dquote");
+ if (context != ParseContext.COMPLETE) {
+ if (eofOnEscapedNewLine && isEscapeChar(line, line.length() - 1)) {
+ throw new EOFError(-1, -1, "Escaped new line", "newline");
+ }
+ if (eofOnUnclosedQuote && quoteStart >= 0) {
+ 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());
+ }
}
- String openingQuote = quoteStart >= 0 ? line.substring(quoteStart, quoteStart + 1) : null;
+ String openingQuote = quotedWord ? line.substring(quoteStart, quoteStart + 1) : null;
return new ArgumentList(line, words, wordIndex, wordCursor, cursor, openingQuote, rawWordCursor, rawWordLength);
}
/**
* Returns true if the specified character is a whitespace parameter. Check to ensure that the character is not
- * escaped by any of {@link #getQuoteChars}, and is not escaped by ant of the {@link #getEscapeChars}, and
+ * escaped by any of {@link #getQuoteChars}, and is not escaped by any of the {@link #getEscapeChars}, and
* returns true from {@link #isDelimiterChar}.
*
* @param buffer The complete command buffer
@@ -202,6 +260,18 @@
return false;
}
+ @Override
+ public boolean isEscapeChar(char ch) {
+ if (escapeChars != null) {
+ for (char e : escapeChars) {
+ if (e == ch) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
/**
* Check if this character is a valid escape char (i.e. one that has not been escaped)
*
@@ -216,14 +286,8 @@
if (pos < 0) {
return false;
}
- if (escapeChars != null) {
- for (char e : escapeChars) {
- if (e == buffer.charAt(pos)) {
- return !isEscaped(buffer, pos);
- }
- }
- }
- return false;
+ char ch = buffer.charAt(pos);
+ return isEscapeChar(ch) && !isEscaped(buffer, pos);
}
/**
@@ -245,7 +309,7 @@
/**
* Returns true if the character at the specified position if a delimiter. This method will only be called if
- * the character is not enclosed in any of the {@link #getQuoteChars}, and is not escaped by ant of the
+ * the character is not enclosed in any of the {@link #getQuoteChars}, and is not escaped by any of the
* {@link #getEscapeChars}. To perform escaping manually, override {@link #isDelimiter} instead.
*
* @param buffer
@@ -280,6 +344,67 @@
return false;
}
+ private class BracketChecker {
+ private int missingOpeningBracket = -1;
+ private List<Integer> nested = new ArrayList<>();
+
+ public BracketChecker(){}
+
+ public void check(final CharSequence buffer, final int pos){
+ if (openingBrackets == null || pos < 0) {
+ return;
+ }
+ int bid = bracketId(openingBrackets, buffer, pos);
+ if (bid >= 0) {
+ nested.add(bid);
+ } else {
+ bid = bracketId(closingBrackets, buffer, pos);
+ if (bid >= 0) {
+ if (!nested.isEmpty() && bid == nested.get(nested.size()-1)) {
+ nested.remove(nested.size()-1);
+ } else {
+ missingOpeningBracket = bid;
+ }
+ }
+ }
+ }
+
+ public boolean isOpeningBracketMissing(){
+ return missingOpeningBracket != -1;
+ }
+
+ public String getMissingOpeningBracket(){
+ if (!isOpeningBracketMissing()) {
+ return null;
+ }
+ return Character.toString(openingBrackets[missingOpeningBracket]);
+ }
+
+ public boolean isClosingBracketMissing(){
+ return !nested.isEmpty();
+ }
+
+ public String getMissingClosingBrackets(){
+ if (!isClosingBracketMissing()) {
+ return null;
+ }
+ StringBuilder out = new StringBuilder();
+ for (int i = nested.size() - 1; i > -1; i--) {
+ out.append(closingBrackets[nested.get(i)]);
+ }
+ return out.toString();
+ }
+
+ 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;
+ }
+ }
+
/**
* The result of a delimited buffer.
*
@@ -367,26 +492,50 @@
public CharSequence escape(CharSequence candidate, boolean complete) {
StringBuilder sb = new StringBuilder(candidate);
Predicate<Integer> needToBeEscaped;
- // Completion is protected by an opening quote:
- // Delimiters (spaces) don't need to be escaped, nor do other quotes, but everything else does.
- // Also, close the quote at the end
- if (openingQuote != null) {
- needToBeEscaped = i -> isRawEscapeChar(sb.charAt(i)) || String.valueOf(sb.charAt(i)).equals(openingQuote);
- }
- // No quote protection, need to escape everything: delimiter chars (spaces), quote chars
- // and escapes themselves
- else {
- needToBeEscaped = i -> isDelimiterChar(sb, i) || isRawEscapeChar(sb.charAt(i)) || isRawQuoteChar(sb.charAt(i));
- }
- for (int i = 0; i < sb.length(); i++) {
- if (needToBeEscaped.test(i)) {
- sb.insert(i++, escapeChars[0]);
+ String quote = openingQuote;
+ boolean middleQuotes = false;
+ if (openingQuote==null) {
+ for (int i=0; i < sb.length(); i++) {
+ if (isQuoteChar(sb, i)) {
+ middleQuotes = true;
+ break;
+ }
}
}
- if (openingQuote != null) {
- sb.insert(0, openingQuote);
+ if (escapeChars != null) {
+ // Completion is protected by an opening quote:
+ // Delimiters (spaces) don't need to be escaped, nor do other quotes, but everything else does.
+ // Also, close the quote at the end
+ if (openingQuote != null) {
+ needToBeEscaped = i -> isRawEscapeChar(sb.charAt(i)) || String.valueOf(sb.charAt(i)).equals(openingQuote);
+ }
+ // Completion is protected by middle quotes:
+ // Delimiters (spaces) don't need to be escaped, nor do quotes, but everything else does.
+ else if (middleQuotes) {
+ needToBeEscaped = i -> isRawEscapeChar(sb.charAt(i));
+ }
+ // No quote protection, need to escape everything: delimiter chars (spaces), quote chars
+ // and escapes themselves
+ else {
+ needToBeEscaped = i -> isDelimiterChar(sb, i) || isRawEscapeChar(sb.charAt(i)) || isRawQuoteChar(sb.charAt(i));
+ }
+ for (int i = 0; i < sb.length(); i++) {
+ if (needToBeEscaped.test(i)) {
+ sb.insert(i++, escapeChars[0]);
+ }
+ }
+ } else if (openingQuote == null && !middleQuotes) {
+ for (int i = 0; i < sb.length(); i++) {
+ if (isDelimiterChar(sb, i)) {
+ quote = "'";
+ break;
+ }
+ }
+ }
+ if (quote != null) {
+ sb.insert(0, quote);
if (complete) {
- sb.append(openingQuote);
+ sb.append(quote);
}
}
return sb;
--- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/KillRing.java Mon Nov 04 14:26:18 2019 +0800
+++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/KillRing.java Mon Nov 04 09:40:35 2019 +0100
@@ -4,7 +4,7 @@
* This software is distributable under the BSD license. See the terms of the
* BSD license in the documentation provided with this software.
*
- * http://www.opensource.org/licenses/bsd-license.php
+ * https://opensource.org/licenses/BSD-3-Clause
*/
package jdk.internal.org.jline.reader.impl;
--- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/LineReaderImpl.java Mon Nov 04 14:26:18 2019 +0800
+++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/LineReaderImpl.java Mon Nov 04 09:40:35 2019 +0100
@@ -1,10 +1,10 @@
/*
- * 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.
*
- * http://www.opensource.org/licenses/bsd-license.php
+ * https://opensource.org/licenses/BSD-3-Clause
*/
package jdk.internal.org.jline.reader.impl;
@@ -17,10 +17,13 @@
import java.util.*;
import java.util.Map.Entry;
import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.locks.Lock;
+import java.util.concurrent.locks.ReentrantLock;
import java.util.function.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
+import java.util.stream.Stream;
import java.util.stream.StreamSupport;
import jdk.internal.org.jline.keymap.BindingReader;
@@ -32,6 +35,7 @@
import jdk.internal.org.jline.terminal.Attributes.ControlChar;
import jdk.internal.org.jline.terminal.Terminal.Signal;
import jdk.internal.org.jline.terminal.Terminal.SignalHandler;
+import jdk.internal.org.jline.terminal.impl.AbstractWindowsTerminal;
import jdk.internal.org.jline.utils.AttributedString;
import jdk.internal.org.jline.utils.AttributedStringBuilder;
import jdk.internal.org.jline.utils.AttributedStyle;
@@ -159,8 +163,8 @@
protected final Size size = new Size();
- protected AttributedString prompt;
- protected AttributedString rightPrompt;
+ protected AttributedString prompt = AttributedString.EMPTY;
+ protected AttributedString rightPrompt = AttributedString.EMPTY;
protected MaskingCallback maskingCallback;
@@ -210,6 +214,10 @@
protected UndoTree<Buffer> undo = new UndoTree<>(this::setBuffer);
protected boolean isUndo;
+ /**
+ * State lock
+ */
+ protected final ReentrantLock lock = new ReentrantLock();
/*
* Current internal state of the line reader
*/
@@ -239,6 +247,11 @@
protected int smallTerminalOffset = 0;
+ /*
+ * accept-and-infer-next-history, accept-and-hold & accept-line-and-down-history
+ */
+ protected boolean nextCommandFromHistory = false;
+ protected int nextHistoryId = -1;
public LineReaderImpl(Terminal terminal) throws IOException {
@@ -266,6 +279,7 @@
builtinWidgets = builtinWidgets();
widgets = new HashMap<>(builtinWidgets);
bindingReader = new BindingReader(terminal.reader());
+ doDisplay();
}
public Terminal getTerminal() {
@@ -467,8 +481,7 @@
SignalHandler previousWinchHandler = null;
SignalHandler previousContHandler = null;
Attributes originalAttributes = null;
- boolean dumb = Terminal.TYPE_DUMB.equals(terminal.getType())
- || Terminal.TYPE_DUMB_COLOR.equals(terminal.getType());
+ boolean dumb = isTerminalDumb();
try {
this.maskingCallback = maskingCallback;
@@ -495,6 +508,17 @@
if (buffer != null) {
buf.write(buffer);
}
+ if (nextCommandFromHistory && nextHistoryId > 0) {
+ if (history.size() > nextHistoryId) {
+ history.moveTo(nextHistoryId);
+ } else {
+ history.moveTo(history.last());
+ }
+ buf.write(history.current());
+ } else {
+ nextHistoryId = -1;
+ }
+ nextCommandFromHistory = false;
undo.clear();
parsedLine = null;
keyMap = MAIN;
@@ -503,7 +527,9 @@
history.attach(this);
}
- synchronized (this) {
+ try {
+ lock.lock();
+
this.reading = true;
previousIntrHandler = terminal.handle(Signal.INT, signal -> readLineThread.interrupt());
@@ -511,18 +537,7 @@
previousContHandler = terminal.handle(Signal.CONT, this::handleSignal);
originalAttributes = terminal.enterRawMode();
- // Cache terminal size for the duration of the call to readLine()
- // It will eventually be updated with WINCH signals
- size.copy(terminal.getSize());
-
- display = new Display(terminal, false);
- if (size.getRows() == 0 || size.getColumns() == 0) {
- display.resize(1, Integer.MAX_VALUE);
- } else {
- display.resize(size.getRows(), size.getColumns());
- }
- if (isSet(Option.DELAY_LINE_WRAP))
- display.setDelayLineWrap(true);
+ doDisplay();
// Move into application mode
if (!dumb) {
@@ -547,6 +562,8 @@
// Draw initial prompt
redrawLine();
redisplay();
+ } finally {
+ lock.unlock();
}
while (true) {
@@ -578,7 +595,8 @@
regionActive = RegionType.NONE;
}
- synchronized (this) {
+ try {
+ lock.lock();
// Get executable widget
Buffer copy = buf.copy();
Widget w = getWidget(o);
@@ -610,6 +628,8 @@
if (!dumb) {
redisplay();
}
+ } finally {
+ lock.unlock();
}
}
} catch (IOError e) {
@@ -620,7 +640,9 @@
}
}
finally {
- synchronized (this) {
+ try {
+ lock.lock();
+
this.reading = false;
cleanup();
@@ -636,26 +658,54 @@
if (previousContHandler != null) {
terminal.handle(Signal.CONT, previousContHandler);
}
+ } finally {
+ lock.unlock();
}
startedReading.set(false);
}
}
+ private boolean isTerminalDumb(){
+ return Terminal.TYPE_DUMB.equals(terminal.getType())
+ || Terminal.TYPE_DUMB_COLOR.equals(terminal.getType());
+ }
+
+ private void doDisplay(){
+ // Cache terminal size for the duration of the call to readLine()
+ // It will eventually be updated with WINCH signals
+ size.copy(terminal.getBufferSize());
+
+ display = new Display(terminal, false);
+ if (size.getRows() == 0 || size.getColumns() == 0) {
+ display.resize(1, Integer.MAX_VALUE);
+ } else {
+ display.resize(size.getRows(), size.getColumns());
+ }
+ if (isSet(Option.DELAY_LINE_WRAP))
+ display.setDelayLineWrap(true);
+ }
+
@Override
- public synchronized void printAbove(String str) {
- boolean reading = this.reading;
- if (reading) {
- display.update(Collections.emptyList(), 0);
- }
- if (str.endsWith("\n")) {
- terminal.writer().print(str);
- } else {
- terminal.writer().println(str);
- }
- if (reading) {
- redisplay(false);
- }
- terminal.flush();
+ public void printAbove(String str) {
+ try {
+ lock.lock();
+
+ boolean reading = this.reading;
+ if (reading) {
+ display.update(Collections.emptyList(), 0);
+ }
+ if (str.endsWith("\n") || str.endsWith("\n\033[m") || str.endsWith("\n\033[0m")) {
+ terminal.writer().print(str);
+ } else {
+ terminal.writer().println(str);
+ }
+ if (reading) {
+ redisplay(false);
+ }
+ terminal.flush();
+ } finally {
+ lock.unlock();
+ }
}
@Override
@@ -664,8 +714,13 @@
}
@Override
- public synchronized boolean isReading() {
- return reading;
+ public boolean isReading() {
+ try {
+ lock.lock();
+ return reading;
+ } finally {
+ lock.unlock();
+ }
}
/* Make sure we position the cursor on column 0 */
@@ -700,27 +755,32 @@
sb.append(" ");
sb.append(KeyMap.key(terminal, Capability.carriage_return));
}
- print(sb.toAnsi(terminal));
+ sb.print(terminal);
return true;
}
@Override
- public synchronized void callWidget(String name) {
- if (!reading) {
- throw new IllegalStateException("Widgets can only be called during a `readLine` call");
- }
+ public void callWidget(String name) {
try {
- Widget w;
- if (name.startsWith(".")) {
- w = builtinWidgets.get(name.substring(1));
- } else {
- w = widgets.get(name);
- }
- if (w != null) {
- w.apply();
- }
- } catch (Throwable t) {
- Log.debug("Error executing widget '", name, "'", t);
+ lock.lock();
+ if (!reading) {
+ throw new IllegalStateException("Widgets can only be called during a `readLine` call");
+ }
+ try {
+ Widget w;
+ if (name.startsWith(".")) {
+ w = builtinWidgets.get(name.substring(1));
+ } else {
+ w = widgets.get(name);
+ }
+ if (w != null) {
+ w.apply();
+ }
+ } catch (Throwable t) {
+ Log.debug("Error executing widget '", name, "'", t);
+ }
+ } finally {
+ lock.unlock();
}
}
@@ -760,13 +820,35 @@
* @return the character, or -1 if an EOF is received.
*/
public int readCharacter() {
- return bindingReader.readCharacter();
+ if (lock.isHeldByCurrentThread()) {
+ try {
+ lock.unlock();
+ return bindingReader.readCharacter();
+ } finally {
+ lock.lock();
+ }
+ } else {
+ return bindingReader.readCharacter();
+ }
}
public int peekCharacter(long timeout) {
return bindingReader.peekCharacter(timeout);
}
+ protected <T> T doReadBinding(KeyMap<T> keys, KeyMap<T> local) {
+ if (lock.isHeldByCurrentThread()) {
+ try {
+ lock.unlock();
+ return bindingReader.readBinding(keys, local);
+ } finally {
+ lock.lock();
+ }
+ } else {
+ return bindingReader.readBinding(keys, local);
+ }
+ }
+
/**
* Read from the input stream and decode an operation from the key map.
*
@@ -783,7 +865,7 @@
}
public Binding readBinding(KeyMap<Binding> keys, KeyMap<Binding> local) {
- Binding o = bindingReader.readBinding(keys, local);
+ Binding o = doReadBinding(keys, local);
/*
* The kill ring keeps record of whether or not the
* previous command was a yank or a kill. We reset
@@ -926,7 +1008,7 @@
if (ch != '\n') {
sb.append(ch);
}
- } else if (ch == '\\') {
+ } else if (parser.isEscapeChar(ch)) {
escaped = true;
} else {
sb.append(ch);
@@ -948,13 +1030,18 @@
protected void handleSignal(Signal signal) {
if (signal == Signal.WINCH) {
- size.copy(terminal.getSize());
+ Status status = Status.getStatus(terminal, false);
+ if (status != null) {
+ status.hardReset();
+ }
+ size.copy(terminal.getBufferSize());
display.resize(size.getRows(), size.getColumns());
+ redrawLine();
redisplay();
}
else if (signal == Signal.CONT) {
terminal.enterRawMode();
- size.copy(terminal.getSize());
+ size.copy(terminal.getBufferSize());
display.resize(size.getRows(), size.getColumns());
terminal.puts(Capability.keypad_xmit);
redrawLine();
@@ -1903,7 +1990,7 @@
while (true) {
post = () -> new AttributedString(searchPrompt + searchBuffer.toString() + "_");
redisplay();
- Binding b = bindingReader.readBinding(keyMap);
+ Binding b = doReadBinding(keyMap, null);
if (b instanceof Reference) {
String func = ((Reference) b).name();
switch (func) {
@@ -2300,7 +2387,7 @@
} else {
viMoveMode = mode;
mark = -1;
- Binding b = bindingReader.readBinding(getKeys(), keyMaps.get(VIOPP));
+ Binding b = doReadBinding(getKeys(), keyMaps.get(VIOPP));
if (b == null || new Reference(SEND_BREAK).equals(b)) {
viMoveMode = ViMoveMode.NORMAL;
mark = oldMark;
@@ -2710,6 +2797,42 @@
return acceptLine();
}
+ protected boolean acceptAndHold() {
+ nextCommandFromHistory = false;
+ acceptLine();
+ if (!buf.toString().isEmpty()) {
+ nextHistoryId = Integer.MAX_VALUE;
+ nextCommandFromHistory = true;
+ }
+ return nextCommandFromHistory;
+ }
+
+ protected boolean acceptLineAndDownHistory() {
+ nextCommandFromHistory = false;
+ acceptLine();
+ if (nextHistoryId < 0) {
+ nextHistoryId = history.index();
+ }
+ if (history.size() > nextHistoryId + 1) {
+ nextHistoryId++;
+ nextCommandFromHistory = true;
+ }
+ 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;
+ }
+ }
+ return nextCommandFromHistory;
+ }
+
protected boolean acceptLine() {
parsedLine = null;
if (!isSet(Option.DISABLE_EVENT_EXPANSION)) {
@@ -3343,255 +3466,317 @@
protected Map<String, Widget> builtinWidgets() {
Map<String, Widget> widgets = new HashMap<>();
- widgets.put(ACCEPT_LINE, this::acceptLine);
- widgets.put(ARGUMENT_BASE, this::argumentBase);
- widgets.put(BACKWARD_CHAR, this::backwardChar);
- widgets.put(BACKWARD_DELETE_CHAR, this::backwardDeleteChar);
- widgets.put(BACKWARD_DELETE_WORD, this::backwardDeleteWord);
- widgets.put(BACKWARD_KILL_LINE, this::backwardKillLine);
- widgets.put(BACKWARD_KILL_WORD, this::backwardKillWord);
- widgets.put(BACKWARD_WORD, this::backwardWord);
- widgets.put(BEEP, this::beep);
- widgets.put(BEGINNING_OF_BUFFER_OR_HISTORY, this::beginningOfBufferOrHistory);
- widgets.put(BEGINNING_OF_HISTORY, this::beginningOfHistory);
- widgets.put(BEGINNING_OF_LINE, this::beginningOfLine);
- widgets.put(BEGINNING_OF_LINE_HIST, this::beginningOfLineHist);
- widgets.put(CAPITALIZE_WORD, this::capitalizeWord);
- widgets.put(CLEAR, this::clear);
- widgets.put(CLEAR_SCREEN, this::clearScreen);
- widgets.put(COMPLETE_PREFIX, this::completePrefix);
- widgets.put(COMPLETE_WORD, this::completeWord);
- widgets.put(COPY_PREV_WORD, this::copyPrevWord);
- widgets.put(COPY_REGION_AS_KILL, this::copyRegionAsKill);
- widgets.put(DELETE_CHAR, this::deleteChar);
- widgets.put(DELETE_CHAR_OR_LIST, this::deleteCharOrList);
- widgets.put(DELETE_WORD, this::deleteWord);
- widgets.put(DIGIT_ARGUMENT, this::digitArgument);
- widgets.put(DO_LOWERCASE_VERSION, this::doLowercaseVersion);
- widgets.put(DOWN_CASE_WORD, this::downCaseWord);
- widgets.put(DOWN_LINE, this::downLine);
- widgets.put(DOWN_LINE_OR_HISTORY, this::downLineOrHistory);
- widgets.put(DOWN_LINE_OR_SEARCH, this::downLineOrSearch);
- widgets.put(DOWN_HISTORY, this::downHistory);
- widgets.put(EMACS_EDITING_MODE, this::emacsEditingMode);
- widgets.put(EMACS_BACKWARD_WORD, this::emacsBackwardWord);
- widgets.put(EMACS_FORWARD_WORD, this::emacsForwardWord);
- widgets.put(END_OF_BUFFER_OR_HISTORY, this::endOfBufferOrHistory);
- widgets.put(END_OF_HISTORY, this::endOfHistory);
- widgets.put(END_OF_LINE, this::endOfLine);
- widgets.put(END_OF_LINE_HIST, this::endOfLineHist);
- widgets.put(EXCHANGE_POINT_AND_MARK, this::exchangePointAndMark);
- widgets.put(EXPAND_HISTORY, this::expandHistory);
- widgets.put(EXPAND_OR_COMPLETE, this::expandOrComplete);
- widgets.put(EXPAND_OR_COMPLETE_PREFIX, this::expandOrCompletePrefix);
- widgets.put(EXPAND_WORD, this::expandWord);
- widgets.put(FRESH_LINE, this::freshLine);
- widgets.put(FORWARD_CHAR, this::forwardChar);
- widgets.put(FORWARD_WORD, this::forwardWord);
- widgets.put(HISTORY_INCREMENTAL_SEARCH_BACKWARD, this::historyIncrementalSearchBackward);
- widgets.put(HISTORY_INCREMENTAL_SEARCH_FORWARD, this::historyIncrementalSearchForward);
- widgets.put(HISTORY_SEARCH_BACKWARD, this::historySearchBackward);
- widgets.put(HISTORY_SEARCH_FORWARD, this::historySearchForward);
- widgets.put(INSERT_CLOSE_CURLY, this::insertCloseCurly);
- widgets.put(INSERT_CLOSE_PAREN, this::insertCloseParen);
- widgets.put(INSERT_CLOSE_SQUARE, this::insertCloseSquare);
- widgets.put(INSERT_COMMENT, this::insertComment);
- widgets.put(KILL_BUFFER, this::killBuffer);
- widgets.put(KILL_LINE, this::killLine);
- widgets.put(KILL_REGION, this::killRegion);
- widgets.put(KILL_WHOLE_LINE, this::killWholeLine);
- widgets.put(KILL_WORD, this::killWord);
- widgets.put(LIST_CHOICES, this::listChoices);
- widgets.put(MENU_COMPLETE, this::menuComplete);
- widgets.put(MENU_EXPAND_OR_COMPLETE, this::menuExpandOrComplete);
- widgets.put(NEG_ARGUMENT, this::negArgument);
- widgets.put(OVERWRITE_MODE, this::overwriteMode);
-// widgets.put(QUIT, this::quit);
- widgets.put(QUOTED_INSERT, this::quotedInsert);
- widgets.put(REDISPLAY, this::redisplay);
- widgets.put(REDRAW_LINE, this::redrawLine);
- widgets.put(REDO, this::redo);
- widgets.put(SELF_INSERT, this::selfInsert);
- widgets.put(SELF_INSERT_UNMETA, this::selfInsertUnmeta);
- widgets.put(SEND_BREAK, this::sendBreak);
- widgets.put(SET_MARK_COMMAND, this::setMarkCommand);
- widgets.put(TRANSPOSE_CHARS, this::transposeChars);
- widgets.put(TRANSPOSE_WORDS, this::transposeWords);
- widgets.put(UNDEFINED_KEY, this::undefinedKey);
- widgets.put(UNIVERSAL_ARGUMENT, this::universalArgument);
- widgets.put(UNDO, this::undo);
- widgets.put(UP_CASE_WORD, this::upCaseWord);
- widgets.put(UP_HISTORY, this::upHistory);
- widgets.put(UP_LINE, this::upLine);
- widgets.put(UP_LINE_OR_HISTORY, this::upLineOrHistory);
- widgets.put(UP_LINE_OR_SEARCH, this::upLineOrSearch);
- widgets.put(VI_ADD_EOL, this::viAddEol);
- widgets.put(VI_ADD_NEXT, this::viAddNext);
- widgets.put(VI_BACKWARD_CHAR, this::viBackwardChar);
- widgets.put(VI_BACKWARD_DELETE_CHAR, this::viBackwardDeleteChar);
- widgets.put(VI_BACKWARD_BLANK_WORD, this::viBackwardBlankWord);
- widgets.put(VI_BACKWARD_BLANK_WORD_END, this::viBackwardBlankWordEnd);
- widgets.put(VI_BACKWARD_KILL_WORD, this::viBackwardKillWord);
- widgets.put(VI_BACKWARD_WORD, this::viBackwardWord);
- widgets.put(VI_BACKWARD_WORD_END, this::viBackwardWordEnd);
- widgets.put(VI_BEGINNING_OF_LINE, this::viBeginningOfLine);
- widgets.put(VI_CMD_MODE, this::viCmdMode);
- widgets.put(VI_DIGIT_OR_BEGINNING_OF_LINE, this::viDigitOrBeginningOfLine);
- widgets.put(VI_DOWN_LINE_OR_HISTORY, this::viDownLineOrHistory);
- widgets.put(VI_CHANGE, this::viChange);
- widgets.put(VI_CHANGE_EOL, this::viChangeEol);
- widgets.put(VI_CHANGE_WHOLE_LINE, this::viChangeWholeLine);
- widgets.put(VI_DELETE_CHAR, this::viDeleteChar);
- widgets.put(VI_DELETE, this::viDelete);
- widgets.put(VI_END_OF_LINE, this::viEndOfLine);
- widgets.put(VI_KILL_EOL, this::viKillEol);
- widgets.put(VI_FIRST_NON_BLANK, this::viFirstNonBlank);
- widgets.put(VI_FIND_NEXT_CHAR, this::viFindNextChar);
- widgets.put(VI_FIND_NEXT_CHAR_SKIP, this::viFindNextCharSkip);
- widgets.put(VI_FIND_PREV_CHAR, this::viFindPrevChar);
- widgets.put(VI_FIND_PREV_CHAR_SKIP, this::viFindPrevCharSkip);
- widgets.put(VI_FORWARD_BLANK_WORD, this::viForwardBlankWord);
- widgets.put(VI_FORWARD_BLANK_WORD_END, this::viForwardBlankWordEnd);
- widgets.put(VI_FORWARD_CHAR, this::viForwardChar);
- widgets.put(VI_FORWARD_WORD, this::viForwardWord);
- widgets.put(VI_FORWARD_WORD, this::viForwardWord);
- widgets.put(VI_FORWARD_WORD_END, this::viForwardWordEnd);
- widgets.put(VI_HISTORY_SEARCH_BACKWARD, this::viHistorySearchBackward);
- widgets.put(VI_HISTORY_SEARCH_FORWARD, this::viHistorySearchForward);
- widgets.put(VI_INSERT, this::viInsert);
- widgets.put(VI_INSERT_BOL, this::viInsertBol);
- widgets.put(VI_INSERT_COMMENT, this::viInsertComment);
- widgets.put(VI_JOIN, this::viJoin);
- widgets.put(VI_KILL_LINE, this::viKillWholeLine);
- widgets.put(VI_MATCH_BRACKET, this::viMatchBracket);
- widgets.put(VI_OPEN_LINE_ABOVE, this::viOpenLineAbove);
- widgets.put(VI_OPEN_LINE_BELOW, this::viOpenLineBelow);
- widgets.put(VI_PUT_AFTER, this::viPutAfter);
- widgets.put(VI_PUT_BEFORE, this::viPutBefore);
- widgets.put(VI_REPEAT_FIND, this::viRepeatFind);
- widgets.put(VI_REPEAT_SEARCH, this::viRepeatSearch);
- widgets.put(VI_REPLACE_CHARS, this::viReplaceChars);
- widgets.put(VI_REV_REPEAT_FIND, this::viRevRepeatFind);
- widgets.put(VI_REV_REPEAT_SEARCH, this::viRevRepeatSearch);
- widgets.put(VI_SWAP_CASE, this::viSwapCase);
- widgets.put(VI_UP_LINE_OR_HISTORY, this::viUpLineOrHistory);
- widgets.put(VI_YANK, this::viYankTo);
- widgets.put(VI_YANK_WHOLE_LINE, this::viYankWholeLine);
- widgets.put(VISUAL_LINE_MODE, this::visualLineMode);
- widgets.put(VISUAL_MODE, this::visualMode);
- widgets.put(WHAT_CURSOR_POSITION, this::whatCursorPosition);
- widgets.put(YANK, this::yank);
- widgets.put(YANK_POP, this::yankPop);
- widgets.put(MOUSE, this::mouse);
- widgets.put(BEGIN_PASTE, this::beginPaste);
- widgets.put(FOCUS_IN, this::focusIn);
- widgets.put(FOCUS_OUT, this::focusOut);
+ addBuiltinWidget(widgets, ACCEPT_AND_INFER_NEXT_HISTORY, this::acceptAndInferNextHistory);
+ addBuiltinWidget(widgets, ACCEPT_AND_HOLD, this::acceptAndHold);
+ addBuiltinWidget(widgets, ACCEPT_LINE, this::acceptLine);
+ addBuiltinWidget(widgets, ACCEPT_LINE_AND_DOWN_HISTORY, this::acceptLineAndDownHistory);
+ addBuiltinWidget(widgets, ARGUMENT_BASE, this::argumentBase);
+ addBuiltinWidget(widgets, BACKWARD_CHAR, this::backwardChar);
+ addBuiltinWidget(widgets, BACKWARD_DELETE_CHAR, this::backwardDeleteChar);
+ addBuiltinWidget(widgets, BACKWARD_DELETE_WORD, this::backwardDeleteWord);
+ addBuiltinWidget(widgets, BACKWARD_KILL_LINE, this::backwardKillLine);
+ addBuiltinWidget(widgets, BACKWARD_KILL_WORD, this::backwardKillWord);
+ addBuiltinWidget(widgets, BACKWARD_WORD, this::backwardWord);
+ addBuiltinWidget(widgets, BEEP, this::beep);
+ addBuiltinWidget(widgets, BEGINNING_OF_BUFFER_OR_HISTORY, this::beginningOfBufferOrHistory);
+ addBuiltinWidget(widgets, BEGINNING_OF_HISTORY, this::beginningOfHistory);
+ addBuiltinWidget(widgets, BEGINNING_OF_LINE, this::beginningOfLine);
+ addBuiltinWidget(widgets, BEGINNING_OF_LINE_HIST, this::beginningOfLineHist);
+ addBuiltinWidget(widgets, CAPITALIZE_WORD, this::capitalizeWord);
+ addBuiltinWidget(widgets, CLEAR, this::clear);
+ addBuiltinWidget(widgets, CLEAR_SCREEN, this::clearScreen);
+ addBuiltinWidget(widgets, COMPLETE_PREFIX, this::completePrefix);
+ addBuiltinWidget(widgets, COMPLETE_WORD, this::completeWord);
+ addBuiltinWidget(widgets, COPY_PREV_WORD, this::copyPrevWord);
+ addBuiltinWidget(widgets, COPY_REGION_AS_KILL, this::copyRegionAsKill);
+ addBuiltinWidget(widgets, DELETE_CHAR, this::deleteChar);
+ addBuiltinWidget(widgets, DELETE_CHAR_OR_LIST, this::deleteCharOrList);
+ addBuiltinWidget(widgets, DELETE_WORD, this::deleteWord);
+ addBuiltinWidget(widgets, DIGIT_ARGUMENT, this::digitArgument);
+ addBuiltinWidget(widgets, DO_LOWERCASE_VERSION, this::doLowercaseVersion);
+ addBuiltinWidget(widgets, DOWN_CASE_WORD, this::downCaseWord);
+ addBuiltinWidget(widgets, DOWN_LINE, this::downLine);
+ addBuiltinWidget(widgets, DOWN_LINE_OR_HISTORY, this::downLineOrHistory);
+ addBuiltinWidget(widgets, DOWN_LINE_OR_SEARCH, this::downLineOrSearch);
+ addBuiltinWidget(widgets, DOWN_HISTORY, this::downHistory);
+ addBuiltinWidget(widgets, EMACS_EDITING_MODE, this::emacsEditingMode);
+ addBuiltinWidget(widgets, EMACS_BACKWARD_WORD, this::emacsBackwardWord);
+ addBuiltinWidget(widgets, EMACS_FORWARD_WORD, this::emacsForwardWord);
+ addBuiltinWidget(widgets, END_OF_BUFFER_OR_HISTORY, this::endOfBufferOrHistory);
+ addBuiltinWidget(widgets, END_OF_HISTORY, this::endOfHistory);
+ addBuiltinWidget(widgets, END_OF_LINE, this::endOfLine);
+ addBuiltinWidget(widgets, END_OF_LINE_HIST, this::endOfLineHist);
+ addBuiltinWidget(widgets, EXCHANGE_POINT_AND_MARK, this::exchangePointAndMark);
+ addBuiltinWidget(widgets, EXPAND_HISTORY, this::expandHistory);
+ addBuiltinWidget(widgets, EXPAND_OR_COMPLETE, this::expandOrComplete);
+ addBuiltinWidget(widgets, EXPAND_OR_COMPLETE_PREFIX, this::expandOrCompletePrefix);
+ addBuiltinWidget(widgets, EXPAND_WORD, this::expandWord);
+ addBuiltinWidget(widgets, FRESH_LINE, this::freshLine);
+ addBuiltinWidget(widgets, FORWARD_CHAR, this::forwardChar);
+ addBuiltinWidget(widgets, FORWARD_WORD, this::forwardWord);
+ addBuiltinWidget(widgets, HISTORY_INCREMENTAL_SEARCH_BACKWARD, this::historyIncrementalSearchBackward);
+ addBuiltinWidget(widgets, HISTORY_INCREMENTAL_SEARCH_FORWARD, this::historyIncrementalSearchForward);
+ addBuiltinWidget(widgets, HISTORY_SEARCH_BACKWARD, this::historySearchBackward);
+ addBuiltinWidget(widgets, HISTORY_SEARCH_FORWARD, this::historySearchForward);
+ addBuiltinWidget(widgets, INSERT_CLOSE_CURLY, this::insertCloseCurly);
+ addBuiltinWidget(widgets, INSERT_CLOSE_PAREN, this::insertCloseParen);
+ addBuiltinWidget(widgets, INSERT_CLOSE_SQUARE, this::insertCloseSquare);
+ addBuiltinWidget(widgets, INSERT_COMMENT, this::insertComment);
+ addBuiltinWidget(widgets, KILL_BUFFER, this::killBuffer);
+ addBuiltinWidget(widgets, KILL_LINE, this::killLine);
+ addBuiltinWidget(widgets, KILL_REGION, this::killRegion);
+ addBuiltinWidget(widgets, KILL_WHOLE_LINE, this::killWholeLine);
+ addBuiltinWidget(widgets, KILL_WORD, this::killWord);
+ addBuiltinWidget(widgets, LIST_CHOICES, this::listChoices);
+ addBuiltinWidget(widgets, MENU_COMPLETE, this::menuComplete);
+ addBuiltinWidget(widgets, MENU_EXPAND_OR_COMPLETE, this::menuExpandOrComplete);
+ addBuiltinWidget(widgets, NEG_ARGUMENT, this::negArgument);
+ addBuiltinWidget(widgets, OVERWRITE_MODE, this::overwriteMode);
+// addBuiltinWidget(widgets, QUIT, this::quit);
+ addBuiltinWidget(widgets, QUOTED_INSERT, this::quotedInsert);
+ addBuiltinWidget(widgets, REDISPLAY, this::redisplay);
+ addBuiltinWidget(widgets, REDRAW_LINE, this::redrawLine);
+ addBuiltinWidget(widgets, REDO, this::redo);
+ addBuiltinWidget(widgets, SELF_INSERT, this::selfInsert);
+ addBuiltinWidget(widgets, SELF_INSERT_UNMETA, this::selfInsertUnmeta);
+ addBuiltinWidget(widgets, SEND_BREAK, this::sendBreak);
+ addBuiltinWidget(widgets, SET_MARK_COMMAND, this::setMarkCommand);
+ addBuiltinWidget(widgets, TRANSPOSE_CHARS, this::transposeChars);
+ addBuiltinWidget(widgets, TRANSPOSE_WORDS, this::transposeWords);
+ addBuiltinWidget(widgets, UNDEFINED_KEY, this::undefinedKey);
+ addBuiltinWidget(widgets, UNIVERSAL_ARGUMENT, this::universalArgument);
+ addBuiltinWidget(widgets, UNDO, this::undo);
+ addBuiltinWidget(widgets, UP_CASE_WORD, this::upCaseWord);
+ addBuiltinWidget(widgets, UP_HISTORY, this::upHistory);
+ addBuiltinWidget(widgets, UP_LINE, this::upLine);
+ addBuiltinWidget(widgets, UP_LINE_OR_HISTORY, this::upLineOrHistory);
+ addBuiltinWidget(widgets, UP_LINE_OR_SEARCH, this::upLineOrSearch);
+ addBuiltinWidget(widgets, VI_ADD_EOL, this::viAddEol);
+ addBuiltinWidget(widgets, VI_ADD_NEXT, this::viAddNext);
+ addBuiltinWidget(widgets, VI_BACKWARD_CHAR, this::viBackwardChar);
+ addBuiltinWidget(widgets, VI_BACKWARD_DELETE_CHAR, this::viBackwardDeleteChar);
+ addBuiltinWidget(widgets, VI_BACKWARD_BLANK_WORD, this::viBackwardBlankWord);
+ addBuiltinWidget(widgets, VI_BACKWARD_BLANK_WORD_END, this::viBackwardBlankWordEnd);
+ addBuiltinWidget(widgets, VI_BACKWARD_KILL_WORD, this::viBackwardKillWord);
+ addBuiltinWidget(widgets, VI_BACKWARD_WORD, this::viBackwardWord);
+ addBuiltinWidget(widgets, VI_BACKWARD_WORD_END, this::viBackwardWordEnd);
+ addBuiltinWidget(widgets, VI_BEGINNING_OF_LINE, this::viBeginningOfLine);
+ addBuiltinWidget(widgets, VI_CMD_MODE, this::viCmdMode);
+ addBuiltinWidget(widgets, VI_DIGIT_OR_BEGINNING_OF_LINE, this::viDigitOrBeginningOfLine);
+ addBuiltinWidget(widgets, VI_DOWN_LINE_OR_HISTORY, this::viDownLineOrHistory);
+ addBuiltinWidget(widgets, VI_CHANGE, this::viChange);
+ addBuiltinWidget(widgets, VI_CHANGE_EOL, this::viChangeEol);
+ addBuiltinWidget(widgets, VI_CHANGE_WHOLE_LINE, this::viChangeWholeLine);
+ addBuiltinWidget(widgets, VI_DELETE_CHAR, this::viDeleteChar);
+ addBuiltinWidget(widgets, VI_DELETE, this::viDelete);
+ addBuiltinWidget(widgets, VI_END_OF_LINE, this::viEndOfLine);
+ addBuiltinWidget(widgets, VI_KILL_EOL, this::viKillEol);
+ addBuiltinWidget(widgets, VI_FIRST_NON_BLANK, this::viFirstNonBlank);
+ addBuiltinWidget(widgets, VI_FIND_NEXT_CHAR, this::viFindNextChar);
+ addBuiltinWidget(widgets, VI_FIND_NEXT_CHAR_SKIP, this::viFindNextCharSkip);
+ addBuiltinWidget(widgets, VI_FIND_PREV_CHAR, this::viFindPrevChar);
+ addBuiltinWidget(widgets, VI_FIND_PREV_CHAR_SKIP, this::viFindPrevCharSkip);
+ addBuiltinWidget(widgets, VI_FORWARD_BLANK_WORD, this::viForwardBlankWord);
+ addBuiltinWidget(widgets, VI_FORWARD_BLANK_WORD_END, this::viForwardBlankWordEnd);
+ addBuiltinWidget(widgets, VI_FORWARD_CHAR, this::viForwardChar);
+ addBuiltinWidget(widgets, VI_FORWARD_WORD, this::viForwardWord);
+ addBuiltinWidget(widgets, VI_FORWARD_WORD, this::viForwardWord);
+ addBuiltinWidget(widgets, VI_FORWARD_WORD_END, this::viForwardWordEnd);
+ addBuiltinWidget(widgets, VI_HISTORY_SEARCH_BACKWARD, this::viHistorySearchBackward);
+ addBuiltinWidget(widgets, VI_HISTORY_SEARCH_FORWARD, this::viHistorySearchForward);
+ addBuiltinWidget(widgets, VI_INSERT, this::viInsert);
+ addBuiltinWidget(widgets, VI_INSERT_BOL, this::viInsertBol);
+ addBuiltinWidget(widgets, VI_INSERT_COMMENT, this::viInsertComment);
+ addBuiltinWidget(widgets, VI_JOIN, this::viJoin);
+ addBuiltinWidget(widgets, VI_KILL_LINE, this::viKillWholeLine);
+ addBuiltinWidget(widgets, VI_MATCH_BRACKET, this::viMatchBracket);
+ addBuiltinWidget(widgets, VI_OPEN_LINE_ABOVE, this::viOpenLineAbove);
+ addBuiltinWidget(widgets, VI_OPEN_LINE_BELOW, this::viOpenLineBelow);
+ addBuiltinWidget(widgets, VI_PUT_AFTER, this::viPutAfter);
+ addBuiltinWidget(widgets, VI_PUT_BEFORE, this::viPutBefore);
+ addBuiltinWidget(widgets, VI_REPEAT_FIND, this::viRepeatFind);
+ addBuiltinWidget(widgets, VI_REPEAT_SEARCH, this::viRepeatSearch);
+ addBuiltinWidget(widgets, VI_REPLACE_CHARS, this::viReplaceChars);
+ addBuiltinWidget(widgets, VI_REV_REPEAT_FIND, this::viRevRepeatFind);
+ addBuiltinWidget(widgets, VI_REV_REPEAT_SEARCH, this::viRevRepeatSearch);
+ addBuiltinWidget(widgets, VI_SWAP_CASE, this::viSwapCase);
+ addBuiltinWidget(widgets, VI_UP_LINE_OR_HISTORY, this::viUpLineOrHistory);
+ addBuiltinWidget(widgets, VI_YANK, this::viYankTo);
+ addBuiltinWidget(widgets, VI_YANK_WHOLE_LINE, this::viYankWholeLine);
+ addBuiltinWidget(widgets, VISUAL_LINE_MODE, this::visualLineMode);
+ addBuiltinWidget(widgets, VISUAL_MODE, this::visualMode);
+ addBuiltinWidget(widgets, WHAT_CURSOR_POSITION, this::whatCursorPosition);
+ addBuiltinWidget(widgets, YANK, this::yank);
+ addBuiltinWidget(widgets, YANK_POP, this::yankPop);
+ addBuiltinWidget(widgets, MOUSE, this::mouse);
+ addBuiltinWidget(widgets, BEGIN_PASTE, this::beginPaste);
+ addBuiltinWidget(widgets, FOCUS_IN, this::focusIn);
+ 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));
+ }
+
+ private Widget namedWidget(String name, Widget widget) {
+ return new Widget() {
+ @Override
+ public String toString() {
+ return name;
+ }
+ @Override
+ public boolean apply() {
+ return widget.apply();
+ }
+ };
+ }
+
public boolean redisplay() {
redisplay(true);
return true;
}
- protected synchronized void redisplay(boolean flush) {
- if (skipRedisplay) {
- skipRedisplay = false;
- return;
- }
-
- Status status = Status.getStatus(terminal, false);
- if (status != null) {
- status.redraw();
- }
-
- if (size.getRows() > 0 && size.getRows() < MIN_ROWS) {
- AttributedStringBuilder sb = new AttributedStringBuilder().tabs(TAB_WIDTH);
-
- sb.append(prompt);
- concat(getHighlightedBuffer(buf.toString()).columnSplitLength(Integer.MAX_VALUE), sb);
- AttributedString full = sb.toAttributedString();
-
- sb.setLength(0);
- sb.append(prompt);
- String line = buf.upToCursor();
- if(maskingCallback != null) {
- line = maskingCallback.display(line);
- }
-
- concat(new AttributedString(line).columnSplitLength(Integer.MAX_VALUE), sb);
- AttributedString toCursor = sb.toAttributedString();
-
- int w = WCWidth.wcwidth('\u2026');
- int width = size.getColumns();
- int cursor = toCursor.columnLength();
- int inc = width /2 + 1;
- while (cursor <= smallTerminalOffset + w) {
- smallTerminalOffset -= inc;
- }
- while (cursor >= smallTerminalOffset + width - w) {
- smallTerminalOffset += inc;
- }
- if (smallTerminalOffset > 0) {
- sb.setLength(0);
- sb.append("\u2026");
- sb.append(full.columnSubSequence(smallTerminalOffset + w, Integer.MAX_VALUE));
- full = sb.toAttributedString();
- }
- int length = full.columnLength();
- if (length >= smallTerminalOffset + width) {
+ protected void redisplay(boolean flush) {
+ try {
+ lock.lock();
+
+ if (skipRedisplay) {
+ skipRedisplay = false;
+ return;
+ }
+
+ Status status = Status.getStatus(terminal, false);
+ if (status != null) {
+ status.redraw();
+ }
+
+ if (size.getRows() > 0 && size.getRows() < MIN_ROWS) {
+ AttributedStringBuilder sb = new AttributedStringBuilder().tabs(TAB_WIDTH);
+
+ sb.append(prompt);
+ concat(getHighlightedBuffer(buf.toString()).columnSplitLength(Integer.MAX_VALUE), sb);
+ AttributedString full = sb.toAttributedString();
+
sb.setLength(0);
- sb.append(full.columnSubSequence(0, width - w));
- sb.append("\u2026");
- full = sb.toAttributedString();
- }
-
- display.update(Collections.singletonList(full), cursor - smallTerminalOffset, flush);
- return;
- }
-
- List<AttributedString> secondaryPrompts = new ArrayList<>();
- AttributedString full = getDisplayedBufferWithPrompts(secondaryPrompts);
-
- List<AttributedString> newLines;
- if (size.getColumns() <= 0) {
- newLines = new ArrayList<>();
- newLines.add(full);
- } else {
- newLines = full.columnSplitLength(size.getColumns(), true, display.delayLineWrap());
- }
-
- List<AttributedString> rightPromptLines;
- if (rightPrompt.length() == 0 || size.getColumns() <= 0) {
- rightPromptLines = new ArrayList<>();
- } else {
- rightPromptLines = rightPrompt.columnSplitLength(size.getColumns());
- }
- while (newLines.size() < rightPromptLines.size()) {
- newLines.add(new AttributedString(""));
- }
- for (int i = 0; i < rightPromptLines.size(); i++) {
- AttributedString line = rightPromptLines.get(i);
- newLines.set(i, addRightPrompt(line, newLines.get(i)));
- }
-
- int cursorPos = -1;
- if (size.getColumns() > 0) {
- AttributedStringBuilder sb = new AttributedStringBuilder().tabs(TAB_WIDTH);
- sb.append(prompt);
- String buffer = buf.upToCursor();
- if (maskingCallback != null) {
- buffer = maskingCallback.display(buffer);
- }
- sb.append(insertSecondaryPrompts(new AttributedString(buffer), secondaryPrompts, false));
- List<AttributedString> promptLines = sb.columnSplitLength(size.getColumns(), false, display.delayLineWrap());
- if (!promptLines.isEmpty()) {
- cursorPos = size.cursorPos(promptLines.size() - 1,
- promptLines.get(promptLines.size() - 1).columnLength());
- }
- }
-
- display.update(newLines, cursorPos, flush);
+ sb.append(prompt);
+ String line = buf.upToCursor();
+ if (maskingCallback != null) {
+ line = maskingCallback.display(line);
+ }
+
+ concat(new AttributedString(line).columnSplitLength(Integer.MAX_VALUE), sb);
+ AttributedString toCursor = sb.toAttributedString();
+
+ int w = WCWidth.wcwidth('\u2026');
+ int width = size.getColumns();
+ int cursor = toCursor.columnLength();
+ int inc = width / 2 + 1;
+ while (cursor <= smallTerminalOffset + w) {
+ smallTerminalOffset -= inc;
+ }
+ while (cursor >= smallTerminalOffset + width - w) {
+ smallTerminalOffset += inc;
+ }
+ if (smallTerminalOffset > 0) {
+ sb.setLength(0);
+ sb.append("\u2026");
+ sb.append(full.columnSubSequence(smallTerminalOffset + w, Integer.MAX_VALUE));
+ full = sb.toAttributedString();
+ }
+ int length = full.columnLength();
+ if (length >= smallTerminalOffset + width) {
+ sb.setLength(0);
+ sb.append(full.columnSubSequence(0, width - w));
+ sb.append("\u2026");
+ full = sb.toAttributedString();
+ }
+
+ display.update(Collections.singletonList(full), cursor - smallTerminalOffset, flush);
+ return;
+ }
+
+ List<AttributedString> secondaryPrompts = new ArrayList<>();
+ AttributedString full = getDisplayedBufferWithPrompts(secondaryPrompts);
+
+ List<AttributedString> newLines;
+ if (size.getColumns() <= 0) {
+ newLines = new ArrayList<>();
+ newLines.add(full);
+ } else {
+ newLines = full.columnSplitLength(size.getColumns(), true, display.delayLineWrap());
+ }
+
+ List<AttributedString> rightPromptLines;
+ if (rightPrompt.length() == 0 || size.getColumns() <= 0) {
+ rightPromptLines = new ArrayList<>();
+ } else {
+ rightPromptLines = rightPrompt.columnSplitLength(size.getColumns());
+ }
+ while (newLines.size() < rightPromptLines.size()) {
+ newLines.add(new AttributedString(""));
+ }
+ for (int i = 0; i < rightPromptLines.size(); i++) {
+ AttributedString line = rightPromptLines.get(i);
+ newLines.set(i, addRightPrompt(line, newLines.get(i)));
+ }
+
+ int cursorPos = -1;
+ int cursorNewLinesId = -1;
+ int cursorColPos = -1;
+ if (size.getColumns() > 0) {
+ AttributedStringBuilder sb = new AttributedStringBuilder().tabs(TAB_WIDTH);
+ sb.append(prompt);
+ String buffer = buf.upToCursor();
+ if (maskingCallback != null) {
+ buffer = maskingCallback.display(buffer);
+ }
+ sb.append(insertSecondaryPrompts(new AttributedString(buffer), secondaryPrompts, false));
+ List<AttributedString> promptLines = sb.columnSplitLength(size.getColumns(), false, display.delayLineWrap());
+ if (!promptLines.isEmpty()) {
+ cursorNewLinesId = promptLines.size() - 1;
+ cursorColPos = promptLines.get(promptLines.size() - 1).columnLength();
+ cursorPos = size.cursorPos(cursorNewLinesId, cursorColPos);
+ }
+ }
+
+ List<AttributedString> newLinesToDisplay = new ArrayList<>();
+ int displaySize = size.getRows() - (status != null ? status.size() : 0);
+ if (newLines.size() > displaySize && !isTerminalDumb()) {
+ StringBuilder sb = new StringBuilder(">....");
+ // blanks are needed when displaying command completion candidate list
+ for (int i = sb.toString().length(); i < size.getColumns(); i++) {
+ sb.append(" ");
+ }
+ AttributedString partialCommandInfo = new AttributedString(sb.toString());
+ int lineId = newLines.size() - displaySize + 1;
+ int endId = displaySize;
+ int startId = 1;
+ if (lineId > cursorNewLinesId) {
+ lineId = cursorNewLinesId;
+ endId = displaySize - 1;
+ startId = 0;
+ } else {
+ newLinesToDisplay.add(partialCommandInfo);
+ }
+ int cursorRowPos = 0;
+ for (int i = startId; i < endId; i++) {
+ if (cursorNewLinesId == lineId) {
+ cursorRowPos = i;
+ }
+ newLinesToDisplay.add(newLines.get(lineId++));
+ }
+ if (startId == 0) {
+ newLinesToDisplay.add(partialCommandInfo);
+ }
+ cursorPos = size.cursorPos(cursorRowPos, cursorColPos);
+ } else {
+ newLinesToDisplay = newLines;
+ }
+ display.update(newLinesToDisplay, cursorPos, flush);
+ } finally {
+ lock.unlock();
+ }
}
private void concat(List<AttributedString> lines, AttributedStringBuilder sb) {
@@ -3656,26 +3841,26 @@
decode: while (true) {
ch = pattern.charAt(i++);
switch (ch) {
- case '{':
- case '}':
- String str = sb.toString();
- AttributedString astr;
- if (!isHidden) {
- astr = AttributedString.fromAnsi(str);
- cols += astr.columnLength();
- } else {
- astr = new AttributedString(str, AttributedStyle.HIDDEN);
- }
- if (padPartIndex == parts.size()) {
- padPartString = sb;
- if (i < plen) {
- sb = new StringBuilder();
- }
- } else {
- sb.setLength(0);
- }
- parts.add(astr);
- isHidden = ch == '{';
+ case '{':
+ case '}':
+ String str = sb.toString();
+ AttributedString astr;
+ if (!isHidden) {
+ astr = AttributedString.fromAnsi(str);
+ cols += astr.columnLength();
+ } else {
+ astr = new AttributedString(str, AttributedStyle.HIDDEN);
+ }
+ if (padPartIndex == parts.size()) {
+ padPartString = sb;
+ if (i < plen) {
+ sb = new StringBuilder();
+ }
+ } else {
+ sb.setLength(0);
+ }
+ parts.add(astr);
+ isHidden = ch == '{';
break decode;
case '%':
sb.append(ch);
@@ -4048,113 +4233,117 @@
if (matching.isEmpty()) {
return false;
}
-
- // If we only need to display the list, do it now
- if (lst == CompletionType.List) {
+ size.copy(terminal.getSize());
+ try {
+ // If we only need to display the list, do it now
+ if (lst == CompletionType.List) {
+ List<Candidate> possible = matching.entrySet().stream()
+ .flatMap(e -> e.getValue().stream())
+ .collect(Collectors.toList());
+ doList(possible, line.word(), false, line::escape);
+ return !possible.isEmpty();
+ }
+
+ // Check if there's a single possible match
+ Candidate completion = null;
+ // If there's a single possible completion
+ if (matching.size() == 1) {
+ completion = matching.values().stream().flatMap(Collection::stream)
+ .findFirst().orElse(null);
+ }
+ // Or if RECOGNIZE_EXACT is set, try to find an exact match
+ else if (isSet(Option.RECOGNIZE_EXACT)) {
+ completion = matching.values().stream().flatMap(Collection::stream)
+ .filter(Candidate::complete)
+ .filter(c -> exact.test(c.value()))
+ .findFirst().orElse(null);
+ }
+ // Complete and exit
+ if (completion != null && !completion.value().isEmpty()) {
+ if (prefix) {
+ buf.backspace(line.rawWordCursor());
+ } else {
+ buf.move(line.rawWordLength() - line.rawWordCursor());
+ buf.backspace(line.rawWordLength());
+ }
+ buf.write(line.escape(completion.value(), completion.complete()));
+ if (completion.complete()) {
+ if (buf.currChar() != ' ') {
+ buf.write(" ");
+ } else {
+ buf.move(1);
+ }
+ }
+ if (completion.suffix() != null) {
+ redisplay();
+ Binding op = readBinding(getKeys());
+ if (op != null) {
+ String chars = getString(REMOVE_SUFFIX_CHARS, DEFAULT_REMOVE_SUFFIX_CHARS);
+ String ref = op instanceof Reference ? ((Reference) op).name() : null;
+ if (SELF_INSERT.equals(ref) && chars.indexOf(getLastBinding().charAt(0)) >= 0
+ || ACCEPT_LINE.equals(ref)) {
+ buf.backspace(completion.suffix().length());
+ if (getLastBinding().charAt(0) != ' ') {
+ buf.write(' ');
+ }
+ }
+ pushBackBinding(true);
+ }
+ }
+ return true;
+ }
+
List<Candidate> possible = matching.entrySet().stream()
.flatMap(e -> e.getValue().stream())
.collect(Collectors.toList());
- doList(possible, line.word(), false, line::escape);
- return !possible.isEmpty();
- }
-
- // Check if there's a single possible match
- Candidate completion = null;
- // If there's a single possible completion
- if (matching.size() == 1) {
- completion = matching.values().stream().flatMap(Collection::stream)
- .findFirst().orElse(null);
- }
- // Or if RECOGNIZE_EXACT is set, try to find an exact match
- else if (isSet(Option.RECOGNIZE_EXACT)) {
- completion = matching.values().stream().flatMap(Collection::stream)
- .filter(Candidate::complete)
- .filter(c -> exact.test(c.value()))
- .findFirst().orElse(null);
- }
- // Complete and exit
- if (completion != null && !completion.value().isEmpty()) {
+
+ if (useMenu) {
+ buf.move(line.word().length() - line.wordCursor());
+ buf.backspace(line.word().length());
+ doMenu(possible, line.word(), line::escape);
+ return true;
+ }
+
+ // Find current word and move to end
+ String current;
if (prefix) {
- buf.backspace(line.rawWordCursor());
+ current = line.word().substring(0, line.wordCursor());
} else {
+ current = line.word();
buf.move(line.rawWordLength() - line.rawWordCursor());
+ }
+ // Now, we need to find the unambiguous completion
+ // TODO: need to find common suffix
+ String commonPrefix = null;
+ for (String key : matching.keySet()) {
+ commonPrefix = commonPrefix == null ? key : getCommonStart(commonPrefix, key, caseInsensitive);
+ }
+ boolean hasUnambiguous = commonPrefix.startsWith(current) && !commonPrefix.equals(current);
+
+ if (hasUnambiguous) {
buf.backspace(line.rawWordLength());
- }
- buf.write(line.escape(completion.value(), completion.complete()));
- if (completion.complete()) {
- if (buf.currChar() != ' ') {
- buf.write(" ");
- } else {
- buf.move(1);
+ buf.write(line.escape(commonPrefix, false));
+ current = commonPrefix;
+ if ((!isSet(Option.AUTO_LIST) && isSet(Option.AUTO_MENU))
+ || (isSet(Option.AUTO_LIST) && isSet(Option.LIST_AMBIGUOUS))) {
+ if (!nextBindingIsComplete()) {
+ return true;
+ }
}
}
- if (completion.suffix() != null) {
- redisplay();
- Binding op = readBinding(getKeys());
- if (op != null) {
- String chars = getString(REMOVE_SUFFIX_CHARS, DEFAULT_REMOVE_SUFFIX_CHARS);
- String ref = op instanceof Reference ? ((Reference) op).name() : null;
- if (SELF_INSERT.equals(ref) && chars.indexOf(getLastBinding().charAt(0)) >= 0
- || ACCEPT_LINE.equals(ref)) {
- buf.backspace(completion.suffix().length());
- if (getLastBinding().charAt(0) != ' ') {
- buf.write(' ');
- }
- }
- pushBackBinding(true);
+ if (isSet(Option.AUTO_LIST)) {
+ if (!doList(possible, current, true, line::escape)) {
+ return true;
}
}
+ if (isSet(Option.AUTO_MENU)) {
+ buf.backspace(current.length());
+ doMenu(possible, line.word(), line::escape);
+ }
return true;
- }
-
- List<Candidate> possible = matching.entrySet().stream()
- .flatMap(e -> e.getValue().stream())
- .collect(Collectors.toList());
-
- if (useMenu) {
- buf.move(line.word().length() - line.wordCursor());
- buf.backspace(line.word().length());
- doMenu(possible, line.word(), line::escape);
- return true;
- }
-
- // Find current word and move to end
- String current;
- if (prefix) {
- current = line.word().substring(0, line.wordCursor());
- } else {
- current = line.word();
- buf.move(line.rawWordLength() - line.rawWordCursor());
- }
- // Now, we need to find the unambiguous completion
- // TODO: need to find common suffix
- String commonPrefix = null;
- for (String key : matching.keySet()) {
- commonPrefix = commonPrefix == null ? key : getCommonStart(commonPrefix, key, caseInsensitive);
- }
- boolean hasUnambiguous = commonPrefix.startsWith(current) && !commonPrefix.equals(current);
-
- if (hasUnambiguous) {
- buf.backspace(line.rawWordLength());
- buf.write(line.escape(commonPrefix, false));
- current = commonPrefix;
- if ((!isSet(Option.AUTO_LIST) && isSet(Option.AUTO_MENU))
- || (isSet(Option.AUTO_LIST) && isSet(Option.LIST_AMBIGUOUS))) {
- if (!nextBindingIsComplete()) {
- return true;
- }
- }
- }
- if (isSet(Option.AUTO_LIST)) {
- if (!doList(possible, current, true, line::escape)) {
- return true;
- }
- }
- if (isSet(Option.AUTO_MENU)) {
- buf.backspace(current.length());
- doMenu(possible, line.word(), line::escape);
- }
- return true;
+ } finally {
+ size.copy(terminal.getBufferSize());
+ }
}
private CompletingParsedLine wrap(ParsedLine line) {
@@ -4534,7 +4723,7 @@
if (listMax > 0 && possible.size() >= listMax
|| lines >= size.getRows() - promptLines) {
// prompt
- post = () -> new AttributedString(getAppName() + ": do you wish to see to see all " + possible.size()
+ post = () -> new AttributedString(getAppName() + ": do you wish to see all " + possible.size()
+ " possibilities (" + lines + " lines)?");
redisplay(true);
int c = readCharacter();
@@ -4586,7 +4775,7 @@
}
redisplay();
// TODO: use a different keyMap ?
- Binding b = bindingReader.readBinding(getKeys());
+ Binding b = doReadBinding(getKeys(), null);
if (b instanceof Reference) {
String name = ((Reference) b).name();
if (BACKWARD_DELETE_CHAR.equals(name) || VI_BACKWARD_DELETE_CHAR.equals(name)) {
@@ -4731,7 +4920,7 @@
@SuppressWarnings("unchecked")
protected void toColumns(Object items, int width, int maxWidth, AttributedStringBuilder sb, Candidate selection, String completed, boolean rowsFirst, int[] out) {
- if (maxWidth <= 0) {
+ if (maxWidth <= 0 || width <= 0) {
return;
}
// This is a group
@@ -4985,7 +5174,9 @@
while (end < buf.length() && buf.atChar(end) != '\n') {
end++;
}
- end++;
+ if (end < buf.length()) {
+ end++;
+ }
}
}
String killed = buf.substring(start, end);
@@ -5188,7 +5379,7 @@
keyMap.bind(END_PASTE, BRACKETED_PASTE_END);
StringBuilder sb = new StringBuilder();
while (true) {
- Object b = bindingReader.readBinding(keyMap);
+ Object b = doReadBinding(keyMap, null);
if (b == END_PASTE) {
break;
}
@@ -5227,6 +5418,11 @@
*/
public boolean clearScreen() {
if (terminal.puts(Capability.clear_screen)) {
+ // ConEMU extended fonts support
+ if (AbstractWindowsTerminal.TYPE_WINDOWS_CONEMU.equals(terminal.getType())
+ && !Boolean.getBoolean("org.jline.terminal.conemu.disable-activate")) {
+ terminal.writer().write("\u001b[9999E");
+ }
Status status = Status.getStatus(terminal, false);
if (status != null) {
status.reset();
@@ -5358,6 +5554,7 @@
public KeyMap<Binding> emacs() {
KeyMap<Binding> emacs = new KeyMap<>();
+ bindKeys(emacs);
bind(emacs, SET_MARK_COMMAND, ctrl('@'));
bind(emacs, BEGINNING_OF_LINE, ctrl('A'));
bind(emacs, BACKWARD_CHAR, ctrl('B'));
@@ -5372,6 +5569,7 @@
bind(emacs, CLEAR_SCREEN, ctrl('L'));
bind(emacs, ACCEPT_LINE, ctrl('M'));
bind(emacs, DOWN_LINE_OR_HISTORY, ctrl('N'));
+ bind(emacs, ACCEPT_LINE_AND_DOWN_HISTORY, ctrl('O'));
bind(emacs, UP_LINE_OR_HISTORY, ctrl('P'));
bind(emacs, HISTORY_INCREMENTAL_SEARCH_BACKWARD, ctrl('R'));
bind(emacs, HISTORY_INCREMENTAL_SEARCH_FORWARD, ctrl('S'));
@@ -5415,6 +5613,7 @@
bind(emacs, END_OF_HISTORY, alt('>'));
bind(emacs, LIST_CHOICES, alt('?'));
bind(emacs, DO_LOWERCASE_VERSION, range("^[A-^[Z"));
+ bind(emacs, ACCEPT_AND_HOLD, alt('a'));
bind(emacs, BACKWARD_WORD, alt('b'));
bind(emacs, CAPITALIZE_WORD, alt('c'));
bind(emacs, KILL_WORD, alt('d'));
@@ -5439,6 +5638,7 @@
public KeyMap<Binding> viInsertion() {
KeyMap<Binding> viins = new KeyMap<>();
+ bindKeys(viins);
bind(viins, SELF_INSERT, range("^@-^_"));
bind(viins, LIST_CHOICES, ctrl('D'));
bind(viins, SEND_BREAK, ctrl('G'));
@@ -5638,6 +5838,14 @@
return KeyMap.key(terminal, capability);
}
+ private void bindKeys(KeyMap<Binding> emacs) {
+ Widget beep = namedWidget("beep", this::beep);
+ Stream.of(Capability.values())
+ .filter(c -> c.name().startsWith("key_"))
+ .map(this::key)
+ .forEach(k -> bind(emacs, beep, k));
+ }
+
private void bindArrowKeys(KeyMap<Binding> map) {
bind(map, UP_LINE_OR_SEARCH, key(Capability.key_up));
bind(map, DOWN_LINE_OR_SEARCH, key(Capability.key_down));
--- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/ReaderUtils.java Mon Nov 04 14:26:18 2019 +0800
+++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/ReaderUtils.java Mon Nov 04 09:40:35 2019 +0100
@@ -4,7 +4,7 @@
* This software is distributable under the BSD license. See the terms of the
* BSD license in the documentation provided with this software.
*
- * http://www.opensource.org/licenses/bsd-license.php
+ * https://opensource.org/licenses/BSD-3-Clause
*/
package jdk.internal.org.jline.reader.impl;
--- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/SimpleMaskingCallback.java Mon Nov 04 14:26:18 2019 +0800
+++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/SimpleMaskingCallback.java Mon Nov 04 09:40:35 2019 +0100
@@ -4,7 +4,7 @@
* This software is distributable under the BSD license. See the terms of the
* BSD license in the documentation provided with this software.
*
- * http://www.opensource.org/licenses/bsd-license.php
+ * https://opensource.org/licenses/BSD-3-Clause
*/
package jdk.internal.org.jline.reader.impl;
--- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/UndoTree.java Mon Nov 04 14:26:18 2019 +0800
+++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/UndoTree.java Mon Nov 04 09:40:35 2019 +0100
@@ -4,7 +4,7 @@
* This software is distributable under the BSD license. See the terms of the
* BSD license in the documentation provided with this software.
*
- * http://www.opensource.org/licenses/bsd-license.php
+ * https://opensource.org/licenses/BSD-3-Clause
*/
package jdk.internal.org.jline.reader.impl;
--- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/completer/AggregateCompleter.java Mon Nov 04 14:26:18 2019 +0800
+++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/completer/AggregateCompleter.java Mon Nov 04 09:40:35 2019 +0100
@@ -4,7 +4,7 @@
* This software is distributable under the BSD license. See the terms of the
* BSD license in the documentation provided with this software.
*
- * http://www.opensource.org/licenses/bsd-license.php
+ * https://opensource.org/licenses/BSD-3-Clause
*/
package jdk.internal.org.jline.reader.impl.completer;
--- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/completer/ArgumentCompleter.java Mon Nov 04 14:26:18 2019 +0800
+++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/completer/ArgumentCompleter.java Mon Nov 04 09:40:35 2019 +0100
@@ -4,7 +4,7 @@
* This software is distributable under the BSD license. See the terms of the
* BSD license in the documentation provided with this software.
*
- * http://www.opensource.org/licenses/bsd-license.php
+ * https://opensource.org/licenses/BSD-3-Clause
*/
package jdk.internal.org.jline.reader.impl.completer;
--- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/completer/EnumCompleter.java Mon Nov 04 14:26:18 2019 +0800
+++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/completer/EnumCompleter.java Mon Nov 04 09:40:35 2019 +0100
@@ -4,7 +4,7 @@
* This software is distributable under the BSD license. See the terms of the
* BSD license in the documentation provided with this software.
*
- * http://www.opensource.org/licenses/bsd-license.php
+ * https://opensource.org/licenses/BSD-3-Clause
*/
package jdk.internal.org.jline.reader.impl.completer;
--- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/completer/FileNameCompleter.java Mon Nov 04 14:26:18 2019 +0800
+++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/completer/FileNameCompleter.java Mon Nov 04 09:40:35 2019 +0100
@@ -4,7 +4,7 @@
* This software is distributable under the BSD license. See the terms of the
* BSD license in the documentation provided with this software.
*
- * http://www.opensource.org/licenses/bsd-license.php
+ * https://opensource.org/licenses/BSD-3-Clause
*/
package jdk.internal.org.jline.reader.impl.completer;
--- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/completer/NullCompleter.java Mon Nov 04 14:26:18 2019 +0800
+++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/completer/NullCompleter.java Mon Nov 04 09:40:35 2019 +0100
@@ -4,7 +4,7 @@
* This software is distributable under the BSD license. See the terms of the
* BSD license in the documentation provided with this software.
*
- * http://www.opensource.org/licenses/bsd-license.php
+ * https://opensource.org/licenses/BSD-3-Clause
*/
package jdk.internal.org.jline.reader.impl.completer;
--- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/completer/StringsCompleter.java Mon Nov 04 14:26:18 2019 +0800
+++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/completer/StringsCompleter.java Mon Nov 04 09:40:35 2019 +0100
@@ -4,7 +4,7 @@
* This software is distributable under the BSD license. See the terms of the
* BSD license in the documentation provided with this software.
*
- * http://www.opensource.org/licenses/bsd-license.php
+ * https://opensource.org/licenses/BSD-3-Clause
*/
package jdk.internal.org.jline.reader.impl.completer;
@@ -43,6 +43,11 @@
}
}
+ public StringsCompleter(Candidate ... candidates) {
+ assert candidates != null;
+ this.candidates.addAll(Arrays.asList(candidates));
+ }
+
public void complete(LineReader reader, final ParsedLine commandLine, final List<Candidate> candidates) {
assert commandLine != null;
assert candidates != null;
--- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/completer/package-info.java Mon Nov 04 14:26:18 2019 +0800
+++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/completer/package-info.java Mon Nov 04 09:40:35 2019 +0100
@@ -4,7 +4,7 @@
* This software is distributable under the BSD license. See the terms of the
* BSD license in the documentation provided with this software.
*
- * http://www.opensource.org/licenses/bsd-license.php
+ * https://opensource.org/licenses/BSD-3-Clause
*/
/**
* JLine 3.
--- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/history/DefaultHistory.java Mon Nov 04 14:26:18 2019 +0800
+++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/history/DefaultHistory.java Mon Nov 04 09:40:35 2019 +0100
@@ -4,12 +4,13 @@
* This software is distributable under the BSD license. See the terms of the
* BSD license in the documentation provided with this software.
*
- * http://www.opensource.org/licenses/bsd-license.php
+ * https://opensource.org/licenses/BSD-3-Clause
*/
package jdk.internal.org.jline.reader.impl.history;
import java.io.*;
import java.nio.file.*;
+import java.time.DateTimeException;
import java.time.Instant;
import java.util.*;
@@ -36,8 +37,7 @@
private LineReader reader;
- private int lastLoaded = 0;
- private int nbEntriesInFile = 0;
+ private Map<String, HistoryFileData> historyFiles = new HashMap<>();
private int offset = 0;
private int index = 0;
@@ -68,7 +68,7 @@
try {
load();
}
- catch (IOException e) {
+ catch (IllegalArgumentException | IOException e) {
Log.warn("Failed to load history", e);
}
}
@@ -84,12 +84,11 @@
try (BufferedReader reader = Files.newBufferedReader(path)) {
internalClear();
reader.lines().forEach(line -> addHistoryLine(path, line));
- lastLoaded = items.size();
- nbEntriesInFile = lastLoaded;
+ setHistoryFileData(path, new HistoryFileData(items.size(), items.size()));
maybeResize();
}
}
- } catch (IOException e) {
+ } catch (IllegalArgumentException | IOException e) {
Log.debug("Failed to load history; clearing", e);
internalClear();
throw e;
@@ -97,20 +96,100 @@
}
}
+ @Override
+ public void read(Path file, boolean incremental) throws IOException {
+ Path path = file != null ? file : getPath();
+ if (path != null) {
+ try {
+ if (Files.exists(path)) {
+ Log.trace("Reading history from: ", path);
+ try (BufferedReader reader = Files.newBufferedReader(path)) {
+ reader.lines().forEach(line -> addHistoryLine(path, line, incremental));
+ setHistoryFileData(path, new HistoryFileData(items.size(), items.size()));
+ maybeResize();
+ }
+ }
+ } catch (IllegalArgumentException | IOException e) {
+ Log.debug("Failed to read history; clearing", e);
+ internalClear();
+ throw e;
+ }
+ }
+ }
+
+ private String doHistoryFileDataKey (Path path){
+ return path != null ? path.toAbsolutePath().toString() : null;
+ }
+
+ private HistoryFileData getHistoryFileData(Path path) {
+ String key = doHistoryFileDataKey(path);
+ if (!historyFiles.containsKey(key)){
+ historyFiles.put(key, new HistoryFileData());
+ }
+ return historyFiles.get(key);
+ }
+
+ private void setHistoryFileData(Path path, HistoryFileData historyFileData) {
+ historyFiles.put(doHistoryFileDataKey(path), historyFileData);
+ }
+
+ private boolean isLineReaderHistory (Path path) throws IOException {
+ Path lrp = getPath();
+ if (lrp == null) {
+ if (path != null) {
+ return false;
+ } else {
+ return true;
+ }
+ }
+ return Files.isSameFile(lrp, path);
+ }
+
+ private void setLastLoaded(Path path, int lastloaded){
+ getHistoryFileData(path).setLastLoaded(lastloaded);
+ }
+
+ private void setEntriesInFile(Path path, int entriesInFile){
+ getHistoryFileData(path).setEntriesInFile(entriesInFile);
+ }
+
+ private void incEntriesInFile(Path path, int amount){
+ getHistoryFileData(path).incEntriesInFile(amount);
+ }
+
+ private int getLastLoaded(Path path){
+ return getHistoryFileData(path).getLastLoaded();
+ }
+
+ private int getEntriesInFile(Path path){
+ return getHistoryFileData(path).getEntriesInFile();
+ }
+
protected void addHistoryLine(Path path, String line) {
+ addHistoryLine(path, line, false);
+ }
+
+ protected void addHistoryLine(Path path, String line, boolean checkDuplicates) {
if (reader.isSet(LineReader.Option.HISTORY_TIMESTAMPED)) {
int idx = line.indexOf(':');
+ final String badHistoryFileSyntax = "Bad history file syntax! " +
+ "The history file `" + path + "` may be an older history: " +
+ "please remove it or use a different history file.";
if (idx < 0) {
- throw new IllegalArgumentException("Bad history file syntax! " +
- "The history file `" + path + "` may be an older history: " +
- "please remove it or use a different history file.");
+ throw new IllegalArgumentException(badHistoryFileSyntax);
}
- Instant time = Instant.ofEpochMilli(Long.parseLong(line.substring(0, idx)));
+ Instant time;
+ try {
+ time = Instant.ofEpochMilli(Long.parseLong(line.substring(0, idx)));
+ } catch (DateTimeException | NumberFormatException e) {
+ throw new IllegalArgumentException(badHistoryFileSyntax);
+ }
+
String unescaped = unescape(line.substring(idx + 1));
- internalAdd(time, unescaped);
+ internalAdd(time, unescaped, checkDuplicates);
}
else {
- internalAdd(Instant.now(), unescape(line));
+ internalAdd(Instant.now(), unescape(line), checkDuplicates);
}
}
@@ -125,28 +204,45 @@
}
@Override
+ public void write(Path file, boolean incremental) throws IOException {
+ Path path = file != null ? file : getPath();
+ if (path != null && Files.exists(path)) {
+ path.toFile().delete();
+ }
+ internalWrite(path, incremental ? getLastLoaded(path) : 0);
+ }
+
+ @Override
+ public void append(Path file, boolean incremental) throws IOException {
+ internalWrite(file != null ? file : getPath(),
+ incremental ? getLastLoaded(file) : 0);
+ }
+
+ @Override
public void save() throws IOException {
- Path path = getPath();
+ internalWrite(getPath(), getLastLoaded(getPath()));
+ }
+
+ private void internalWrite(Path path, int from) throws IOException {
if (path != null) {
Log.trace("Saving history to: ", path);
Files.createDirectories(path.toAbsolutePath().getParent());
// Append new items to the history file
try (BufferedWriter writer = Files.newBufferedWriter(path.toAbsolutePath(),
StandardOpenOption.WRITE, StandardOpenOption.APPEND, StandardOpenOption.CREATE)) {
- for (Entry entry : items.subList(lastLoaded, items.size())) {
+ for (Entry entry : items.subList(from, items.size())) {
if (isPersistable(entry)) {
writer.append(format(entry));
}
}
}
- nbEntriesInFile += items.size() - lastLoaded;
- // If we are over 25% max size, trim history file
+ incEntriesInFile(path, items.size() - from);
int max = getInt(reader, LineReader.HISTORY_FILE_SIZE, DEFAULT_HISTORY_FILE_SIZE);
- if (nbEntriesInFile > max + max / 4) {
+ if (getEntriesInFile(path) > max + max / 4) {
trimHistory(path, max);
}
}
- lastLoaded = items.size();
+ setLastLoaded(path, items.size());
}
protected void trimHistory(Path path, int max) throws IOException {
@@ -172,11 +268,14 @@
}
Files.move(temp, path, StandardCopyOption.REPLACE_EXISTING);
// Keep items in memory
- internalClear();
- offset = allItems.get(0).index();
- items.addAll(allItems);
- lastLoaded = items.size();
- nbEntriesInFile = items.size();
+ if (isLineReaderHistory(path)) {
+ internalClear();
+ offset = allItems.get(0).index();
+ items.addAll(allItems);
+ setHistoryFileData(path, new HistoryFileData(items.size(), items.size()));
+ } else {
+ setEntriesInFile(path, allItems.size());
+ }
maybeResize();
}
@@ -194,8 +293,7 @@
private void internalClear() {
offset = 0;
index = 0;
- lastLoaded = 0;
- nbEntriesInFile = 0;
+ historyFiles = new HashMap<>();
items.clear();
}
@@ -302,7 +400,18 @@
}
protected void internalAdd(Instant time, String line) {
+ internalAdd(time, line, false);
+ }
+
+ protected void internalAdd(Instant time, String line, boolean checkDuplicates) {
Entry entry = new EntryImpl(offset + items.size(), time, line);
+ if (checkDuplicates) {
+ for (Entry e: items) {
+ if (e.line().trim().equals(line.trim())) {
+ return;
+ }
+ }
+ }
items.add(entry);
maybeResize();
}
@@ -310,7 +419,9 @@
private void maybeResize() {
while (size() > getInt(reader, LineReader.HISTORY_SIZE, DEFAULT_HISTORY_SIZE)) {
items.removeFirst();
- lastLoaded--;
+ for (HistoryFileData hfd: historyFiles.values()) {
+ hfd.decLastLoaded();
+ }
offset++;
}
index = size();
@@ -503,5 +614,46 @@
return sb.toString();
}
+ private class HistoryFileData {
+ private int lastLoaded = 0;
+ private int entriesInFile = 0;
+
+ public HistoryFileData() {
+ }
+
+ public HistoryFileData(int lastLoaded, int entriesInFile) {
+ this.lastLoaded = lastLoaded;
+ this.entriesInFile = entriesInFile;
+ }
+
+ public int getLastLoaded() {
+ return lastLoaded;
+ }
+
+ public void setLastLoaded(int lastLoaded) {
+ this.lastLoaded = lastLoaded;
+ }
+
+ public void decLastLoaded() {
+ lastLoaded = lastLoaded - 1;
+ if (lastLoaded < 0) {
+ lastLoaded = 0;
+ }
+ }
+
+ public int getEntriesInFile() {
+ return entriesInFile;
+ }
+
+ public void setEntriesInFile(int entriesInFile) {
+ this.entriesInFile = entriesInFile;
+ }
+
+ public void incEntriesInFile(int amount) {
+ entriesInFile = entriesInFile + amount;
+ }
+
+ }
+
}
--- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/history/package-info.java Mon Nov 04 14:26:18 2019 +0800
+++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/history/package-info.java Mon Nov 04 09:40:35 2019 +0100
@@ -4,7 +4,7 @@
* This software is distributable under the BSD license. See the terms of the
* BSD license in the documentation provided with this software.
*
- * http://www.opensource.org/licenses/bsd-license.php
+ * https://opensource.org/licenses/BSD-3-Clause
*/
/**
* JLine 3.
--- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/package-info.java Mon Nov 04 14:26:18 2019 +0800
+++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/package-info.java Mon Nov 04 09:40:35 2019 +0100
@@ -4,7 +4,7 @@
* This software is distributable under the BSD license. See the terms of the
* BSD license in the documentation provided with this software.
*
- * http://www.opensource.org/licenses/bsd-license.php
+ * https://opensource.org/licenses/BSD-3-Clause
*/
/**
* JLine 3.
--- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/Attributes.java Mon Nov 04 14:26:18 2019 +0800
+++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/Attributes.java Mon Nov 04 09:40:35 2019 +0100
@@ -4,7 +4,7 @@
* This software is distributable under the BSD license. See the terms of the
* BSD license in the documentation provided with this software.
*
- * http://www.opensource.org/licenses/bsd-license.php
+ * https://opensource.org/licenses/BSD-3-Clause
*/
package jdk.internal.org.jline.terminal;
--- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/Cursor.java Mon Nov 04 14:26:18 2019 +0800
+++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/Cursor.java Mon Nov 04 09:40:35 2019 +0100
@@ -4,7 +4,7 @@
* This software is distributable under the BSD license. See the terms of the
* BSD license in the documentation provided with this software.
*
- * http://www.opensource.org/licenses/bsd-license.php
+ * https://opensource.org/licenses/BSD-3-Clause
*/
package jdk.internal.org.jline.terminal;
--- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/MouseEvent.java Mon Nov 04 14:26:18 2019 +0800
+++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/MouseEvent.java Mon Nov 04 09:40:35 2019 +0100
@@ -4,7 +4,7 @@
* This software is distributable under the BSD license. See the terms of the
* BSD license in the documentation provided with this software.
*
- * http://www.opensource.org/licenses/bsd-license.php
+ * https://opensource.org/licenses/BSD-3-Clause
*/
package jdk.internal.org.jline.terminal;
--- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/Size.java Mon Nov 04 14:26:18 2019 +0800
+++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/Size.java Mon Nov 04 09:40:35 2019 +0100
@@ -4,7 +4,7 @@
* This software is distributable under the BSD license. See the terms of the
* BSD license in the documentation provided with this software.
*
- * http://www.opensource.org/licenses/bsd-license.php
+ * https://opensource.org/licenses/BSD-3-Clause
*/
package jdk.internal.org.jline.terminal;
--- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/Terminal.java Mon Nov 04 14:26:18 2019 +0800
+++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/Terminal.java Mon Nov 04 09:40:35 2019 +0100
@@ -4,7 +4,7 @@
* This software is distributable under the BSD license. See the terms of the
* BSD license in the documentation provided with this software.
*
- * http://www.opensource.org/licenses/bsd-license.php
+ * https://opensource.org/licenses/BSD-3-Clause
*/
package jdk.internal.org.jline.terminal;
@@ -111,7 +111,7 @@
*
* @return The output stream
*
- * @see #writer();
+ * @see #writer()
*/
OutputStream output();
@@ -183,6 +183,11 @@
void setAttributes(Attributes attr);
+ /**
+ * Retrieve the size of the visible window
+ * @return the visible terminal size
+ * @see #getBufferSize()
+ */
Size getSize();
void setSize(Size size);
@@ -195,6 +200,22 @@
return getSize().getRows();
}
+ /**
+ * Retrieve the size of the window buffer.
+ * Some terminals can be configured to have a buffer size
+ * larger than the visible window size and provide scroll bars.
+ * In such cases, this method should attempt to return the size
+ * of the whole buffer. The <code>getBufferSize()</code> method
+ * can be used to avoid wrapping when using the terminal in a line
+ * editing mode, while the {@link #getSize()} method should be
+ * used when using full screen mode.
+ * @return the terminal buffer size
+ * @see #getSize()
+ */
+ default Size getBufferSize() {
+ return getSize();
+ }
+
void flush();
//
--- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/TerminalBuilder.java Mon Nov 04 14:26:18 2019 +0800
+++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/TerminalBuilder.java Mon Nov 04 09:40:35 2019 +0100
@@ -1,10 +1,10 @@
/*
- * 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.
*
- * http://www.opensource.org/licenses/bsd-license.php
+ * https://opensource.org/licenses/BSD-3-Clause
*/
package jdk.internal.org.jline.terminal;
@@ -33,9 +33,6 @@
import jdk.internal.org.jline.utils.Log;
import jdk.internal.org.jline.utils.OSUtils;
-import static jdk.internal.org.jline.terminal.impl.AbstractWindowsTerminal.TYPE_WINDOWS;
-import static jdk.internal.org.jline.terminal.impl.AbstractWindowsTerminal.TYPE_WINDOWS_256_COLOR;
-
/**
* Builder class to create terminals.
*/
--- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/AbstractPosixTerminal.java Mon Nov 04 14:26:18 2019 +0800
+++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/AbstractPosixTerminal.java Mon Nov 04 09:40:35 2019 +0100
@@ -4,7 +4,7 @@
* This software is distributable under the BSD license. See the terms of the
* BSD license in the documentation provided with this software.
*
- * http://www.opensource.org/licenses/bsd-license.php
+ * https://opensource.org/licenses/BSD-3-Clause
*/
package jdk.internal.org.jline.terminal.impl;
--- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/AbstractPty.java Mon Nov 04 14:26:18 2019 +0800
+++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/AbstractPty.java Mon Nov 04 09:40:35 2019 +0100
@@ -1,3 +1,11 @@
+/*
+ * 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.
+ *
+ * https://opensource.org/licenses/BSD-3-Clause
+ */
package jdk.internal.org.jline.terminal.impl;
import jdk.internal.org.jline.terminal.Attributes;
--- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/AbstractTerminal.java Mon Nov 04 14:26:18 2019 +0800
+++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/AbstractTerminal.java Mon Nov 04 09:40:35 2019 +0100
@@ -4,7 +4,7 @@
* This software is distributable under the BSD license. See the terms of the
* BSD license in the documentation provided with this software.
*
- * http://www.opensource.org/licenses/bsd-license.php
+ * https://opensource.org/licenses/BSD-3-Clause
*/
package jdk.internal.org.jline.terminal.impl;
--- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/AbstractWindowsConsoleWriter.java Mon Nov 04 14:26:18 2019 +0800
+++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/AbstractWindowsConsoleWriter.java Mon Nov 04 09:40:35 2019 +0100
@@ -4,7 +4,7 @@
* This software is distributable under the BSD license. See the terms of the
* BSD license in the documentation provided with this software.
*
- * http://www.opensource.org/licenses/bsd-license.php
+ * https://opensource.org/licenses/BSD-3-Clause
*/
package jdk.internal.org.jline.terminal.impl;
--- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/AbstractWindowsTerminal.java Mon Nov 04 14:26:18 2019 +0800
+++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/AbstractWindowsTerminal.java Mon Nov 04 09:40:35 2019 +0100
@@ -1,10 +1,10 @@
/*
- * 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.
*
- * http://www.opensource.org/licenses/bsd-license.php
+ * https://opensource.org/licenses/BSD-3-Clause
*/
package jdk.internal.org.jline.terminal.impl;
@@ -21,12 +21,10 @@
import jdk.internal.org.jline.utils.Signals;
import jdk.internal.org.jline.utils.WriterOutputStream;
-import java.io.IOError;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
-import java.io.StringWriter;
import java.io.Writer;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
@@ -50,6 +48,7 @@
public static final String TYPE_WINDOWS = "windows";
public static final String TYPE_WINDOWS_256_COLOR = "windows-256color";
+ public static final String TYPE_WINDOWS_CONEMU = "windows-conemu";
public static final String TYPE_WINDOWS_VTP = "windows-vtp";
public static final int ENABLE_VIRTUAL_TERMINAL_PROCESSING = 0x0004;
@@ -110,7 +109,7 @@
closer = this::close;
ShutdownHooks.add(closer);
// ConEMU extended fonts support
- if (TYPE_WINDOWS_256_COLOR.equals(getType())
+ if (TYPE_WINDOWS_CONEMU.equals(getType())
&& !Boolean.getBoolean("org.jline.terminal.conemu.disable-activate")) {
writer.write("\u001b[9999E");
writer.flush();
--- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/CursorSupport.java Mon Nov 04 14:26:18 2019 +0800
+++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/CursorSupport.java Mon Nov 04 09:40:35 2019 +0100
@@ -4,7 +4,7 @@
* This software is distributable under the BSD license. See the terms of the
* BSD license in the documentation provided with this software.
*
- * http://www.opensource.org/licenses/bsd-license.php
+ * https://opensource.org/licenses/BSD-3-Clause
*/
package jdk.internal.org.jline.terminal.impl;
--- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/DumbTerminal.java Mon Nov 04 14:26:18 2019 +0800
+++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/DumbTerminal.java Mon Nov 04 09:40:35 2019 +0100
@@ -4,7 +4,7 @@
* This software is distributable under the BSD license. See the terms of the
* BSD license in the documentation provided with this software.
*
- * http://www.opensource.org/licenses/bsd-license.php
+ * https://opensource.org/licenses/BSD-3-Clause
*/
package jdk.internal.org.jline.terminal.impl;
--- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/ExecPty.java Mon Nov 04 14:26:18 2019 +0800
+++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/ExecPty.java Mon Nov 04 09:40:35 2019 +0100
@@ -1,10 +1,10 @@
/*
- * Copyright (c) 2002-2019, the original author or authors.
+ * Copyright (c) 2002-2016, 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.
*
- * http://www.opensource.org/licenses/bsd-license.php
+ * https://opensource.org/licenses/BSD-3-Clause
*/
package jdk.internal.org.jline.terminal.impl;
@@ -137,15 +137,12 @@
}
String undef = System.getProperty("os.name").toLowerCase().startsWith("hp") ? "^-" : "undef";
for (ControlChar cchar : ControlChar.values()) {
- if (attr.getControlChar(cchar) != current.getControlChar(cchar)) {
+ int v = attr.getControlChar(cchar);
+ if (v >= 0 && v != current.getControlChar(cchar)) {
String str = "";
- int v = attr.getControlChar(cchar);
- if (v == -1) { // Skip if ControlChar is <UNDEF>
- continue;
- }
commands.add(cchar.name().toLowerCase().substring(1));
if (cchar == ControlChar.VMIN || cchar == ControlChar.VTIME) {
- commands.add(Integer.toBinaryString(v));
+ commands.add(Integer.toString(v));
}
else if (v == 0) {
commands.add(undef);
--- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/ExternalTerminal.java Mon Nov 04 14:26:18 2019 +0800
+++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/ExternalTerminal.java Mon Nov 04 09:40:35 2019 +0100
@@ -4,7 +4,7 @@
* This software is distributable under the BSD license. See the terms of the
* BSD license in the documentation provided with this software.
*
- * http://www.opensource.org/licenses/bsd-license.php
+ * https://opensource.org/licenses/BSD-3-Clause
*/
package jdk.internal.org.jline.terminal.impl;
--- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/LineDisciplineTerminal.java Mon Nov 04 14:26:18 2019 +0800
+++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/LineDisciplineTerminal.java Mon Nov 04 09:40:35 2019 +0100
@@ -4,7 +4,7 @@
* This software is distributable under the BSD license. See the terms of the
* BSD license in the documentation provided with this software.
*
- * http://www.opensource.org/licenses/bsd-license.php
+ * https://opensource.org/licenses/BSD-3-Clause
*/
package jdk.internal.org.jline.terminal.impl;
--- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/MouseSupport.java Mon Nov 04 14:26:18 2019 +0800
+++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/MouseSupport.java Mon Nov 04 09:40:35 2019 +0100
@@ -4,7 +4,7 @@
* This software is distributable under the BSD license. See the terms of the
* BSD license in the documentation provided with this software.
*
- * http://www.opensource.org/licenses/bsd-license.php
+ * https://opensource.org/licenses/BSD-3-Clause
*/
package jdk.internal.org.jline.terminal.impl;
--- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/NativeSignalHandler.java Mon Nov 04 14:26:18 2019 +0800
+++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/NativeSignalHandler.java Mon Nov 04 09:40:35 2019 +0100
@@ -4,7 +4,7 @@
* This software is distributable under the BSD license. See the terms of the
* BSD license in the documentation provided with this software.
*
- * http://www.opensource.org/licenses/bsd-license.php
+ * https://opensource.org/licenses/BSD-3-Clause
*/
package jdk.internal.org.jline.terminal.impl;
--- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/PosixPtyTerminal.java Mon Nov 04 14:26:18 2019 +0800
+++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/PosixPtyTerminal.java Mon Nov 04 09:40:35 2019 +0100
@@ -4,7 +4,7 @@
* This software is distributable under the BSD license. See the terms of the
* BSD license in the documentation provided with this software.
*
- * http://www.opensource.org/licenses/bsd-license.php
+ * https://opensource.org/licenses/BSD-3-Clause
*/
package jdk.internal.org.jline.terminal.impl;
--- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/PosixSysTerminal.java Mon Nov 04 14:26:18 2019 +0800
+++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/PosixSysTerminal.java Mon Nov 04 09:40:35 2019 +0100
@@ -4,7 +4,7 @@
* This software is distributable under the BSD license. See the terms of the
* BSD license in the documentation provided with this software.
*
- * http://www.opensource.org/licenses/bsd-license.php
+ * https://opensource.org/licenses/BSD-3-Clause
*/
package jdk.internal.org.jline.terminal.impl;
--- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/package-info.java Mon Nov 04 14:26:18 2019 +0800
+++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/package-info.java Mon Nov 04 09:40:35 2019 +0100
@@ -4,7 +4,7 @@
* This software is distributable under the BSD license. See the terms of the
* BSD license in the documentation provided with this software.
*
- * http://www.opensource.org/licenses/bsd-license.php
+ * https://opensource.org/licenses/BSD-3-Clause
*/
/**
* JLine 3.
--- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/spi/JansiSupport.java Mon Nov 04 14:26:18 2019 +0800
+++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/spi/JansiSupport.java Mon Nov 04 09:40:35 2019 +0100
@@ -1,3 +1,11 @@
+/*
+ * 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.
+ *
+ * https://opensource.org/licenses/BSD-3-Clause
+ */
package jdk.internal.org.jline.terminal.spi;
import jdk.internal.org.jline.terminal.Attributes;
--- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/spi/JnaSupport.java Mon Nov 04 14:26:18 2019 +0800
+++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/spi/JnaSupport.java Mon Nov 04 09:40:35 2019 +0100
@@ -1,3 +1,11 @@
+/*
+ * 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.
+ *
+ * https://opensource.org/licenses/BSD-3-Clause
+ */
package jdk.internal.org.jline.terminal.spi;
import jdk.internal.org.jline.terminal.Attributes;
--- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/spi/Pty.java Mon Nov 04 14:26:18 2019 +0800
+++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/spi/Pty.java Mon Nov 04 09:40:35 2019 +0100
@@ -4,7 +4,7 @@
* This software is distributable under the BSD license. See the terms of the
* BSD license in the documentation provided with this software.
*
- * http://www.opensource.org/licenses/bsd-license.php
+ * https://opensource.org/licenses/BSD-3-Clause
*/
package jdk.internal.org.jline.terminal.spi;
--- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/AttributedCharSequence.java Mon Nov 04 14:26:18 2019 +0800
+++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/AttributedCharSequence.java Mon Nov 04 09:40:35 2019 +0100
@@ -1,10 +1,10 @@
/*
- * Copyright (c) 2002-2016, 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.
*
- * http://www.opensource.org/licenses/bsd-license.php
+ * https://opensource.org/licenses/BSD-3-Clause
*/
package jdk.internal.org.jline.utils;
@@ -38,6 +38,14 @@
// cache the value here as we can't afford to get it each time
static final boolean DISABLE_ALTERNATE_CHARSET = Boolean.getBoolean(PROP_DISABLE_ALTERNATE_CHARSET);
+ public void print(Terminal terminal) {
+ terminal.writer().print(toAnsi(terminal));
+ }
+
+ public void println(Terminal terminal) {
+ terminal.writer().println(toAnsi(terminal));
+ }
+
public String toAnsi() {
return toAnsi(null);
}
@@ -54,7 +62,8 @@
if (max_colors != null) {
colors = max_colors;
}
- force256colors = AbstractWindowsTerminal.TYPE_WINDOWS_256_COLOR.equals(terminal.getType());
+ force256colors = AbstractWindowsTerminal.TYPE_WINDOWS_256_COLOR.equals(terminal.getType())
+ || AbstractWindowsTerminal.TYPE_WINDOWS_CONEMU.equals(terminal.getType());
if (!DISABLE_ALTERNATE_CHARSET) {
alternateIn = Curses.tputs(terminal.getStringCapability(Capability.enter_alt_charset_mode));
alternateOut = Curses.tputs(terminal.getStringCapability(Capability.exit_alt_charset_mode));
@@ -293,7 +302,7 @@
if (col + w > start) {
break;
}
- begin++;
+ begin += Character.charCount(cp);
col += w;
}
int end = begin;
@@ -305,7 +314,7 @@
if (col + w > stop) {
break;
}
- end++;
+ end += Character.charCount(cp);
col += w;
}
return subSequence(begin, end);
--- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/AttributedString.java Mon Nov 04 14:26:18 2019 +0800
+++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/AttributedString.java Mon Nov 04 09:40:35 2019 +0100
@@ -4,12 +4,13 @@
* This software is distributable under the BSD license. See the terms of the
* BSD license in the documentation provided with this software.
*
- * http://www.opensource.org/licenses/bsd-license.php
+ * https://opensource.org/licenses/BSD-3-Clause
*/
package jdk.internal.org.jline.utils;
import java.security.InvalidParameterException;
import java.util.Arrays;
+import java.util.List;
import java.util.Objects;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@@ -98,6 +99,10 @@
}
public static AttributedString fromAnsi(String ansi, int tabs) {
+ return fromAnsi(ansi, Arrays.asList(tabs));
+ }
+
+ public static AttributedString fromAnsi(String ansi, List<Integer> tabs) {
if (ansi == null) {
return null;
}
--- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/AttributedStringBuilder.java Mon Nov 04 14:26:18 2019 +0800
+++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/AttributedStringBuilder.java Mon Nov 04 09:40:35 2019 +0100
@@ -4,11 +4,13 @@
* This software is distributable under the BSD license. See the terms of the
* BSD license in the documentation provided with this software.
*
- * http://www.opensource.org/licenses/bsd-license.php
+ * https://opensource.org/licenses/BSD-3-Clause
*/
package jdk.internal.org.jline.utils;
+import java.util.ArrayList;
import java.util.Arrays;
+import java.util.List;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.regex.Matcher;
@@ -24,7 +26,7 @@
private char[] buffer;
private int[] style;
private int length;
- private int tabs = 0;
+ private TabStops tabs = new TabStops(0);
private int lastLineLength = 0;
private AttributedStyle current = AttributedStyle.DEFAULT;
@@ -151,7 +153,7 @@
for (int i = start; i < end; i++) {
char c = str.charAt(i);
int s = str.styleCodeAt(i) & ~current.getMask() | current.getStyle();
- if (tabs > 0 && c == '\t') {
+ if (tabs.defined() && c == '\t') {
insertTab(new AttributedStyle(s, 0));
} else {
ensureCapacity(length + 1);
@@ -332,7 +334,7 @@
// This is not a SGR code, so ignore
ansiState = 0;
}
- } else if (c == '\t' && tabs > 0) {
+ } else if (c == '\t' && tabs.defined()) {
insertTab(current);
} else {
ensureCapacity(length + 1);
@@ -350,7 +352,7 @@
}
protected void insertTab(AttributedStyle s) {
- int nb = tabs - lastLineLength % tabs;
+ int nb = tabs.spaces(lastLineLength);
ensureCapacity(length + nb);
for (int i = 0; i < nb; i++) {
buffer[length] = ' ';
@@ -373,13 +375,17 @@
* @return this
*/
public AttributedStringBuilder tabs(int tabsize) {
+ if (tabsize < 0) {
+ throw new IllegalArgumentException("Tab size must be non negative");
+ }
+ return tabs(Arrays.asList(tabsize));
+ }
+
+ public AttributedStringBuilder tabs(List<Integer> tabs) {
if (length > 0) {
throw new IllegalStateException("Cannot change tab size after appending text");
}
- if (tabsize < 0) {
- throw new IllegalArgumentException("Tab size must be non negative");
- }
- this.tabs = tabsize;
+ this.tabs = new TabStops(tabs);
return this;
}
@@ -393,4 +399,60 @@
return this;
}
+ public AttributedStringBuilder styleMatches(Pattern pattern, List<AttributedStyle> styles) {
+ Matcher matcher = pattern.matcher(this);
+ while (matcher.find()) {
+ for (int group = 0; group < matcher.groupCount(); group++) {
+ AttributedStyle s = styles.get(group);
+ for (int i = matcher.start(group + 1); i < matcher.end(group + 1); i++) {
+ style[i] = (style[i] & ~s.getMask()) | s.getStyle();
+ }
+ }
+ }
+ return this;
+ }
+
+ private class TabStops {
+ private List<Integer> tabs = new ArrayList<>();
+ private int lastStop = 0;
+ private int lastSize = 0;
+
+ public TabStops(int tabs) {
+ this.lastSize = tabs;
+ }
+
+ public TabStops(List<Integer> tabs) {
+ this.tabs = tabs;
+ int p = 0;
+ for (int s: tabs) {
+ if (s <= p) {
+ continue;
+ }
+ lastStop = s;
+ lastSize = s - p;
+ p = s;
+ }
+ }
+
+ boolean defined() {
+ return lastSize > 0;
+ }
+
+ int spaces(int lastLineLength) {
+ int out = 0;
+ if (lastLineLength >= lastStop) {
+ out = lastSize - (lastLineLength - lastStop) % lastSize;
+ } else {
+ for (int s: tabs) {
+ if (s > lastLineLength) {
+ out = s - lastLineLength;
+ break;
+ }
+ }
+ }
+ return out;
+ }
+
+ }
+
}
--- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/AttributedStyle.java Mon Nov 04 14:26:18 2019 +0800
+++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/AttributedStyle.java Mon Nov 04 09:40:35 2019 +0100
@@ -4,7 +4,7 @@
* This software is distributable under the BSD license. See the terms of the
* BSD license in the documentation provided with this software.
*
- * http://www.opensource.org/licenses/bsd-license.php
+ * https://opensource.org/licenses/BSD-3-Clause
*/
package jdk.internal.org.jline.utils;
--- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/ClosedException.java Mon Nov 04 14:26:18 2019 +0800
+++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/ClosedException.java Mon Nov 04 09:40:35 2019 +0100
@@ -4,7 +4,7 @@
* This software is distributable under the BSD license. See the terms of the
* BSD license in the documentation provided with this software.
*
- * http://www.opensource.org/licenses/bsd-license.php
+ * https://opensource.org/licenses/BSD-3-Clause
*/
package jdk.internal.org.jline.utils;
--- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/Colors.java Mon Nov 04 14:26:18 2019 +0800
+++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/Colors.java Mon Nov 04 09:40:35 2019 +0100
@@ -4,7 +4,7 @@
* This software is distributable under the BSD license. See the terms of the
* BSD license in the documentation provided with this software.
*
- * http://www.opensource.org/licenses/bsd-license.php
+ * https://opensource.org/licenses/BSD-3-Clause
*/
package jdk.internal.org.jline.utils;
--- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/Curses.java Mon Nov 04 14:26:18 2019 +0800
+++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/Curses.java Mon Nov 04 09:40:35 2019 +0100
@@ -4,7 +4,7 @@
* This software is distributable under the BSD license. See the terms of the
* BSD license in the documentation provided with this software.
*
- * http://www.opensource.org/licenses/bsd-license.php
+ * https://opensource.org/licenses/BSD-3-Clause
*/
package jdk.internal.org.jline.utils;
@@ -74,8 +74,16 @@
switch (ch) {
case '\\':
ch = str.charAt(index++);
- if (ch >= '0' && ch <= '9') {
- throw new UnsupportedOperationException(); // todo
+ if (ch >= '0' && ch <= '7') {
+ int val = ch - '0';
+ for (int i = 0; i < 2; i++) {
+ ch = str.charAt(index++);
+ if (ch < '0' || ch > '7') {
+ throw new IllegalStateException();
+ }
+ val = val * 8 + (ch - '0');
+ }
+ out.append((char) val);
} else {
switch (ch) {
case 'e':
--- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/DiffHelper.java Mon Nov 04 14:26:18 2019 +0800
+++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/DiffHelper.java Mon Nov 04 09:40:35 2019 +0100
@@ -4,7 +4,7 @@
* This software is distributable under the BSD license. See the terms of the
* BSD license in the documentation provided with this software.
*
- * http://www.opensource.org/licenses/bsd-license.php
+ * https://opensource.org/licenses/BSD-3-Clause
*/
package jdk.internal.org.jline.utils;
--- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/Display.java Mon Nov 04 14:26:18 2019 +0800
+++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/Display.java Mon Nov 04 09:40:35 2019 +0100
@@ -4,7 +4,7 @@
* This software is distributable under the BSD license. See the terms of the
* BSD license in the documentation provided with this software.
*
- * http://www.opensource.org/licenses/bsd-license.php
+ * https://opensource.org/licenses/BSD-3-Clause
*/
package jdk.internal.org.jline.utils;
@@ -492,7 +492,7 @@
}
void rawPrint(AttributedString str) {
- terminal.writer().write(str.toAnsi(terminal));
+ str.print(terminal);
}
public int wcwidth(String str) {
--- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/ExecHelper.java Mon Nov 04 14:26:18 2019 +0800
+++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/ExecHelper.java Mon Nov 04 09:40:35 2019 +0100
@@ -4,7 +4,7 @@
* This software is distributable under the BSD license. See the terms of the
* BSD license in the documentation provided with this software.
*
- * http://www.opensource.org/licenses/bsd-license.php
+ * https://opensource.org/licenses/BSD-3-Clause
*/
package jdk.internal.org.jline.utils;
--- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/InfoCmp.java Mon Nov 04 14:26:18 2019 +0800
+++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/InfoCmp.java Mon Nov 04 09:40:35 2019 +0100
@@ -1,10 +1,10 @@
/*
- * Copyright (c) 2002-2016, 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.
*
- * http://www.opensource.org/licenses/bsd-license.php
+ * https://opensource.org/licenses/BSD-3-Clause
*/
package jdk.internal.org.jline.utils;
@@ -578,6 +578,8 @@
int iVal;
if (val.startsWith("0x")) {
iVal = Integer.parseInt(val.substring(2), 16);
+ } else if (val.startsWith("0")) {
+ iVal = Integer.parseInt(val.substring(1), 8);
} else {
iVal = Integer.parseInt(val);
}
@@ -614,7 +616,7 @@
static {
for (String s : Arrays.asList("dumb", "ansi", "xterm", "xterm-256color",
- "windows", "windows-256color", "windows-vtp",
+ "windows", "windows-256color", "windows-conemu", "windows-vtp",
"screen", "screen-256color")) {
setDefaultInfoCmp(s, () -> loadDefaultInfoCmp(s));
}
--- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/InputStreamReader.java Mon Nov 04 14:26:18 2019 +0800
+++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/InputStreamReader.java Mon Nov 04 09:40:35 2019 +0100
@@ -4,7 +4,7 @@
* This software is distributable under the BSD license. See the terms of the
* BSD license in the documentation provided with this software.
*
- * http://www.opensource.org/licenses/bsd-license.php
+ * https://opensource.org/licenses/BSD-3-Clause
*/
package jdk.internal.org.jline.utils;
--- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/Levenshtein.java Mon Nov 04 14:26:18 2019 +0800
+++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/Levenshtein.java Mon Nov 04 09:40:35 2019 +0100
@@ -4,7 +4,7 @@
* This software is distributable under the BSD license. See the terms of the
* BSD license in the documentation provided with this software.
*
- * http://www.opensource.org/licenses/bsd-license.php
+ * https://opensource.org/licenses/BSD-3-Clause
*/
package jdk.internal.org.jline.utils;
--- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/Log.java Mon Nov 04 14:26:18 2019 +0800
+++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/Log.java Mon Nov 04 09:40:35 2019 +0100
@@ -4,7 +4,7 @@
* This software is distributable under the BSD license. See the terms of the
* BSD license in the documentation provided with this software.
*
- * http://www.opensource.org/licenses/bsd-license.php
+ * https://opensource.org/licenses/BSD-3-Clause
*/
package jdk.internal.org.jline.utils;
--- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/NonBlocking.java Mon Nov 04 14:26:18 2019 +0800
+++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/NonBlocking.java Mon Nov 04 09:40:35 2019 +0100
@@ -4,7 +4,7 @@
* This software is distributable under the BSD license. See the terms of the
* BSD license in the documentation provided with this software.
*
- * http://www.opensource.org/licenses/bsd-license.php
+ * https://opensource.org/licenses/BSD-3-Clause
*/
package jdk.internal.org.jline.utils;
--- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/NonBlockingInputStream.java Mon Nov 04 14:26:18 2019 +0800
+++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/NonBlockingInputStream.java Mon Nov 04 09:40:35 2019 +0100
@@ -4,7 +4,7 @@
* This software is distributable under the BSD license. See the terms of the
* BSD license in the documentation provided with this software.
*
- * http://www.opensource.org/licenses/bsd-license.php
+ * https://opensource.org/licenses/BSD-3-Clause
*/
package jdk.internal.org.jline.utils;
--- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/NonBlockingInputStreamImpl.java Mon Nov 04 14:26:18 2019 +0800
+++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/NonBlockingInputStreamImpl.java Mon Nov 04 09:40:35 2019 +0100
@@ -4,7 +4,7 @@
* This software is distributable under the BSD license. See the terms of the
* BSD license in the documentation provided with this software.
*
- * http://www.opensource.org/licenses/bsd-license.php
+ * https://opensource.org/licenses/BSD-3-Clause
*/
package jdk.internal.org.jline.utils;
--- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/NonBlockingPumpInputStream.java Mon Nov 04 14:26:18 2019 +0800
+++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/NonBlockingPumpInputStream.java Mon Nov 04 09:40:35 2019 +0100
@@ -4,7 +4,7 @@
* This software is distributable under the BSD license. See the terms of the
* BSD license in the documentation provided with this software.
*
- * http://www.opensource.org/licenses/bsd-license.php
+ * https://opensource.org/licenses/BSD-3-Clause
*/
package jdk.internal.org.jline.utils;
--- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/NonBlockingPumpReader.java Mon Nov 04 14:26:18 2019 +0800
+++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/NonBlockingPumpReader.java Mon Nov 04 09:40:35 2019 +0100
@@ -4,7 +4,7 @@
* This software is distributable under the BSD license. See the terms of the
* BSD license in the documentation provided with this software.
*
- * http://www.opensource.org/licenses/bsd-license.php
+ * https://opensource.org/licenses/BSD-3-Clause
*/
package jdk.internal.org.jline.utils;
--- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/NonBlockingReader.java Mon Nov 04 14:26:18 2019 +0800
+++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/NonBlockingReader.java Mon Nov 04 09:40:35 2019 +0100
@@ -4,7 +4,7 @@
* This software is distributable under the BSD license. See the terms of the
* BSD license in the documentation provided with this software.
*
- * http://www.opensource.org/licenses/bsd-license.php
+ * https://opensource.org/licenses/BSD-3-Clause
*/
package jdk.internal.org.jline.utils;
--- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/NonBlockingReaderImpl.java Mon Nov 04 14:26:18 2019 +0800
+++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/NonBlockingReaderImpl.java Mon Nov 04 09:40:35 2019 +0100
@@ -4,7 +4,7 @@
* This software is distributable under the BSD license. See the terms of the
* BSD license in the documentation provided with this software.
*
- * http://www.opensource.org/licenses/bsd-license.php
+ * https://opensource.org/licenses/BSD-3-Clause
*/
package jdk.internal.org.jline.utils;
--- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/OSUtils.java Mon Nov 04 14:26:18 2019 +0800
+++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/OSUtils.java Mon Nov 04 09:40:35 2019 +0100
@@ -4,7 +4,7 @@
* This software is distributable under the BSD license. See the terms of the
* BSD license in the documentation provided with this software.
*
- * http://www.opensource.org/licenses/bsd-license.php
+ * https://opensource.org/licenses/BSD-3-Clause
*/
package jdk.internal.org.jline.utils;
--- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/PumpReader.java Mon Nov 04 14:26:18 2019 +0800
+++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/PumpReader.java Mon Nov 04 09:40:35 2019 +0100
@@ -4,7 +4,7 @@
* This software is distributable under the BSD license. See the terms of the
* BSD license in the documentation provided with this software.
*
- * http://www.opensource.org/licenses/bsd-license.php
+ * https://opensource.org/licenses/BSD-3-Clause
*/
package jdk.internal.org.jline.utils;
--- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/ShutdownHooks.java Mon Nov 04 14:26:18 2019 +0800
+++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/ShutdownHooks.java Mon Nov 04 09:40:35 2019 +0100
@@ -4,7 +4,7 @@
* This software is distributable under the BSD license. See the terms of the
* BSD license in the documentation provided with this software.
*
- * http://www.opensource.org/licenses/bsd-license.php
+ * https://opensource.org/licenses/BSD-3-Clause
*/
package jdk.internal.org.jline.utils;
--- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/Signals.java Mon Nov 04 14:26:18 2019 +0800
+++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/Signals.java Mon Nov 04 09:40:35 2019 +0100
@@ -4,10 +4,11 @@
* This software is distributable under the BSD license. See the terms of the
* BSD license in the documentation provided with this software.
*
- * http://www.opensource.org/licenses/bsd-license.php
+ * https://opensource.org/licenses/BSD-3-Clause
*/
package jdk.internal.org.jline.utils;
+import java.lang.reflect.Constructor;
import java.lang.reflect.Proxy;
import java.util.Objects;
@@ -85,13 +86,16 @@
private static Object doRegister(String name, Object handler) throws Exception {
Log.trace(() -> "Registering signal " + name + " with handler " + toString(handler));
- if ("QUIT".equals(name) || "INFO".equals(name) && "9".equals(System.getProperty("java.specification.version"))) {
+ Class<?> signalClass = Class.forName("sun.misc.Signal");
+ Constructor<?> constructor = signalClass.getConstructor(String.class);
+ Object signal;
+ try {
+ signal = constructor.newInstance(name);
+ } catch (IllegalArgumentException e) {
Log.trace(() -> "Ignoring unsupported signal " + name);
return null;
}
- Class<?> signalClass = Class.forName("sun.misc.Signal");
Class<?> signalHandlerClass = Class.forName("sun.misc.SignalHandler");
- Object signal = signalClass.getConstructor(String.class).newInstance(name);
return signalClass.getMethod("handle", signalClass, signalHandlerClass)
.invoke(null, signal, handler);
}
--- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/Status.java Mon Nov 04 14:26:18 2019 +0800
+++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/Status.java Mon Nov 04 09:40:35 2019 +0100
@@ -4,7 +4,7 @@
* This software is distributable under the BSD license. See the terms of the
* BSD license in the documentation provided with this software.
*
- * http://www.opensource.org/licenses/bsd-license.php
+ * https://opensource.org/licenses/BSD-3-Clause
*/
package jdk.internal.org.jline.utils;
@@ -24,9 +24,11 @@
protected final AbstractTerminal terminal;
protected final boolean supported;
protected List<AttributedString> oldLines = Collections.emptyList();
+ protected List<AttributedString> linesToRestore = Collections.emptyList();
protected int rows;
protected int columns;
protected boolean force;
+ protected boolean suspended = false;
public static Status getStatus(Terminal terminal) {
return getStatus(terminal, true);
@@ -61,15 +63,34 @@
this.force = true;
}
+ public void hardReset() {
+ if (suspended) {
+ return;
+ }
+ List<AttributedString> lines = new ArrayList<>(oldLines);
+ update(null);
+ update(lines);
+ }
+
public void redraw() {
+ if (suspended) {
+ return;
+ }
update(oldLines);
}
public void update(List<AttributedString> lines) {
+ if (!supported) {
+ return;
+ }
if (lines == null) {
lines = Collections.emptyList();
}
- if (!supported || (oldLines.equals(lines) && !force)) {
+ if (suspended) {
+ linesToRestore = new ArrayList<>(lines);
+ return;
+ }
+ if (oldLines.equals(lines) && !force) {
return;
}
int nb = lines.size() - oldLines.size();
@@ -82,10 +103,11 @@
}
}
terminal.puts(Capability.save_cursor);
+ terminal.puts(Capability.cursor_address, rows - lines.size(), 0);
terminal.puts(Capability.clr_eos);
for (int i = 0; i < lines.size(); i++) {
terminal.puts(Capability.cursor_address, rows - lines.size() + i, 0);
- terminal.writer().write(lines.get(i).columnSubSequence(0, columns).toAnsi(terminal));
+ lines.get(i).columnSubSequence(0, columns).print(terminal);
}
terminal.puts(Capability.change_scroll_region, 0, rows - 1 - lines.size());
terminal.puts(Capability.restore_cursor);
@@ -93,4 +115,27 @@
oldLines = new ArrayList<>(lines);
force = false;
}
+
+ public void suspend() {
+ if (suspended) {
+ return;
+ }
+ linesToRestore = new ArrayList<>(oldLines);
+ update(null);
+ suspended = true;
+ }
+
+ public void restore() {
+ if (!suspended) {
+ return;
+ }
+ suspended = false;
+ update(linesToRestore);
+ linesToRestore = Collections.emptyList();
+ }
+
+ public int size() {
+ return oldLines.size();
+ }
+
}
--- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/StyleResolver.java Mon Nov 04 14:26:18 2019 +0800
+++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/StyleResolver.java Mon Nov 04 09:40:35 2019 +0100
@@ -4,7 +4,7 @@
* This software is distributable under the BSD license. See the terms of the
* BSD license in the documentation provided with this software.
*
- * http://www.opensource.org/licenses/bsd-license.php
+ * https://opensource.org/licenses/BSD-3-Clause
*/
package jdk.internal.org.jline.utils;
--- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/WCWidth.java Mon Nov 04 14:26:18 2019 +0800
+++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/WCWidth.java Mon Nov 04 09:40:35 2019 +0100
@@ -4,7 +4,7 @@
* This software is distributable under the BSD license. See the terms of the
* BSD license in the documentation provided with this software.
*
- * http://www.opensource.org/licenses/bsd-license.php
+ * https://opensource.org/licenses/BSD-3-Clause
*/
package jdk.internal.org.jline.utils;
--- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/WriterOutputStream.java Mon Nov 04 14:26:18 2019 +0800
+++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/WriterOutputStream.java Mon Nov 04 09:40:35 2019 +0100
@@ -4,7 +4,7 @@
* This software is distributable under the BSD license. See the terms of the
* BSD license in the documentation provided with this software.
*
- * http://www.opensource.org/licenses/bsd-license.php
+ * https://opensource.org/licenses/BSD-3-Clause
*/
package jdk.internal.org.jline.utils;
--- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/capabilities.txt Mon Nov 04 14:26:18 2019 +0800
+++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/capabilities.txt Mon Nov 04 09:40:35 2019 +0100
@@ -4,7 +4,7 @@
# This software is distributable under the BSD license. See the terms of the
# BSD license in the documentation provided with this software.
#
-# http://www.opensource.org/licenses/bsd-license.php
+# https://opensource.org/licenses/BSD-3-Clause
#
auto_left_margin, bw, bw
--- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/colors.txt Mon Nov 04 14:26:18 2019 +0800
+++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/colors.txt Mon Nov 04 09:40:35 2019 +0100
@@ -4,7 +4,7 @@
# This software is distributable under the BSD license. See the terms of the
# BSD license in the documentation provided with this software.
#
-# http://www.opensource.org/licenses/bsd-license.php
+# https://opensource.org/licenses/BSD-3-Clause
#
black
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/dumb-colors.caps Mon Nov 04 09:40:35 2019 +0100
@@ -0,0 +1,4 @@
+dumb-color|80-column dumb tty with 256 coors,
+ am,
+ colors#256, cols#80,
+ bel=^G, cr=^M, cud1=^J, ind=^J,
--- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/package-info.java Mon Nov 04 14:26:18 2019 +0800
+++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/package-info.java Mon Nov 04 09:40:35 2019 +0100
@@ -4,7 +4,7 @@
* This software is distributable under the BSD license. See the terms of the
* BSD license in the documentation provided with this software.
*
- * http://www.opensource.org/licenses/bsd-license.php
+ * https://opensource.org/licenses/BSD-3-Clause
*/
/**
* JLine 3.
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/windows-conemu.caps Mon Nov 04 09:40:35 2019 +0100
@@ -0,0 +1,27 @@
+windows-conemu|conemu windows terminal,
+ am, mc5i, mir, msgr,
+ colors#256, cols#80, it#8, lines#24, ncv#3, pairs#64,
+ bel=^G, blink=\E[5m, bold=\E[1m, cbt=\E[Z, clear=\E[H\E[J,
+ cr=^M, cub=\E[%p1%dD, cub1=\E[D, cud=\E[%p1%dB, cud1=\E[B,
+ cuf=\E[%p1%dC, cuf1=\E[C, cup=\E[%i%p1%d;%p2%dH,
+ cuu=\E[%p1%dA, cuu1=\E[A,
+ il=\E[%p1%dL, il1=\E[L,
+ dl=\E[%p1%dM, dl1=\E[M,
+ ech=\E[%p1%dX,
+ el=\E[K, ed=\E[2K,
+ el1=\E[1K, home=\E[H, hpa=\E[%i%p1%dG,
+ ind=^J,
+ invis=\E[8m, kbs=^H, kcbt=\E[Z,
+ kcub1=\EOD, kcud1=\EOB, kcuf1=\EOC, kcuu1=\EOA,
+ khome=\E[H,
+ op=\E[39;49m,
+ rev=\E[7m,
+ rmacs=\E[10m, rmpch=\E[10m, rmso=\E[m, rmul=\E[m,
+ setab=\E[4%p1%dm, setaf=\E[3%p1%dm,
+ sgr=\E[0;10%?%p1%t;7%;%?%p2%t;4%;%?%p3%t;7%;%?%p4%t;5%;%?%p6%t;1%;%?%p7%t;8%;%?%p9%t;11%;m,
+ sgr0=\E[0;10m,
+ smso=\E[7m,
+ smul=\E[4m,
+ kdch1=\E[3~, kich1=\E[2~, kend=\E[4~, knp=\E[6~, kpp=\E[5~,
+ kf1=\EOP, kf2=\EOQ, kf3=\EOR, kf4=\EOS, kf5=\E[15~, kf6=\E[17~,
+ kf7=\E[18~, kf8=\E[19~, kf9=\E[20~, kf10=\E[21~, kf11=\E[23~, kf12=\E[24~,
--- a/src/jdk.internal.le/share/legal/jline.md Mon Nov 04 14:26:18 2019 +0800
+++ b/src/jdk.internal.le/share/legal/jline.md Mon Nov 04 09:40:35 2019 +0100
@@ -1,4 +1,4 @@
-## JLine v3.9.0
+## JLine v3.12.1
### JLine License
<pre>
--- a/src/jdk.internal.le/windows/classes/jdk/internal/org/jline/terminal/impl/jna/JnaSupportImpl.java Mon Nov 04 14:26:18 2019 +0800
+++ b/src/jdk.internal.le/windows/classes/jdk/internal/org/jline/terminal/impl/jna/JnaSupportImpl.java Mon Nov 04 09:40:35 2019 +0100
@@ -1,3 +1,11 @@
+/*
+ * Copyright (c) 2002-2018, 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.
+ *
+ * https://opensource.org/licenses/BSD-3-Clause
+ */
package jdk.internal.org.jline.terminal.impl.jna;
import jdk.internal.org.jline.terminal.Attributes;
--- a/src/jdk.internal.le/windows/classes/jdk/internal/org/jline/terminal/impl/jna/win/JnaWinConsoleWriter.java Mon Nov 04 14:26:18 2019 +0800
+++ b/src/jdk.internal.le/windows/classes/jdk/internal/org/jline/terminal/impl/jna/win/JnaWinConsoleWriter.java Mon Nov 04 09:40:35 2019 +0100
@@ -4,7 +4,7 @@
* This software is distributable under the BSD license. See the terms of the
* BSD license in the documentation provided with this software.
*
- * http://www.opensource.org/licenses/bsd-license.php
+ * https://opensource.org/licenses/BSD-3-Clause
*/
package jdk.internal.org.jline.terminal.impl.jna.win;
--- a/src/jdk.internal.le/windows/classes/jdk/internal/org/jline/terminal/impl/jna/win/JnaWinSysTerminal.java Mon Nov 04 14:26:18 2019 +0800
+++ b/src/jdk.internal.le/windows/classes/jdk/internal/org/jline/terminal/impl/jna/win/JnaWinSysTerminal.java Mon Nov 04 09:40:35 2019 +0100
@@ -1,10 +1,10 @@
/*
- * 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.
*
- * http://www.opensource.org/licenses/bsd-license.php
+ * https://opensource.org/licenses/BSD-3-Clause
*/
package jdk.internal.org.jline.terminal.impl.jna.win;
@@ -36,7 +36,7 @@
Writer writer;
if (ansiPassThrough) {
if (type == null) {
- type = OSUtils.IS_CONEMU ? TYPE_WINDOWS_256_COLOR : TYPE_WINDOWS;
+ type = OSUtils.IS_CONEMU ? TYPE_WINDOWS_CONEMU : TYPE_WINDOWS;
}
writer = new JnaWinConsoleWriter(consoleOut);
} else {
@@ -51,7 +51,7 @@
} catch (LastErrorException e) {
if (OSUtils.IS_CONEMU) {
if (type == null) {
- type = TYPE_WINDOWS_256_COLOR;
+ type = TYPE_WINDOWS_CONEMU;
}
writer = new JnaWinConsoleWriter(consoleOut);
} else {
@@ -95,6 +95,12 @@
public Size getSize() {
Kernel32.CONSOLE_SCREEN_BUFFER_INFO info = new Kernel32.CONSOLE_SCREEN_BUFFER_INFO();
Kernel32.INSTANCE.GetConsoleScreenBufferInfo(consoleOut, info);
+ return new Size(info.windowWidth(), info.windowHeight());
+ }
+
+ public Size getBufferSize() {
+ Kernel32.CONSOLE_SCREEN_BUFFER_INFO info = new Kernel32.CONSOLE_SCREEN_BUFFER_INFO();
+ Kernel32.INSTANCE.GetConsoleScreenBufferInfo(consoleOut, info);
return new Size(info.dwSize.X, info.dwSize.Y);
}
--- a/src/jdk.internal.le/windows/classes/jdk/internal/org/jline/terminal/impl/jna/win/Kernel32.java Mon Nov 04 14:26:18 2019 +0800
+++ b/src/jdk.internal.le/windows/classes/jdk/internal/org/jline/terminal/impl/jna/win/Kernel32.java Mon Nov 04 09:40:35 2019 +0100
@@ -4,7 +4,7 @@
* This software is distributable under the BSD license. See the terms of the
* BSD license in the documentation provided with this software.
*
- * http://www.opensource.org/licenses/bsd-license.php
+ * https://opensource.org/licenses/BSD-3-Clause
*/
package jdk.internal.org.jline.terminal.impl.jna.win;
@@ -26,7 +26,7 @@
interface Kernel32 {//extends StdCallLibrary {
Kernel32 INSTANCE = new Kernel32Impl();
-// Kernel32 INSTANCE = (Kernel32) Native.loadLibrary("kernel32", Kernel32.class, W32APIOptions.UNICODE_OPTIONS);
+// Kernel32 INSTANCE = Native.load("kernel32", Kernel32.class, W32APIOptions.UNICODE_OPTIONS);
// Pointer INVALID_HANDLE_VALUE = Pointer.createConstant(-1L);
--- a/src/jdk.internal.le/windows/classes/jdk/internal/org/jline/terminal/impl/jna/win/WindowsAnsiWriter.java Mon Nov 04 14:26:18 2019 +0800
+++ b/src/jdk.internal.le/windows/classes/jdk/internal/org/jline/terminal/impl/jna/win/WindowsAnsiWriter.java Mon Nov 04 09:40:35 2019 +0100
@@ -4,7 +4,7 @@
* This software is distributable under the BSD license. See the terms of the
* BSD license in the documentation provided with this software.
*
- * http://www.opensource.org/licenses/bsd-license.php
+ * https://opensource.org/licenses/BSD-3-Clause
*/
package jdk.internal.org.jline.terminal.impl.jna.win;