All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.aspectran.shell.jline.console.JLineConsole Maven / Gradle / Ivy

There is a newer version: 8.1.5
Show newest version
/*
 * Copyright (c) 2008-2023 The Aspectran Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.aspectran.shell.jline.console;

import com.aspectran.shell.console.AbstractConsole;
import com.aspectran.shell.console.CommandReadFailedException;
import com.aspectran.shell.console.ConsoleTerminatedException;
import org.jline.reader.EndOfFileException;
import org.jline.reader.History;
import org.jline.reader.LineReader;
import org.jline.reader.LineReaderBuilder;
import org.jline.reader.UserInterruptException;
import org.jline.reader.impl.history.DefaultHistory;
import org.jline.terminal.Terminal;
import org.jline.terminal.TerminalBuilder;
import org.jline.utils.AttributedString;
import org.jline.utils.AttributedStyle;
import org.jline.utils.InfoCmp;
import org.jline.widget.AutosuggestionWidgets;

import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.List;

/**
 * Console I/O implementation that supports JLine.
 *
 * 

Created: 2017. 3. 4.

*/ public class JLineConsole extends AbstractConsole { private static final String TERMINAL_NAME = "Aspectran JLine terminal"; private final Terminal terminal; private final LineReader reader; private final LineReader commandReader; private final CommandCompleter commandCompleter; private final CommandHighlighter commandHighlighter; private final History commandHistory; private final boolean dumb; private final boolean dumbColor; private AttributedStyle attributedStyle; private String[] styles; public JLineConsole() throws IOException { this(null); } public JLineConsole(String encoding) throws IOException { super(encoding); this.terminal = TerminalBuilder.builder() .name(TERMINAL_NAME) .encoding(getEncoding()) .build(); this.dumb = Terminal.TYPE_DUMB.equals(terminal.getType()); this.dumbColor = Terminal.TYPE_DUMB_COLOR.equals(terminal.getType()); this.reader = LineReaderBuilder.builder() .terminal(terminal) .build(); this.reader.setOpt(LineReader.Option.DISABLE_EVENT_EXPANSION); this.reader.unsetOpt(LineReader.Option.INSERT_TAB); this.commandCompleter = new CommandCompleter(this); this.commandHighlighter = new CommandHighlighter(this); this.commandHistory = new DefaultHistory(); this.commandReader = LineReaderBuilder.builder() .completer(commandCompleter) .highlighter(commandHighlighter) .history(commandHistory) .terminal(terminal) .build(); this.commandReader.setOpt(LineReader.Option.DISABLE_EVENT_EXPANSION); this.commandReader.unsetOpt(LineReader.Option.INSERT_TAB); AutosuggestionWidgets autosuggestionWidgets = new AutosuggestionWidgets(commandReader); autosuggestionWidgets.enable(); } @Override public void setCommandHistoryFile(String historyFile) { commandReader.setVariable(LineReader.HISTORY_FILE, historyFile); commandHistory.attach(commandReader); } @Override public List getCommandHistory() { List result = new ArrayList<>(commandHistory.size()); commandHistory.forEach(e -> result.add(e.line())); return result; } @Override public void clearCommandHistory() { try { commandHistory.purge(); } catch (IOException e) { // ignore } } @Override public String readCommandLine() { String prompt = toAnsi(getCommandPrompt()); return readCommandLine(prompt); } @Override public String readCommandLine(String prompt) { try { String line = readRawCommandLine(prompt).trim(); commandCompleter.setLimited(true); commandHighlighter.setLimited(true); line = readMultiCommandLine(line); commandCompleter.setLimited(false); commandHighlighter.setLimited(false); return line; } catch (EndOfFileException e) { throw new ConsoleTerminatedException(); } catch (IllegalStateException e) { if (e.getMessage() == null) { return null; } else { throw new CommandReadFailedException(e); } } catch (UserInterruptException e) { if (confirmQuit()) { throw new ConsoleTerminatedException(); } else { return null; } } catch (Exception e) { throw new CommandReadFailedException(e); } } @Override public String readLine() { return readLine(null); } @Override public String readLine(String prompt) { return readLine(prompt, null); } @Override public String readLine(String prompt, String buffer) { try { if (prompt == null) { prompt = getPrompt(); } return readMultiLine(readRawLine(prompt, null, buffer)); } catch (EndOfFileException | UserInterruptException e) { throw new ConsoleTerminatedException(); } } @Override public String readPassword() { return readPassword(null); } @Override public String readPassword(String prompt) { return readPassword(prompt, null); } @Override public String readPassword(String prompt, String buffer) { try { if (prompt == null) { prompt = getPrompt(); } return readRawLine(prompt, MASK_CHAR, buffer); } catch (EndOfFileException | UserInterruptException e) { throw new ConsoleTerminatedException(); } } @Override protected String readRawCommandLine(String prompt) { return commandReader.readLine(prompt); } @Override protected String readRawLine(String prompt) { return readRawLine(prompt, null, null); } private String readRawLine(String prompt, Character mask, String buffer) { return reader.readLine(prompt, mask, buffer); } @Override public void write(String string) { if (attributedStyle != null) { AttributedString as = new AttributedString(string, attributedStyle); getWriter().print(as.toAnsi(terminal)); } else { getWriter().print(toAnsi(string)); } } @Override public void write(String format, Object... args) { write(String.format(format, args)); } @Override public void writeLine(String string) { write(string); getWriter().println(); getWriter().flush(); } @Override public void writeLine(String format, Object... args) { writeLine(String.format(format, args)); } @Override public void writeLine() { getWriter().println(); } @Override public void writeError(String string) { String[] oldStyles = getStyles(); setStyle("red"); writeLine(string); if (oldStyles != null) { setStyle(oldStyles); } else { styleOff(); } } @Override public void writeError(String format, Object... args) { writeError(String.format(format, args)); } @Override public void appendPrompt(String string) { if (attributedStyle != null) { AttributedString as = new AttributedString(string, attributedStyle); super.appendPrompt(as.toAnsi(terminal)); } else { super.appendPrompt(toAnsi(string)); } } @Override public void clearScreen() { if (!dumb) { if (commandReader.isReading()) { commandReader.callWidget(LineReader.CLEAR_SCREEN); commandReader.callWidget(LineReader.REDRAW_LINE); commandReader.callWidget(LineReader.REDISPLAY); } else if (reader.isReading()) { reader.callWidget(LineReader.CLEAR_SCREEN); reader.callWidget(LineReader.REDRAW_LINE); reader.callWidget(LineReader.REDISPLAY); } else { terminal.puts(InfoCmp.Capability.clear_screen); terminal.flush(); } } } @Override public void clearLine() { if (!dumb) { if (!dumbColor) { if (commandReader.isReading()) { commandReader.callWidget(LineReader.CLEAR); } else if (reader.isReading()) { reader.callWidget(LineReader.CLEAR); } } else { getWriter().print("\r"); getWriter().flush(); } } } @Override public void redrawLine() { if (!dumb) { if (commandReader.isReading()) { commandReader.callWidget(LineReader.REDRAW_LINE); commandReader.callWidget(LineReader.REDISPLAY); } else if (reader.isReading()) { reader.callWidget(LineReader.REDRAW_LINE); reader.callWidget(LineReader.REDISPLAY); } } } @Override public OutputStream getOutput() { return terminal.output(); } @Override public PrintWriter getWriter() { return terminal.writer(); } @Override public String[] getStyles() { return styles; } @Override public void setStyle(String... styles) { this.styles = styles; this.attributedStyle = JLineAnsiStyler.makeStyle(styles); } @Override public void styleOff() { this.styles = null; this.attributedStyle = null; } private String toAnsi(String string) { return JLineAnsiStyler.parse(string, terminal); } @Override public boolean isBusy() { return reader.isReading(); } @Override public boolean confirmRestart() { return confirmRestart(null); } @Override public boolean confirmRestart(String message) { if (reader.isReading()) { reader.printAbove("Illegal State"); return false; } if (message != null) { if (!dumb) { String message2 = toAnsi("{{YELLOW}}" + message + "{{reset}}"); reader.printAbove(message2); } else { reader.printAbove(message); } } String confirm = "Would you like to restart this shell [Y/n]? "; if (!dumb) { confirm = toAnsi("{{YELLOW}}" + confirm + "{{reset}}"); } String yn = readLine(confirm); return (yn.isEmpty() || yn.equalsIgnoreCase("Y")); } @Override public boolean confirmQuit() { String confirm = "Are you sure you want to quit [Y/n]? "; if (!dumb) { confirm = toAnsi("{{YELLOW}}" + confirm + "{{reset}}"); } String yn = readLine(confirm); return (yn.isEmpty() || yn.equalsIgnoreCase("Y")); } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy