8229815: Upgrade Jline to 3.12.1

Reviewed-by: rfield
This commit is contained in:
Jan Lahoda 2019-11-04 09:40:35 +01:00
parent a66829bc89
commit a9952bb5d9
103 changed files with 1387 additions and 627 deletions

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;
@ -41,6 +42,26 @@ public interface History extends Iterable<History.Entry>
*/
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

View File

@ -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 @@ public interface LineReader {
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";

View File

@ -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 final class LineReaderBuilder {
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.");

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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 @@ public interface Parser {
return parse(line, cursor, ParseContext.UNSPECIFIED);
}
default boolean isEscapeChar(char ch) {
return ch == '\\';
}
enum ParseContext {
UNSPECIFIED,

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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 @@ import jdk.internal.org.jline.reader.Parser;
public class DefaultParser implements Parser {
public enum Bracket {
ROUND, // ()
CURLY, // {}
SQUARE, // []
ANGLE; // <>
}
private char[] quoteChars = {'\'', '"'};
private char[] escapeChars = {'\\'};
@ -26,6 +33,10 @@ public class DefaultParser implements Parser {
private boolean eofOnEscapedNewLine;
private char[] openingBrackets = null;
private char[] closingBrackets = null;
//
// Chainable setters
//
@ -45,6 +56,11 @@ public class DefaultParser implements Parser {
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 @@ public class DefaultParser implements Parser {
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 @@ public class DefaultParser implements Parser {
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,25 +161,22 @@ public class DefaultParser implements Parser {
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
words.add(current.toString());
current.setLength(0);
quoteStart = -1;
if (rawWordCursor >= 0 && rawWordLength < 0) {
rawWordLength = i - rawWordStart + 1;
}
if (current.length()==0) {
quotedWord = true;
} else {
if (!isEscapeChar(line, i)) {
// Take the next character
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;
}
} else {
// Not in a quote block
if (isDelimiter(line, i)) {
quoteStart = -1;
quotedWord = false;
} else if (quoteStart < 0 && isDelimiter(line, i)) {
// Delimiter
if (current.length() > 0) {
words.add(current.toString());
current.setLength(0); // reset the arg
@ -140,6 +188,8 @@ public class DefaultParser implements Parser {
} else {
if (!isEscapeChar(line, i)) {
current.append(line.charAt(i));
if (quoteStart < 0) {
bracketChecker.check(line, i);
}
}
}
@ -159,21 +209,29 @@ public class DefaultParser implements Parser {
rawWordLength = rawWordCursor;
}
if (context != ParseContext.COMPLETE) {
if (eofOnEscapedNewLine && isEscapeChar(line, line.length() - 1)) {
throw new EOFError(-1, -1, "Escaped new line", "newline");
}
if (eofOnUnclosedQuote && quoteStart >= 0 && context != ParseContext.COMPLETE) {
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 @@ public class DefaultParser implements Parser {
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 @@ public class DefaultParser implements Parser {
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 @@ public class DefaultParser implements Parser {
/**
* 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 @@ public class DefaultParser implements Parser {
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,12 +492,28 @@ public class DefaultParser implements Parser {
public CharSequence escape(CharSequence candidate, boolean complete) {
StringBuilder sb = new StringBuilder(candidate);
Predicate<Integer> needToBeEscaped;
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 (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 {
@ -383,10 +524,18 @@ public class DefaultParser implements Parser {
sb.insert(i++, escapeChars[0]);
}
}
if (openingQuote != null) {
sb.insert(0, openingQuote);
} 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;

View File

@ -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;

View File

@ -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.time.Instant;
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.*;
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 @@ public class LineReaderImpl implements LineReader, Flushable
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 @@ public class LineReaderImpl implements LineReader, Flushable
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 @@ public class LineReaderImpl implements LineReader, Flushable
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 @@ public class LineReaderImpl implements LineReader, Flushable
builtinWidgets = builtinWidgets();
widgets = new HashMap<>(builtinWidgets);
bindingReader = new BindingReader(terminal.reader());
doDisplay();
}
public Terminal getTerminal() {
@ -467,8 +481,7 @@ public class LineReaderImpl implements LineReader, Flushable
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 @@ public class LineReaderImpl implements LineReader, Flushable
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 @@ public class LineReaderImpl implements LineReader, Flushable
history.attach(this);
}
synchronized (this) {
try {
lock.lock();
this.reading = true;
previousIntrHandler = terminal.handle(Signal.INT, signal -> readLineThread.interrupt());
@ -511,18 +537,7 @@ public class LineReaderImpl implements LineReader, Flushable
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 @@ public class LineReaderImpl implements LineReader, Flushable
// Draw initial prompt
redrawLine();
redisplay();
} finally {
lock.unlock();
}
while (true) {
@ -578,7 +595,8 @@ public class LineReaderImpl implements LineReader, Flushable
regionActive = RegionType.NONE;
}
synchronized (this) {
try {
lock.lock();
// Get executable widget
Buffer copy = buf.copy();
Widget w = getWidget(o);
@ -610,6 +628,8 @@ public class LineReaderImpl implements LineReader, Flushable
if (!dumb) {
redisplay();
}
} finally {
lock.unlock();
}
}
} catch (IOError e) {
@ -620,7 +640,9 @@ public class LineReaderImpl implements LineReader, Flushable
}
}
finally {
synchronized (this) {
try {
lock.lock();
this.reading = false;
cleanup();
@ -636,18 +658,43 @@ public class LineReaderImpl implements LineReader, Flushable
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) {
public void printAbove(String str) {
try {
lock.lock();
boolean reading = this.reading;
if (reading) {
display.update(Collections.emptyList(), 0);
}
if (str.endsWith("\n")) {
if (str.endsWith("\n") || str.endsWith("\n\033[m") || str.endsWith("\n\033[0m")) {
terminal.writer().print(str);
} else {
terminal.writer().println(str);
@ -656,6 +703,9 @@ public class LineReaderImpl implements LineReader, Flushable
redisplay(false);
}
terminal.flush();
} finally {
lock.unlock();
}
}
@Override
@ -664,8 +714,13 @@ public class LineReaderImpl implements LineReader, Flushable
}
@Override
public synchronized boolean isReading() {
public boolean isReading() {
try {
lock.lock();
return reading;
} finally {
lock.unlock();
}
}
/* Make sure we position the cursor on column 0 */
@ -700,12 +755,14 @@ public class LineReaderImpl implements LineReader, Flushable
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) {
public void callWidget(String name) {
try {
lock.lock();
if (!reading) {
throw new IllegalStateException("Widgets can only be called during a `readLine` call");
}
@ -722,6 +779,9 @@ public class LineReaderImpl implements LineReader, Flushable
} catch (Throwable t) {
Log.debug("Error executing widget '", name, "'", t);
}
} finally {
lock.unlock();
}
}
/**
@ -760,13 +820,35 @@ public class LineReaderImpl implements LineReader, Flushable
* @return the character, or -1 if an EOF is received.
*/
public int 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 class LineReaderImpl implements LineReader, Flushable
}
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 @@ public class LineReaderImpl implements LineReader, Flushable
if (ch != '\n') {
sb.append(ch);
}
} else if (ch == '\\') {
} else if (parser.isEscapeChar(ch)) {
escaped = true;
} else {
sb.append(ch);
@ -948,13 +1030,18 @@ public class LineReaderImpl implements LineReader, Flushable
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 @@ public class LineReaderImpl implements LineReader, Flushable
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 @@ public class LineReaderImpl implements LineReader, Flushable
} 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 @@ public class LineReaderImpl implements LineReader, Flushable
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,158 +3466,181 @@ public class LineReaderImpl implements LineReader, Flushable
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) {
protected void redisplay(boolean flush) {
try {
lock.lock();
if (skipRedisplay) {
skipRedisplay = false;
return;
@ -3515,7 +3661,7 @@ public class LineReaderImpl implements LineReader, Flushable
sb.setLength(0);
sb.append(prompt);
String line = buf.upToCursor();
if(maskingCallback != null) {
if (maskingCallback != null) {
line = maskingCallback.display(line);
}
@ -3525,7 +3671,7 @@ public class LineReaderImpl implements LineReader, Flushable
int w = WCWidth.wcwidth('\u2026');
int width = size.getColumns();
int cursor = toCursor.columnLength();
int inc = width /2 + 1;
int inc = width / 2 + 1;
while (cursor <= smallTerminalOffset + w) {
smallTerminalOffset -= inc;
}
@ -3576,6 +3722,8 @@ public class LineReaderImpl implements LineReader, Flushable
}
int cursorPos = -1;
int cursorNewLinesId = -1;
int cursorColPos = -1;
if (size.getColumns() > 0) {
AttributedStringBuilder sb = new AttributedStringBuilder().tabs(TAB_WIDTH);
sb.append(prompt);
@ -3586,12 +3734,49 @@ public class LineReaderImpl implements LineReader, Flushable
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());
cursorNewLinesId = promptLines.size() - 1;
cursorColPos = promptLines.get(promptLines.size() - 1).columnLength();
cursorPos = size.cursorPos(cursorNewLinesId, cursorColPos);
}
}
display.update(newLines, cursorPos, flush);
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) {
@ -4048,7 +4233,8 @@ public class LineReaderImpl implements LineReader, Flushable
if (matching.isEmpty()) {
return false;
}
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()
@ -4155,6 +4341,9 @@ public class LineReaderImpl implements LineReader, Flushable
doMenu(possible, line.word(), line::escape);
}
return true;
} finally {
size.copy(terminal.getBufferSize());
}
}
private CompletingParsedLine wrap(ParsedLine line) {
@ -4534,7 +4723,7 @@ public class LineReaderImpl implements LineReader, Flushable
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 @@ public class LineReaderImpl implements LineReader, Flushable
}
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 @@ public class LineReaderImpl implements LineReader, Flushable
@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,9 +5174,11 @@ public class LineReaderImpl implements LineReader, Flushable
while (end < buf.length() && buf.atChar(end) != '\n') {
end++;
}
if (end < buf.length()) {
end++;
}
}
}
String killed = buf.substring(start, end);
buf.cursor(start);
buf.delete(end - start);
@ -5188,7 +5379,7 @@ public class LineReaderImpl implements LineReader, Flushable
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 class LineReaderImpl implements LineReader, Flushable
*/
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 class LineReaderImpl implements LineReader, Flushable
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 @@ public class LineReaderImpl implements LineReader, Flushable
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 @@ public class LineReaderImpl implements LineReader, Flushable
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 class LineReaderImpl implements LineReader, Flushable
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 @@ public class LineReaderImpl implements LineReader, Flushable
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));

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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 class StringsCompleter implements Completer
}
}
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;

View File

@ -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.

View File

@ -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 @@ public class DefaultHistory implements History {
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 @@ public class DefaultHistory implements History {
try {
load();
}
catch (IOException e) {
catch (IllegalArgumentException | IOException e) {
Log.warn("Failed to load history", e);
}
}
@ -84,12 +84,11 @@ public class DefaultHistory implements History {
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 @@ public class DefaultHistory implements History {
}
}
@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(':');
if (idx < 0) {
throw new IllegalArgumentException("Bad history file syntax! " +
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.");
"please remove it or use a different history file.";
if (idx < 0) {
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);
}
}
@ -124,29 +203,46 @@ public class DefaultHistory implements History {
}
}
@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 @@ public class DefaultHistory implements History {
}
Files.move(temp, path, StandardCopyOption.REPLACE_EXISTING);
// Keep items in memory
if (isLineReaderHistory(path)) {
internalClear();
offset = allItems.get(0).index();
items.addAll(allItems);
lastLoaded = items.size();
nbEntriesInFile = items.size();
setHistoryFileData(path, new HistoryFileData(items.size(), items.size()));
} else {
setEntriesInFile(path, allItems.size());
}
maybeResize();
}
@ -194,8 +293,7 @@ public class DefaultHistory implements History {
private void internalClear() {
offset = 0;
index = 0;
lastLoaded = 0;
nbEntriesInFile = 0;
historyFiles = new HashMap<>();
items.clear();
}
@ -302,7 +400,18 @@ public class DefaultHistory implements History {
}
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 @@ public class DefaultHistory implements History {
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 @@ public class DefaultHistory implements History {
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;
}
}
}

View File

@ -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.

View File

@ -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.

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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 @@ public interface Terminal extends Closeable, Flushable {
*
* @return The output stream
*
* @see #writer();
* @see #writer()
*/
OutputStream output();
@ -183,6 +183,11 @@ public interface Terminal extends Closeable, Flushable {
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 @@ public interface Terminal extends Closeable, Flushable {
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();
//

View File

@ -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.terminal.spi.Pty;
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.
*/

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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.ShutdownHooks;
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 abstract class AbstractWindowsTerminal extends AbstractTerminal {
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 @@ public abstract class AbstractWindowsTerminal extends AbstractTerminal {
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();

View File

@ -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;

View File

@ -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;

View File

@ -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 @@ public class ExecPty extends AbstractPty implements Pty {
}
String undef = System.getProperty("os.name").toLowerCase().startsWith("hp") ? "^-" : "undef";
for (ControlChar cchar : ControlChar.values()) {
if (attr.getControlChar(cchar) != current.getControlChar(cchar)) {
String str = "";
int v = attr.getControlChar(cchar);
if (v == -1) { // Skip if ControlChar is <UNDEF>
continue;
}
if (v >= 0 && v != current.getControlChar(cchar)) {
String str = "";
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);

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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.

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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 @@ public abstract class AttributedCharSequence implements CharSequence {
// 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 @@ public abstract class AttributedCharSequence implements CharSequence {
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 @@ public abstract class AttributedCharSequence implements CharSequence {
if (col + w > start) {
break;
}
begin++;
begin += Character.charCount(cp);
col += w;
}
int end = begin;
@ -305,7 +314,7 @@ public abstract class AttributedCharSequence implements CharSequence {
if (col + w > stop) {
break;
}
end++;
end += Character.charCount(cp);
col += w;
}
return subSequence(begin, end);

View File

@ -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 class AttributedString extends AttributedCharSequence {
}
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;
}

View File

@ -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 @@ public class AttributedStringBuilder extends AttributedCharSequence implements A
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 @@ public class AttributedStringBuilder extends AttributedCharSequence implements A
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 @@ public class AttributedStringBuilder extends AttributedCharSequence implements A
// 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 @@ public class AttributedStringBuilder extends AttributedCharSequence implements A
}
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 @@ public class AttributedStringBuilder extends AttributedCharSequence implements A
* @return this
*/
public AttributedStringBuilder tabs(int tabsize) {
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;
return tabs(Arrays.asList(tabsize));
}
public AttributedStringBuilder tabs(List<Integer> tabs) {
if (length > 0) {
throw new IllegalStateException("Cannot change tab size after appending text");
}
this.tabs = new TabStops(tabs);
return this;
}
@ -393,4 +399,60 @@ public class AttributedStringBuilder extends AttributedCharSequence implements A
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;
}
}
}

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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 @@ public final class Curses {
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':

View File

@ -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;

View File

@ -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 @@ public class Display {
}
void rawPrint(AttributedString str) {
terminal.writer().write(str.toAnsi(terminal));
str.print(terminal);
}
public int wcwidth(String str) {

View File

@ -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;

View File

@ -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 @@ public final class InfoCmp {
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 @@ public final class InfoCmp {
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));
}

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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 @@ public final class Signals {
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);
}

View File

@ -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 @@ public class Status {
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 @@ public class Status {
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 @@ public class Status {
}
}
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 @@ public class Status {
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();
}
}

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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

View File

@ -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

View File

@ -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,

View File

@ -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.

View File

@ -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~,

View File

@ -1,4 +1,4 @@
## JLine v3.9.0
## JLine v3.12.1
### JLine License
<pre>

View File

@ -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;

View File

@ -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;

Some files were not shown because too many files have changed in this diff Show More