diff --git a/CHANGELOG.md b/CHANGELOG.md
index dfa09bc..1d26db4 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -3,17 +3,19 @@ All notable changes to this project will be documented in this file.
## [0.2]
### Added
+- Syntax highlight.
- JShell-like Kotlin snippets.
- Completely new REPL architecture with object based class layout `kshell-repl-api`.
- HDFS browser plugin.
- Kotlin interpreter for Zeppelin.
### Changed
+- Switch to JLine3
- Kotlin version 1.2.20 -> 1.2.30.
- Unit testes moved to `kshell-repl-api`.
### Fixed
-- Custom REPL fixes [#7](http://github.com/khud/sparklin/issues/7)
+- Custom REPL fixes [#7](http://github.com/khud/sparklin/issues/7).
- Problem with custom commands which start with the same letter.
### Removed
@@ -30,8 +32,8 @@ All notable changes to this project will be documented in this file.
- Added 2 methods to `ConsoleReader` to support history changes.
### Fixed
-- Problem with multiline code [#9](http://github.com/khud/sparklin/issues/9)
-- Doubled colon problem [#10](http://github.com/khud/sparklin/issues/10)
+- Problem with multiline code [#9](http://github.com/khud/sparklin/issues/9).
+- Doubled colon problem [#10](http://github.com/khud/sparklin/issues/10).
## [0.1.1] - 2018-02-08
### Added
diff --git a/bin/kshell.sh b/bin/kshell.sh
index 7db95b4..a6a8ed3 100755
--- a/bin/kshell.sh
+++ b/bin/kshell.sh
@@ -12,12 +12,12 @@ KOTLIN_REFLECT=${MAVEN_REPO_BASE}/kotlin-reflect/${KOTLIN_VERSION}/kotlin-reflec
# JLine2 console support
FUSE_JANSI=$HOME/.m2/repository/org/fusesource/jansi/jansi/1.15/jansi-1.15.jar
-KSHELL_CONSOLE_JLINE2=$HOME/.m2/repository/sparklin/kshell-console-jline2/${SPARKLIN_VERSION}/kshell-console-jline2-${SPARKLIN_VERSION}.jar
+KSHELL_CONSOLE_JLINE3=$HOME/.m2/repository/sparklin/jline3-shaded/${SPARKLIN_VERSION}/jline3-shaded-${SPARKLIN_VERSION}.jar
KSHELL_REPL_API=$HOME/.m2/repository/sparklin/kshell-repl-api/${SPARKLIN_VERSION}/kshell-repl-api-${SPARKLIN_VERSION}.jar
# KShell path
KSHELL=$HOME/.m2/repository/sparklin/kshell/${SPARKLIN_VERSION}/kshell-${SPARKLIN_VERSION}.jar
-JARS=${KOTLIN_COMPILER}:${KOTLIN_STDLIB}:${KOTLIN_REFLECT}:${KOTLIN_SCRIPT_RUNTIME}:${KSHELL_CONSOLE_JLINE2}:${KSHELL_REPL_API}
+JARS=${KOTLIN_COMPILER}:${KOTLIN_STDLIB}:${KOTLIN_REFLECT}:${KOTLIN_SCRIPT_RUNTIME}:${KSHELL_CONSOLE_JLINE3}:${KSHELL_REPL_API}
java -classpath ${JARS}:${KSHELL} sparklin.kshell.KotlinShell $@
diff --git a/bin/sparklin-spark1x.sh b/bin/sparklin-spark1x.sh
index 33f2527..422d234 100755
--- a/bin/sparklin-spark1x.sh
+++ b/bin/sparklin-spark1x.sh
@@ -12,7 +12,7 @@ KOTLIN_REFLECT=${MAVEN_REPO_BASE}/kotlin-reflect/${KOTLIN_VERSION}/kotlin-reflec
# JLine2 console support
FUSE_JANSI=$HOME/.m2/repository/org/fusesource/jansi/jansi/1.15/jansi-1.15.jar
-KSHELL_CONSOLE_JLINE2=$HOME/.m2/repository/sparklin/kshell-console-jline2/${SPARKLIN_VERSION}/kshell-console-jline2-${SPARKLIN_VERSION}.jar
+KSHELL_CONSOLE_JLINE3=$HOME/.m2/repository/sparklin/jline3-shaded/${SPARKLIN_VERSION}/jline3-shaded-${SPARKLIN_VERSION}.jar
KSHELL_REPL_API=$HOME/.m2/repository/sparklin/kshell-repl-api/${SPARKLIN_VERSION}/kshell-repl-api-${SPARKLIN_VERSION}.jar
# Spark 1.x support
@@ -30,7 +30,7 @@ KSHELL=$HOME/.m2/repository/sparklin/kshell/${SPARKLIN_VERSION}/kshell-${SPARKLI
# Apache Spark home directory must point to Spark version 1.x > 1.6
SPARK_HOME=$HOME/Programs/spark-1.6.1-bin-hadoop2.6
-JARS=${KOTLIN_COMPILER},${KOTLIN_STDLIB},${KOTLIN_REFLECT},${KOTLIN_SCRIPT_RUNTIME},${KSHELL_CONSOLE_JLINE2},${KSHELL_REPL_API},${SPARKLIN_PLUGIN},${HDFS_BROWSER_PLUGIN}
+JARS=${KOTLIN_COMPILER},${KOTLIN_STDLIB},${KOTLIN_REFLECT},${KOTLIN_SCRIPT_RUNTIME},${KSHELL_CONSOLE_JLINE3},${KSHELL_REPL_API},${SPARKLIN_PLUGIN},${HDFS_BROWSER_PLUGIN}
${SPARK_HOME}/bin/spark-submit --jars=${JARS} --conf "spark.driver.extraJavaOptions=-Dconfig.path=${SPARKLIN_CONFIG}" \
--master "local[2]" --class "sparklin.kshell.KotlinShell" \
diff --git a/bin/sparklin-spark2x.sh b/bin/sparklin-spark2x.sh
index ed1f9f0..599fa17 100755
--- a/bin/sparklin-spark2x.sh
+++ b/bin/sparklin-spark2x.sh
@@ -12,7 +12,7 @@ KOTLIN_REFLECT=${MAVEN_REPO_BASE}/kotlin-reflect/${KOTLIN_VERSION}/kotlin-reflec
# JLine2 console support
FUSE_JANSI=$HOME/.m2/repository/org/fusesource/jansi/jansi/1.15/jansi-1.15.jar
-KSHELL_CONSOLE_JLINE2=$HOME/.m2/repository/sparklin/kshell-console-jline2/${SPARKLIN_VERSION}/kshell-console-jline2-${SPARKLIN_VERSION}.jar
+KSHELL_CONSOLE_JLINE3=$HOME/.m2/repository/sparklin/jline3-shaded/${SPARKLIN_VERSION}/jline3-shaded-${SPARKLIN_VERSION}.jar
KSHELL_REPL_API=$HOME/.m2/repository/sparklin/kshell-repl-api/${SPARKLIN_VERSION}/kshell-repl-api-${SPARKLIN_VERSION}.jar
# Spark 2.x support
@@ -30,7 +30,7 @@ KSHELL=$HOME/.m2/repository/sparklin/kshell/${SPARKLIN_VERSION}/kshell-${SPARKLI
# Apache Spark home directory must point to Spark version 2.x
SPARK_HOME=$HOME/Programs/spark-2.2.0-bin-hadoop2.7
-JARS=${KOTLIN_COMPILER},${KOTLIN_STDLIB},${KOTLIN_REFLECT},${KOTLIN_SCRIPT_RUNTIME},${KSHELL_CONSOLE_JLINE2},${KSHELL_REPL_API},${SPARKLIN_PLUGIN},${HDFS_BROWSER_PLUGIN}
+JARS=${KOTLIN_COMPILER},${KOTLIN_STDLIB},${KOTLIN_REFLECT},${KOTLIN_SCRIPT_RUNTIME},${KSHELL_CONSOLE_JLINE3},${KSHELL_REPL_API},${SPARKLIN_PLUGIN},${HDFS_BROWSER_PLUGIN}
${SPARK_HOME}/bin/spark-submit --jars=${JARS} --conf "spark.driver.extraJavaOptions=-Dconfig.path=${SPARKLIN_CONFIG}" \
--master "local[2]" --class "sparklin.kshell.KotlinShell" \
diff --git a/conf/spark1x.properties b/conf/spark1x.properties
index 3619f9b..b75340b 100644
--- a/conf/spark1x.properties
+++ b/conf/spark1x.properties
@@ -3,4 +3,6 @@ plugins=sparklin.kshell.plugins.LoadFilePlugin, \
sparklin.kshell.plugins.HelpPlugin, \
sparklin.kshell.plugins.PastePlugin, \
sparklin.spark1x.Spark1xPlugin, \
- sparklin.hdfsbrowser.HdfsBrowserPlugin
\ No newline at end of file
+ sparklin.hdfsbrowser.HdfsBrowserPlugin, \
+ sparklin.kshell.plugins.SyntaxPlugin, \
+ sparklin.kshell.plugins.PromptPlugin
\ No newline at end of file
diff --git a/conf/spark2x.properties b/conf/spark2x.properties
index d1ebd8a..caab20e 100644
--- a/conf/spark2x.properties
+++ b/conf/spark2x.properties
@@ -3,4 +3,6 @@ plugins=sparklin.kshell.plugins.LoadFilePlugin, \
sparklin.kshell.plugins.HelpPlugin, \
sparklin.kshell.plugins.PastePlugin, \
sparklin.spark2x.Spark2xPlugin, \
- sparklin.hdfsbrowser.HdfsBrowserPlugin
\ No newline at end of file
+ sparklin.hdfsbrowser.HdfsBrowserPlugin, \
+ sparklin.kshell.plugins.SyntaxPlugin, \
+ sparklin.kshell.plugins.PromptPlugin
\ No newline at end of file
diff --git a/hdfs-browser/src/main/kotlin/sparklin/hdfsbrowser/HdfsBrowserPlugin.kt b/hdfs-browser/src/main/kotlin/sparklin/hdfsbrowser/HdfsBrowserPlugin.kt
index 798da46..e14e476 100644
--- a/hdfs-browser/src/main/kotlin/sparklin/hdfsbrowser/HdfsBrowserPlugin.kt
+++ b/hdfs-browser/src/main/kotlin/sparklin/hdfsbrowser/HdfsBrowserPlugin.kt
@@ -1,11 +1,11 @@
package sparklin.hdfsbrowser
-import sparklin.kshell.console.ConsoleReader
import org.apache.hadoop.fs.FileSystem
import org.apache.hadoop.fs.Path
import sparklin.kshell.BaseCommand
import sparklin.kshell.KShell
import sparklin.kshell.Plugin
+import sparklin.kshell.calcHumanReadableSize
import sparklin.kshell.configuration.Configuration
import sparklin.kshell.plugins.SparkPlugin
import kotlin.reflect.KClass
@@ -15,7 +15,6 @@ import org.apache.hadoop.conf.Configuration as HadoopConfiguration
class HdfsBrowserPlugin : Plugin {
private lateinit var repl: KShell
private lateinit var fs: FileSystem
- private lateinit var console: ConsoleReader
private var workingDirectory = "."
inner class LsCommand(conf: Configuration) : BaseCommand() {
@@ -29,7 +28,7 @@ class HdfsBrowserPlugin : Plugin {
val p = line.indexOf(' ')
val parseResult = parseOpts(if (p < 0) "" else line.substring(p + 1).trim(), "h")
when (parseResult) {
- is ParseResult.ParseError -> console.println(parseResult.msg)
+ is ParseResult.ParseError -> println(parseResult.msg)
is ParseResult.ParsedOptions -> {
val path = if (parseResult.other.isBlank()) workingDirectory else parseResult.other
listFiles(path, parseResult.opts.isNotEmpty())
@@ -41,7 +40,6 @@ class HdfsBrowserPlugin : Plugin {
override fun init(repl: KShell, config: Configuration) {
this.repl = repl
this.fs = FileSystem.get(findHadoopConfiguration(config))
- this.console = config.getConsoleReader()
repl.registerCommand(LsCommand(config))
}
@@ -66,18 +64,10 @@ class HdfsBrowserPlugin : Plugin {
fs.listStatus(Path(path)).forEach {
val summary = fs.getContentSummary(it.path)
val size = if (isHumanReadable) calcHumanReadableSize(summary.length) else summary.length.toString()
- console.println(String.format("%-20s%s", size, it.path))
+ println(String.format("%-20s%s", size, it.path))
}
}
- private fun calcHumanReadableSize(bytes: Long, si: Boolean = false): String {
- val unit = if (si) 1000 else 1024
- if (bytes < unit) return "$bytes B"
- val exp = (Math.log(bytes.toDouble()) / Math.log(unit.toDouble())).toInt()
- val pre = (if (si) "kMGTPE" else "KMGTPE")[exp - 1] + if (si) "" else "i"
- return String.format("%.1f %sB", bytes / Math.pow(unit.toDouble(), exp.toDouble()), pre)
- }
-
override fun cleanUp() { }
companion object {
diff --git a/jline3-shaded/pom.xml b/jline3-shaded/pom.xml
new file mode 100644
index 0000000..4c50227
--- /dev/null
+++ b/jline3-shaded/pom.xml
@@ -0,0 +1,49 @@
+
+
+ 4.0.0
+
+ sparklin
+ sparklin
+ 0.2-SNAPSHOT
+
+
+
+ jline3-shaded
+ 0.2-SNAPSHOT
+
+
+
+ org.jline
+ jline
+ 3.6.2
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-shade-plugin
+ 3.1.0
+
+
+ package
+
+ shade
+
+
+
+
+ org.jline
+ sparklin.kshell.org.jline
+
+
+
+
+
+
+
+
+
diff --git a/kshell-console-jline2/pom.xml b/kshell-console-jline2/pom.xml
deleted file mode 100644
index a3559be..0000000
--- a/kshell-console-jline2/pom.xml
+++ /dev/null
@@ -1,131 +0,0 @@
-
-
- 4.0.0
-
- sparklin
- sparklin
- 0.2-SNAPSHOT
-
-
- kshell-console-jline2
- 0.2-SNAPSHOT
-
-
-
- org.jetbrains.kotlin
- kotlin-stdlib-jdk8
- ${kotlin.version}
-
-
- org.jetbrains.kotlin
- kotlin-stdlib
- ${kotlin.version}
-
-
- org.jetbrains.kotlin
- kotlin-reflect
- ${kotlin.version}
-
-
-
- org.fusesource.jansi
- jansi
- 1.16
-
-
- junit
- junit
- 4.0
-
-
- sparklin
- kshell
- ${sparklin.version}
-
-
-
-
-
-
- ${project.basedir}/src/main/resources
-
-
-
-
-
-
- kotlin-maven-plugin
-
- ${jvm.version}
-
- org.jetbrains.kotlin
- ${kotlin.version}
-
-
-
- compile
- compile
- compile
-
-
- src/main/kotlin
- src/main/java
-
-
-
-
- test-compile
- test-compile
- test-compile
-
-
-
-
- org.apache.maven.plugins
- maven-compiler-plugin
- 3.5.1
-
-
-
- default-compile
- none
-
-
-
- default-testCompile
- none
-
-
- java-compile
- compile
- compile
-
-
- java-test-compile
- test-compile
- testCompile
-
-
-
- 1.6
- 1.6
-
-
-
- org.apache.maven.plugins
- maven-jar-plugin
- 2.6
-
-
-
-
- sparklin.repl.Main
-
-
-
-
-
-
-
diff --git a/kshell-console-jline2/src/main/java/lib/jline/AnsiWindowsTerminal.java b/kshell-console-jline2/src/main/java/lib/jline/AnsiWindowsTerminal.java
deleted file mode 100644
index c89a6fd..0000000
--- a/kshell-console-jline2/src/main/java/lib/jline/AnsiWindowsTerminal.java
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- * 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
- */
-package lib.jline;
-
-import org.fusesource.jansi.AnsiConsole;
-import org.fusesource.jansi.AnsiOutputStream;
-import org.fusesource.jansi.WindowsAnsiOutputStream;
-
-import java.io.ByteArrayOutputStream;
-import java.io.OutputStream;
-
-/**
- * ANSI-supported {@link WindowsTerminal}.
- *
- * @since 2.0
- */
-public class AnsiWindowsTerminal
- extends WindowsTerminal
-{
- private final boolean ansiSupported = detectAnsiSupport();
-
- @Override
- public OutputStream wrapOutIfNeeded(OutputStream out) {
- return wrapOutputStream(out);
- }
-
- /**
- * Returns an ansi output stream handler. We return whatever was
- * passed if we determine we cannot handle ansi based on Kernel32 calls.
- *
- * @return an @{link AltWindowAnsiOutputStream} instance or the passed
- * stream.
- */
- private static OutputStream wrapOutputStream(final OutputStream stream) {
- if (lib.jline.internal.Configuration.isWindows()) {
- // On windows we know the console does not interpret ANSI codes..
- try {
- return new WindowsAnsiOutputStream(stream);
- } catch (Throwable ignore) {
- // this happens when JNA is not in the path.. or
- // this happens when the stdout is being redirected to a file.
- }
- // Use the ANSIOutputStream to strip out the ANSI escape sequences.
- return new AnsiOutputStream(stream);
- }
- return stream;
- }
-
- private static boolean detectAnsiSupport() {
- OutputStream out = AnsiConsole.wrapOutputStream(new ByteArrayOutputStream());
- try {
- out.close();
- }
- catch (Exception e) {
- // ignore;
- }
- return out instanceof WindowsAnsiOutputStream;
- }
-
- public AnsiWindowsTerminal() throws Exception {
- super();
- }
-
- @Override
- public boolean isAnsiSupported() {
- return ansiSupported;
- }
-
- @Override
- public boolean hasWeirdWrap() {
- return false;
- }
-}
diff --git a/kshell-console-jline2/src/main/java/lib/jline/DefaultTerminal2.java b/kshell-console-jline2/src/main/java/lib/jline/DefaultTerminal2.java
deleted file mode 100644
index 3866023..0000000
--- a/kshell-console-jline2/src/main/java/lib/jline/DefaultTerminal2.java
+++ /dev/null
@@ -1,135 +0,0 @@
-/*
- * 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
- */
-package lib.jline;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Map;
-import java.util.Set;
-
-import lib.jline.internal.InfoCmp;
-
-/**
- * Terminal wrapper with default ansi capabilities
- */
-public class DefaultTerminal2 implements Terminal2 {
-
- private final Terminal terminal;
- private final Set bools = new HashSet();
- private final Map strings = new HashMap();
-
- public DefaultTerminal2(Terminal terminal) {
- this.terminal = terminal;
- registerCap("key_backspace", "^H");
- registerCap("bell", "^G");
- registerCap("carriage_return", "^M");
- if (isSupported() && isAnsiSupported()) {
- registerCap("clr_eol", "\\E[K");
- registerCap("clr_bol", "\\E[1K");
- registerCap("cursor_up", "\\E[A");
- registerCap("cursor_down", "^J");
- registerCap("column_address", "\\E[%i%p1%dG");
- registerCap("clear_screen", "\\E[H\\E[2J");
- registerCap("parm_down_cursor", "\\E[%p1%dB");
- registerCap("cursor_left", "^H");
- registerCap("cursor_right", "\\E[C");
- }
- if (hasWeirdWrap()) {
- registerCap("eat_newline_glitch");
- registerCap("auto_right_margin");
- }
- }
-
- public void init() throws Exception {
- terminal.init();
- }
-
- public void restore() throws Exception {
- terminal.restore();
- }
-
- public void reset() throws Exception {
- terminal.reset();
- }
-
- public boolean isSupported() {
- return terminal.isSupported();
- }
-
- public int getWidth() {
- return terminal.getWidth();
- }
-
- public int getHeight() {
- return terminal.getHeight();
- }
-
- public boolean isAnsiSupported() {
- return terminal.isAnsiSupported();
- }
-
- public OutputStream wrapOutIfNeeded(OutputStream out) {
- return terminal.wrapOutIfNeeded(out);
- }
-
- public InputStream wrapInIfNeeded(InputStream in) throws IOException {
- return terminal.wrapInIfNeeded(in);
- }
-
- public boolean hasWeirdWrap() {
- return terminal.hasWeirdWrap();
- }
-
- public boolean isEchoEnabled() {
- return terminal.isEchoEnabled();
- }
-
- public void setEchoEnabled(boolean enabled) {
- terminal.setEchoEnabled(enabled);
- }
-
- public void disableInterruptCharacter() {
- terminal.disableInterruptCharacter();
- }
-
- public void enableInterruptCharacter() {
- terminal.enableInterruptCharacter();
- }
-
- public String getOutputEncoding() {
- return terminal.getOutputEncoding();
- }
-
- private void registerCap(String cap, String value) {
- for (String key : InfoCmp.getNames(cap)) {
- strings.put(key, value);
- }
- }
-
- private void registerCap(String cap) {
- Collections.addAll(bools, InfoCmp.getNames(cap));
- }
-
- public boolean getBooleanCapability(String capability) {
- return bools.contains(capability);
- }
-
- public Integer getNumericCapability(String capability) {
- return null;
- }
-
- public String getStringCapability(String capability) {
- return strings.get(capability);
- }
-
-}
diff --git a/kshell-console-jline2/src/main/java/lib/jline/NoInterruptUnixTerminal.java b/kshell-console-jline2/src/main/java/lib/jline/NoInterruptUnixTerminal.java
deleted file mode 100644
index 70bcd20..0000000
--- a/kshell-console-jline2/src/main/java/lib/jline/NoInterruptUnixTerminal.java
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * 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
- */
-package lib.jline;
-
-// Based on Apache Karaf impl
-
-/**
- * Non-interruptible (via CTRL-C) {@link UnixTerminal}.
- *
- * @since 2.0
- */
-public class NoInterruptUnixTerminal
- extends UnixTerminal
-{
- private String intr;
-
- public NoInterruptUnixTerminal() throws Exception {
- super();
- }
-
- @Override
- public void init() throws Exception {
- super.init();
- intr = getSettings().getPropertyAsString("intr");
- if ("".equals(intr)) {
- intr = null;
- }
- if (intr != null) {
- getSettings().undef("intr");
- }
- }
-
- @Override
- public void restore() throws Exception {
- if (intr != null) {
- getSettings().set("intr", intr);
- }
- super.restore();
- }
-}
diff --git a/kshell-console-jline2/src/main/java/lib/jline/OSvTerminal.java b/kshell-console-jline2/src/main/java/lib/jline/OSvTerminal.java
deleted file mode 100644
index 65d5b19..0000000
--- a/kshell-console-jline2/src/main/java/lib/jline/OSvTerminal.java
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * 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
- */
-package lib.jline;
-
-import lib.jline.internal.Log;
-
-/**
- * Terminal that is used for OSv. This is seperate to unix terminal
- * implementation because exec cannot be used as currently used by UnixTerminal.
- *
- * This implimentation is derrived from the implementation at
- * http://github.com/cloudius-systems/mgmt/blob/master/crash/src/main/java/com/cloudius/cli/OSvTerminal.java
- * authored by Or Cohen.
- *
- * @author Or Cohen
- * @author Arun Neelicattu
- * @since 2.13
- */
-public class OSvTerminal
- extends TerminalSupport
-{
-
- public Class> sttyClass = null;
- public Object stty = null;
-
- public OSvTerminal() {
- super(true);
-
- setAnsiSupported(true);
-
- try {
- if (stty == null) {
- sttyClass = Class.forName("com.cloudius.util.Stty");
- stty = sttyClass.newInstance();
- }
- } catch (Exception e) {
- Log.warn("Failed to load com.cloudius.util.Stty", e);
- }
- }
-
- @Override
- public void init() throws Exception {
- super.init();
-
- if (stty != null) {
- sttyClass.getMethod("jlineMode").invoke(stty);
- }
- }
-
- @Override
- public void restore() throws Exception {
- if (stty != null) {
- sttyClass.getMethod("reset").invoke(stty);
- }
- super.restore();
-
- // Newline in end of restore like in UnixTerminal
- System.out.println();
- }
-
-}
diff --git a/kshell-console-jline2/src/main/java/lib/jline/Terminal.java b/kshell-console-jline2/src/main/java/lib/jline/Terminal.java
deleted file mode 100644
index 5049147..0000000
--- a/kshell-console-jline2/src/main/java/lib/jline/Terminal.java
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * 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
- */
-package lib.jline;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-
-/**
- * Representation of the input terminal for a platform.
- *
- * @author Marc Prud'hommeaux
- * @author Jason Dillon
- * @since 2.0
- */
-public interface Terminal
-{
- void init() throws Exception;
-
- void restore() throws Exception;
-
- void reset() throws Exception;
-
- boolean isSupported();
-
- int getWidth();
-
- int getHeight();
-
- boolean isAnsiSupported();
-
- /**
- * When ANSI is not natively handled, the output will have to be wrapped.
- */
- OutputStream wrapOutIfNeeded(OutputStream out);
-
- /**
- * When using native support, return the InputStream to use for reading characters
- * else return the input stream passed as a parameter.
- *
- * @since 2.6
- */
- InputStream wrapInIfNeeded(InputStream in) throws IOException;
-
- /**
- * For terminals that don't wrap when character is written in last column,
- * only when the next character is written.
- * These are the ones that have 'am' and 'xn' termcap attributes (xterm and
- * rxvt flavors falls under that category)
- */
- boolean hasWeirdWrap();
-
- boolean isEchoEnabled();
-
- void setEchoEnabled(boolean enabled);
-
- void disableInterruptCharacter();
- void enableInterruptCharacter();
-
- String getOutputEncoding();
-
-}
diff --git a/kshell-console-jline2/src/main/java/lib/jline/Terminal2.java b/kshell-console-jline2/src/main/java/lib/jline/Terminal2.java
deleted file mode 100644
index e53c670..0000000
--- a/kshell-console-jline2/src/main/java/lib/jline/Terminal2.java
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * 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
- */
-package lib.jline;
-
-/**
- * Terminal extension.
- *
- * @author Guillaume Nodet
- * @since 2.13
- */
-public interface Terminal2 extends Terminal
-{
- boolean getBooleanCapability(String capability);
-
- Integer getNumericCapability(String capability);
-
- String getStringCapability(String capability);
-
-}
diff --git a/kshell-console-jline2/src/main/java/lib/jline/TerminalFactory.java b/kshell-console-jline2/src/main/java/lib/jline/TerminalFactory.java
deleted file mode 100644
index c5cb7f1..0000000
--- a/kshell-console-jline2/src/main/java/lib/jline/TerminalFactory.java
+++ /dev/null
@@ -1,223 +0,0 @@
-/*
- * 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
- */
-package lib.jline;
-
-import lib.jline.internal.Configuration;
-import lib.jline.internal.Log;
-import lib.jline.internal.Preconditions;
-
-import java.lang.reflect.Constructor;
-import java.text.MessageFormat;
-import java.util.HashMap;
-import java.util.Map;
-
-/**
- * Creates terminal instances.
- *
- * @author Jason Dillon
- * @since 2.0
- */
-public class TerminalFactory
-{
- public static final String JLINE_TERMINAL = "jline.terminal";
-
- public static final String AUTO = "auto";
-
- public static final String UNIX = "unix";
-
- public static final String OSV = "osv";
-
- public static final String WIN = "win";
-
- public static final String WINDOWS = "windows";
-
- public static final String FREEBSD = "freebsd";
-
- public static final String NONE = "none";
-
- public static final String OFF = "off";
-
- public static final String FALSE = "false";
-
- private static lib.jline.Terminal term = null;
-
- public static synchronized lib.jline.Terminal create() {
- return create(null);
- }
-
- public static synchronized lib.jline.Terminal create(String ttyDevice) {
- if (Log.TRACE) {
- //noinspection ThrowableInstanceNeverThrown
- Log.trace(new Throwable("CREATE MARKER"));
- }
-
- String type = Configuration.getString(JLINE_TERMINAL);
- if (type == null) {
- type = AUTO;
- if ("dumb".equals(System.getenv("TERM"))) {
- // emacs communicates with shell through a 'dumb' terminal
- // but sets these env variables to let programs know
- // it is ok to send ANSI control sequences
- String emacs = System.getenv("EMACS");
- String insideEmacs = System.getenv("INSIDE_EMACS");
- if (emacs == null || insideEmacs == null) {
- type = NONE;
- }
- }
- }
-
- Log.debug("Creating terminal; type=", type);
-
- lib.jline.Terminal t;
- try {
- String tmp = type.toLowerCase();
-
- if (tmp.equals(UNIX)) {
- t = getFlavor(Flavor.UNIX);
- }
- else if (tmp.equals(OSV)) {
- t = getFlavor(Flavor.OSV);
- }
- else if (tmp.equals(WIN) || tmp.equals(WINDOWS)) {
- t = getFlavor(Flavor.WINDOWS);
- }
- else if (tmp.equals(NONE) || tmp.equals(OFF) || tmp.equals(FALSE)) {
- t = new UnsupportedTerminal();
- }
- else {
- if (tmp.equals(AUTO)) {
- String os = Configuration.getOsName();
- Flavor flavor = Flavor.UNIX;
- if (os.contains(WINDOWS)) {
- flavor = Flavor.WINDOWS;
- } else if (System.getenv("OSV_CPUS") != null) {
- flavor = Flavor.OSV;
- }
- t = getFlavor(flavor, ttyDevice);
- }
- else {
- try {
- t = (lib.jline.Terminal) Thread.currentThread().getContextClassLoader().loadClass(type).newInstance();
- }
- catch (Exception e) {
- throw new IllegalArgumentException(MessageFormat.format("Invalid terminal type: {0}", type), e);
- }
- }
- }
- }
- catch (Exception e) {
- Log.error("Failed to construct terminal; falling back to unsupported", e);
- t = new UnsupportedTerminal();
- }
-
- Log.debug("Created Terminal: ", t);
-
- try {
- t.init();
- }
- catch (Throwable e) {
- Log.error("Terminal initialization failed; falling back to unsupported", e);
- return new UnsupportedTerminal();
- }
-
- return t;
- }
-
- public static synchronized void reset() {
- term = null;
- }
-
- public static synchronized void resetIf(final lib.jline.Terminal t) {
- if(t == term) {
- reset();
- }
- }
-
- public static enum Type
- {
- AUTO,
- WINDOWS,
- UNIX,
- OSV,
- NONE
- }
-
- public static synchronized void configure(final String type) {
- Preconditions.checkNotNull(type);
- System.setProperty(JLINE_TERMINAL, type);
- }
-
- public static synchronized void configure(final Type type) {
- Preconditions.checkNotNull(type);
- configure(type.name().toLowerCase());
- }
-
- //
- // Flavor Support
- //
-
- public static enum Flavor
- {
- WINDOWS,
- UNIX,
- OSV
- }
-
- private static final Map> FLAVORS = new HashMap>();
-
- static {
- registerFlavor(Flavor.WINDOWS, lib.jline.AnsiWindowsTerminal.class);
- registerFlavor(Flavor.UNIX, lib.jline.UnixTerminal.class);
- registerFlavor(Flavor.OSV, OSvTerminal.class);
- }
-
- public static synchronized lib.jline.Terminal get(String ttyDevice) {
- // The code is assuming we've got only one terminal per process.
- // Continuing this assumption, if this terminal is already initialized,
- // we don't check if it's using the same tty line either. Both assumptions
- // are a bit crude. TODO: check single terminal assumption.
- if (term == null) {
- term = create(ttyDevice);
- }
- return term;
- }
-
- public static synchronized lib.jline.Terminal get() {
- return get(null);
- }
-
- public static lib.jline.Terminal getFlavor(final Flavor flavor) throws Exception {
- return getFlavor(flavor, null);
- }
-
- public static lib.jline.Terminal getFlavor(final Flavor flavor, String ttyDevice) throws Exception {
- Class extends lib.jline.Terminal> type = FLAVORS.get(flavor);
- lib.jline.Terminal result = null;
- if (type != null) {
- if (ttyDevice != null) {
- Constructor> ttyDeviceConstructor = type.getConstructor(String.class);
- if (ttyDeviceConstructor != null) {
- result = (lib.jline.Terminal) ttyDeviceConstructor.newInstance(ttyDevice);
- } else {
- result = type.newInstance();
- }
- } else {
- result = type.newInstance();
- }
- } else {
- throw new InternalError();
- }
- return result;
- }
-
- public static void registerFlavor(final Flavor flavor, final Class extends lib.jline.Terminal> type) {
- FLAVORS.put(flavor, type);
- }
-
-}
diff --git a/kshell-console-jline2/src/main/java/lib/jline/TerminalSupport.java b/kshell-console-jline2/src/main/java/lib/jline/TerminalSupport.java
deleted file mode 100644
index d40afea..0000000
--- a/kshell-console-jline2/src/main/java/lib/jline/TerminalSupport.java
+++ /dev/null
@@ -1,128 +0,0 @@
-/*
- * 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
- */
-package lib.jline;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-
-import lib.jline.internal.Log;
-import lib.jline.internal.ShutdownHooks;
-
-/**
- * Provides support for {@link Terminal} instances.
- *
- * @author Jason Dillon
- * @since 2.0
- */
-public abstract class TerminalSupport
- implements Terminal
-{
- public static final int DEFAULT_WIDTH = 80;
-
- public static final int DEFAULT_HEIGHT = 24;
-
- private ShutdownHooks.Task shutdownTask;
-
- private boolean supported;
-
- private boolean echoEnabled;
-
- private boolean ansiSupported;
-
- protected TerminalSupport(final boolean supported) {
- this.supported = supported;
- }
-
- public void init() throws Exception {
- if (shutdownTask != null) {
- ShutdownHooks.remove(shutdownTask);
- }
- // Register a task to restore the terminal on shutdown
- this.shutdownTask = ShutdownHooks.add(new ShutdownHooks.Task()
- {
- public void run() throws Exception {
- restore();
- }
- });
- }
-
- public void restore() throws Exception {
- TerminalFactory.resetIf(this);
- if (shutdownTask != null) {
- ShutdownHooks.remove(shutdownTask);
- shutdownTask = null;
- }
- }
-
- public void reset() throws Exception {
- restore();
- init();
- }
-
- public final boolean isSupported() {
- return supported;
- }
-
- public synchronized boolean isAnsiSupported() {
- return ansiSupported;
- }
-
- protected synchronized void setAnsiSupported(final boolean supported) {
- this.ansiSupported = supported;
- Log.debug("Ansi supported: ", supported);
- }
-
- /**
- * Subclass to change behavior if needed.
- * @return the passed out
- */
- public OutputStream wrapOutIfNeeded(OutputStream out) {
- return out;
- }
-
- /**
- * Defaults to true which was the behaviour before this method was added.
- */
- public boolean hasWeirdWrap() {
- return true;
- }
-
- public int getWidth() {
- return DEFAULT_WIDTH;
- }
-
- public int getHeight() {
- return DEFAULT_HEIGHT;
- }
-
- public synchronized boolean isEchoEnabled() {
- return echoEnabled;
- }
-
- public synchronized void setEchoEnabled(final boolean enabled) {
- this.echoEnabled = enabled;
- Log.debug("Echo enabled: ", enabled);
- }
-
- public void disableInterruptCharacter() {
- }
-
- public void enableInterruptCharacter() {
- }
-
- public InputStream wrapInIfNeeded(InputStream in) throws IOException {
- return in;
- }
-
- public String getOutputEncoding() {
- // null for unknown
- return null;
- }
-}
diff --git a/kshell-console-jline2/src/main/java/lib/jline/UnixTerminal.java b/kshell-console-jline2/src/main/java/lib/jline/UnixTerminal.java
deleted file mode 100644
index af75d7e..0000000
--- a/kshell-console-jline2/src/main/java/lib/jline/UnixTerminal.java
+++ /dev/null
@@ -1,241 +0,0 @@
-/*
- * 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
- */
-package lib.jline;
-
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Map;
-import java.util.Set;
-
-import lib.jline.internal.*;
-import lib.jline.internal.Configuration;
-import lib.jline.internal.Log;
-
-/**
- * Terminal that is used for unix platforms. Terminal initialization
- * is handled by issuing the stty command against the
- * /dev/tty file to disable character echoing and enable
- * character input. All known unix systems (including
- * Linux and Macintosh OS X) support the stty), so this
- * implementation should work for an reasonable POSIX system.
- *
- * @author Marc Prud'hommeaux
- * @author Dale Kemp
- * @author Jason Dillon
- * @author Jean-Baptiste Onofr��
- * @since 2.0
- */
-public class UnixTerminal
- extends TerminalSupport
- implements Terminal2
-{
- private final lib.jline.internal.TerminalLineSettings settings;
- private final String type;
- private String intr;
- private String lnext;
- private Set bools = new HashSet();
- private Map ints = new HashMap();
- private Map strings = new HashMap();
-
- public UnixTerminal() throws Exception {
- this(lib.jline.internal.TerminalLineSettings.DEFAULT_TTY, null);
- }
-
- public UnixTerminal(String ttyDevice) throws Exception {
- this(ttyDevice, null);
- }
-
- public UnixTerminal(String ttyDevice, String type) throws Exception {
- super(true);
- lib.jline.internal.Preconditions.checkNotNull(ttyDevice);
- this.settings = lib.jline.internal.TerminalLineSettings.getSettings(ttyDevice);
- if (type == null) {
- type = System.getenv("TERM");
- }
- this.type = type;
- parseInfoCmp();
- }
-
- public lib.jline.internal.TerminalLineSettings getSettings() {
- return settings;
- }
-
- /**
- * Remove line-buffered input by invoking "stty -icanon min 1"
- * against the current terminal.
- */
- @Override
- public void init() throws Exception {
- super.init();
-
- setAnsiSupported(true);
-
- // Set the console to be character-buffered instead of line-buffered.
- // Make sure we're distinguishing carriage return from newline.
- // Allow ctrl-s keypress to be used (as forward search)
- //
- // Please note that FreeBSD does not seem to support -icrnl and thus
- // has to be handled separately. Otherwise the console will be "stuck"
- // and will neither accept input nor print anything to stdout.
- if (Configuration.getOsName().contains(TerminalFactory.FREEBSD)) {
- settings.set("-icanon min 1 -inlcr -ixon");
- } else {
- settings.set("-icanon min 1 -icrnl -inlcr -ixon");
- }
- settings.undef("dsusp");
-
- setEchoEnabled(false);
-
- parseInfoCmp();
- }
-
- /**
- * Restore the original terminal configuration, which can be used when
- * shutting down the console reader. The ConsoleReader cannot be
- * used after calling this method.
- */
- @Override
- public void restore() throws Exception {
- settings.restore();
- super.restore();
- }
-
- /**
- * Returns the value of stty columns param.
- */
- @Override
- public int getWidth() {
- int w = settings.getProperty("columns");
- return w < 1 ? DEFAULT_WIDTH : w;
- }
-
- /**
- * Returns the value of stty rows>/tt> param.
- */
- @Override
- public int getHeight() {
- int h = settings.getProperty("rows");
- return h < 1 ? DEFAULT_HEIGHT : h;
- }
-
- @Override
- public boolean hasWeirdWrap() {
- return getBooleanCapability("auto_right_margin")
- && getBooleanCapability("eat_newline_glitch");
- }
-
- @Override
- public synchronized void setEchoEnabled(final boolean enabled) {
- try {
- if (enabled) {
- settings.set("echo");
- }
- else {
- settings.set("-echo");
- }
- super.setEchoEnabled(enabled);
- }
- catch (Exception e) {
- if (e instanceof InterruptedException) {
- Thread.currentThread().interrupt();
- }
- Log.error("Failed to ", enabled ? "enable" : "disable", " echo", e);
- }
- }
-
- public void disableInterruptCharacter()
- {
- try {
- intr = getSettings().getPropertyAsString("intr");
- if ("".equals(intr)) {
- intr = null;
- }
- settings.undef("intr");
- }
- catch (Exception e) {
- if (e instanceof InterruptedException) {
- Thread.currentThread().interrupt();
- }
- Log.error("Failed to disable interrupt character", e);
- }
- }
-
- public void enableInterruptCharacter()
- {
- try {
- if (intr != null) {
- settings.set("intr", intr);
- }
- }
- catch (Exception e) {
- if (e instanceof InterruptedException) {
- Thread.currentThread().interrupt();
- }
- Log.error("Failed to enable interrupt character", e);
- }
- }
-
- public void disableLitteralNextCharacter()
- {
- try {
- lnext = getSettings().getPropertyAsString("lnext");
- if ("".equals(lnext)) {
- lnext = null;
- }
- settings.undef("lnext");
- }
- catch (Exception e) {
- if (e instanceof InterruptedException) {
- Thread.currentThread().interrupt();
- }
- Log.error("Failed to disable litteral next character", e);
- }
- }
-
- public void enableLitteralNextCharacter()
- {
- try {
- if (lnext != null) {
- settings.set("lnext", lnext);
- }
- }
- catch (Exception e) {
- if (e instanceof InterruptedException) {
- Thread.currentThread().interrupt();
- }
- Log.error("Failed to enable litteral next character", e);
- }
- }
-
- public boolean getBooleanCapability(String capability) {
- return bools.contains(capability);
- }
-
- public Integer getNumericCapability(String capability) {
- return ints.get(capability);
- }
-
- public String getStringCapability(String capability) {
- return strings.get(capability);
- }
-
- private void parseInfoCmp() {
- String capabilities = null;
- if (type != null) {
- try {
- capabilities = InfoCmp.getInfoCmp(type);
- } catch (Exception e) {
- }
- }
- if (capabilities == null) {
- capabilities = InfoCmp.getAnsiCaps();
- }
- InfoCmp.parseInfoCmp(capabilities, bools, ints, strings);
- }
-}
diff --git a/kshell-console-jline2/src/main/java/lib/jline/UnsupportedTerminal.java b/kshell-console-jline2/src/main/java/lib/jline/UnsupportedTerminal.java
deleted file mode 100644
index a11bf4f..0000000
--- a/kshell-console-jline2/src/main/java/lib/jline/UnsupportedTerminal.java
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * 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
- */
-package lib.jline;
-
-/**
- * An unsupported terminal.
- *
- * @author Marc Prud'hommeaux
- * @author Jason Dillon
- * @since 2.0
- */
-public class UnsupportedTerminal
- extends TerminalSupport
-{
- public UnsupportedTerminal() {
- super(false);
- setAnsiSupported(false);
- setEchoEnabled(true);
- }
-}
diff --git a/kshell-console-jline2/src/main/java/lib/jline/WindowsTerminal.java b/kshell-console-jline2/src/main/java/lib/jline/WindowsTerminal.java
deleted file mode 100644
index 716bcf6..0000000
--- a/kshell-console-jline2/src/main/java/lib/jline/WindowsTerminal.java
+++ /dev/null
@@ -1,384 +0,0 @@
-/*
- * 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
- */
-package lib.jline;
-
-import java.io.FileDescriptor;
-import java.io.FileInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-
-import lib.jline.internal.Log;
-import org.fusesource.jansi.internal.WindowsSupport;
-import org.fusesource.jansi.internal.Kernel32;
-import static org.fusesource.jansi.internal.Kernel32.*;
-
-import static lib.jline.WindowsTerminal.ConsoleMode.ENABLE_ECHO_INPUT;
-import static lib.jline.WindowsTerminal.ConsoleMode.ENABLE_LINE_INPUT;
-import static lib.jline.WindowsTerminal.ConsoleMode.ENABLE_PROCESSED_INPUT;
-import static lib.jline.WindowsTerminal.ConsoleMode.ENABLE_WINDOW_INPUT;
-
-/**
- * Terminal implementation for Microsoft Windows. Terminal initialization in
- * {@link #init} is accomplished by extracting the
- * jline_version.dll, saving it to the system temporary
- * directoy (determined by the setting of the java.io.tmpdir System
- * property), loading the library, and then calling the Win32 APIs SetConsoleMode and
- * GetConsoleMode to
- * disable character echoing.
- *
- *
- * By default, the {@link #wrapInIfNeeded(java.io.InputStream)} method will attempt
- * to test to see if the specified {@link InputStream} is {@link System#in} or a wrapper
- * around {@link FileDescriptor#in}, and if so, will bypass the character reading to
- * directly invoke the readc() method in the JNI library. This is so the class
- * can read special keys (like arrow keys) which are otherwise inaccessible via
- * the {@link System#in} stream. Using JNI reading can be bypassed by setting
- * the WindowsTerminal.directConsole system property
- * to false.
- *
- *
- * @author Marc Prud'hommeaux
- * @author Jason Dillon
- * @since 2.0
- */
-public class WindowsTerminal
- extends TerminalSupport
-{
- public static final String DIRECT_CONSOLE = WindowsTerminal.class.getName() + ".directConsole";
-
- public static final String ANSI = WindowsTerminal.class.getName() + ".ansi";
-
- private boolean directConsole;
-
- private int originalMode;
-
- public WindowsTerminal() throws Exception {
- super(true);
- }
-
- @Override
- public void init() throws Exception {
- super.init();
-
- setAnsiSupported(lib.jline.internal.Configuration.getBoolean(ANSI, true));
-
- //
- // FIXME: Need a way to disable direct console and sysin detection muck
- //
-
- setDirectConsole(lib.jline.internal.Configuration.getBoolean(DIRECT_CONSOLE, true));
-
- this.originalMode = getConsoleMode();
- setConsoleMode(originalMode & ~ENABLE_ECHO_INPUT.code);
- setEchoEnabled(false);
- }
-
- /**
- * Restore the original terminal configuration, which can be used when
- * shutting down the console reader. The ConsoleReader cannot be
- * used after calling this method.
- */
- @Override
- public void restore() throws Exception {
- // restore the old console mode
- setConsoleMode(originalMode);
- super.restore();
- }
-
- @Override
- public int getWidth() {
- int w = getWindowsTerminalWidth();
- return w < 1 ? DEFAULT_WIDTH : w;
- }
-
- @Override
- public int getHeight() {
- int h = getWindowsTerminalHeight();
- return h < 1 ? DEFAULT_HEIGHT : h;
- }
-
- @Override
- public void setEchoEnabled(final boolean enabled) {
- // Must set these four modes at the same time to make it work fine.
- if (enabled) {
- setConsoleMode(getConsoleMode() |
- ENABLE_ECHO_INPUT.code |
- ENABLE_LINE_INPUT.code |
- ENABLE_WINDOW_INPUT.code);
- }
- else {
- setConsoleMode(getConsoleMode() &
- ~(ENABLE_LINE_INPUT.code |
- ENABLE_ECHO_INPUT.code |
- ENABLE_WINDOW_INPUT.code));
- }
- super.setEchoEnabled(enabled);
- }
-
- public void disableInterruptCharacter() {
- setConsoleMode(getConsoleMode() &
- ~(ENABLE_PROCESSED_INPUT.code));
- }
-
- public void enableInterruptCharacter() {
- setConsoleMode(getConsoleMode() |
- ENABLE_PROCESSED_INPUT.code);
- }
-
- /**
- * Whether or not to allow the use of the JNI console interaction.
- */
- public void setDirectConsole(final boolean flag) {
- this.directConsole = flag;
- Log.debug("Direct console: ", flag);
- }
-
- /**
- * Whether or not to allow the use of the JNI console interaction.
- */
- public Boolean getDirectConsole() {
- return directConsole;
- }
-
-
- @Override
- public InputStream wrapInIfNeeded(InputStream in) throws IOException {
- if (directConsole && isSystemIn(in)) {
- return new InputStream() {
- private byte[] buf = null;
- int bufIdx = 0;
-
- @Override
- public int read() throws IOException {
- while (buf == null || bufIdx == buf.length) {
- buf = readConsoleInput();
- bufIdx = 0;
- }
- int c = buf[bufIdx] & 0xFF;
- bufIdx++;
- return c;
- }
- };
- } else {
- return super.wrapInIfNeeded(in);
- }
- }
-
- protected boolean isSystemIn(final InputStream in) throws IOException {
- if (in == null) {
- return false;
- }
- else if (in == System.in) {
- return true;
- }
- else if (in instanceof FileInputStream && ((FileInputStream) in).getFD() == FileDescriptor.in) {
- return true;
- }
-
- return false;
- }
-
- @Override
- public String getOutputEncoding() {
- int codepage = getConsoleOutputCodepage();
- //http://docs.oracle.com/javase/6/docs/technotes/guides/intl/encoding.doc.html
- String charsetMS = "ms" + codepage;
- if (java.nio.charset.Charset.isSupported(charsetMS)) {
- return charsetMS;
- }
- String charsetCP = "cp" + codepage;
- if (java.nio.charset.Charset.isSupported(charsetCP)) {
- return charsetCP;
- }
- Log.debug("can't figure out the Java Charset of this code page (" + codepage + ")...");
- return super.getOutputEncoding();
- }
-
- //
- // Native Bits
- //
- private static int getConsoleMode() {
- return WindowsSupport.getConsoleMode();
- }
-
- private static void setConsoleMode(int mode) {
- WindowsSupport.setConsoleMode(mode);
- }
-
- private byte[] readConsoleInput() {
- // XXX does how many events to read in one call matter?
- INPUT_RECORD[] events = null;
- try {
- events = WindowsSupport.readConsoleInput(1);
- } catch (IOException e) {
- Log.debug("read Windows console input error: ", e);
- }
- if (events == null) {
- return new byte[0];
- }
- StringBuilder sb = new StringBuilder();
- for (int i = 0; i < events.length; i++ ) {
- KEY_EVENT_RECORD keyEvent = events[i].keyEvent;
- //Log.trace(keyEvent.keyDown? "KEY_DOWN" : "KEY_UP", "key code:", keyEvent.keyCode, "char:", (long)keyEvent.uchar);
- if (keyEvent.keyDown) {
- if (keyEvent.uchar > 0) {
- // support some C1 control sequences: ALT + [@-_] (and [a-z]?) => ESC
- // http://en.wikipedia.org/wiki/C0_and_C1_control_codes#C1_set
- final int altState = KEY_EVENT_RECORD.LEFT_ALT_PRESSED | KEY_EVENT_RECORD.RIGHT_ALT_PRESSED;
- // Pressing "Alt Gr" is translated to Alt-Ctrl, hence it has to be checked that Ctrl is _not_ pressed,
- // otherwise inserting of "Alt Gr" codes on non-US keyboards would yield errors
- final int ctrlState = KEY_EVENT_RECORD.LEFT_CTRL_PRESSED | KEY_EVENT_RECORD.RIGHT_CTRL_PRESSED;
- if (((keyEvent.uchar >= '@' && keyEvent.uchar <= '_') || (keyEvent.uchar >= 'a' && keyEvent.uchar <= 'z'))
- && ((keyEvent.controlKeyState & altState) != 0) && ((keyEvent.controlKeyState & ctrlState) == 0)) {
- sb.append('\u001B'); // ESC
- }
-
- sb.append(keyEvent.uchar);
- continue;
- }
- // virtual keycodes: http://msdn.microsoft.com/en-us/library/windows/desktop/dd375731(v=vs.85).aspx
- // just add support for basic editing keys (no control state, no numpad keys)
- String escapeSequence = null;
- switch (keyEvent.keyCode) {
- case 0x21: // VK_PRIOR PageUp
- escapeSequence = "\u001B[5~";
- break;
- case 0x22: // VK_NEXT PageDown
- escapeSequence = "\u001B[6~";
- break;
- case 0x23: // VK_END
- escapeSequence = "\u001B[4~";
- break;
- case 0x24: // VK_HOME
- escapeSequence = "\u001B[1~";
- break;
- case 0x25: // VK_LEFT
- escapeSequence = "\u001B[D";
- break;
- case 0x26: // VK_UP
- escapeSequence = "\u001B[A";
- break;
- case 0x27: // VK_RIGHT
- escapeSequence = "\u001B[C";
- break;
- case 0x28: // VK_DOWN
- escapeSequence = "\u001B[B";
- break;
- case 0x2D: // VK_INSERT
- escapeSequence = "\u001B[2~";
- break;
- case 0x2E: // VK_DELETE
- escapeSequence = "\u001B[3~";
- break;
- default:
- break;
- }
- if (escapeSequence != null) {
- for (int k = 0; k < keyEvent.repeatCount; k++) {
- sb.append(escapeSequence);
- }
- }
- } else {
- // key up event
- // support ALT+NumPad input method
- if (keyEvent.keyCode == 0x12/*VK_MENU ALT key*/ && keyEvent.uchar > 0) {
- sb.append(keyEvent.uchar);
- }
- }
- }
- return sb.toString().getBytes();
- }
-
- private static int getConsoleOutputCodepage() {
- return Kernel32.GetConsoleOutputCP();
- }
-
- private static int getWindowsTerminalWidth() {
- return WindowsSupport.getWindowsTerminalWidth();
- }
-
- private static int getWindowsTerminalHeight() {
- return WindowsSupport.getWindowsTerminalHeight();
- }
-
- /**
- * Console mode
- *
- * Constants copied wincon.h.
- */
- public static enum ConsoleMode
- {
- /**
- * The ReadFile or ReadConsole function returns only when a carriage return
- * character is read. If this mode is disable, the functions return when one
- * or more characters are available.
- */
- ENABLE_LINE_INPUT(2),
-
- /**
- * Characters read by the ReadFile or ReadConsole function are written to
- * the active screen buffer as they are read. This mode can be used only if
- * the ENABLE_LINE_INPUT mode is also enabled.
- */
- ENABLE_ECHO_INPUT(4),
-
- /**
- * CTRL+C is processed by the system and is not placed in the input buffer.
- * If the input buffer is being read by ReadFile or ReadConsole, other
- * control keys are processed by the system and are not returned in the
- * ReadFile or ReadConsole buffer. If the ENABLE_LINE_INPUT mode is also
- * enabled, backspace, carriage return, and linefeed characters are handled
- * by the system.
- */
- ENABLE_PROCESSED_INPUT(1),
-
- /**
- * User interactions that change the size of the console screen buffer are
- * reported in the console's input buffee. Information about these events
- * can be read from the input buffer by applications using
- * theReadConsoleInput function, but not by those using ReadFile
- * orReadConsole.
- */
- ENABLE_WINDOW_INPUT(8),
-
- /**
- * If the mouse pointer is within the borders of the console window and the
- * window has the keyboard focus, mouse events generated by mouse movement
- * and button presses are placed in the input buffer. These events are
- * discarded by ReadFile or ReadConsole, even when this mode is enabled.
- */
- ENABLE_MOUSE_INPUT(16),
-
- /**
- * When enabled, text entered in a console window will be inserted at the
- * current cursor location and all text following that location will not be
- * overwritten. When disabled, all following text will be overwritten. An OR
- * operation must be performed with this flag and the ENABLE_EXTENDED_FLAGS
- * flag to enable this functionality.
- */
- ENABLE_PROCESSED_OUTPUT(1),
-
- /**
- * This flag enables the user to use the mouse to select and edit text. To
- * enable this option, use the OR to combine this flag with
- * ENABLE_EXTENDED_FLAGS.
- */
- ENABLE_WRAP_AT_EOL_OUTPUT(2),;
-
- public final int code;
-
- ConsoleMode(final int code) {
- this.code = code;
- }
- }
-
-}
diff --git a/kshell-console-jline2/src/main/java/lib/jline/console/ConsoleKeys.java b/kshell-console-jline2/src/main/java/lib/jline/console/ConsoleKeys.java
deleted file mode 100644
index 92d987c..0000000
--- a/kshell-console-jline2/src/main/java/lib/jline/console/ConsoleKeys.java
+++ /dev/null
@@ -1,387 +0,0 @@
-/*
- * 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
- */
-package lib.jline.console;
-
-import java.io.BufferedReader;
-import java.io.File;
-import java.io.IOException;
-import java.io.InputStream;
-import java.net.URL;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-import lib.jline.internal.Log;
-
-/**
- * @author Ståle W. Pedersen
- */
-public class ConsoleKeys {
-
- private KeyMap keys;
-
- private Map keyMaps;
- private Map variables = new HashMap();
-
- public ConsoleKeys(String appName, URL inputrcUrl) {
- keyMaps = KeyMap.keyMaps();
- setVar("editing-mode", "emacs");
- loadKeys(appName, inputrcUrl);
- }
-
- protected boolean setKeyMap (String name) {
- KeyMap map = keyMaps.get(name);
- if (map == null) {
- return false;
- }
- this.keys = map;
- return true;
- }
-
- protected Map getKeyMaps() {
- return keyMaps;
- }
-
- protected KeyMap getKeys() {
- return keys;
- }
-
- protected void setKeys(KeyMap keys) {
- this.keys = keys;
- }
-
- protected void loadKeys(String appName, URL inputrcUrl) {
- keys = keyMaps.get(KeyMap.EMACS);
-
- try {
- InputStream input = inputrcUrl.openStream();
- try {
- loadKeys(input, appName);
- Log.debug("Loaded user configuration: ", inputrcUrl);
- }
- finally {
- try {
- input.close();
- } catch (IOException e) {
- // Ignore
- }
- }
- }
- catch (IOException e) {
- if (inputrcUrl.getProtocol().equals("file")) {
- File file = new File(inputrcUrl.getPath());
- if (file.exists()) {
- Log.warn("Unable to read user configuration: ", inputrcUrl, e);
- }
- } else {
- Log.warn("Unable to read user configuration: ", inputrcUrl, e);
- }
- }
- }
-
- private void loadKeys(InputStream input, String appName) throws IOException {
- BufferedReader reader = new BufferedReader( new java.io.InputStreamReader( input ) );
- String line;
- boolean parsing = true;
- List ifsStack = new ArrayList();
- while ( (line = reader.readLine()) != null ) {
- try {
- line = line.trim();
- if (line.length() == 0) {
- continue;
- }
- if (line.charAt(0) == '#') {
- continue;
- }
- int i = 0;
- if (line.charAt(i) == '$') {
- String cmd;
- String args;
- for (++i; i < line.length() && (line.charAt(i) == ' ' || line.charAt(i) == '\t'); i++);
- int s = i;
- for (; i < line.length() && (line.charAt(i) != ' ' && line.charAt(i) != '\t'); i++);
- cmd = line.substring(s, i);
- for (; i < line.length() && (line.charAt(i) == ' ' || line.charAt(i) == '\t'); i++);
- s = i;
- for (; i < line.length() && (line.charAt(i) != ' ' && line.charAt(i) != '\t'); i++);
- args = line.substring(s, i);
- if ("if".equalsIgnoreCase(cmd)) {
- ifsStack.add( parsing );
- if (!parsing) {
- continue;
- }
- if (args.startsWith("term=")) {
- // TODO
- } else if (args.startsWith("mode=")) {
- String mode = variables.get("editing-mode");
- parsing = args.substring("mode=".length()).equalsIgnoreCase(mode);
- } else {
- parsing = args.equalsIgnoreCase(appName);
- }
- } else if ("else".equalsIgnoreCase(cmd)) {
- if (ifsStack.isEmpty()) {
- throw new IllegalArgumentException("$else found without matching $if");
- }
- boolean invert = true;
- for (boolean b : ifsStack) {
- if (!b) {
- invert = false;
- break;
- }
- }
- if (invert) {
- parsing = !parsing;
- }
- } else if ("endif".equalsIgnoreCase(cmd)) {
- if (ifsStack.isEmpty()) {
- throw new IllegalArgumentException("endif found without matching $if");
- }
- parsing = ifsStack.remove( ifsStack.size() - 1 );
- } else if ("include".equalsIgnoreCase(cmd)) {
- // TODO
- }
- continue;
- }
- if (!parsing) {
- continue;
- }
- boolean equivalency;
- String keySeq = "";
- if (line.charAt(i++) == '"') {
- boolean esc = false;
- for (;; i++) {
- if (i >= line.length()) {
- throw new IllegalArgumentException("Missing closing quote on line '" + line + "'");
- }
- if (esc) {
- esc = false;
- } else if (line.charAt(i) == '\\') {
- esc = true;
- } else if (line.charAt(i) == '"') {
- break;
- }
- }
- }
- for (; i < line.length() && line.charAt(i) != ':'
- && line.charAt(i) != ' ' && line.charAt(i) != '\t'
- ; i++);
- keySeq = line.substring(0, i);
- equivalency = i + 1 < line.length() && line.charAt(i) == ':' && line.charAt(i + 1) == '=';
- i++;
- if (equivalency) {
- i++;
- }
- if (keySeq.equalsIgnoreCase("set")) {
- String key;
- String val;
- for (; i < line.length() && (line.charAt(i) == ' ' || line.charAt(i) == '\t'); i++);
- int s = i;
- for (; i < line.length() && (line.charAt(i) != ' ' && line.charAt(i) != '\t'); i++);
- key = line.substring( s, i );
- for (; i < line.length() && (line.charAt(i) == ' ' || line.charAt(i) == '\t'); i++);
- s = i;
- for (; i < line.length() && (line.charAt(i) != ' ' && line.charAt(i) != '\t'); i++);
- val = line.substring( s, i );
- setVar( key, val );
- } else {
- for (; i < line.length() && (line.charAt(i) == ' ' || line.charAt(i) == '\t'); i++);
- int start = i;
- if (i < line.length() && (line.charAt(i) == '\'' || line.charAt(i) == '\"')) {
- char delim = line.charAt(i++);
- boolean esc = false;
- for (;; i++) {
- if (i >= line.length()) {
- break;
- }
- if (esc) {
- esc = false;
- } else if (line.charAt(i) == '\\') {
- esc = true;
- } else if (line.charAt(i) == delim) {
- break;
- }
- }
- }
- for (; i < line.length() && line.charAt(i) != ' ' && line.charAt(i) != '\t'; i++);
- String val = line.substring(Math.min(start, line.length()), Math.min(i, line.length()));
- if (keySeq.charAt(0) == '"') {
- keySeq = translateQuoted(keySeq);
- } else {
- // Bind key name
- String keyName = keySeq.lastIndexOf('-') > 0 ? keySeq.substring( keySeq.lastIndexOf('-') + 1 ) : keySeq;
- char key = getKeyFromName(keyName);
- keyName = keySeq.toLowerCase();
- keySeq = "";
- if (keyName.contains("meta-") || keyName.contains("m-")) {
- keySeq += "\u001b";
- }
- if (keyName.contains("control-") || keyName.contains("c-") || keyName.contains("ctrl-")) {
- key = (char)(Character.toUpperCase( key ) & 0x1f);
- }
- keySeq += key;
- }
- if (val.length() > 0 && (val.charAt(0) == '\'' || val.charAt(0) == '\"')) {
- keys.bind( keySeq, translateQuoted(val) );
- } else {
- String operationName = val.replace('-', '_').toUpperCase();
- try {
- keys.bind(keySeq, Operation.valueOf(operationName));
- } catch(IllegalArgumentException e) {
- Log.info("Unable to bind key for unsupported operation: ", val);
- }
- }
- }
- } catch (IllegalArgumentException e) {
- Log.warn("Unable to parse user configuration: ", e);
- }
- }
- }
-
- private static String translateQuoted(String keySeq) {
- int i;
- String str = keySeq.substring( 1, keySeq.length() - 1 );
- keySeq = "";
- for (i = 0; i < str.length(); i++) {
- char c = str.charAt(i);
- if (c == '\\') {
- boolean ctrl = str.regionMatches(i, "\\C-", 0, 3)|| str.regionMatches(i, "\\M-\\C-", 0, 6);
- boolean meta = str.regionMatches(i, "\\M-", 0, 3)|| str.regionMatches(i, "\\C-\\M-", 0, 6);
- i += (meta ? 3 : 0) + (ctrl ? 3 : 0) + (!meta && !ctrl ? 1 : 0);
- if (i >= str.length()) {
- break;
- }
- c = str.charAt(i);
- if (meta) {
- keySeq += "\u001b";
- }
- if (ctrl) {
- c = c == '?' ? 0x7f : (char)(Character.toUpperCase( c ) & 0x1f);
- }
- if (!meta && !ctrl) {
- switch (c) {
- case 'a': c = 0x07; break;
- case 'b': c = '\b'; break;
- case 'd': c = 0x7f; break;
- case 'e': c = 0x1b; break;
- case 'f': c = '\f'; break;
- case 'n': c = '\n'; break;
- case 'r': c = '\r'; break;
- case 't': c = '\t'; break;
- case 'v': c = 0x0b; break;
- case '\\': c = '\\'; break;
- case '0': case '1': case '2': case '3':
- case '4': case '5': case '6': case '7':
- c = 0;
- for (int j = 0; j < 3; j++, i++) {
- if (i >= str.length()) {
- break;
- }
- int k = Character.digit(str.charAt(i), 8);
- if (k < 0) {
- break;
- }
- c = (char)(c * 8 + k);
- }
- c &= 0xFF;
- break;
- case 'x':
- i++;
- c = 0;
- for (int j = 0; j < 2; j++, i++) {
- if (i >= str.length()) {
- break;
- }
- int k = Character.digit(str.charAt(i), 16);
- if (k < 0) {
- break;
- }
- c = (char)(c * 16 + k);
- }
- c &= 0xFF;
- break;
- case 'u':
- i++;
- c = 0;
- for (int j = 0; j < 4; j++, i++) {
- if (i >= str.length()) {
- break;
- }
- int k = Character.digit(str.charAt(i), 16);
- if (k < 0) {
- break;
- }
- c = (char)(c * 16 + k);
- }
- break;
- }
- }
- keySeq += c;
- } else {
- keySeq += c;
- }
- }
- return keySeq;
- }
-
- private static char getKeyFromName(String name) {
- if ("DEL".equalsIgnoreCase(name) || "Rubout".equalsIgnoreCase(name)) {
- return 0x7f;
- } else if ("ESC".equalsIgnoreCase(name) || "Escape".equalsIgnoreCase(name)) {
- return '\033';
- } else if ("LFD".equalsIgnoreCase(name) || "NewLine".equalsIgnoreCase(name)) {
- return '\n';
- } else if ("RET".equalsIgnoreCase(name) || "Return".equalsIgnoreCase(name)) {
- return '\r';
- } else if ("SPC".equalsIgnoreCase(name) || "Space".equalsIgnoreCase(name)) {
- return ' ';
- } else if ("Tab".equalsIgnoreCase(name)) {
- return '\t';
- } else {
- return name.charAt(0);
- }
- }
-
- private void setVar(String key, String val) {
- if ("keymap".equalsIgnoreCase(key)) {
- if (keyMaps.containsKey(val)) {
- keys = keyMaps.get(val);
- }
- } else if ("editing-mode".equals(key)) {
- if ("vi".equalsIgnoreCase(val)) {
- keys = keyMaps.get(KeyMap.VI_INSERT);
- } else if ("emacs".equalsIgnoreCase(key)) {
- keys = keyMaps.get(KeyMap.EMACS);
- }
- } else if ("blink-matching-paren".equals(key)) {
- if ("on".equalsIgnoreCase(val)) {
- keys.setBlinkMatchingParen(true);
- } else if ("off".equalsIgnoreCase(val)) {
- keys.setBlinkMatchingParen(false);
- }
- }
-
- /*
- * Technically variables should be defined as a functor class
- * so that validation on the variable value can be done at parse
- * time. This is a stop-gap.
- */
- variables.put(key, val);
- }
-
- /**
- * Retrieves the value of a variable that was set in the .inputrc file
- * during processing
- * @param var The variable name
- * @return The variable value.
- */
- public String getVariable(String var) {
- return variables.get (var);
- }
-}
diff --git a/kshell-console-jline2/src/main/java/lib/jline/console/ConsoleReader.java b/kshell-console-jline2/src/main/java/lib/jline/console/ConsoleReader.java
deleted file mode 100644
index 96d2a0d..0000000
--- a/kshell-console-jline2/src/main/java/lib/jline/console/ConsoleReader.java
+++ /dev/null
@@ -1,4006 +0,0 @@
-/*
- * 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
- */
-package lib.jline.console;
-
-import java.awt.*;
-import java.awt.datatransfer.Clipboard;
-import java.awt.datatransfer.DataFlavor;
-import java.awt.datatransfer.Transferable;
-import java.awt.datatransfer.UnsupportedFlavorException;
-import java.awt.event.ActionListener;
-import java.io.BufferedReader;
-import java.io.Closeable;
-import java.io.File;
-import java.io.FileDescriptor;
-import java.io.FileInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.io.OutputStreamWriter;
-import java.io.Reader;
-import java.io.Writer;
-import java.lang.reflect.InvocationHandler;
-import java.lang.reflect.Method;
-import java.lang.reflect.Proxy;
-import java.net.URL;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.ListIterator;
-import java.util.ResourceBundle;
-import java.util.Stack;
-
-import lib.jline.console.history.History;
-import lib.jline.console.history.MemoryHistory;
-import lib.jline.internal.*;
-import lib.jline.DefaultTerminal2;
-import lib.jline.Terminal2;
-import lib.jline.internal.Ansi;
-import lib.jline.internal.InputStreamReader;
-import lib.jline.internal.NonBlockingInputStream;
-import lib.jline.internal.TerminalLineSettings;
-
-/**
- * A reader for console applications. It supports custom tab-completion,
- * saveable command history, and command line editing. On some platforms,
- * platform-specific commands will need to be issued before the reader will
- * function properly. See {@link lib.jline.Terminal#init} for convenience
- * methods for issuing platform-specific setup commands.
- *
- * @author Marc Prud'hommeaux
- * @author Jason Dillon
- * @author Guillaume Nodet
- */
-public class ConsoleReader implements Closeable
-{
- public static final String JLINE_NOBELL = "jline.nobell";
-
- public static final String JLINE_ESC_TIMEOUT = "jline.esc.timeout";
-
- public static final String JLINE_INPUTRC = "jline.inputrc";
-
- public static final String INPUT_RC = ".inputrc";
-
- public static final String DEFAULT_INPUT_RC = "/etc/inputrc";
-
- public static final String JLINE_EXPAND_EVENTS = "jline.expandevents";
-
- public static final char BACKSPACE = '\b';
-
- public static final char RESET_LINE = '\r';
-
- public static final char KEYBOARD_BELL = '\07';
-
- public static final char NULL_MASK = 0;
-
- public static final int TAB_WIDTH = 8;
-
- private static final ResourceBundle
- resources = ResourceBundle.getBundle(lib.jline.console.completer.CandidateListCompletionHandler.class.getName());
-
- private static final int ESCAPE = 27;
- private static final int READ_EXPIRED = -2;
-
- private final Terminal2 terminal;
-
- private final Writer out;
-
- private final CursorBuffer buf = new CursorBuffer();
- private boolean cursorOk;
-
- private String prompt;
- private int promptLen;
-
- private boolean expandEvents = lib.jline.internal.Configuration.getBoolean(JLINE_EXPAND_EVENTS, true);
-
- private boolean bellEnabled = !lib.jline.internal.Configuration.getBoolean(JLINE_NOBELL, true);
-
- private boolean handleUserInterrupt = false;
-
- private boolean handleLitteralNext = true;
-
- private Character mask;
-
- private Character echoCharacter;
-
- private CursorBuffer originalBuffer = null;
-
- private StringBuffer searchTerm = null;
-
- private String previousSearchTerm = "";
-
- private int searchIndex = -1;
-
- private int parenBlinkTimeout = 500;
-
- // Reading buffers
- private final StringBuilder opBuffer = new StringBuilder();
- private final Stack pushBackChar = new Stack();
-
- /*
- * The reader and the nonBlockingInput go hand-in-hand. The reader wraps
- * the nonBlockingInput, but we have to retain a handle to it so that
- * we can shut down its blocking read thread when we go away.
- */
- private NonBlockingInputStream in;
- private long escapeTimeout;
- private Reader reader;
-
- /**
- * Last character searched for with a vi character search
- */
- private char charSearchChar = 0; // Character to search for
- private char charSearchLastInvokeChar = 0; // Most recent invocation key
- private char charSearchFirstInvokeChar = 0;// First character that invoked
-
- /**
- * The vi yank buffer
- */
- private String yankBuffer = "";
-
- private KillRing killRing = new KillRing();
-
- private String encoding;
-
- private boolean quotedInsert;
-
- private boolean recording;
-
- private String macro = "";
-
- private String appName;
-
- private URL inputrcUrl;
-
- private ConsoleKeys consoleKeys;
-
- private String commentBegin = null;
-
- private boolean skipLF = false;
-
- /**
- * Set to true if the reader should attempt to detect copy-n-paste. The
- * effect of this that an attempt is made to detect if tab is quickly
- * followed by another character, then it is assumed that the tab was
- * a literal tab as part of a copy-and-paste operation and is inserted as
- * such.
- */
- private boolean copyPasteDetection = false;
-
- /*
- * Current internal state of the line reader
- */
- private State state = State.NORMAL;
-
- /**
- * Possible states in which the current readline operation may be in.
- */
- private static enum State {
- /**
- * The user is just typing away
- */
- NORMAL,
- /**
- * In the middle of a emacs seach
- */
- SEARCH,
- FORWARD_SEARCH,
- /**
- * VI "yank-to" operation ("y" during move mode)
- */
- VI_YANK_TO,
- /**
- * VI "delete-to" operation ("d" during move mode)
- */
- VI_DELETE_TO,
- /**
- * VI "change-to" operation ("c" during move mode)
- */
- VI_CHANGE_TO
- }
-
- public ConsoleReader() throws IOException {
- this(null, new FileInputStream(FileDescriptor.in), System.out, null);
- }
-
- public ConsoleReader(final InputStream in, final OutputStream out) throws IOException {
- this(null, in, out, null);
- }
-
- public ConsoleReader(final InputStream in, final OutputStream out, final lib.jline.Terminal term) throws IOException {
- this(null, in, out, term);
- }
-
- public ConsoleReader(final @Nullable String appName, final InputStream in, final OutputStream out, final @Nullable lib.jline.Terminal term) throws IOException {
- this(appName, in, out, term, null);
- }
-
- public ConsoleReader(final @Nullable String appName, final InputStream in, final OutputStream out, final @Nullable lib.jline.Terminal term, final @Nullable String encoding)
- throws IOException
- {
- this.appName = appName != null ? appName : "JLine";
- this.encoding = encoding != null ? encoding : lib.jline.internal.Configuration.getEncoding();
- lib.jline.Terminal terminal = term != null ? term : lib.jline.TerminalFactory.get();
- this.terminal = terminal instanceof Terminal2 ? (Terminal2) terminal : new DefaultTerminal2(terminal);
- String outEncoding = terminal.getOutputEncoding() != null? terminal.getOutputEncoding() : this.encoding;
- this.out = new OutputStreamWriter(terminal.wrapOutIfNeeded(out), outEncoding);
- setInput( in );
-
- this.inputrcUrl = getInputRc();
-
- consoleKeys = new ConsoleKeys(this.appName, inputrcUrl);
-
- if (terminal instanceof lib.jline.UnixTerminal
- && TerminalLineSettings.DEFAULT_TTY.equals(((lib.jline.UnixTerminal) terminal).getSettings().getTtyDevice())
- && lib.jline.internal.Configuration.getBoolean("jline.sigcont", false)) {
- setupSigCont();
- }
- }
-
- private void setupSigCont() {
- // Check that sun.misc.SignalHandler and sun.misc.Signal exists
- try {
- Class> signalClass = Class.forName("sun.misc.Signal");
- Class> signalHandlerClass = Class.forName("sun.misc.SignalHandler");
- // Implement signal handler
- Object signalHandler = Proxy.newProxyInstance(getClass().getClassLoader(),
- new Class>[]{signalHandlerClass}, new InvocationHandler() {
- public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
- // only method we are proxying is handle()
- terminal.init();
- try {
- drawLine();
- flush();
- } catch (IOException e) {
- e.printStackTrace();
- }
- return null;
- }
- });
- // Register the signal handler, this code is equivalent to:
- // Signal.handle(new Signal("CONT"), signalHandler);
- signalClass.getMethod("handle", signalClass, signalHandlerClass).invoke(null, signalClass.getConstructor(String.class).newInstance("CONT"), signalHandler);
- } catch (ClassNotFoundException cnfe) {
- // sun.misc Signal handler classes don't exist
- } catch (Exception e) {
- // Ignore this one too, if the above failed, the signal API is incompatible with what we're expecting
- }
- }
-
- private static URL getInputRc() throws IOException {
- String path = lib.jline.internal.Configuration.getString(JLINE_INPUTRC);
- if (path == null) {
- File f = new File(lib.jline.internal.Configuration.getUserHome(), INPUT_RC);
- if (!f.exists()) {
- f = new File(DEFAULT_INPUT_RC);
- }
- return f.toURI().toURL();
- } else {
- return lib.jline.internal.Urls.create(path);
- }
- }
-
- public KeyMap getKeys() {
- return consoleKeys.getKeys();
- }
-
- void setInput(final InputStream in) throws IOException {
- this.escapeTimeout = lib.jline.internal.Configuration.getLong(JLINE_ESC_TIMEOUT, 100);
- boolean nonBlockingEnabled =
- escapeTimeout > 0L
- && terminal.isSupported()
- && in != null;
-
- /*
- * If we had a non-blocking thread already going, then shut it down
- * and start a new one.
- */
- if (this.in != null) {
- this.in.shutdown();
- }
-
- final InputStream wrapped = terminal.wrapInIfNeeded( in );
-
- this.in = new NonBlockingInputStream(wrapped, nonBlockingEnabled);
- this.reader = new InputStreamReader( this.in, encoding );
- }
-
- /**
- * Shuts the console reader down. This method should be called when you
- * have completed using the reader as it shuts down and cleans up resources
- * that would otherwise be "leaked".
- */
- @Override
- public void close() {
- if (in != null) {
- in.shutdown();
- }
- }
-
- /**
- * Shuts the console reader down. The same as {@link #close()}.
- * @deprecated Use {@link #close()} instead.
- */
- @Deprecated
- public void shutdown() {
- this.close();
- }
-
- /**
- * Shuts down the ConsoleReader if the JVM attempts to clean it up.
- */
- @Override
- protected void finalize() throws Throwable {
- try {
- close();
- }
- finally {
- super.finalize();
- }
- }
-
- public InputStream getInput() {
- return in;
- }
-
- public Writer getOutput() {
- return out;
- }
-
- public lib.jline.Terminal getTerminal() {
- return terminal;
- }
-
- public CursorBuffer getCursorBuffer() {
- return buf;
- }
-
- public void setExpandEvents(final boolean expand) {
- this.expandEvents = expand;
- }
-
- public boolean getExpandEvents() {
- return expandEvents;
- }
-
- /**
- * Enables or disables copy and paste detection. The effect of enabling this
- * this setting is that when a tab is received immediately followed by another
- * character, the tab will not be treated as a completion, but as a tab literal.
- * @param onoff true if detection is enabled
- */
- public void setCopyPasteDetection(final boolean onoff) {
- copyPasteDetection = onoff;
- }
-
- /**
- * @return true if copy and paste detection is enabled.
- */
- public boolean isCopyPasteDetectionEnabled() {
- return copyPasteDetection;
- }
-
- /**
- * Set whether the console bell is enabled.
- *
- * @param enabled true if enabled; false otherwise
- * @since 2.7
- */
- public void setBellEnabled(boolean enabled) {
- this.bellEnabled = enabled;
- }
-
- /**
- * Get whether the console bell is enabled
- *
- * @return true if enabled; false otherwise
- * @since 2.7
- */
- public boolean getBellEnabled() {
- return bellEnabled;
- }
-
- /**
- * Set whether user interrupts (ctrl-C) are handled by having JLine
- * throw {@link UserInterruptException} from {@link #readLine}.
- * Otherwise, the JVM will handle {@code SIGINT} as normal, which
- * usually causes it to exit. The default is {@code false}.
- *
- * @since 2.10
- */
- public void setHandleUserInterrupt(boolean enabled)
- {
- this.handleUserInterrupt = enabled;
- }
-
- /**
- * Get whether user interrupt handling is enabled
- *
- * @return true if enabled; false otherwise
- * @since 2.10
- */
- public boolean getHandleUserInterrupt()
- {
- return handleUserInterrupt;
- }
-
- /**
- * Set wether literal next are handled by JLine.
- *
- * @since 2.13
- */
- public void setHandleLitteralNext(boolean handleLitteralNext) {
- this.handleLitteralNext = handleLitteralNext;
- }
-
- /**
- * Get wether literal next are handled by JLine.
- *
- * @since 2.13
- */
- public boolean getHandleLitteralNext() {
- return handleLitteralNext;
- }
-
- /**
- * Sets the string that will be used to start a comment when the
- * insert-comment key is struck.
- * @param commentBegin The begin comment string.
- * @since 2.7
- */
- public void setCommentBegin(String commentBegin) {
- this.commentBegin = commentBegin;
- }
-
- /**
- * @return the string that will be used to start a comment when the
- * insert-comment key is struck.
- * @since 2.7
- */
- public String getCommentBegin() {
- String str = commentBegin;
-
- if (str == null) {
- str = consoleKeys.getVariable("comment-begin");
- if (str == null) {
- str = "#";
- }
- }
- return str;
- }
-
- public void setPrompt(final String prompt) {
- this.prompt = prompt;
- this.promptLen = (prompt == null) ? 0 : wcwidth(Ansi.stripAnsi(lastLine(prompt)), 0);
- }
-
- public String getPrompt() {
- return prompt;
- }
-
- /**
- * Set the echo character. For example, to have "*" entered when a password is typed:
- *
- * Setting the character to null will restore normal character echoing.
- * Setting the character to Character.valueOf(0) will cause nothing to be echoed.
- *
- * @param c the character to echo to the console in place of the typed character.
- */
- public void setEchoCharacter(final Character c) {
- this.echoCharacter = c;
- }
-
- /**
- * Returns the echo character.
- */
- public Character getEchoCharacter() {
- return echoCharacter;
- }
-
- /**
- * Erase the current line.
- *
- * @return false if we failed (e.g., the buffer was empty)
- */
- protected final boolean resetLine() throws IOException {
- if (buf.cursor == 0) {
- return false;
- }
-
- StringBuilder killed = new StringBuilder();
-
- while (buf.cursor > 0) {
- char c = buf.current();
- if (c == 0) {
- break;
- }
-
- killed.append(c);
- backspace();
- }
-
- String copy = killed.reverse().toString();
- killRing.addBackwards(copy);
-
- return true;
- }
-
- int wcwidth(CharSequence str, int pos) {
- return wcwidth(str, 0, str.length(), pos);
- }
-
- int wcwidth(CharSequence str, int start, int end, int pos) {
- int cur = pos;
- for (int i = start; i < end;) {
- int ucs;
- char c1 = str.charAt(i++);
- if (!Character.isHighSurrogate(c1) || i >= end) {
- ucs = c1;
- } else {
- char c2 = str.charAt(i);
- if (Character.isLowSurrogate(c2)) {
- i++;
- ucs = Character.toCodePoint(c1, c2);
- } else {
- ucs = c1;
- }
- }
- cur += wcwidth(ucs, cur);
- }
- return cur - pos;
- }
-
- int wcwidth(int ucs, int pos) {
- if (ucs == '\t') {
- return nextTabStop(pos);
- } else if (ucs < 32) {
- return 2;
- } else {
- int w = WCWidth.wcwidth(ucs);
- return w > 0 ? w : 0;
- }
- }
-
- int nextTabStop(int pos) {
- int tabWidth = TAB_WIDTH;
- int width = getTerminal().getWidth();
- int mod = (pos + tabWidth - 1) % tabWidth;
- int npos = pos + tabWidth - mod;
- return npos < width ? npos - pos : width - pos;
- }
-
- int getCursorPosition() {
- return promptLen + wcwidth(buf.buffer, 0, buf.cursor, promptLen);
- }
-
- /**
- * Returns the text after the last '\n'.
- * prompt is returned if no '\n' characters are present.
- * null is returned if prompt is null.
- */
- private static String lastLine(String str) {
- if (str == null) return "";
- int last = str.lastIndexOf("\n");
-
- if (last >= 0) {
- return str.substring(last + 1, str.length());
- }
-
- return str;
- }
-
- /**
- * Move the cursor position to the specified absolute index.
- */
- public boolean setCursorPosition(final int position) throws IOException {
- if (position == buf.cursor) {
- return true;
- }
-
- return moveCursor(position - buf.cursor) != 0;
- }
-
- /**
- * Set the current buffer's content to the specified {@link String}. The
- * visual console will be modified to show the current buffer.
- *
- * @param buffer the new contents of the buffer.
- */
- private void setBuffer(final String buffer) throws IOException {
- // don't bother modifying it if it is unchanged
- if (buffer.equals(buf.buffer.toString())) {
- return;
- }
-
- // obtain the difference between the current buffer and the new one
- int sameIndex = 0;
-
- for (int i = 0, l1 = buffer.length(), l2 = buf.buffer.length(); (i < l1)
- && (i < l2); i++) {
- if (buffer.charAt(i) == buf.buffer.charAt(i)) {
- sameIndex++;
- }
- else {
- break;
- }
- }
-
- int diff = buf.cursor - sameIndex;
- if (diff < 0) { // we can't backspace here so try from the end of the buffer
- moveToEnd();
- diff = buf.buffer.length() - sameIndex;
- }
-
- backspace(diff); // go back for the differences
- killLine(); // cleanUp to the end of the line
- buf.buffer.setLength(sameIndex); // the new length
- putString(buffer.substring(sameIndex)); // append the differences
- }
-
- private void setBuffer(final CharSequence buffer) throws IOException {
- setBuffer(String.valueOf(buffer));
- }
-
- private void setBufferKeepPos(final String buffer) throws IOException {
- int pos = buf.cursor;
- setBuffer(buffer);
- setCursorPosition(pos);
- }
-
- private void setBufferKeepPos(final CharSequence buffer) throws IOException {
- setBufferKeepPos(String.valueOf(buffer));
- }
-
- /**
- * Output put the prompt + the current buffer
- */
- public void drawLine() throws IOException {
- String prompt = getPrompt();
- if (prompt != null) {
- rawPrint(prompt);
- }
-
- fmtPrint(buf.buffer, 0, buf.cursor, promptLen);
-
- // force drawBuffer to check for weird wrap (after cleanUp screen)
- drawBuffer();
- }
-
- /**
- * Clear the line and redraw it.
- */
- public void redrawLine() throws IOException {
- tputs("carriage_return");
- drawLine();
- }
-
- /**
- * Clear the buffer and add its contents to the history.
- *
- * @return the former contents of the buffer.
- */
- final String finishBuffer() throws IOException { // FIXME: Package protected because used by tests
- String str = buf.buffer.toString();
- String historyLine = str;
-
- if (expandEvents) {
- try {
- str = expandEvents(str);
- // all post-expansion occurrences of '!' must have been escaped, so re-add escape to each
- historyLine = str.replace("!", "\\!");
- // only leading '^' results in expansion, so only re-add escape for that case
- historyLine = historyLine.replaceAll("^\\^", "\\\\^");
- } catch(IllegalArgumentException e) {
- lib.jline.internal.Log.error("Could not expand event", e);
- beep();
- buf.clear();
- str = "";
- }
- }
-
- // we only add it to the history if the buffer is not empty
- // and if mask is null, since having a mask typically means
- // the string was a password. We cleanUp the mask after this call
- if (str.length() > 0) {
- if (mask == null && isHistoryEnabled()) {
- history.add(historyLine);
- }
- else {
- mask = null;
- }
- }
-
- history.moveToEnd();
-
- buf.buffer.setLength(0);
- buf.cursor = 0;
-
- return str;
- }
-
- /**
- * Expand event designator such as !!, !#, !3, etc...
- * See http://www.gnu.org/software/bash/manual/html_node/Event-Designators.html
- */
- @SuppressWarnings("fallthrough")
- protected String expandEvents(String str) throws IOException {
- StringBuilder sb = new StringBuilder();
- for (int i = 0; i < str.length(); i++) {
- char c = str.charAt(i);
- switch (c) {
- case '\\':
- // any '\!' should be considered an expansion escape, so skip expansion and strip the escape character
- // a leading '\^' should be considered an expansion escape, so skip expansion and strip the escape character
- // otherwise, add the escape
- if (i + 1 < str.length()) {
- char nextChar = str.charAt(i+1);
- if (nextChar == '!' || (nextChar == '^' && i == 0)) {
- c = nextChar;
- i++;
- }
- }
- sb.append(c);
- break;
- case '!':
- if (i + 1 < str.length()) {
- c = str.charAt(++i);
- boolean neg = false;
- String rep = null;
- int i1, idx;
- switch (c) {
- case '!':
- if (history.size() == 0) {
- throw new IllegalArgumentException("!!: event not found");
- }
- rep = history.get(history.index() - 1).toString();
- break;
- case '#':
- sb.append(sb.toString());
- break;
- case '?':
- i1 = str.indexOf('?', i + 1);
- if (i1 < 0) {
- i1 = str.length();
- }
- String sc = str.substring(i + 1, i1);
- i = i1;
- idx = searchBackwards(sc);
- if (idx < 0) {
- throw new IllegalArgumentException("!?" + sc + ": event not found");
- } else {
- rep = history.get(idx).toString();
- }
- break;
- case '$':
- if (history.size() == 0) {
- throw new IllegalArgumentException("!$: event not found");
- }
- String previous = history.get(history.index() - 1).toString().trim();
- int lastSpace = previous.lastIndexOf(' ');
- if(lastSpace != -1) {
- rep = previous.substring(lastSpace+1);
- } else {
- rep = previous;
- }
- break;
- case ' ':
- case '\t':
- sb.append('!');
- sb.append(c);
- break;
- case '-':
- neg = true;
- i++;
- // fall through
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9':
- i1 = i;
- for (; i < str.length(); i++) {
- c = str.charAt(i);
- if (c < '0' || c > '9') {
- break;
- }
- }
- idx = 0;
- try {
- idx = Integer.parseInt(str.substring(i1, i));
- } catch (NumberFormatException e) {
- throw new IllegalArgumentException((neg ? "!-" : "!") + str.substring(i1, i) + ": event not found");
- }
- if (neg) {
- if (idx > 0 && idx <= history.size()) {
- rep = (history.get(history.index() - idx)).toString();
- } else {
- throw new IllegalArgumentException((neg ? "!-" : "!") + str.substring(i1, i) + ": event not found");
- }
- } else {
- if (idx > history.index() - history.size() && idx <= history.index()) {
- rep = (history.get(idx - 1)).toString();
- } else {
- throw new IllegalArgumentException((neg ? "!-" : "!") + str.substring(i1, i) + ": event not found");
- }
- }
- break;
- default:
- String ss = str.substring(i);
- i = str.length();
- idx = searchBackwards(ss, history.index(), true);
- if (idx < 0) {
- throw new IllegalArgumentException("!" + ss + ": event not found");
- } else {
- rep = history.get(idx).toString();
- }
- break;
- }
- if (rep != null) {
- sb.append(rep);
- }
- } else {
- sb.append(c);
- }
- break;
- case '^':
- if (i == 0) {
- int i1 = str.indexOf('^', i + 1);
- int i2 = str.indexOf('^', i1 + 1);
- if (i2 < 0) {
- i2 = str.length();
- }
- if (i1 > 0 && i2 > 0) {
- String s1 = str.substring(i + 1, i1);
- String s2 = str.substring(i1 + 1, i2);
- String s = history.get(history.index() - 1).toString().replace(s1, s2);
- sb.append(s);
- i = i2 + 1;
- break;
- }
- }
- sb.append(c);
- break;
- default:
- sb.append(c);
- break;
- }
- }
- String result = sb.toString();
- if (!str.equals(result)) {
- fmtPrint(result, getCursorPosition());
- println();
- flush();
- }
- return result;
-
- }
-
- /**
- * Write out the specified string to the buffer and the output stream.
- */
- public void putString(final CharSequence str) throws IOException {
- int pos = getCursorPosition();
- buf.write(str);
- if (mask == null) {
- // no masking
- fmtPrint(str, pos);
- } else if (mask == NULL_MASK) {
- // don't print anything
- } else {
- rawPrint(mask, str.length());
- }
- drawBuffer();
- }
-
- /**
- * Redraw the rest of the buffer from the cursor onwards. This is necessary
- * for inserting text into the buffer.
- *
- * @param clear the number of characters to cleanUp after the end of the buffer
- */
- private void drawBuffer(final int clear) throws IOException {
- // debug ("drawBuffer: " + cleanUp);
- int nbChars = buf.length() - buf.cursor;
- if (buf.cursor != buf.length() || clear != 0) {
- if (mask != null) {
- if (mask != NULL_MASK) {
- rawPrint(mask, nbChars);
- } else {
- nbChars = 0;
- }
- } else {
- fmtPrint(buf.buffer, buf.cursor, buf.length());
- }
- }
- int cursorPos = promptLen + wcwidth(buf.buffer, 0, buf.length(), promptLen);
- if (terminal.hasWeirdWrap() && !cursorOk) {
- int width = terminal.getWidth();
- // best guess on whether the cursor is in that weird location...
- // Need to do this without calling ansi cursor location methods
- // otherwise it breaks paste of wrapped lines in xterm.
- if (cursorPos > 0 && (cursorPos % width == 0)) {
- // the following workaround is reverse-engineered from looking
- // at what bash sent to the terminal in the same situation
- rawPrint(' '); // move cursor to next line by printing dummy space
- tputs("carriage_return"); // CR / not newline.
- }
- cursorOk = true;
- }
- clearAhead(clear, cursorPos);
- back(nbChars);
- }
-
- /**
- * Redraw the rest of the buffer from the cursor onwards. This is necessary
- * for inserting text into the buffer.
- */
- private void drawBuffer() throws IOException {
- drawBuffer(0);
- }
-
- /**
- * Clear ahead the specified number of characters without moving the cursor.
- *
- * @param num the number of characters to cleanUp
- * @param pos the current screen cursor position
- */
- private void clearAhead(int num, final int pos) throws IOException {
- if (num == 0) return;
-
- int width = terminal.getWidth();
- // Use kill line
- if (terminal.getStringCapability("clr_eol") != null) {
- int cur = pos;
- int c0 = cur % width;
- // Erase end of current line
- int nb = Math.min(num, width - c0);
- tputs("clr_eol");
- num -= nb;
- // Loop
- while (num > 0) {
- // Move to beginning of next line
- int prev = cur;
- cur = cur - cur % width + width;
- moveCursorFromTo(prev, cur);
- // Erase
- nb = Math.min(num, width);
- tputs("clr_eol");
- num -= nb;
- }
- moveCursorFromTo(cur, pos);
- }
- // Terminal does not wrap on the right margin
- else if (!terminal.getBooleanCapability("auto_right_margin")) {
- int cur = pos;
- int c0 = cur % width;
- // Erase end of current line
- int nb = Math.min(num, width - c0);
- rawPrint(' ', nb);
- num -= nb;
- cur += nb;
- // Loop
- while (num > 0) {
- // Move to beginning of next line
- moveCursorFromTo(cur, ++cur);
- // Erase
- nb = Math.min(num, width);
- rawPrint(' ', nb);
- num -= nb;
- cur += nb;
- }
- moveCursorFromTo(cur, pos);
- }
- // Simple erasure
- else {
- rawPrint(' ', num);
- moveCursorFromTo(pos + num, pos);
- }
- }
-
- /**
- * Move the visual cursor backward without modifying the buffer cursor.
- */
- protected void back(final int num) throws IOException {
- if (num == 0) return;
- int i0 = promptLen + wcwidth(buf.buffer, 0, buf.cursor, promptLen);
- int i1 = i0 + ((mask != null) ? num : wcwidth(buf.buffer, buf.cursor, buf.cursor + num, i0));
- moveCursorFromTo(i1, i0);
- }
-
- /**
- * Flush the console output stream. This is important for printout out single characters (like a backspace or
- * keyboard) that we want the console to handle immediately.
- */
- public void flush() throws IOException {
- out.flush();
- }
-
- private int backspaceAll() throws IOException {
- return backspace(Integer.MAX_VALUE);
- }
-
- /**
- * Issue num backspaces.
- *
- * @return the number of characters backed up
- */
- private int backspace(final int num) throws IOException {
- if (buf.cursor == 0) {
- return 0;
- }
-
- int count = - moveCursor(-num);
- int clear = wcwidth(buf.buffer, buf.cursor, buf.cursor + count, getCursorPosition());
- buf.buffer.delete(buf.cursor, buf.cursor + count);
-
- drawBuffer(clear);
- return count;
- }
-
- /**
- * Issue a backspace.
- *
- * @return true if successful
- */
- public boolean backspace() throws IOException {
- return backspace(1) == 1;
- }
-
- protected boolean moveToEnd() throws IOException {
- if (buf.cursor == buf.length()) {
- return true;
- }
- return moveCursor(buf.length() - buf.cursor) > 0;
- }
-
- /**
- * Delete the character at the current position and redraw the remainder of the buffer.
- */
- private boolean deleteCurrentCharacter() throws IOException {
- if (buf.length() == 0 || buf.cursor == buf.length()) {
- return false;
- }
-
- buf.buffer.deleteCharAt(buf.cursor);
- drawBuffer(1);
- return true;
- }
-
- /**
- * This method is calling while doing a delete-to ("d"), change-to ("c"),
- * or yank-to ("y") and it filters out only those movement operations
- * that are allowable during those operations. Any operation that isn't
- * allow drops you back into movement mode.
- *
- * @param op The incoming operation to remap
- * @return The remaped operation
- */
- private lib.jline.console.Operation viDeleteChangeYankToRemap (lib.jline.console.Operation op) {
- switch (op) {
- case VI_EOF_MAYBE:
- case ABORT:
- case BACKWARD_CHAR:
- case FORWARD_CHAR:
- case END_OF_LINE:
- case VI_MATCH:
- case VI_BEGINNING_OF_LINE_OR_ARG_DIGIT:
- case VI_ARG_DIGIT:
- case VI_PREV_WORD:
- case VI_END_WORD:
- case VI_CHAR_SEARCH:
- case VI_NEXT_WORD:
- case VI_FIRST_PRINT:
- case VI_GOTO_MARK:
- case VI_COLUMN:
- case VI_DELETE_TO:
- case VI_YANK_TO:
- case VI_CHANGE_TO:
- return op;
-
- default:
- return lib.jline.console.Operation.VI_MOVEMENT_MODE;
- }
- }
-
- /**
- * Deletes the previous character from the cursor position
- * @param count number of times to do it.
- * @return true if it was done.
- */
- private boolean viRubout(int count) throws IOException {
- boolean ok = true;
- for (int i = 0; ok && i < count; i++) {
- ok = backspace();
- }
- return ok;
- }
-
- /**
- * Deletes the character you are sitting on and sucks the rest of
- * the line in from the right.
- * @param count Number of times to perform the operation.
- * @return true if its works, false if it didn't
- */
- private boolean viDelete(int count) throws IOException {
- boolean ok = true;
- for (int i = 0; ok && i < count; i++) {
- ok = deleteCurrentCharacter();
- }
- return ok;
- }
-
- /**
- * Switches the case of the current character from upper to lower
- * or lower to upper as necessary and advances the cursor one
- * position to the right.
- * @param count The number of times to repeat
- * @return true if it completed successfully, false if not all
- * case changes could be completed.
- */
- private boolean viChangeCase(int count) throws IOException {
- boolean ok = true;
- for (int i = 0; ok && i < count; i++) {
-
- ok = buf.cursor < buf.buffer.length ();
- if (ok) {
- char ch = buf.buffer.charAt(buf.cursor);
- if (Character.isUpperCase(ch)) {
- ch = Character.toLowerCase(ch);
- }
- else if (Character.isLowerCase(ch)) {
- ch = Character.toUpperCase(ch);
- }
- buf.buffer.setCharAt(buf.cursor, ch);
- drawBuffer(1);
- moveCursor(1);
- }
- }
- return ok;
- }
-
- /**
- * Implements the vi change character command (in move-mode "r"
- * followed by the character to change to).
- * @param count Number of times to perform the action
- * @param c The character to change to
- * @return Whether or not there were problems encountered
- */
- private boolean viChangeChar(int count, int c) throws IOException {
- // EOF, ESC, or CTRL-C aborts.
- if (c < 0 || c == '\033' || c == '\003') {
- return true;
- }
-
- boolean ok = true;
- for (int i = 0; ok && i < count; i++) {
- ok = buf.cursor < buf.buffer.length ();
- if (ok) {
- buf.buffer.setCharAt(buf.cursor, (char) c);
- drawBuffer(1);
- if (i < (count-1)) {
- moveCursor(1);
- }
- }
- }
- return ok;
- }
-
- /**
- * This is a close facsimile of the actual vi previous word logic. In
- * actual vi words are determined by boundaries of identity characterse.
- * This logic is a bit more simple and simply looks at white space or
- * digits or characters. It should be revised at some point.
- *
- * @param count number of iterations
- * @return true if the move was successful, false otherwise
- */
- private boolean viPreviousWord(int count) throws IOException {
- boolean ok = true;
- if (buf.cursor == 0) {
- return false;
- }
-
- int pos = buf.cursor - 1;
- for (int i = 0; pos > 0 && i < count; i++) {
- // If we are on white space, then move back.
- while (pos > 0 && isWhitespace(buf.buffer.charAt(pos))) {
- --pos;
- }
-
- while (pos > 0 && !isDelimiter(buf.buffer.charAt(pos-1))) {
- --pos;
- }
-
- if (pos > 0 && i < (count-1)) {
- --pos;
- }
- }
- setCursorPosition(pos);
- return ok;
- }
-
- /**
- * Performs the vi "delete-to" action, deleting characters between a given
- * span of the input line.
- * @param startPos The start position
- * @param endPos The end position.
- * @param isChange If true, then the delete is part of a change operationg
- * (e.g. "c$" is change-to-end-of line, so we first must delete to end
- * of line to start the change
- * @return true if it succeeded, false otherwise
- */
- private boolean viDeleteTo(int startPos, int endPos, boolean isChange) throws IOException {
- if (startPos == endPos) {
- return true;
- }
-
- if (endPos < startPos) {
- int tmp = endPos;
- endPos = startPos;
- startPos = tmp;
- }
-
- setCursorPosition(startPos);
- buf.cursor = startPos;
- buf.buffer.delete(startPos, endPos);
- drawBuffer(endPos - startPos);
-
- // If we are doing a delete operation (e.g. "d$") then don't leave the
- // cursor dangling off the end. In reality the "isChange" flag is silly
- // what is really happening is that if we are in "move-mode" then the
- // cursor can't be moved off the end of the line, but in "edit-mode" it
- // is ok, but I have no easy way of knowing which mode we are in.
- if (! isChange && startPos > 0 && startPos == buf.length()) {
- moveCursor(-1);
- }
- return true;
- }
-
- /**
- * Implement the "vi" yank-to operation. This operation allows you
- * to yank the contents of the current line based upon a move operation,
- * for exaple "yw" yanks the current word, "3yw" yanks 3 words, etc.
- *
- * @param startPos The starting position from which to yank
- * @param endPos The ending position to which to yank
- * @return true if the yank succeeded
- */
- private boolean viYankTo(int startPos, int endPos) throws IOException {
- int cursorPos = startPos;
-
- if (endPos < startPos) {
- int tmp = endPos;
- endPos = startPos;
- startPos = tmp;
- }
-
- if (startPos == endPos) {
- yankBuffer = "";
- return true;
- }
-
- yankBuffer = buf.buffer.substring(startPos, endPos);
-
- /*
- * It was a movement command that moved the cursor to find the
- * end position, so put the cursor back where it started.
- */
- setCursorPosition(cursorPos);
- return true;
- }
-
- /**
- * Pasts the yank buffer to the right of the current cursor position
- * and moves the cursor to the end of the pasted region.
- *
- * @param count Number of times to perform the operation.
- * @return true if it worked, false otherwise
- */
- private boolean viPut(int count) throws IOException {
- if (yankBuffer.length () == 0) {
- return true;
- }
- if (buf.cursor < buf.buffer.length ()) {
- moveCursor(1);
- }
- for (int i = 0; i < count; i++) {
- putString(yankBuffer);
- }
- moveCursor(-1);
- return true;
- }
-
- /**
- * Searches forward of the current position for a character and moves
- * the cursor onto it.
- * @param count Number of times to repeat the process.
- * @param ch The character to search for
- * @return true if the char was found, false otherwise
- */
- private boolean viCharSearch(int count, int invokeChar, int ch) throws IOException {
- if (ch < 0 || invokeChar < 0) {
- return false;
- }
-
- char searchChar = (char)ch;
- boolean isForward;
- boolean stopBefore;
-
- /*
- * The character stuff turns out to be hairy. Here is how it works:
- * f - search forward for ch
- * F - search backward for ch
- * t - search forward for ch, but stop just before the match
- * T - search backward for ch, but stop just after the match
- * ; - After [fFtT;], repeat the last search, after ',' reverse it
- * , - After [fFtT;], reverse the last search, after ',' repeat it
- */
- if (invokeChar == ';' || invokeChar == ',') {
- // No recent search done? Then bail
- if (charSearchChar == 0) {
- return false;
- }
-
- // Reverse direction if switching between ',' and ';'
- if (charSearchLastInvokeChar == ';' || charSearchLastInvokeChar == ',') {
- if (charSearchLastInvokeChar != invokeChar) {
- charSearchFirstInvokeChar = switchCase(charSearchFirstInvokeChar);
- }
- }
- else {
- if (invokeChar == ',') {
- charSearchFirstInvokeChar = switchCase(charSearchFirstInvokeChar);
- }
- }
-
- searchChar = charSearchChar;
- }
- else {
- charSearchChar = searchChar;
- charSearchFirstInvokeChar = (char) invokeChar;
- }
-
- charSearchLastInvokeChar = (char)invokeChar;
-
- isForward = Character.isLowerCase(charSearchFirstInvokeChar);
- stopBefore = (Character.toLowerCase(charSearchFirstInvokeChar) == 't');
-
- boolean ok = false;
-
- if (isForward) {
- while (count-- > 0) {
- int pos = buf.cursor + 1;
- while (pos < buf.buffer.length()) {
- if (buf.buffer.charAt(pos) == searchChar) {
- setCursorPosition(pos);
- ok = true;
- break;
- }
- ++pos;
- }
- }
-
- if (ok) {
- if (stopBefore)
- moveCursor(-1);
-
- /*
- * When in yank-to, move-to, del-to state we actually want to
- * go to the character after the one we landed on to make sure
- * that the character we ended up on is included in the
- * operation
- */
- if (isInViMoveOperationState()) {
- moveCursor(1);
- }
- }
- }
- else {
- while (count-- > 0) {
- int pos = buf.cursor - 1;
- while (pos >= 0) {
- if (buf.buffer.charAt(pos) == searchChar) {
- setCursorPosition(pos);
- ok = true;
- break;
- }
- --pos;
- }
- }
-
- if (ok && stopBefore)
- moveCursor(1);
- }
-
- return ok;
- }
-
- private static char switchCase(char ch) {
- if (Character.isUpperCase(ch)) {
- return Character.toLowerCase(ch);
- }
- return Character.toUpperCase(ch);
- }
-
- /**
- * @return true if line reader is in the middle of doing a change-to
- * delete-to or yank-to.
- */
- private final boolean isInViMoveOperationState() {
- return state == State.VI_CHANGE_TO
- || state == State.VI_DELETE_TO
- || state == State.VI_YANK_TO;
- }
-
- /**
- * This is a close facsimile of the actual vi next word logic.
- * As with viPreviousWord() this probably needs to be improved
- * at some point.
- *
- * @param count number of iterations
- * @return true if the move was successful, false otherwise
- */
- private boolean viNextWord(int count) throws IOException {
- int pos = buf.cursor;
- int end = buf.buffer.length();
-
- for (int i = 0; pos < end && i < count; i++) {
- // Skip over letter/digits
- while (pos < end && !isDelimiter(buf.buffer.charAt(pos))) {
- ++pos;
- }
-
- /*
- * Don't you love special cases? During delete-to and yank-to
- * operations the word movement is normal. However, during a
- * change-to, the trailing spaces behind the last word are
- * left in tact.
- */
- if (i < (count-1) || !(state == State.VI_CHANGE_TO)) {
- while (pos < end && isDelimiter(buf.buffer.charAt(pos))) {
- ++pos;
- }
- }
- }
-
- setCursorPosition(pos);
- return true;
- }
-
- /**
- * Implements a close facsimile of the vi end-of-word movement.
- * If the character is on white space, it takes you to the end
- * of the next word. If it is on the last character of a word
- * it takes you to the next of the next word. Any other character
- * of a word, takes you to the end of the current word.
- *
- * @param count Number of times to repeat the action
- * @return true if it worked.
- */
- private boolean viEndWord(int count) throws IOException {
- int pos = buf.cursor;
- int end = buf.buffer.length();
-
- for (int i = 0; pos < end && i < count; i++) {
- if (pos < (end-1)
- && !isDelimiter(buf.buffer.charAt(pos))
- && isDelimiter(buf.buffer.charAt (pos+1))) {
- ++pos;
- }
-
- // If we are on white space, then move back.
- while (pos < end && isDelimiter(buf.buffer.charAt(pos))) {
- ++pos;
- }
-
- while (pos < (end-1) && !isDelimiter(buf.buffer.charAt(pos+1))) {
- ++pos;
- }
- }
- setCursorPosition(pos);
- return true;
- }
-
- private boolean previousWord() throws IOException {
- while (isDelimiter(buf.current()) && (moveCursor(-1) != 0)) {
- // nothing
- }
-
- while (!isDelimiter(buf.current()) && (moveCursor(-1) != 0)) {
- // nothing
- }
-
- return true;
- }
-
- private boolean nextWord() throws IOException {
- while (isDelimiter(buf.nextChar()) && (moveCursor(1) != 0)) {
- // nothing
- }
-
- while (!isDelimiter(buf.nextChar()) && (moveCursor(1) != 0)) {
- // nothing
- }
-
- return true;
- }
-
- /**
- * Deletes to the beginning of the word that the cursor is sitting on.
- * If the cursor is on white-space, it deletes that and to the beginning
- * of the word before it. If the user is not on a word or whitespace
- * it deletes up to the end of the previous word.
- *
- * @param count Number of times to perform the operation
- * @return true if it worked, false if you tried to delete too many words
- */
- private boolean unixWordRubout(int count) throws IOException {
- boolean success = true;
- StringBuilder killed = new StringBuilder();
-
- for (; count > 0; --count) {
- if (buf.cursor == 0) {
- success = false;
- break;
- }
-
- while (isWhitespace(buf.current())) {
- char c = buf.current();
- if (c == 0) {
- break;
- }
-
- killed.append(c);
- backspace();
- }
-
- while (!isWhitespace(buf.current())) {
- char c = buf.current();
- if (c == 0) {
- break;
- }
-
- killed.append(c);
- backspace();
- }
- }
-
- String copy = killed.reverse().toString();
- killRing.addBackwards(copy);
-
- return success;
- }
-
- private String insertComment(boolean isViMode) throws IOException {
- String comment = this.getCommentBegin();
- setCursorPosition(0);
- putString(comment);
- if (isViMode) {
- consoleKeys.setKeyMap(KeyMap.VI_INSERT);
- }
- return accept();
- }
-
- /**
- * Implements vi search ("/" or "?").
- */
- @SuppressWarnings("fallthrough")
- private int viSearch(char searchChar) throws IOException {
- boolean isForward = (searchChar == '/');
-
- /*
- * This is a little gross, I'm sure there is a more appropriate way
- * of saving and restoring state.
- */
- CursorBuffer origBuffer = buf.copy();
-
- // Clear the contents of the current line and
- setCursorPosition (0);
- killLine();
-
- // Our new "prompt" is the character that got us into search mode.
- putString(Character.toString(searchChar));
- flush();
-
- boolean isAborted = false;
- boolean isComplete = false;
-
- /*
- * Readline doesn't seem to do any special character map handling
- * here, so I think we are safe.
- */
- int ch = -1;
- while (!isAborted && !isComplete && (ch = readCharacter()) != -1) {
- switch (ch) {
- case '\033': // ESC
- /*
- * The ESC behavior doesn't appear to be readline behavior,
- * but it is a little tweak of my own. I like it.
- */
- isAborted = true;
- break;
- case '\010': // Backspace
- case '\177': // Delete
- backspace();
- /*
- * Backspacing through the "prompt" aborts the search.
- */
- if (buf.cursor == 0) {
- isAborted = true;
- }
- break;
- case '\012': // NL
- case '\015': // CR
- isComplete = true;
- break;
- default:
- putString(Character.toString((char) ch));
- }
-
- flush();
- }
-
- // If we aborted, then put ourself at the end of the original buffer.
- if (ch == -1 || isAborted) {
- setCursorPosition(0);
- killLine();
- putString(origBuffer.buffer);
- setCursorPosition(origBuffer.cursor);
- return -1;
- }
-
- /*
- * The first character of the buffer was the search character itself
- * so we discard it.
- */
- String searchTerm = buf.buffer.substring(1);
- int idx = -1;
-
- /*
- * The semantics of the history thing is gross when you want to
- * explicitly iterate over entries (without an iterator) as size()
- * returns the actual number of entries in the list but get()
- * doesn't work the way you think.
- */
- int end = history.index();
- int start = (end <= history.size()) ? 0 : end - history.size();
-
- if (isForward) {
- for (int i = start; i < end; i++) {
- if (history.get(i).toString().contains(searchTerm)) {
- idx = i;
- break;
- }
- }
- }
- else {
- for (int i = end-1; i >= start; i--) {
- if (history.get(i).toString().contains(searchTerm)) {
- idx = i;
- break;
- }
- }
- }
-
- /*
- * No match? Then restore what we were working on, but make sure
- * the cursor is at the beginning of the line.
- */
- if (idx == -1) {
- setCursorPosition(0);
- killLine();
- putString(origBuffer.buffer);
- setCursorPosition(0);
- return -1;
- }
-
- /*
- * Show the match.
- */
- setCursorPosition(0);
- killLine();
- putString(history.get(idx));
- setCursorPosition(0);
- flush();
-
- /*
- * While searching really only the "n" and "N" keys are interpreted
- * as movement, any other key is treated as if you are editing the
- * line with it, so we return it back up to the caller for interpretation.
- */
- isComplete = false;
- while (!isComplete && (ch = readCharacter()) != -1) {
- boolean forward = isForward;
- switch (ch) {
- case 'p': case 'P':
- forward = !isForward;
- // Fallthru
- case 'n': case 'N':
- boolean isMatch = false;
- if (forward) {
- for (int i = idx+1; !isMatch && i < end; i++) {
- if (history.get(i).toString().contains(searchTerm)) {
- idx = i;
- isMatch = true;
- }
- }
- }
- else {
- for (int i = idx - 1; !isMatch && i >= start; i--) {
- if (history.get(i).toString().contains(searchTerm)) {
- idx = i;
- isMatch = true;
- }
- }
- }
- if (isMatch) {
- setCursorPosition(0);
- killLine();
- putString(history.get(idx));
- setCursorPosition(0);
- }
- break;
- default:
- isComplete = true;
- }
- flush();
- }
-
- /*
- * Complete?
- */
- return ch;
- }
-
- public void setParenBlinkTimeout(int timeout) {
- parenBlinkTimeout = timeout;
- }
-
- private void insertClose(String s) throws IOException {
- putString(s);
- int closePosition = buf.cursor;
-
- moveCursor(-1);
- viMatch();
-
-
- if (in.isNonBlockingEnabled()) {
- in.peek(parenBlinkTimeout);
- }
-
- setCursorPosition(closePosition);
- flush();
- }
-
- /**
- * Implements vi style bracket matching ("%" command). The matching
- * bracket for the current bracket type that you are sitting on is matched.
- * The logic works like so:
- * @return true if it worked, false if the cursor was not on a bracket
- * character or if there was no matching bracket.
- */
- private boolean viMatch() throws IOException {
- int pos = buf.cursor;
-
- if (pos == buf.length()) {
- return false;
- }
-
- int type = getBracketType(buf.buffer.charAt (pos));
- int move = (type < 0) ? -1 : 1;
- int count = 1;
-
- if (type == 0)
- return false;
-
- while (count > 0) {
- pos += move;
-
- // Fell off the start or end.
- if (pos < 0 || pos >= buf.buffer.length ()) {
- return false;
- }
-
- int curType = getBracketType(buf.buffer.charAt (pos));
- if (curType == type) {
- ++count;
- }
- else if (curType == -type) {
- --count;
- }
- }
-
- /*
- * Slight adjustment for delete-to, yank-to, change-to to ensure
- * that the matching paren is consumed
- */
- if (move > 0 && isInViMoveOperationState())
- ++pos;
-
- setCursorPosition(pos);
- flush();
- return true;
- }
-
- /**
- * Given a character determines what type of bracket it is (paren,
- * square, curly, or none).
- * @param ch The character to check
- * @return 1 is square, 2 curly, 3 parent, or zero for none. The value
- * will be negated if it is the closing form of the bracket.
- */
- private static int getBracketType (char ch) {
- switch (ch) {
- case '[': return 1;
- case ']': return -1;
- case '{': return 2;
- case '}': return -2;
- case '(': return 3;
- case ')': return -3;
- default:
- return 0;
- }
- }
-
- private boolean deletePreviousWord() throws IOException {
- StringBuilder killed = new StringBuilder();
- char c;
-
- while (isDelimiter((c = buf.current()))) {
- if (c == 0) {
- break;
- }
-
- killed.append(c);
- backspace();
- }
-
- while (!isDelimiter((c = buf.current()))) {
- if (c == 0) {
- break;
- }
-
- killed.append(c);
- backspace();
- }
-
- String copy = killed.reverse().toString();
- killRing.addBackwards(copy);
- return true;
- }
-
- private boolean deleteNextWord() throws IOException {
- StringBuilder killed = new StringBuilder();
- char c;
-
- while (isDelimiter((c = buf.nextChar()))) {
- if (c == 0) {
- break;
- }
- killed.append(c);
- delete();
- }
-
- while (!isDelimiter((c = buf.nextChar()))) {
- if (c == 0) {
- break;
- }
- killed.append(c);
- delete();
- }
-
- String copy = killed.toString();
- killRing.add(copy);
-
- return true;
- }
-
- private boolean capitalizeWord() throws IOException {
- boolean first = true;
- int i = 1;
- char c;
- while (buf.cursor + i - 1< buf.length() && !isDelimiter((c = buf.buffer.charAt(buf.cursor + i - 1)))) {
- buf.buffer.setCharAt(buf.cursor + i - 1, first ? Character.toUpperCase(c) : Character.toLowerCase(c));
- first = false;
- i++;
- }
- drawBuffer();
- moveCursor(i - 1);
- return true;
- }
-
- private boolean upCaseWord() throws IOException {
- int i = 1;
- char c;
- while (buf.cursor + i - 1 < buf.length() && !isDelimiter((c = buf.buffer.charAt(buf.cursor + i - 1)))) {
- buf.buffer.setCharAt(buf.cursor + i - 1, Character.toUpperCase(c));
- i++;
- }
- drawBuffer();
- moveCursor(i - 1);
- return true;
- }
-
- private boolean downCaseWord() throws IOException {
- int i = 1;
- char c;
- while (buf.cursor + i - 1 < buf.length() && !isDelimiter((c = buf.buffer.charAt(buf.cursor + i - 1)))) {
- buf.buffer.setCharAt(buf.cursor + i - 1, Character.toLowerCase(c));
- i++;
- }
- drawBuffer();
- moveCursor(i - 1);
- return true;
- }
-
- /**
- * Performs character transpose. The character prior to the cursor and the
- * character under the cursor are swapped and the cursor is advanced one
- * character unless you are already at the end of the line.
- *
- * @param count The number of times to perform the transpose
- * @return true if the operation succeeded, false otherwise (e.g. transpose
- * cannot happen at the beginning of the line).
- */
- private boolean transposeChars(int count) throws IOException {
- for (; count > 0; --count) {
- if (buf.cursor == 0 || buf.cursor == buf.buffer.length()) {
- return false;
- }
-
- int first = buf.cursor-1;
- int second = buf.cursor;
-
- char tmp = buf.buffer.charAt (first);
- buf.buffer.setCharAt(first, buf.buffer.charAt(second));
- buf.buffer.setCharAt(second, tmp);
-
- // This could be done more efficiently by only re-drawing at the end.
- moveInternal(-1);
- drawBuffer();
- moveInternal(2);
- }
-
- return true;
- }
-
- public boolean isKeyMap(String name) {
- // Current keymap.
- KeyMap map = consoleKeys.getKeys();
- KeyMap mapByName = consoleKeys.getKeyMaps().get(name);
-
- if (mapByName == null)
- return false;
-
- /*
- * This may not be safe to do, but there doesn't appear to be a
- * clean way to find this information out.
- */
- return map == mapByName;
- }
-
-
- /**
- * The equivalent of hitting <RET>. The line is considered
- * complete and is returned.
- *
- * @return The completed line of text.
- */
- public String accept() throws IOException {
- moveToEnd();
- println(); // output newline
- flush();
- return finishBuffer();
- }
-
- private void abort() throws IOException {
- beep();
- buf.clear();
- println();
- redrawLine();
- }
-
- /**
- * Move the cursor where characters.
- *
- * @param num If less than 0, move abs(where) to the left, otherwise move where to the right.
- * @return The number of spaces we moved
- */
- public int moveCursor(final int num) throws IOException {
- int where = num;
-
- if ((buf.cursor == 0) && (where <= 0)) {
- return 0;
- }
-
- if ((buf.cursor == buf.buffer.length()) && (where >= 0)) {
- return 0;
- }
-
- if ((buf.cursor + where) < 0) {
- where = -buf.cursor;
- }
- else if ((buf.cursor + where) > buf.buffer.length()) {
- where = buf.buffer.length() - buf.cursor;
- }
-
- moveInternal(where);
-
- return where;
- }
-
- /**
- * Move the cursor where characters, without checking the current buffer.
- *
- * @param where the number of characters to move to the right or left.
- */
- private void moveInternal(final int where) throws IOException {
- // debug ("move cursor " + where + " ("
- // + buf.cursor + " => " + (buf.cursor + where) + ")");
- buf.cursor += where;
-
- int i0;
- int i1;
- if (mask == null) {
- if (where < 0) {
- i1 = promptLen + wcwidth(buf.buffer, 0, buf.cursor, promptLen);
- i0 = i1 + wcwidth(buf.buffer, buf.cursor, buf.cursor - where, i1);
- } else {
- i0 = promptLen + wcwidth(buf.buffer, 0, buf.cursor - where, promptLen);
- i1 = i0 + wcwidth(buf.buffer, buf.cursor - where, buf.cursor, i0);
- }
- } else if (mask != NULL_MASK) {
- i1 = promptLen + buf.cursor;
- i0 = i1 - where;
- } else {
- return;
- }
- moveCursorFromTo(i0, i1);
- }
-
- private void moveCursorFromTo(int i0, int i1) throws IOException {
- if (i0 == i1) return;
- int width = getTerminal().getWidth();
- int l0 = i0 / width;
- int c0 = i0 % width;
- int l1 = i1 / width;
- int c1 = i1 % width;
- if (l0 == l1 + 1) {
- if (!tputs("cursor_up")) {
- tputs("parm_up_cursor", 1);
- }
- } else if (l0 > l1) {
- if (!tputs("parm_up_cursor", l0 - l1)) {
- for (int i = l1; i < l0; i++) {
- tputs("cursor_up");
- }
- }
- } else if (l0 < l1) {
- tputs("carriage_return");
- rawPrint('\n', l1 - l0);
- c0 = 0;
- }
- if (c0 == c1 - 1) {
- tputs("cursor_right");
- } else if (c0 == c1 + 1) {
- tputs("cursor_left");
- } else if (c0 < c1) {
- if (!tputs("parm_right_cursor", c1 - c0)) {
- for (int i = c0; i < c1; i++) {
- tputs("cursor_right");
- }
- }
- } else if (c0 > c1) {
- if (!tputs("parm_left_cursor", c0 - c1)) {
- for (int i = c1; i < c0; i++) {
- tputs("cursor_left");
- }
- }
- }
- cursorOk = true;
- }
-
- /**
- * Read a character from the console.
- *
- * @return the character, or -1 if an EOF is received.
- */
- public int readCharacter() throws IOException {
- return readCharacter(false);
- }
-
- /**
- * Read a character from the console. If boolean parameter is "true", it will check whether the keystroke was an "alt-" key combination, and
- * if so add 1000 to the value returned. Better way...?
- *
- * @return the character, or -1 if an EOF is received.
- */
- public int readCharacter(boolean checkForAltKeyCombo) throws IOException {
- int c = reader.read();
- if (c >= 0) {
- lib.jline.internal.Log.trace("Keystroke: ", c);
- // cleanUp any echo characters
- if (terminal.isSupported()) {
- clearEcho(c);
- }
- if (c == ESCAPE && checkForAltKeyCombo && in.peek(escapeTimeout) >= 32) {
- /* When ESC is encountered and there is a pending
- * character in the pushback queue, then it seems to be
- * an Alt-[key] combination. Is this true, cross-platform?
- * It's working for me on Debian GNU/Linux at the moment anyway.
- * I removed the "isNonBlockingEnabled" check, though it was
- * in the similar code in "readLine(String prompt, final Character mask)" (way down),
- * as I am not sure / didn't look up what it's about, and things are working so far w/o it.
- */
- int next = reader.read();
- // with research, there's probably a much cleaner way to do this, but, this is now it flags an Alt key combination for now:
- next = next + 1000;
- return next;
- }
- }
- return c;
- }
-
- /**
- * Clear the echoed characters for the specified character code.
- */
- private int clearEcho(final int c) throws IOException {
- // if the terminal is not echoing, then ignore
- if (!terminal.isEchoEnabled()) {
- return 0;
- }
-
- // otherwise, cleanUp
- int pos = getCursorPosition();
- int num = wcwidth(c, pos);
- moveCursorFromTo(pos + num, pos);
- drawBuffer(num);
-
- return num;
- }
-
- public int readCharacter(final char... allowed) throws IOException {
- return readCharacter(false, allowed);
- }
-
- public int readCharacter(boolean checkForAltKeyCombo, final char... allowed) throws IOException {
- // if we restrict to a limited set and the current character is not in the set, then try again.
- char c;
-
- Arrays.sort(allowed); // always need to sort before binarySearch
-
- while (Arrays.binarySearch(allowed, c = (char) readCharacter(checkForAltKeyCombo)) < 0) {
- // nothing
- }
-
- return c;
- }
-
- /**
- * Read from the input stream and decode an operation from the key map.
- *
- * The input stream will be read character by character until a matching
- * binding can be found. Characters that can't possibly be matched to
- * any binding will be discarded.
- *
- * @param keys the KeyMap to use for decoding the input stream
- * @return the decoded binding or null if the end of
- * stream has been reached
- */
- public Object readBinding(KeyMap keys) throws IOException {
- Object o;
- opBuffer.setLength(0);
- do {
- int c = pushBackChar.isEmpty() ? readCharacter() : pushBackChar.pop();
- if (c == -1) {
- return null;
- }
- opBuffer.appendCodePoint(c);
-
- if (recording) {
- macro += new String(Character.toChars(c));
- }
-
- if (quotedInsert) {
- o = lib.jline.console.Operation.SELF_INSERT;
- quotedInsert = false;
- } else {
- o = keys.getBound(opBuffer);
- }
-
- /*
- * The kill ring keeps record of whether or not the
- * previous command was a yank or a kill. We reset
- * that state here if needed.
- */
- if (!recording && !(o instanceof KeyMap)) {
- if (o != lib.jline.console.Operation.YANK_POP && o != lib.jline.console.Operation.YANK) {
- killRing.resetLastYank();
- }
- if (o != lib.jline.console.Operation.KILL_LINE && o != lib.jline.console.Operation.KILL_WHOLE_LINE
- && o != lib.jline.console.Operation.BACKWARD_KILL_WORD && o != lib.jline.console.Operation.KILL_WORD
- && o != lib.jline.console.Operation.UNIX_LINE_DISCARD && o != lib.jline.console.Operation.UNIX_WORD_RUBOUT) {
- killRing.resetLastKill();
- }
- }
-
- if (o == lib.jline.console.Operation.DO_LOWERCASE_VERSION) {
- opBuffer.setLength(opBuffer.length() - 1);
- opBuffer.append(Character.toLowerCase((char) c));
- o = keys.getBound(opBuffer);
- }
-
- /*
- * A KeyMap indicates that the key that was struck has a
- * number of keys that can follow it as indicated in the
- * map. This is used primarily for Emacs style ESC-META-x
- * lookups. Since more keys must follow, go back to waiting
- * for the next key.
- */
- if (o instanceof KeyMap) {
- /*
- * The ESC key (#27) is special in that it is ambiguous until
- * you know what is coming next. The ESC could be a literal
- * escape, like the user entering vi-move mode, or it could
- * be part of a terminal control sequence. The following
- * logic attempts to disambiguate things in the same
- * fashion as regular vi or readline.
- *
- * When ESC is encountered and there is no other pending
- * character in the pushback queue, then attempt to peek
- * into the input stream (if the feature is enabled) for
- * 150ms. If nothing else is coming, then assume it is
- * not a terminal control sequence, but a raw escape.
- */
- if (c == ESCAPE
- && pushBackChar.isEmpty()
- && in.isNonBlockingEnabled()
- && in.peek(escapeTimeout) == READ_EXPIRED) {
- o = ((KeyMap) o).getAnotherKey();
- if (o == null || o instanceof KeyMap) {
- continue;
- }
- opBuffer.setLength(0);
- } else {
- continue;
- }
- }
-
- /*
- * If we didn't find a binding for the key and there is
- * more than one character accumulated then start checking
- * the largest span of characters from the beginning to
- * see if there is a binding for them.
- *
- * For example if our buffer has ESC,CTRL-M,C the getBound()
- * called previously indicated that there is no binding for
- * this sequence, so this then checks ESC,CTRL-M, and failing
- * that, just ESC. Each keystroke that is pealed off the end
- * during these tests is stuffed onto the pushback buffer so
- * they won't be lost.
- *
- * If there is no binding found, then we go back to waiting for
- * input.
- */
- while (o == null && opBuffer.length() > 0) {
- c = opBuffer.charAt(opBuffer.length() - 1);
- opBuffer.setLength(opBuffer.length() - 1);
- Object o2 = keys.getBound(opBuffer);
- if (o2 instanceof KeyMap) {
- o = ((KeyMap) o2).getAnotherKey();
- if (o == null) {
- continue;
- } else {
- pushBackChar.push((char) c);
- }
- }
- }
-
- } while (o == null || o instanceof KeyMap);
-
- return o;
- }
-
- public String getLastBinding() {
- return opBuffer.toString();
- }
-
- //
- // Key Bindings
- //
-
- public static final String JLINE_COMPLETION_THRESHOLD = "jline.completion.threshold";
-
- //
- // Line Reading
- //
-
- /**
- * Read the next line and return the contents of the buffer.
- */
- public String readLine() throws IOException {
- return readLine((String) null);
- }
-
- /**
- * Read the next line with the specified character mask. If null, then
- * characters will be echoed. If 0, then no characters will be echoed.
- */
- public String readLine(final Character mask) throws IOException {
- return readLine(null, mask);
- }
-
- public String readLine(final String prompt) throws IOException {
- return readLine(prompt, null);
- }
-
- /**
- * Read a line from the in {@link InputStream}, and return the line
- * (without any trailing newlines).
- *
- * @param prompt The prompt to issue to the console, may be null.
- * @return A line that is read from the terminal, or null if there was null input (e.g., CTRL-D
- * was pressed).
- */
- public String readLine(String prompt, final Character mask) throws IOException {
- return readLine(prompt, mask, null);
- }
-
- /**
- * Sets the current keymap by name. Supported keymaps are "emacs",
- * "vi-insert", "vi-move".
- * @param name The name of the keymap to switch to
- * @return true if the keymap was set, or false if the keymap is
- * not recognized.
- */
- public boolean setKeyMap(String name) {
- return consoleKeys.setKeyMap(name);
- }
-
- /**
- * Returns the name of the current key mapping.
- * @return the name of the key mapping. This will be the canonical name
- * of the current mode of the key map and may not reflect the name that
- * was used with {@link #setKeyMap(String)}.
- */
- public String getKeyMap() {
- return consoleKeys.getKeys().getName();
- }
-
- /**
- * Read a line from the in {@link InputStream}, and return the line
- * (without any trailing newlines).
- *
- * @param prompt The prompt to issue to the console, may be null.
- * @return A line that is read from the terminal, or null if there was null input (e.g., CTRL-D
- * was pressed).
- */
- public String readLine(String prompt, final Character mask, String buffer) throws IOException {
- // prompt may be null
- // mask may be null
- // buffer may be null
-
- /*
- * This is the accumulator for VI-mode repeat count. That is, while in
- * move mode, if you type 30x it will delete 30 characters. This is
- * where the "30" is accumulated until the command is struck.
- */
- int repeatCount = 0;
-
- // FIXME: This blows, each call to readLine will reset the console's state which doesn't seem very nice.
- this.mask = mask != null ? mask : this.echoCharacter;
- if (prompt != null) {
- setPrompt(prompt);
- }
- else {
- prompt = getPrompt();
- }
-
- try {
- if (buffer != null) {
- buf.write(buffer);
- }
-
- if (!terminal.isSupported()) {
- beforeReadLine(prompt, mask);
- }
-
- if (buffer != null && buffer.length() > 0
- || prompt != null && prompt.length() > 0) {
- drawLine();
- out.flush();
- }
-
- // if the terminal is unsupported, just use plain-java reading
- if (!terminal.isSupported()) {
- return readLineSimple();
- }
-
- if (handleUserInterrupt) {
- terminal.disableInterruptCharacter();
- }
- if (handleLitteralNext && (terminal instanceof lib.jline.UnixTerminal)) {
- ((lib.jline.UnixTerminal) terminal).disableLitteralNextCharacter();
- }
-
- String originalPrompt = this.prompt;
-
- state = State.NORMAL;
-
- boolean success = true;
-
- pushBackChar.clear();
- while (true) {
-
- Object o = readBinding(getKeys());
- if (o == null) {
- return null;
- }
- int c = 0;
- if (opBuffer.length() > 0) {
- c = opBuffer.codePointBefore(opBuffer.length());
- }
- lib.jline.internal.Log.trace("Binding: ", o);
-
-
- // Handle macros
- if (o instanceof String) {
- String macro = (String) o;
- for (int i = 0; i < macro.length(); i++) {
- pushBackChar.push(macro.charAt(macro.length() - 1 - i));
- }
- opBuffer.setLength(0);
- continue;
- }
-
- // Handle custom callbacks
- if (o instanceof ActionListener) {
- ((ActionListener) o).actionPerformed(null);
- opBuffer.setLength(0);
- continue;
- }
-
- CursorBuffer oldBuf = new CursorBuffer();
- oldBuf.buffer.append(buf.buffer);
- oldBuf.cursor = buf.cursor;
-
- // Search mode.
- //
- // Note that we have to do this first, because if there is a command
- // not linked to a search command, we leave the search mode and fall
- // through to the normal state.
- if (state == State.SEARCH || state == State.FORWARD_SEARCH) {
- int cursorDest = -1;
- // TODO: check the isearch-terminators variable terminating the search
- switch ( ((lib.jline.console.Operation) o )) {
- case ABORT:
- state = State.NORMAL;
- buf.clear();
- buf.write(originalBuffer.buffer);
- buf.cursor = originalBuffer.cursor;
- break;
-
- case REVERSE_SEARCH_HISTORY:
- state = State.SEARCH;
- if (searchTerm.length() == 0) {
- searchTerm.append(previousSearchTerm);
- }
-
- if (searchIndex > 0) {
- searchIndex = searchBackwards(searchTerm.toString(), searchIndex);
- }
- break;
-
- case FORWARD_SEARCH_HISTORY:
- state = State.FORWARD_SEARCH;
- if (searchTerm.length() == 0) {
- searchTerm.append(previousSearchTerm);
- }
-
- if (searchIndex > -1 && searchIndex < history.size() - 1) {
- searchIndex = searchForwards(searchTerm.toString(), searchIndex);
- }
- break;
-
- case BACKWARD_DELETE_CHAR:
- if (searchTerm.length() > 0) {
- searchTerm.deleteCharAt(searchTerm.length() - 1);
- if (state == State.SEARCH) {
- searchIndex = searchBackwards(searchTerm.toString());
- } else {
- searchIndex = searchForwards(searchTerm.toString());
- }
- }
- break;
-
- case SELF_INSERT:
- searchTerm.appendCodePoint(c);
- if (state == State.SEARCH) {
- searchIndex = searchBackwards(searchTerm.toString());
- } else {
- searchIndex = searchForwards(searchTerm.toString());
- }
- break;
-
- default:
- // Set buffer and cursor position to the found string.
- if (searchIndex != -1) {
- history.moveTo(searchIndex);
- // set cursor position to the found string
- cursorDest = history.current().toString().indexOf(searchTerm.toString());
- }
- if (o != lib.jline.console.Operation.ACCEPT_LINE) {
- o = null;
- }
- state = State.NORMAL;
- break;
- }
-
- // if we're still in search mode, print the search status
- if (state == State.SEARCH || state == State.FORWARD_SEARCH) {
- if (searchTerm.length() == 0) {
- if (state == State.SEARCH) {
- printSearchStatus("", "");
- } else {
- printForwardSearchStatus("", "");
- }
- searchIndex = -1;
- } else {
- if (searchIndex == -1) {
- beep();
- printSearchStatus(searchTerm.toString(), "");
- } else if (state == State.SEARCH) {
- printSearchStatus(searchTerm.toString(), history.get(searchIndex).toString());
- } else {
- printForwardSearchStatus(searchTerm.toString(), history.get(searchIndex).toString());
- }
- }
- }
- // otherwise, restore the line
- else {
- restoreLine(originalPrompt, cursorDest);
- }
- }
- if (state != State.SEARCH && state != State.FORWARD_SEARCH) {
- /*
- * If this is still false at the end of the switch, then
- * we reset our repeatCount to 0.
- */
- boolean isArgDigit = false;
-
- /*
- * Every command that can be repeated a specified number
- * of times, needs to know how many times to repeat, so
- * we figure that out here.
- */
- int count = (repeatCount == 0) ? 1 : repeatCount;
-
- /*
- * Default success to true. You only need to explicitly
- * set it if something goes wrong.
- */
- success = true;
-
- if (o instanceof lib.jline.console.Operation) {
- lib.jline.console.Operation op = (lib.jline.console.Operation)o;
- /*
- * Current location of the cursor (prior to the operation).
- * These are used by vi *-to operation (e.g. delete-to)
- * so we know where we came from.
- */
- int cursorStart = buf.cursor;
- State origState = state;
-
- /*
- * If we are on a "vi" movement based operation, then we
- * need to restrict the sets of inputs pretty heavily.
- */
- if (state == State.VI_CHANGE_TO
- || state == State.VI_YANK_TO
- || state == State.VI_DELETE_TO) {
-
- op = viDeleteChangeYankToRemap(op);
- }
-
- switch ( op ) {
- case COMPLETE: // tab
- // There is an annoyance with tab completion in that
- // sometimes the user is actually pasting input in that
- // has physical tabs in it. This attempts to look at how
- // quickly a character follows the tab, if the character
- // follows *immediately*, we assume it is a tab literal.
- boolean isTabLiteral = false;
- if (copyPasteDetection
- && c == 9
- && (!pushBackChar.isEmpty()
- || (in.isNonBlockingEnabled() && in.peek(escapeTimeout) != -2))) {
- isTabLiteral = true;
- }
-
- if (! isTabLiteral) {
- success = complete();
- }
- else {
- putString(opBuffer);
- }
- break;
-
- case POSSIBLE_COMPLETIONS:
- printCompletionCandidates();
- break;
-
- case BEGINNING_OF_LINE:
- success = setCursorPosition(0);
- break;
-
- case YANK:
- success = yank();
- break;
-
- case YANK_POP:
- success = yankPop();
- break;
-
- case KILL_LINE: // CTRL-K
- success = killLine();
- break;
-
- case KILL_WHOLE_LINE:
- success = setCursorPosition(0) && killLine();
- break;
-
- case CLEAR_SCREEN: // CTRL-L
- success = clearScreen();
- redrawLine();
- break;
-
- case OVERWRITE_MODE:
- buf.setOverTyping(!buf.isOverTyping());
- break;
-
- case SELF_INSERT:
- putString(opBuffer);
- break;
-
- case ACCEPT_LINE:
- return accept();
-
- case ABORT:
- if (searchTerm == null) {
- abort();
- }
- break;
-
- case INTERRUPT:
- if (handleUserInterrupt) {
- println();
- flush();
- String partialLine = buf.buffer.toString();
- buf.clear();
- history.moveToEnd();
- throw new UserInterruptException(partialLine);
- }
- break;
-
- /*
- * VI_MOVE_ACCEPT_LINE is the result of an ENTER
- * while in move mode. This is the same as a normal
- * ACCEPT_LINE, except that we need to enter
- * insert mode as well.
- */
- case VI_MOVE_ACCEPT_LINE:
- consoleKeys.setKeyMap(KeyMap.VI_INSERT);
- return accept();
-
- case BACKWARD_WORD:
- success = previousWord();
- break;
-
- case FORWARD_WORD:
- success = nextWord();
- break;
-
- case PREVIOUS_HISTORY:
- success = moveHistory(false);
- break;
-
- /*
- * According to bash/readline move through history
- * in "vi" mode will move the cursor to the
- * start of the line. If there is no previous
- * history, then the cursor doesn't move.
- */
- case VI_PREVIOUS_HISTORY:
- success = moveHistory(false, count)
- && setCursorPosition(0);
- break;
-
- case NEXT_HISTORY:
- success = moveHistory(true);
- break;
-
- /*
- * According to bash/readline move through history
- * in "vi" mode will move the cursor to the
- * start of the line. If there is no next history,
- * then the cursor doesn't move.
- */
- case VI_NEXT_HISTORY:
- success = moveHistory(true, count)
- && setCursorPosition(0);
- break;
-
- case BACKWARD_DELETE_CHAR: // backspace
- success = backspace();
- break;
-
- case EXIT_OR_DELETE_CHAR:
- if (buf.buffer.length() == 0) {
- return null;
- }
- success = deleteCurrentCharacter();
- break;
-
- case DELETE_CHAR: // delete
- success = deleteCurrentCharacter();
- break;
-
- case BACKWARD_CHAR:
- success = moveCursor(-(count)) != 0;
- break;
-
- case FORWARD_CHAR:
- success = moveCursor(count) != 0;
- break;
-
- case UNIX_LINE_DISCARD:
- success = resetLine();
- break;
-
- case UNIX_WORD_RUBOUT:
- success = unixWordRubout(count);
- break;
-
- case BACKWARD_KILL_WORD:
- success = deletePreviousWord();
- break;
-
- case KILL_WORD:
- success = deleteNextWord();
- break;
-
- case BEGINNING_OF_HISTORY:
- success = history.moveToFirst();
- if (success) {
- setBuffer(history.current());
- }
- break;
-
- case END_OF_HISTORY:
- success = history.moveToLast();
- if (success) {
- setBuffer(history.current());
- }
- break;
-
- case HISTORY_SEARCH_BACKWARD:
- searchTerm = new StringBuffer(buf.upToCursor());
- searchIndex = searchBackwards(searchTerm.toString(), history.index(), true);
-
- if (searchIndex == -1) {
- beep();
- } else {
- // Maintain cursor position while searching.
- success = history.moveTo(searchIndex);
- if (success) {
- setBufferKeepPos(history.current());
- }
- }
- break;
-
- case HISTORY_SEARCH_FORWARD:
- searchTerm = new StringBuffer(buf.upToCursor());
- int index = history.index() + 1;
-
- if (index == history.size()) {
- history.moveToEnd();
- setBufferKeepPos(searchTerm.toString());
- } else if (index < history.size()) {
- searchIndex = searchForwards(searchTerm.toString(), index, true);
- if (searchIndex == -1) {
- beep();
- } else {
- // Maintain cursor position while searching.
- success = history.moveTo(searchIndex);
- if (success) {
- setBufferKeepPos(history.current());
- }
- }
- }
- break;
-
- case REVERSE_SEARCH_HISTORY:
- originalBuffer = new CursorBuffer();
- originalBuffer.write(buf.buffer);
- originalBuffer.cursor = buf.cursor;
- if (searchTerm != null) {
- previousSearchTerm = searchTerm.toString();
- }
- searchTerm = new StringBuffer(buf.buffer);
- state = State.SEARCH;
- if (searchTerm.length() > 0) {
- searchIndex = searchBackwards(searchTerm.toString());
- if (searchIndex == -1) {
- beep();
- }
- printSearchStatus(searchTerm.toString(),
- searchIndex > -1 ? history.get(searchIndex).toString() : "");
- } else {
- searchIndex = -1;
- printSearchStatus("", "");
- }
- break;
-
- case FORWARD_SEARCH_HISTORY:
- originalBuffer = new CursorBuffer();
- originalBuffer.write(buf.buffer);
- originalBuffer.cursor = buf.cursor;
- if (searchTerm != null) {
- previousSearchTerm = searchTerm.toString();
- }
- searchTerm = new StringBuffer(buf.buffer);
- state = State.FORWARD_SEARCH;
- if (searchTerm.length() > 0) {
- searchIndex = searchForwards(searchTerm.toString());
- if (searchIndex == -1) {
- beep();
- }
- printForwardSearchStatus(searchTerm.toString(),
- searchIndex > -1 ? history.get(searchIndex).toString() : "");
- } else {
- searchIndex = -1;
- printForwardSearchStatus("", "");
- }
- break;
-
- case CAPITALIZE_WORD:
- success = capitalizeWord();
- break;
-
- case UPCASE_WORD:
- success = upCaseWord();
- break;
-
- case DOWNCASE_WORD:
- success = downCaseWord();
- break;
-
- case END_OF_LINE:
- success = moveToEnd();
- break;
-
- case TAB_INSERT:
- putString( "\t" );
- break;
-
- case RE_READ_INIT_FILE:
- consoleKeys.loadKeys(appName, inputrcUrl);
- break;
-
- case START_KBD_MACRO:
- recording = true;
- break;
-
- case END_KBD_MACRO:
- recording = false;
- macro = macro.substring(0, macro.length() - opBuffer.length());
- break;
-
- case CALL_LAST_KBD_MACRO:
- for (int i = 0; i < macro.length(); i++) {
- pushBackChar.push(macro.charAt(macro.length() - 1 - i));
- }
- opBuffer.setLength(0);
- break;
-
- case VI_EDITING_MODE:
- consoleKeys.setKeyMap(KeyMap.VI_INSERT);
- break;
-
- case VI_MOVEMENT_MODE:
- /*
- * If we are re-entering move mode from an
- * aborted yank-to, delete-to, change-to then
- * don't move the cursor back. The cursor is
- * only move on an expclit entry to movement
- * mode.
- */
- if (state == State.NORMAL) {
- moveCursor(-1);
- }
- consoleKeys.setKeyMap(KeyMap.VI_MOVE);
- break;
-
- case VI_INSERTION_MODE:
- consoleKeys.setKeyMap(KeyMap.VI_INSERT);
- break;
-
- case VI_APPEND_MODE:
- moveCursor(1);
- consoleKeys.setKeyMap(KeyMap.VI_INSERT);
- break;
-
- case VI_APPEND_EOL:
- success = moveToEnd();
- consoleKeys.setKeyMap(KeyMap.VI_INSERT);
- break;
-
- /*
- * Handler for CTRL-D. Attempts to follow readline
- * behavior. If the line is empty, then it is an EOF
- * otherwise it is as if the user hit enter.
- */
- case VI_EOF_MAYBE:
- if (buf.buffer.length() == 0) {
- return null;
- }
- return accept();
-
- case TRANSPOSE_CHARS:
- success = transposeChars(count);
- break;
-
- case INSERT_COMMENT:
- return insertComment (false);
-
- case INSERT_CLOSE_CURLY:
- insertClose("}");
- break;
-
- case INSERT_CLOSE_PAREN:
- insertClose(")");
- break;
-
- case INSERT_CLOSE_SQUARE:
- insertClose("]");
- break;
-
- case VI_INSERT_COMMENT:
- return insertComment (true);
-
- case VI_MATCH:
- success = viMatch ();
- break;
-
- case VI_SEARCH:
- int lastChar = viSearch(opBuffer.charAt(0));
- if (lastChar != -1) {
- pushBackChar.push((char)lastChar);
- }
- break;
-
- case VI_ARG_DIGIT:
- repeatCount = (repeatCount * 10) + opBuffer.charAt(0) - '0';
- isArgDigit = true;
- break;
-
- case VI_BEGINNING_OF_LINE_OR_ARG_DIGIT:
- if (repeatCount > 0) {
- repeatCount = (repeatCount * 10) + opBuffer.charAt(0) - '0';
- isArgDigit = true;
- }
- else {
- success = setCursorPosition(0);
- }
- break;
-
- case VI_FIRST_PRINT:
- success = setCursorPosition(0) && viNextWord(1);
- break;
-
- case VI_PREV_WORD:
- success = viPreviousWord(count);
- break;
-
- case VI_NEXT_WORD:
- success = viNextWord(count);
- break;
-
- case VI_END_WORD:
- success = viEndWord(count);
- break;
-
- case VI_INSERT_BEG:
- success = setCursorPosition(0);
- consoleKeys.setKeyMap(KeyMap.VI_INSERT);
- break;
-
- case VI_RUBOUT:
- success = viRubout(count);
- break;
-
- case VI_DELETE:
- success = viDelete(count);
- break;
-
- case VI_DELETE_TO:
- /*
- * This is a weird special case. In vi
- * "dd" deletes the current line. So if we
- * get a delete-to, followed by a delete-to,
- * we delete the line.
- */
- if (state == State.VI_DELETE_TO) {
- success = setCursorPosition(0) && killLine();
- state = origState = State.NORMAL;
- }
- else {
- state = State.VI_DELETE_TO;
- }
- break;
-
- case VI_YANK_TO:
- // Similar to delete-to, a "yy" yanks the whole line.
- if (state == State.VI_YANK_TO) {
- yankBuffer = buf.buffer.toString();
- state = origState = State.NORMAL;
- }
- else {
- state = State.VI_YANK_TO;
- }
- break;
-
- case VI_CHANGE_TO:
- if (state == State.VI_CHANGE_TO) {
- success = setCursorPosition(0) && killLine();
- state = origState = State.NORMAL;
- consoleKeys.setKeyMap(KeyMap.VI_INSERT);
- }
- else {
- state = State.VI_CHANGE_TO;
- }
- break;
-
- case VI_KILL_WHOLE_LINE:
- success = setCursorPosition(0) && killLine();
- consoleKeys.setKeyMap(KeyMap.VI_INSERT);
- break;
-
- case VI_PUT:
- success = viPut(count);
- break;
-
- case VI_CHAR_SEARCH: {
- // ';' and ',' don't need another character. They indicate repeat next or repeat prev.
- int searchChar = (c != ';' && c != ',')
- ? (pushBackChar.isEmpty()
- ? readCharacter()
- : pushBackChar.pop ())
- : 0;
-
- success = viCharSearch(count, c, searchChar);
- }
- break;
-
- case VI_CHANGE_CASE:
- success = viChangeCase(count);
- break;
-
- case VI_CHANGE_CHAR:
- success = viChangeChar(count,
- pushBackChar.isEmpty()
- ? readCharacter()
- : pushBackChar.pop());
- break;
-
- case VI_DELETE_TO_EOL:
- success = viDeleteTo(buf.cursor, buf.buffer.length(), false);
- break;
-
- case VI_CHANGE_TO_EOL:
- success = viDeleteTo(buf.cursor, buf.buffer.length(), true);
- consoleKeys.setKeyMap(KeyMap.VI_INSERT);
- break;
-
- case EMACS_EDITING_MODE:
- consoleKeys.setKeyMap(KeyMap.EMACS);
- break;
-
- case QUIT:
- getCursorBuffer().clear();
- return accept();
-
- case QUOTED_INSERT:
- quotedInsert = true;
- break;
-
- case PASTE_FROM_CLIPBOARD:
- paste();
- break;
-
- default:
- break;
- }
-
- /*
- * If we were in a yank-to, delete-to, move-to
- * when this operation started, then fall back to
- */
- if (origState != State.NORMAL) {
- if (origState == State.VI_DELETE_TO) {
- success = viDeleteTo(cursorStart, buf.cursor, false);
- }
- else if (origState == State.VI_CHANGE_TO) {
- success = viDeleteTo(cursorStart, buf.cursor, true);
- consoleKeys.setKeyMap(KeyMap.VI_INSERT);
- }
- else if (origState == State.VI_YANK_TO) {
- success = viYankTo(cursorStart, buf.cursor);
- }
- state = State.NORMAL;
- }
-
- /*
- * Another subtly. The check for the NORMAL state is
- * to ensure that we do not cleanUp out the repeat
- * count when in delete-to, yank-to, or move-to modes.
- */
- if (state == State.NORMAL && !isArgDigit) {
- /*
- * If the operation performed wasn't a vi argument
- * digit, then cleanUp out the current repeatCount;
- */
- repeatCount = 0;
- }
-
- if (state != State.SEARCH && state != State.FORWARD_SEARCH) {
- originalBuffer = null;
- previousSearchTerm = "";
- searchTerm = null;
- searchIndex = -1;
- }
- }
- }
- if (!success) {
- beep();
- }
- opBuffer.setLength(0);
-
- flush();
- }
- }
- finally {
- if (!terminal.isSupported()) {
- afterReadLine();
- }
- if (handleUserInterrupt) {
- terminal.enableInterruptCharacter();
- }
- }
- }
-
- /**
- * Read a line for unsupported terminals.
- */
- private String readLineSimple() throws IOException {
- StringBuilder buff = new StringBuilder();
-
- if (skipLF) {
- skipLF = false;
-
- int i = readCharacter();
-
- if (i == -1 || i == '\r') {
- return buff.toString();
- } else if (i == '\n') {
- // ignore
- } else {
- buff.append((char) i);
- }
- }
-
- while (true) {
- int i = readCharacter();
-
- if (i == -1 && buff.length() == 0) {
- return null;
- }
-
- if (i == -1 || i == '\n') {
- return buff.toString();
- } else if (i == '\r') {
- skipLF = true;
- return buff.toString();
- } else {
- buff.append((char) i);
- }
- }
- }
-
- //
- // Completion
- //
-
- private final List completers = new LinkedList();
-
- private lib.jline.console.completer.CompletionHandler completionHandler = new lib.jline.console.completer.CandidateListCompletionHandler();
-
- /**
- * Add the specified {@link lib.jline.console.completer.Completer} to the list of handlers for tab-completion.
- *
- * @param completer the {@link lib.jline.console.completer.Completer} to add
- * @return true if it was successfully added
- */
- public boolean addCompleter(final lib.jline.console.completer.Completer completer) {
- return completers.add(completer);
- }
-
- /**
- * Remove the specified {@link lib.jline.console.completer.Completer} from the list of handlers for tab-completion.
- *
- * @param completer The {@link lib.jline.console.completer.Completer} to remove
- * @return True if it was successfully removed
- */
- public boolean removeCompleter(final lib.jline.console.completer.Completer completer) {
- return completers.remove(completer);
- }
-
- /**
- * Returns an unmodifiable list of all the completers.
- */
- public Collection getCompleters() {
- return Collections.unmodifiableList(completers);
- }
-
- public void setCompletionHandler(final lib.jline.console.completer.CompletionHandler handler) {
- this.completionHandler = lib.jline.internal.Preconditions.checkNotNull(handler);
- }
-
- public lib.jline.console.completer.CompletionHandler getCompletionHandler() {
- return this.completionHandler;
- }
-
- /**
- * Use the completers to modify the buffer with the appropriate completions.
- *
- * @return true if successful
- */
- protected boolean complete() throws IOException {
- // debug ("tab for (" + buf + ")");
- if (completers.size() == 0) {
- return false;
- }
-
- List candidates = new LinkedList();
- String bufstr = buf.buffer.toString();
- int cursor = buf.cursor;
-
- int position = -1;
-
- for (lib.jline.console.completer.Completer comp : completers) {
- if ((position = comp.complete(bufstr, cursor, candidates)) != -1) {
- break;
- }
- }
-
- return candidates.size() != 0 && getCompletionHandler().complete(this, candidates, position);
- }
-
- protected void printCompletionCandidates() throws IOException {
- // debug ("tab for (" + buf + ")");
- if (completers.size() == 0) {
- return;
- }
-
- List candidates = new LinkedList();
- String bufstr = buf.buffer.toString();
- int cursor = buf.cursor;
-
- for (lib.jline.console.completer.Completer comp : completers) {
- if (comp.complete(bufstr, cursor, candidates) != -1) {
- break;
- }
- }
- lib.jline.console.completer.CandidateListCompletionHandler.printCandidates(this, candidates);
- drawLine();
- }
-
- /**
- * The number of tab-completion candidates above which a warning will be
- * prompted before showing all the candidates.
- */
- private int autoprintThreshold = lib.jline.internal.Configuration.getInteger(JLINE_COMPLETION_THRESHOLD, 100); // same default as bash
-
- /**
- * @param threshold the number of candidates to print without issuing a warning.
- */
- public void setAutoprintThreshold(final int threshold) {
- this.autoprintThreshold = threshold;
- }
-
- /**
- * @return the number of candidates to print without issuing a warning.
- */
- public int getAutoprintThreshold() {
- return autoprintThreshold;
- }
-
- private boolean paginationEnabled;
-
- /**
- * Whether to use pagination when the number of rows of candidates exceeds the height of the terminal.
- */
- public void setPaginationEnabled(final boolean enabled) {
- this.paginationEnabled = enabled;
- }
-
- /**
- * Whether to use pagination when the number of rows of candidates exceeds the height of the terminal.
- */
- public boolean isPaginationEnabled() {
- return paginationEnabled;
- }
-
- //
- // History
- //
-
- private History history = new MemoryHistory();
-
- public void setHistory(final History history) {
- this.history = history;
- }
-
- public History getHistory() {
- return history;
- }
-
- private boolean historyEnabled = true;
-
- /**
- * Whether or not to add new commands to the history buffer.
- */
- public void setHistoryEnabled(final boolean enabled) {
- this.historyEnabled = enabled;
- }
-
- /**
- * Whether or not to add new commands to the history buffer.
- */
- public boolean isHistoryEnabled() {
- return historyEnabled;
- }
-
- /**
- * Used in "vi" mode for argumented history move, to move a specific
- * number of history entries forward or back.
- *
- * @param next If true, move forward
- * @param count The number of entries to move
- * @return true if the move was successful
- */
- private boolean moveHistory(final boolean next, int count) throws IOException {
- boolean ok = true;
- for (int i = 0; i < count && (ok = moveHistory(next)); i++) {
- /* empty */
- }
- return ok;
- }
-
- /**
- * Move up or down the history tree.
- */
- private boolean moveHistory(final boolean next) throws IOException {
- if (next && !history.next()) {
- return false;
- }
- else if (!next && !history.previous()) {
- return false;
- }
-
- setBuffer(history.current());
-
- return true;
- }
-
- //
- // Printing
- //
-
- /**
- * Output the specified characters to the output stream without manipulating the current buffer.
- */
- private int fmtPrint(final CharSequence buff, int cursorPos) throws IOException {
- return fmtPrint(buff, 0, buff.length(), cursorPos);
- }
-
- private int fmtPrint(final CharSequence buff, int start, int end) throws IOException {
- return fmtPrint(buff, start, end, getCursorPosition());
- }
-
- private int fmtPrint(final CharSequence buff, int start, int end, int cursorPos) throws IOException {
- lib.jline.internal.Preconditions.checkNotNull(buff);
- for (int i = start; i < end; i++) {
- char c = buff.charAt(i);
- if (c == '\t') {
- int nb = nextTabStop(cursorPos);
- cursorPos += nb;
- while (nb-- > 0) {
- out.write(' ');
- }
- } else if (c < 32) {
- out.write('^');
- out.write((char) (c + '@'));
- cursorPos += 2;
- } else {
- int w = WCWidth.wcwidth(c);
- if (w > 0) {
- out.write(c);
- cursorPos += w;
- }
- }
- }
- cursorOk = false;
- return cursorPos;
- }
-
- /**
- * Output the specified string to the output stream (but not the buffer).
- */
- public void print(final CharSequence s) throws IOException {
- rawPrint(s.toString());
- }
-
- public void println(final CharSequence s) throws IOException {
- print(s);
- println();
- }
-
- /**
- * Output a platform-dependant newline.
- */
- public void println() throws IOException {
- tputs("carriage_return");
- rawPrint('\n');
- }
-
- /**
- * Raw output printing
- */
- final void rawPrint(final int c) throws IOException {
- out.write(c);
- cursorOk = false;
- }
-
- final void rawPrint(final String str) throws IOException {
- out.write(str);
- cursorOk = false;
- }
-
- private void rawPrint(final char c, final int num) throws IOException {
- for (int i = 0; i < num; i++) {
- rawPrint(c);
- }
- }
-
- private void rawPrintln(final String s) throws IOException {
- rawPrint(s);
- println();
- }
-
-
- //
- // Actions
- //
-
- /**
- * Issue a delete.
- *
- * @return true if successful
- */
- public boolean delete() throws IOException {
- if (buf.cursor == buf.buffer.length()) {
- return false;
- }
-
- buf.buffer.delete(buf.cursor, buf.cursor + 1);
- drawBuffer(1);
-
- return true;
- }
-
- /**
- * Kill the buffer ahead of the current cursor position.
- *
- * @return true if successful
- */
- public boolean killLine() throws IOException {
- int cp = buf.cursor;
- int len = buf.buffer.length();
-
- if (cp >= len) {
- return false;
- }
-
- int num = len - cp;
- int pos = getCursorPosition();
- int width = wcwidth(buf.buffer, cp, len, pos);
- clearAhead(width, pos);
-
- char[] killed = new char[num];
- buf.buffer.getChars(cp, (cp + num), killed, 0);
- buf.buffer.delete(cp, (cp + num));
-
- String copy = new String(killed);
- killRing.add(copy);
-
- return true;
- }
-
- public boolean yank() throws IOException {
- String yanked = killRing.yank();
-
- if (yanked == null) {
- return false;
- }
- putString(yanked);
- return true;
- }
-
- public boolean yankPop() throws IOException {
- if (!killRing.lastYank()) {
- return false;
- }
- String current = killRing.yank();
- if (current == null) {
- // This shouldn't happen.
- return false;
- }
- backspace(current.length());
- String yanked = killRing.yankPop();
- if (yanked == null) {
- // This shouldn't happen.
- return false;
- }
-
- putString(yanked);
- return true;
- }
-
- /**
- * Clear the screen by issuing the ANSI "cleanUp screen" code.
- */
- public boolean clearScreen() throws IOException {
- if (!tputs("clear_screen")) {
- println();
- }
- return true;
- }
-
- /**
- * Issue an audible keyboard bell.
- */
- public void beep() throws IOException {
- if (bellEnabled) {
- if (tputs("bell")) {
- // need to flush so the console actually beeps
- flush();
- }
- }
- }
-
- /**
- * Paste the contents of the clipboard into the console buffer
- *
- * @return true if clipboard contents pasted
- */
- public boolean paste() throws IOException {
- Clipboard clipboard;
- try { // May throw ugly exception on system without X
- clipboard = Toolkit.getDefaultToolkit().getSystemClipboard();
- }
- catch (Exception e) {
- return false;
- }
-
- if (clipboard == null) {
- return false;
- }
-
- Transferable transferable = clipboard.getContents(null);
-
- if (transferable == null) {
- return false;
- }
-
- try {
- @SuppressWarnings("deprecation")
- Object content = transferable.getTransferData(DataFlavor.plainTextFlavor);
-
- // This fix was suggested in bug #1060649 at
- // http://sourceforge.net/tracker/index.php?func=detail&aid=1060649&group_id=64033&atid=506056
- // to get around the deprecated DataFlavor.plainTextFlavor, but it
- // raises a UnsupportedFlavorException on Mac OS X
-
- if (content == null) {
- try {
- content = new DataFlavor().getReaderForText(transferable);
- }
- catch (Exception e) {
- // ignore
- }
- }
-
- if (content == null) {
- return false;
- }
-
- String value;
-
- if (content instanceof Reader) {
- // TODO: we might want instead connect to the input stream
- // so we can interpret individual lines
- value = "";
- String line;
-
- BufferedReader read = new BufferedReader((Reader) content);
- while ((line = read.readLine()) != null) {
- if (value.length() > 0) {
- value += "\n";
- }
-
- value += line;
- }
- }
- else {
- value = content.toString();
- }
-
- if (value == null) {
- return true;
- }
-
- putString(value);
-
- return true;
- }
- catch (UnsupportedFlavorException e) {
- lib.jline.internal.Log.error("Paste failed: ", e);
-
- return false;
- }
- }
-
- /**
- * Adding a triggered Command allows to give another curse of action if a character passed the pre-processing.
- *
- * Say you want to close the application if the user enter q.
- * addTriggerAction('q', new ActionListener(){ System.exit(0); }); would do the trick.
- */
- public void addTriggeredAction(final char c, final ActionListener listener) {
- getKeys().bind(Character.toString(c), listener);
- }
-
- //
- // Formatted Output
- //
-
- /**
- * Output the specified {@link Collection} in proper columns.
- */
- public void printColumns(final Collection extends CharSequence> items) throws IOException {
- if (items == null || items.isEmpty()) {
- return;
- }
-
- int width = getTerminal().getWidth();
- int height = getTerminal().getHeight();
-
- int maxWidth = 0;
- for (CharSequence item : items) {
- // we use 0 here, as we don't really support tabulations inside candidates
- int len = wcwidth(Ansi.stripAnsi(item.toString()), 0);
- maxWidth = Math.max(maxWidth, len);
- }
- maxWidth = maxWidth + 3;
- lib.jline.internal.Log.debug("Max width: ", maxWidth);
-
- int showLines;
- if (isPaginationEnabled()) {
- showLines = height - 1; // page limit
- }
- else {
- showLines = Integer.MAX_VALUE;
- }
-
- StringBuilder buff = new StringBuilder();
- int realLength = 0;
- for (CharSequence item : items) {
- if ((realLength + maxWidth) > width) {
- rawPrintln(buff.toString());
- buff.setLength(0);
- realLength = 0;
-
- if (--showLines == 0) {
- // Overflow
- print(resources.getString("DISPLAY_MORE"));
- flush();
- int c = readCharacter();
- if (c == '\r' || c == '\n') {
- // one step forward
- showLines = 1;
- }
- else if (c != 'q') {
- // page forward
- showLines = height - 1;
- }
-
- tputs("carriage_return");
- if (c == 'q') {
- // cancel
- break;
- }
- }
- }
-
- // NOTE: toString() is important here due to AnsiString being retarded
- buff.append(item.toString());
- int strippedItemLength = wcwidth(Ansi.stripAnsi(item.toString()), 0);
- for (int i = 0; i < (maxWidth - strippedItemLength); i++) {
- buff.append(' ');
- }
- realLength += maxWidth;
- }
-
- if (buff.length() > 0) {
- rawPrintln(buff.toString());
- }
- }
-
- //
- // Non-supported Terminal Support
- //
-
- private Thread maskThread;
-
- private void beforeReadLine(final String prompt, final Character mask) {
- if (mask != null && maskThread == null) {
- final String fullPrompt = "\r" + prompt
- + " "
- + " "
- + " "
- + "\r" + prompt;
-
- maskThread = new Thread()
- {
- public void run() {
- while (!interrupted()) {
- try {
- Writer out = getOutput();
- out.write(fullPrompt);
- out.flush();
- sleep(3);
- }
- catch (IOException e) {
- return;
- }
- catch (InterruptedException e) {
- return;
- }
- }
- }
- };
-
- maskThread.setPriority(Thread.MAX_PRIORITY);
- maskThread.setDaemon(true);
- maskThread.start();
- }
- }
-
- private void afterReadLine() {
- if (maskThread != null && maskThread.isAlive()) {
- maskThread.interrupt();
- }
-
- maskThread = null;
- }
-
- /**
- * Erases the current line with the existing prompt, then redraws the line
- * with the provided prompt and buffer
- * @param prompt
- * the new prompt
- * @param buffer
- * the buffer to be drawn
- * @param cursorDest
- * where you want the cursor set when the line has been drawn.
- * -1 for end of line.
- * */
- public void resetPromptLine(String prompt, String buffer, int cursorDest) throws IOException {
- // move cursor to end of line
- moveToEnd();
-
- // backspace all text, including prompt
- buf.buffer.append(this.prompt);
- int promptLength = 0;
- if (this.prompt != null) {
- promptLength = this.prompt.length();
- }
-
- buf.cursor += promptLength;
- setPrompt("");
- backspaceAll();
-
- setPrompt(prompt);
- redrawLine();
- setBuffer(buffer);
-
- // move cursor to destination (-1 will move to end of line)
- if (cursorDest < 0) cursorDest = buffer.length();
- setCursorPosition(cursorDest);
-
- flush();
- }
-
- public void printSearchStatus(String searchTerm, String match) throws IOException {
- printSearchStatus(searchTerm, match, "(reverse-i-search)`");
- }
-
- public void printForwardSearchStatus(String searchTerm, String match) throws IOException {
- printSearchStatus(searchTerm, match, "(i-search)`");
- }
-
- private void printSearchStatus(String searchTerm, String match, String searchLabel) throws IOException {
- String prompt = searchLabel + searchTerm + "': ";
- int cursorDest = match.indexOf(searchTerm);
- resetPromptLine(prompt, match, cursorDest);
- }
-
- public void restoreLine(String originalPrompt, int cursorDest) throws IOException {
- // TODO move cursor to matched string
- String prompt = lastLine(originalPrompt);
- String buffer = buf.buffer.toString();
- resetPromptLine(prompt, buffer, cursorDest);
- }
-
- //
- // History search
- //
- /**
- * Search backward in history from a given position.
- *
- * @param searchTerm substring to search for.
- * @param startIndex the index from which on to search
- * @return index where this substring has been found, or -1 else.
- */
- public int searchBackwards(String searchTerm, int startIndex) {
- return searchBackwards(searchTerm, startIndex, false);
- }
-
- /**
- * Search backwards in history from the current position.
- *
- * @param searchTerm substring to search for.
- * @return index where the substring has been found, or -1 else.
- */
- public int searchBackwards(String searchTerm) {
- return searchBackwards(searchTerm, history.index());
- }
-
-
- public int searchBackwards(String searchTerm, int startIndex, boolean startsWith) {
- ListIterator it = history.entries(startIndex);
- while (it.hasPrevious()) {
- History.Entry e = it.previous();
- if (startsWith) {
- if (e.value().toString().startsWith(searchTerm)) {
- return e.index();
- }
- } else {
- if (e.value().toString().contains(searchTerm)) {
- return e.index();
- }
- }
- }
- return -1;
- }
-
- /**
- * Search forward in history from a given position.
- *
- * @param searchTerm substring to search for.
- * @param startIndex the index from which on to search
- * @return index where this substring has been found, or -1 else.
- */
- public int searchForwards(String searchTerm, int startIndex) {
- return searchForwards(searchTerm, startIndex, false);
- }
- /**
- * Search forwards in history from the current position.
- *
- * @param searchTerm substring to search for.
- * @return index where the substring has been found, or -1 else.
- */
- public int searchForwards(String searchTerm) {
- return searchForwards(searchTerm, history.index());
- }
-
- public int searchForwards(String searchTerm, int startIndex, boolean startsWith) {
- if (startIndex >= history.size()) {
- startIndex = history.size() - 1;
- }
-
- ListIterator it = history.entries(startIndex);
-
- if (searchIndex != -1 && it.hasNext()) {
- it.next();
- }
-
- while (it.hasNext()) {
- History.Entry e = it.next();
- if (startsWith) {
- if (e.value().toString().startsWith(searchTerm)) {
- return e.index();
- }
- } else {
- if (e.value().toString().contains(searchTerm)) {
- return e.index();
- }
- }
- }
- return -1;
- }
-
- //
- // Helpers
- //
-
- /**
- * Checks to see if the specified character is a delimiter. We consider a
- * character a delimiter if it is anything but a letter or digit.
- *
- * @param c The character to test
- * @return True if it is a delimiter
- */
- private static boolean isDelimiter(final char c) {
- return !Character.isLetterOrDigit(c);
- }
-
- /**
- * Checks to see if a character is a whitespace character. Currently
- * this delegates to {@link Character#isWhitespace(char)}, however
- * eventually it should be hooked up so that the definition of whitespace
- * can be configured, as readline does.
- *
- * @param c The character to check
- * @return true if the character is a whitespace
- */
- private static boolean isWhitespace(final char c) {
- return Character.isWhitespace (c);
- }
-
- private boolean tputs(String cap, Object... params) throws IOException {
- String str = terminal.getStringCapability(cap);
- if (str == null) {
- return false;
- }
- Curses.tputs(out, str, params);
- return true;
- }
-
-}
diff --git a/kshell-console-jline2/src/main/java/lib/jline/console/CursorBuffer.java b/kshell-console-jline2/src/main/java/lib/jline/console/CursorBuffer.java
deleted file mode 100644
index aaaa863..0000000
--- a/kshell-console-jline2/src/main/java/lib/jline/console/CursorBuffer.java
+++ /dev/null
@@ -1,119 +0,0 @@
-/*
- * 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
- */
-package lib.jline.console;
-
-/**
- * A holder for a {@link StringBuilder} that also contains the current cursor position.
- *
- * @author Marc Prud'hommeaux
- * @author Jason Dillon
- * @since 2.0
- */
-public class CursorBuffer
-{
- private boolean overTyping = false;
-
- public int cursor = 0;
-
- public final StringBuilder buffer = new StringBuilder();
-
- public CursorBuffer copy () {
- CursorBuffer that = new CursorBuffer();
- that.overTyping = this.overTyping;
- that.cursor = this.cursor;
- that.buffer.append (this.toString());
-
- return that;
- }
-
- public boolean isOverTyping() {
- return overTyping;
- }
-
- public void setOverTyping(final boolean b) {
- overTyping = b;
- }
-
- public int length() {
- return buffer.length();
- }
-
- public char nextChar() {
- if (cursor == buffer.length()) {
- return 0;
- } else {
- return buffer.charAt(cursor);
- }
- }
-
- public char current() {
- if (cursor <= 0) {
- return 0;
- }
-
- return buffer.charAt(cursor - 1);
- }
-
- /**
- * Write the specific character into the buffer, setting the cursor position
- * ahead one. The text may overwrite or insert based on the current setting
- * of {@link #isOverTyping}.
- *
- * @param c the character to insert
- */
- public void write(final char c) {
- buffer.insert(cursor++, c);
- if (isOverTyping() && cursor < buffer.length()) {
- buffer.deleteCharAt(cursor);
- }
- }
-
- /**
- * Insert the specified chars into the buffer, setting the cursor to the end of the insertion point.
- */
- public void write(final CharSequence str) {
- lib.jline.internal.Preconditions.checkNotNull(str);
-
- if (buffer.length() == 0) {
- buffer.append(str);
- }
- else {
- buffer.insert(cursor, str);
- }
-
- cursor += str.length();
-
- if (isOverTyping() && cursor < buffer.length()) {
- buffer.delete(cursor, cursor + str.length());
- }
- }
-
- public boolean clear() {
- if (buffer.length() == 0) {
- return false;
- }
-
- buffer.delete(0, buffer.length());
- cursor = 0;
- return true;
- }
-
- public String upToCursor() {
- if (cursor <= 0) {
- return "";
- }
-
- return buffer.substring(0, cursor);
- }
-
- @Override
- public String toString() {
- return buffer.toString();
- }
-}
diff --git a/kshell-console-jline2/src/main/java/lib/jline/console/KeyMap.java b/kshell-console-jline2/src/main/java/lib/jline/console/KeyMap.java
deleted file mode 100644
index c80023d..0000000
--- a/kshell-console-jline2/src/main/java/lib/jline/console/KeyMap.java
+++ /dev/null
@@ -1,577 +0,0 @@
-/*
- * 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
- */
-package lib.jline.console;
-
-import java.util.HashMap;
-import java.util.Map;
-
-/**
- * The KeyMap class contains all bindings from keys to operations.
- *
- * @author Guillaume Nodet
- * @since 2.6
- */
-public class KeyMap {
-
- public static final String VI_MOVE = "vi-move";
- public static final String VI_INSERT = "vi-insert";
- public static final String EMACS = "emacs";
- public static final String EMACS_STANDARD = "emacs-standard";
- public static final String EMACS_CTLX = "emacs-ctlx";
- public static final String EMACS_META = "emacs-meta";
-
- private static final int KEYMAP_LENGTH = 256;
-
- private static final Object NULL_FUNCTION = new Object();
-
- private Object[] mapping = new Object[KEYMAP_LENGTH];
- private Object anotherKey = null;
- private String name;
-
- public KeyMap(String name) {
- this(name, new Object[KEYMAP_LENGTH]);
- }
-
- @Deprecated
- public KeyMap(String name, boolean unused) {
- this(name);
- }
-
- protected KeyMap(String name, Object[] mapping) {
- this.mapping = mapping;
- this.name = name;
- }
-
- public String getName() {
- return name;
- }
-
- public Object getAnotherKey() {
- return anotherKey;
- }
-
- public void from(KeyMap other) {
- this.mapping = other.mapping;
- this.anotherKey = other.anotherKey;
- }
-
- public Object getBound( CharSequence keySeq ) {
- if (keySeq != null && keySeq.length() > 0) {
- KeyMap map = this;
- for (int i = 0; i < keySeq.length(); i++) {
- char c = keySeq.charAt(i);
- if (c > 255) {
- return Operation.SELF_INSERT;
- }
- if (map.mapping[c] instanceof KeyMap) {
- if (i == keySeq.length() - 1) {
- return map.mapping[c];
- } else {
- map = (KeyMap) map.mapping[c];
- }
- } else {
- return map.mapping[c];
- }
- }
- }
- return null;
- }
-
- public void bindIfNotBound( CharSequence keySeq, Object function ) {
-
- bind (this, keySeq, function, true);
- }
-
- public void bind( CharSequence keySeq, Object function ) {
-
- bind (this, keySeq, function, false);
- }
-
- private static void bind( KeyMap map, CharSequence keySeq, Object function ) {
-
- bind (map, keySeq, function, false);
- }
-
- private static void bind( KeyMap map, CharSequence keySeq, Object function,
- boolean onlyIfNotBound ) {
-
- if (keySeq != null && keySeq.length() > 0) {
- for (int i = 0; i < keySeq.length(); i++) {
- char c = keySeq.charAt(i);
- if (c >= map.mapping.length) {
- return;
- }
- if (i < keySeq.length() - 1) {
- if (!(map.mapping[c] instanceof KeyMap)) {
- KeyMap m = new KeyMap("anonymous");
- if (map.mapping[c] != Operation.DO_LOWERCASE_VERSION) {
- m.anotherKey = map.mapping[c];
- }
- map.mapping[c] = m;
- }
- map = (KeyMap) map.mapping[c];
- } else {
- if (function == null) {
- function = NULL_FUNCTION;
- }
- if (map.mapping[c] instanceof KeyMap) {
- map.anotherKey = function;
- } else {
- Object op = map.mapping[c];
- if (onlyIfNotBound == false
- || op == null
- || op == Operation.DO_LOWERCASE_VERSION
- || op == Operation.VI_MOVEMENT_MODE ) {
-
- }
-
- map.mapping[c] = function;
- }
- }
- }
- }
- }
-
- public void setBlinkMatchingParen(boolean on) {
- if (on) {
- bind( "}", Operation.INSERT_CLOSE_CURLY );
- bind( ")", Operation.INSERT_CLOSE_PAREN );
- bind( "]", Operation.INSERT_CLOSE_SQUARE );
- }
- }
-
- private static void bindArrowKeys(KeyMap map) {
-
- // MS-DOS
- bind( map, "\033[0A", Operation.PREVIOUS_HISTORY );
- bind( map, "\033[0B", Operation.BACKWARD_CHAR );
- bind( map, "\033[0C", Operation.FORWARD_CHAR );
- bind( map, "\033[0D", Operation.NEXT_HISTORY );
-
- // Windows
- bind( map, "\340\000", Operation.KILL_WHOLE_LINE );
- bind( map, "\340\107", Operation.BEGINNING_OF_LINE );
- bind( map, "\340\110", Operation.PREVIOUS_HISTORY );
- bind( map, "\340\111", Operation.BEGINNING_OF_HISTORY );
- bind( map, "\340\113", Operation.BACKWARD_CHAR );
- bind( map, "\340\115", Operation.FORWARD_CHAR );
- bind( map, "\340\117", Operation.END_OF_LINE );
- bind( map, "\340\120", Operation.NEXT_HISTORY );
- bind( map, "\340\121", Operation.END_OF_HISTORY );
- bind( map, "\340\122", Operation.OVERWRITE_MODE );
- bind( map, "\340\123", Operation.DELETE_CHAR );
-
- bind( map, "\000\107", Operation.BEGINNING_OF_LINE );
- bind( map, "\000\110", Operation.PREVIOUS_HISTORY );
- bind( map, "\000\111", Operation.BEGINNING_OF_HISTORY );
- bind( map, "\000\110", Operation.PREVIOUS_HISTORY );
- bind( map, "\000\113", Operation.BACKWARD_CHAR );
- bind( map, "\000\115", Operation.FORWARD_CHAR );
- bind( map, "\000\117", Operation.END_OF_LINE );
- bind( map, "\000\120", Operation.NEXT_HISTORY );
- bind( map, "\000\121", Operation.END_OF_HISTORY );
- bind( map, "\000\122", Operation.OVERWRITE_MODE );
- bind( map, "\000\123", Operation.DELETE_CHAR );
-
- bind( map, "\033[A", Operation.PREVIOUS_HISTORY );
- bind( map, "\033[B", Operation.NEXT_HISTORY );
- bind( map, "\033[C", Operation.FORWARD_CHAR );
- bind( map, "\033[D", Operation.BACKWARD_CHAR );
- bind( map, "\033[H", Operation.BEGINNING_OF_LINE );
- bind( map, "\033[F", Operation.END_OF_LINE );
-
- bind( map, "\033OA", Operation.PREVIOUS_HISTORY );
- bind( map, "\033OB", Operation.NEXT_HISTORY );
- bind( map, "\033OC", Operation.FORWARD_CHAR );
- bind( map, "\033OD", Operation.BACKWARD_CHAR );
- bind( map, "\033OH", Operation.BEGINNING_OF_LINE );
- bind( map, "\033OF", Operation.END_OF_LINE );
-
- bind( map, "\033[1~", Operation.BEGINNING_OF_LINE);
- bind( map, "\033[4~", Operation.END_OF_LINE);
- bind( map, "\033[3~", Operation.DELETE_CHAR);
-
- // MINGW32
- bind( map, "\0340H", Operation.PREVIOUS_HISTORY );
- bind( map, "\0340P", Operation.NEXT_HISTORY );
- bind( map, "\0340M", Operation.FORWARD_CHAR );
- bind( map, "\0340K", Operation.BACKWARD_CHAR );
- }
-
-// public boolean isConvertMetaCharsToAscii() {
-// return convertMetaCharsToAscii;
-// }
-
-// public void setConvertMetaCharsToAscii(boolean convertMetaCharsToAscii) {
-// this.convertMetaCharsToAscii = convertMetaCharsToAscii;
-// }
-
- public static boolean isMeta( char c ) {
- return c > 0x7f && c <= 0xff;
- }
-
- public static char unMeta( char c ) {
- return (char) (c & 0x7F);
- }
-
- public static char meta( char c ) {
- return (char) (c | 0x80);
- }
-
- public static Map keyMaps() {
- Map keyMaps = new HashMap();
-
- KeyMap emacs = emacs();
- bindArrowKeys(emacs);
- keyMaps.put(EMACS, emacs);
- keyMaps.put(EMACS_STANDARD, emacs);
- keyMaps.put(EMACS_CTLX, (KeyMap) emacs.getBound("\u0018"));
- keyMaps.put(EMACS_META, (KeyMap) emacs.getBound("\u001b"));
-
- KeyMap viMov = viMovement();
- bindArrowKeys(viMov);
- keyMaps.put(VI_MOVE, viMov);
- keyMaps.put("vi-command", viMov);
- keyMaps.put("vi", viMov);
-
- KeyMap viIns = viInsertion();
- bindArrowKeys(viIns);
- keyMaps.put(VI_INSERT, viIns);
-
- return keyMaps;
- }
-
- public static KeyMap emacs() {
- Object[] map = new Object[KEYMAP_LENGTH];
- Object[] ctrl = new Object[] {
- // Control keys.
- Operation.SET_MARK, /* Control-@ */
- Operation.BEGINNING_OF_LINE, /* Control-A */
- Operation.BACKWARD_CHAR, /* Control-B */
- Operation.INTERRUPT, /* Control-C */
- Operation.EXIT_OR_DELETE_CHAR, /* Control-D */
- Operation.END_OF_LINE, /* Control-E */
- Operation.FORWARD_CHAR, /* Control-F */
- Operation.ABORT, /* Control-G */
- Operation.BACKWARD_DELETE_CHAR, /* Control-H */
- Operation.COMPLETE, /* Control-I */
- Operation.ACCEPT_LINE, /* Control-J */
- Operation.KILL_LINE, /* Control-K */
- Operation.CLEAR_SCREEN, /* Control-L */
- Operation.ACCEPT_LINE, /* Control-M */
- Operation.NEXT_HISTORY, /* Control-N */
- null, /* Control-O */
- Operation.PREVIOUS_HISTORY, /* Control-P */
- Operation.QUOTED_INSERT, /* Control-Q */
- Operation.REVERSE_SEARCH_HISTORY, /* Control-R */
- Operation.FORWARD_SEARCH_HISTORY, /* Control-S */
- Operation.TRANSPOSE_CHARS, /* Control-T */
- Operation.UNIX_LINE_DISCARD, /* Control-U */
- Operation.QUOTED_INSERT, /* Control-V */
- Operation.UNIX_WORD_RUBOUT, /* Control-W */
- emacsCtrlX(), /* Control-X */
- Operation.YANK, /* Control-Y */
- null, /* Control-Z */
- emacsMeta(), /* Control-[ */
- null, /* Control-\ */
- Operation.CHARACTER_SEARCH, /* Control-] */
- null, /* Control-^ */
- Operation.UNDO, /* Control-_ */
- };
- System.arraycopy( ctrl, 0, map, 0, ctrl.length );
- for (int i = 32; i < 256; i++) {
- map[i] = Operation.SELF_INSERT;
- }
- map[DELETE] = Operation.BACKWARD_DELETE_CHAR;
- return new KeyMap(EMACS, map);
- }
-
- public static final char CTRL_D = (char) 4;
- public static final char CTRL_G = (char) 7;
- public static final char CTRL_H = (char) 8;
- public static final char CTRL_I = (char) 9;
- public static final char CTRL_J = (char) 10;
- public static final char CTRL_M = (char) 13;
- public static final char CTRL_R = (char) 18;
- public static final char CTRL_S = (char) 19;
- public static final char CTRL_U = (char) 21;
- public static final char CTRL_X = (char) 24;
- public static final char CTRL_Y = (char) 25;
- public static final char ESCAPE = (char) 27; /* Ctrl-[ */
- public static final char CTRL_OB = (char) 27; /* Ctrl-[ */
- public static final char CTRL_CB = (char) 29; /* Ctrl-] */
-
- public static final int DELETE = (char) 127;
-
- public static KeyMap emacsCtrlX() {
- Object[] map = new Object[KEYMAP_LENGTH];
- map[CTRL_G] = Operation.ABORT;
- map[CTRL_R] = Operation.RE_READ_INIT_FILE;
- map[CTRL_U] = Operation.UNDO;
- map[CTRL_X] = Operation.EXCHANGE_POINT_AND_MARK;
- map['('] = Operation.START_KBD_MACRO;
- map[')'] = Operation.END_KBD_MACRO;
- for (int i = 'A'; i <= 'Z'; i++) {
- map[i] = Operation.DO_LOWERCASE_VERSION;
- }
- map['e'] = Operation.CALL_LAST_KBD_MACRO;
- map[DELETE] = Operation.KILL_LINE;
- return new KeyMap(EMACS_CTLX, map);
- }
-
- public static KeyMap emacsMeta() {
- Object[] map = new Object[KEYMAP_LENGTH];
- map[CTRL_G] = Operation.ABORT;
- map[CTRL_H] = Operation.BACKWARD_KILL_WORD;
- map[CTRL_I] = Operation.TAB_INSERT;
- map[CTRL_J] = Operation.VI_EDITING_MODE;
- map[CTRL_M] = Operation.VI_EDITING_MODE;
- map[CTRL_R] = Operation.REVERT_LINE;
- map[CTRL_Y] = Operation.YANK_NTH_ARG;
- map[CTRL_OB] = Operation.COMPLETE;
- map[CTRL_CB] = Operation.CHARACTER_SEARCH_BACKWARD;
- map[' '] = Operation.SET_MARK;
- map['#'] = Operation.INSERT_COMMENT;
- map['&'] = Operation.TILDE_EXPAND;
- map['*'] = Operation.INSERT_COMPLETIONS;
- map['-'] = Operation.DIGIT_ARGUMENT;
- map['.'] = Operation.YANK_LAST_ARG;
- map['<'] = Operation.BEGINNING_OF_HISTORY;
- map['='] = Operation.POSSIBLE_COMPLETIONS;
- map['>'] = Operation.END_OF_HISTORY;
- map['?'] = Operation.POSSIBLE_COMPLETIONS;
- for (int i = 'A'; i <= 'Z'; i++) {
- map[i] = Operation.DO_LOWERCASE_VERSION;
- }
- map['\\'] = Operation.DELETE_HORIZONTAL_SPACE;
- map['_'] = Operation.YANK_LAST_ARG;
- map['b'] = Operation.BACKWARD_WORD;
- map['c'] = Operation.CAPITALIZE_WORD;
- map['d'] = Operation.KILL_WORD;
- map['f'] = Operation.FORWARD_WORD;
- map['l'] = Operation.DOWNCASE_WORD;
- map['p'] = Operation.NON_INCREMENTAL_REVERSE_SEARCH_HISTORY;
- map['r'] = Operation.REVERT_LINE;
- map['t'] = Operation.TRANSPOSE_WORDS;
- map['u'] = Operation.UPCASE_WORD;
- map['y'] = Operation.YANK_POP;
- map['~'] = Operation.TILDE_EXPAND;
- map[DELETE] = Operation.BACKWARD_KILL_WORD;
- return new KeyMap(EMACS_META, map);
- }
-
- public static KeyMap viInsertion() {
- Object[] map = new Object[KEYMAP_LENGTH];
- Object[] ctrl = new Object[] {
- // Control keys.
- null, /* Control-@ */
- Operation.SELF_INSERT, /* Control-A */
- Operation.SELF_INSERT, /* Control-B */
- Operation.SELF_INSERT, /* Control-C */
- Operation.VI_EOF_MAYBE, /* Control-D */
- Operation.SELF_INSERT, /* Control-E */
- Operation.SELF_INSERT, /* Control-F */
- Operation.SELF_INSERT, /* Control-G */
- Operation.BACKWARD_DELETE_CHAR, /* Control-H */
- Operation.COMPLETE, /* Control-I */
- Operation.ACCEPT_LINE, /* Control-J */
- Operation.SELF_INSERT, /* Control-K */
- Operation.SELF_INSERT, /* Control-L */
- Operation.ACCEPT_LINE, /* Control-M */
- Operation.MENU_COMPLETE, /* Control-N */
- Operation.SELF_INSERT, /* Control-O */
- Operation.MENU_COMPLETE_BACKWARD, /* Control-P */
- Operation.SELF_INSERT, /* Control-Q */
- Operation.REVERSE_SEARCH_HISTORY, /* Control-R */
- Operation.FORWARD_SEARCH_HISTORY, /* Control-S */
- Operation.TRANSPOSE_CHARS, /* Control-T */
- Operation.UNIX_LINE_DISCARD, /* Control-U */
- Operation.QUOTED_INSERT, /* Control-V */
- Operation.UNIX_WORD_RUBOUT, /* Control-W */
- Operation.SELF_INSERT, /* Control-X */
- Operation.YANK, /* Control-Y */
- Operation.SELF_INSERT, /* Control-Z */
- Operation.VI_MOVEMENT_MODE, /* Control-[ */
- Operation.SELF_INSERT, /* Control-\ */
- Operation.SELF_INSERT, /* Control-] */
- Operation.SELF_INSERT, /* Control-^ */
- Operation.UNDO, /* Control-_ */
- };
- System.arraycopy( ctrl, 0, map, 0, ctrl.length );
- for (int i = 32; i < 256; i++) {
- map[i] = Operation.SELF_INSERT;
- }
- map[DELETE] = Operation.BACKWARD_DELETE_CHAR;
- return new KeyMap(VI_INSERT, map);
- }
-
- public static KeyMap viMovement() {
- Object[] map = new Object[KEYMAP_LENGTH];
- Object[] low = new Object[] {
- // Control keys.
- null, /* Control-@ */
- null, /* Control-A */
- null, /* Control-B */
- Operation.INTERRUPT, /* Control-C */
- /*
- * ^D is supposed to move down half a screen. In bash
- * appears to be ignored.
- */
- Operation.VI_EOF_MAYBE, /* Control-D */
- Operation.EMACS_EDITING_MODE, /* Control-E */
- null, /* Control-F */
- Operation.ABORT, /* Control-G */
- Operation.BACKWARD_CHAR, /* Control-H */
- null, /* Control-I */
- Operation.VI_MOVE_ACCEPT_LINE, /* Control-J */
- Operation.KILL_LINE, /* Control-K */
- Operation.CLEAR_SCREEN, /* Control-L */
- Operation.VI_MOVE_ACCEPT_LINE, /* Control-M */
- Operation.VI_NEXT_HISTORY, /* Control-N */
- null, /* Control-O */
- Operation.VI_PREVIOUS_HISTORY, /* Control-P */
- /*
- * My testing with readline is the ^Q is ignored.
- * Maybe this should be null?
- */
- Operation.QUOTED_INSERT, /* Control-Q */
-
- /*
- * TODO - Very broken. While in forward/reverse
- * history search the VI keyset should go out the
- * window and we need to enter a very simple keymap.
- */
- Operation.REVERSE_SEARCH_HISTORY, /* Control-R */
- /* TODO */
- Operation.FORWARD_SEARCH_HISTORY, /* Control-S */
- Operation.TRANSPOSE_CHARS, /* Control-T */
- Operation.UNIX_LINE_DISCARD, /* Control-U */
- /* TODO */
- Operation.QUOTED_INSERT, /* Control-V */
- Operation.UNIX_WORD_RUBOUT, /* Control-W */
- null, /* Control-X */
- /* TODO */
- Operation.YANK, /* Control-Y */
- null, /* Control-Z */
- emacsMeta(), /* Control-[ */
- null, /* Control-\ */
- /* TODO */
- Operation.CHARACTER_SEARCH, /* Control-] */
- null, /* Control-^ */
- /* TODO */
- Operation.UNDO, /* Control-_ */
- Operation.FORWARD_CHAR, /* SPACE */
- null, /* ! */
- null, /* " */
- Operation.VI_INSERT_COMMENT, /* # */
- Operation.END_OF_LINE, /* $ */
- Operation.VI_MATCH, /* % */
- Operation.VI_TILDE_EXPAND, /* & */
- null, /* ' */
- null, /* ( */
- null, /* ) */
- /* TODO */
- Operation.VI_COMPLETE, /* * */
- Operation.VI_NEXT_HISTORY, /* + */
- Operation.VI_CHAR_SEARCH, /* , */
- Operation.VI_PREVIOUS_HISTORY, /* - */
- /* TODO */
- Operation.VI_REDO, /* . */
- Operation.VI_SEARCH, /* / */
- Operation.VI_BEGINNING_OF_LINE_OR_ARG_DIGIT, /* 0 */
- Operation.VI_ARG_DIGIT, /* 1 */
- Operation.VI_ARG_DIGIT, /* 2 */
- Operation.VI_ARG_DIGIT, /* 3 */
- Operation.VI_ARG_DIGIT, /* 4 */
- Operation.VI_ARG_DIGIT, /* 5 */
- Operation.VI_ARG_DIGIT, /* 6 */
- Operation.VI_ARG_DIGIT, /* 7 */
- Operation.VI_ARG_DIGIT, /* 8 */
- Operation.VI_ARG_DIGIT, /* 9 */
- null, /* : */
- Operation.VI_CHAR_SEARCH, /* ; */
- null, /* < */
- Operation.VI_COMPLETE, /* = */
- null, /* > */
- Operation.VI_SEARCH, /* ? */
- null, /* @ */
- Operation.VI_APPEND_EOL, /* A */
- Operation.VI_PREV_WORD, /* B */
- Operation.VI_CHANGE_TO_EOL, /* C */
- Operation.VI_DELETE_TO_EOL, /* D */
- Operation.VI_END_WORD, /* E */
- Operation.VI_CHAR_SEARCH, /* F */
- /* I need to read up on what this does */
- Operation.VI_FETCH_HISTORY, /* G */
- null, /* H */
- Operation.VI_INSERT_BEG, /* I */
- null, /* J */
- null, /* K */
- null, /* L */
- null, /* M */
- Operation.VI_SEARCH_AGAIN, /* N */
- null, /* O */
- Operation.VI_PUT, /* P */
- null, /* Q */
- /* TODO */
- Operation.VI_REPLACE, /* R */
- Operation.VI_KILL_WHOLE_LINE, /* S */
- Operation.VI_CHAR_SEARCH, /* T */
- /* TODO */
- Operation.REVERT_LINE, /* U */
- null, /* V */
- Operation.VI_NEXT_WORD, /* W */
- Operation.VI_RUBOUT, /* X */
- Operation.VI_YANK_TO, /* Y */
- null, /* Z */
- null, /* [ */
- Operation.VI_COMPLETE, /* \ */
- null, /* ] */
- Operation.VI_FIRST_PRINT, /* ^ */
- Operation.VI_YANK_ARG, /* _ */
- Operation.VI_GOTO_MARK, /* ` */
- Operation.VI_APPEND_MODE, /* a */
- Operation.VI_PREV_WORD, /* b */
- Operation.VI_CHANGE_TO, /* c */
- Operation.VI_DELETE_TO, /* d */
- Operation.VI_END_WORD, /* e */
- Operation.VI_CHAR_SEARCH, /* f */
- null, /* g */
- Operation.BACKWARD_CHAR, /* h */
- Operation.VI_INSERTION_MODE, /* i */
- Operation.NEXT_HISTORY, /* j */
- Operation.PREVIOUS_HISTORY, /* k */
- Operation.FORWARD_CHAR, /* l */
- Operation.VI_SET_MARK, /* m */
- Operation.VI_SEARCH_AGAIN, /* n */
- null, /* o */
- Operation.VI_PUT, /* p */
- null, /* q */
- Operation.VI_CHANGE_CHAR, /* r */
- Operation.VI_SUBST, /* s */
- Operation.VI_CHAR_SEARCH, /* t */
- Operation.UNDO, /* u */
- null, /* v */
- Operation.VI_NEXT_WORD, /* w */
- Operation.VI_DELETE, /* x */
- Operation.VI_YANK_TO, /* y */
- null, /* z */
- null, /* { */
- Operation.VI_COLUMN, /* | */
- null, /* } */
- Operation.VI_CHANGE_CASE, /* ~ */
- Operation.VI_DELETE /* DEL */
- };
- System.arraycopy( low, 0, map, 0, low.length );
- for (int i = 128; i < 256; i++) {
- map[i] = null;
- }
- return new KeyMap(VI_MOVE, map);
- }
-}
diff --git a/kshell-console-jline2/src/main/java/lib/jline/console/KillRing.java b/kshell-console-jline2/src/main/java/lib/jline/console/KillRing.java
deleted file mode 100644
index 4144764..0000000
--- a/kshell-console-jline2/src/main/java/lib/jline/console/KillRing.java
+++ /dev/null
@@ -1,164 +0,0 @@
-/*
- * 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
- */
-package lib.jline.console;
-
-/**
- * The kill ring class keeps killed text in a fixed size ring. In this
- * class we also keep record of whether or not the last command was a
- * kill or a yank. Depending on this, the class may behave
- * different. For instance, two consecutive kill-word commands fill
- * the same slot such that the next yank will return the two
- * previously killed words instead that only the last one. Likewise
- * yank pop requires that the previous command was either a yank or a
- * yank-pop.
- */
-public final class KillRing {
-
- /**
- * Default size is 60, like in emacs.
- */
- private static final int DEFAULT_SIZE = 60;
-
- private final String[] slots;
- private int head = 0;
- private boolean lastKill = false;
- private boolean lastYank = false;
-
- /**
- * Creates a new kill ring of the given size.
- */
- public KillRing(int size) {
- slots = new String[size];
- }
-
- /**
- * Creates a new kill ring of the default size. See {@link #DEFAULT_SIZE}.
- */
- public KillRing() {
- this(DEFAULT_SIZE);
- }
-
- /**
- * Resets the last-yank state.
- */
- public void resetLastYank() {
- lastYank = false;
- }
-
- /**
- * Resets the last-kill state.
- */
- public void resetLastKill() {
- lastKill = false;
- }
-
- /**
- * Returns {@code true} if the last command was a yank.
- */
- public boolean lastYank() {
- return lastYank;
- }
-
- /**
- * Adds the string to the kill-ring. Also sets lastYank to false
- * and lastKill to true.
- */
- public void add(String str) {
- lastYank = false;
-
- if (lastKill) {
- if (slots[head] != null) {
- slots[head] += str;
- return;
- }
- }
-
- lastKill = true;
- next();
- slots[head] = str;
- }
-
- /**
- * Adds the string to the kill-ring product of killing
- * backwards. If the previous command was a kill text one then
- * adds the text at the beginning of the previous kill to avoid
- * that two consecutive backwards kills followed by a yank leaves
- * things reversed.
- */
- public void addBackwards(String str) {
- lastYank = false;
-
- if (lastKill) {
- if (slots[head] != null) {
- slots[head] = str + slots[head];
- return;
- }
- }
-
- lastKill = true;
- next();
- slots[head] = str;
- }
-
- /**
- * Yanks a previously killed text. Returns {@code null} if the
- * ring is empty.
- */
- public String yank() {
- lastKill = false;
- lastYank = true;
- return slots[head];
- }
-
- /**
- * Moves the pointer to the current slot back and returns the text
- * in that position. If the previous command was not yank returns
- * null.
- */
- public String yankPop() {
- lastKill = false;
- if (lastYank) {
- prev();
- return slots[head];
- }
- return null;
- }
-
- /**
- * Moves the pointer to the current slot forward. If the end of
- * the slots is reached then points back to the beginning.
- */
- private void next() {
- if (head == 0 && slots[0] == null) {
- return;
- }
- head++;
- if (head == slots.length) {
- head = 0;
- }
- }
-
- /**
- * Moves the pointer to the current slot backwards. If the
- * beginning of the slots is reached then traverses the slot
- * backwards until one with not null content is found.
- */
- private void prev() {
- head--;
- if (head == -1) {
- int x = slots.length - 1;
- for (; x >= 0; x--) {
- if (slots[x] != null) {
- break;
- }
- }
- head = x;
- }
- }
-}
diff --git a/kshell-console-jline2/src/main/java/lib/jline/console/Operation.java b/kshell-console-jline2/src/main/java/lib/jline/console/Operation.java
deleted file mode 100644
index ae70a22..0000000
--- a/kshell-console-jline2/src/main/java/lib/jline/console/Operation.java
+++ /dev/null
@@ -1,161 +0,0 @@
-/*
- * 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
- */
-package lib.jline.console;
-
-/**
- * List of all operations.
- *
- * @author Guillaume Nodet
- * @since 2.6
- */
-public enum Operation {
-
- ABORT,
- ACCEPT_LINE,
- ARROW_KEY_PREFIX,
- BACKWARD_BYTE,
- BACKWARD_CHAR,
- BACKWARD_DELETE_CHAR,
- BACKWARD_KILL_LINE,
- BACKWARD_KILL_WORD,
- BACKWARD_WORD,
- BEGINNING_OF_HISTORY,
- BEGINNING_OF_LINE,
- CALL_LAST_KBD_MACRO,
- CAPITALIZE_WORD,
- CHARACTER_SEARCH,
- CHARACTER_SEARCH_BACKWARD,
- CLEAR_SCREEN,
- COMPLETE,
- COPY_BACKWARD_WORD,
- COPY_FORWARD_WORD,
- COPY_REGION_AS_KILL,
- DELETE_CHAR,
- DELETE_CHAR_OR_LIST,
- DELETE_HORIZONTAL_SPACE,
- DIGIT_ARGUMENT,
- DO_LOWERCASE_VERSION,
- DOWNCASE_WORD,
- DUMP_FUNCTIONS,
- DUMP_MACROS,
- DUMP_VARIABLES,
- EMACS_EDITING_MODE,
- END_KBD_MACRO,
- END_OF_HISTORY,
- END_OF_LINE,
- EXCHANGE_POINT_AND_MARK,
- EXIT_OR_DELETE_CHAR,
- FORWARD_BACKWARD_DELETE_CHAR,
- FORWARD_BYTE,
- FORWARD_CHAR,
- FORWARD_SEARCH_HISTORY,
- FORWARD_WORD,
- HISTORY_SEARCH_BACKWARD,
- HISTORY_SEARCH_FORWARD,
- INSERT_CLOSE_CURLY,
- INSERT_CLOSE_PAREN,
- INSERT_CLOSE_SQUARE,
- INSERT_COMMENT,
- INSERT_COMPLETIONS,
- INTERRUPT,
- KILL_WHOLE_LINE,
- KILL_LINE,
- KILL_REGION,
- KILL_WORD,
- MENU_COMPLETE,
- MENU_COMPLETE_BACKWARD,
- NEXT_HISTORY,
- NON_INCREMENTAL_FORWARD_SEARCH_HISTORY,
- NON_INCREMENTAL_REVERSE_SEARCH_HISTORY,
- NON_INCREMENTAL_FORWARD_SEARCH_HISTORY_AGAIN,
- NON_INCREMENTAL_REVERSE_SEARCH_HISTORY_AGAIN,
- OLD_MENU_COMPLETE,
- OVERWRITE_MODE,
- PASTE_FROM_CLIPBOARD,
- POSSIBLE_COMPLETIONS,
- PREVIOUS_HISTORY,
- QUOTED_INSERT,
- QUIT,
- RE_READ_INIT_FILE,
- REDRAW_CURRENT_LINE,
- REVERSE_SEARCH_HISTORY,
- REVERT_LINE,
- SELF_INSERT,
- SET_MARK,
- SKIP_CSI_SEQUENCE,
- START_KBD_MACRO,
- TAB_INSERT,
- TILDE_EXPAND,
- TRANSPOSE_CHARS,
- TRANSPOSE_WORDS,
- TTY_STATUS,
- UNDO,
- UNIVERSAL_ARGUMENT,
- UNIX_FILENAME_RUBOUT,
- UNIX_LINE_DISCARD,
- UNIX_WORD_RUBOUT,
- UPCASE_WORD,
- YANK,
- YANK_LAST_ARG,
- YANK_NTH_ARG,
- YANK_POP,
- VI_APPEND_EOL,
- VI_APPEND_MODE,
- VI_ARG_DIGIT,
- VI_BACK_TO_INDENT,
- VI_BACKWARD_BIGWORD,
- VI_BACKWARD_WORD,
- VI_BWORD,
- VI_CHANGE_CASE,
- VI_CHANGE_CHAR,
- VI_CHANGE_TO,
- VI_CHANGE_TO_EOL,
- VI_CHAR_SEARCH,
- VI_COLUMN,
- VI_COMPLETE,
- VI_DELETE,
- VI_DELETE_TO,
- VI_DELETE_TO_EOL,
- VI_EDITING_MODE,
- VI_END_BIGWORD,
- VI_END_WORD,
- VI_EOF_MAYBE,
- VI_EWORD,
- VI_FWORD,
- VI_FETCH_HISTORY,
- VI_FIRST_PRINT,
- VI_FORWARD_BIGWORD,
- VI_FORWARD_WORD,
- VI_GOTO_MARK,
- VI_INSERT_BEG,
- VI_INSERTION_MODE,
- VI_KILL_WHOLE_LINE,
- VI_MATCH,
- VI_MOVEMENT_MODE,
- VI_NEXT_WORD,
- VI_OVERSTRIKE,
- VI_OVERSTRIKE_DELETE,
- VI_PREV_WORD,
- VI_PUT,
- VI_REDO,
- VI_REPLACE,
- VI_RUBOUT,
- VI_SEARCH,
- VI_SEARCH_AGAIN,
- VI_SET_MARK,
- VI_SUBST,
- VI_TILDE_EXPAND,
- VI_YANK_ARG,
- VI_YANK_TO,
- VI_MOVE_ACCEPT_LINE,
- VI_NEXT_HISTORY,
- VI_PREVIOUS_HISTORY,
- VI_INSERT_COMMENT,
- VI_BEGINNING_OF_LINE_OR_ARG_DIGIT,
-}
diff --git a/kshell-console-jline2/src/main/java/lib/jline/console/UserInterruptException.java b/kshell-console-jline2/src/main/java/lib/jline/console/UserInterruptException.java
deleted file mode 100644
index d597859..0000000
--- a/kshell-console-jline2/src/main/java/lib/jline/console/UserInterruptException.java
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * 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
- */
-package lib.jline.console;
-
-/**
- * This exception is thrown by {@link ConsoleReader#readLine} when
- * user interrupt handling is enabled and the user types the
- * interrupt character (ctrl-C). The partially entered line is
- * available via the {@link #getPartialLine()} method.
- */
-public class UserInterruptException
- extends RuntimeException
-{
- private static final long serialVersionUID = 6172232572140736750L;
-
- private final String partialLine;
-
- public UserInterruptException(String partialLine)
- {
- this.partialLine = partialLine;
- }
-
- /**
- * @return the partially entered line when ctrl-C was pressed
- */
- public String getPartialLine()
- {
- return partialLine;
- }
-}
diff --git a/kshell-console-jline2/src/main/java/lib/jline/console/WCWidth.java b/kshell-console-jline2/src/main/java/lib/jline/console/WCWidth.java
deleted file mode 100644
index 592860e..0000000
--- a/kshell-console-jline2/src/main/java/lib/jline/console/WCWidth.java
+++ /dev/null
@@ -1,158 +0,0 @@
-/*
- * 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
- */
-package lib.jline.console;
-
-public class WCWidth {
-
- /* The following two functions define the column width of an ISO 10646
- * character as follows:
- *
- * - The null character (U+0000) has a column width of 0.
- *
- * - Other C0/C1 control characters and DEL will lead to a return
- * value of -1.
- *
- * - Non-spacing and enclosing combining characters (general
- * category code Mn or Me in the Unicode database) have a
- * column width of 0.
- *
- * - SOFT HYPHEN (U+00AD) has a column width of 1.
- *
- * - Other format characters (general category code Cf in the Unicode
- * database) and ZERO WIDTH SPACE (U+200B) have a column width of 0.
- *
- * - Hangul Jamo medial vowels and final consonants (U+1160-U+11FF)
- * have a column width of 0.
- *
- * - Spacing characters in the East Asian Wide (W) or East Asian
- * Full-width (F) category as defined in Unicode Technical
- * Report #11 have a column width of 2.
- *
- * - All remaining characters (including all printable
- * ISO 8859-1 and WGL4 characters, Unicode control characters,
- * etc.) have a column width of 1.
- *
- * This implementation assumes that wchar_t characters are encoded
- * in ISO 10646.
- */
- public static int wcwidth(int ucs)
- {
-
- /* test for 8-bit control characters */
- if (ucs == 0)
- return 0;
- if (ucs < 32 || (ucs >= 0x7f && ucs < 0xa0))
- return -1;
-
- /* binary search in table of non-spacing characters */
- if (bisearch(ucs, combining, combining.length - 1))
- return 0;
-
- /* if we arrive here, ucs is not a combining or C0/C1 control character */
- return 1 +
- ((ucs >= 0x1100 &&
- (ucs <= 0x115f || /* Hangul Jamo init. consonants */
- ucs == 0x2329 || ucs == 0x232a ||
- (ucs >= 0x2e80 && ucs <= 0xa4cf &&
- ucs != 0x303f) || /* CJK ... Yi */
- (ucs >= 0xac00 && ucs <= 0xd7a3) || /* Hangul Syllables */
- (ucs >= 0xf900 && ucs <= 0xfaff) || /* CJK Compatibility Ideographs */
- (ucs >= 0xfe10 && ucs <= 0xfe19) || /* Vertical forms */
- (ucs >= 0xfe30 && ucs <= 0xfe6f) || /* CJK Compatibility Forms */
- (ucs >= 0xff00 && ucs <= 0xff60) || /* Fullwidth Forms */
- (ucs >= 0xffe0 && ucs <= 0xffe6) ||
- (ucs >= 0x20000 && ucs <= 0x2fffd) ||
- (ucs >= 0x30000 && ucs <= 0x3fffd))) ? 1 : 0);
- }
-
- /* sorted list of non-overlapping intervals of non-spacing characters */
- /* generated by "uniset +cat=Me +cat=Mn +cat=Cf -00AD +1160-11FF +200B c" */
- static Interval[] combining = {
- new Interval( 0x0300, 0x036F ), new Interval( 0x0483, 0x0486 ), new Interval( 0x0488, 0x0489 ),
- new Interval( 0x0591, 0x05BD ), new Interval( 0x05BF, 0x05BF ), new Interval( 0x05C1, 0x05C2 ),
- new Interval( 0x05C4, 0x05C5 ), new Interval( 0x05C7, 0x05C7 ), new Interval( 0x0600, 0x0603 ),
- new Interval( 0x0610, 0x0615 ), new Interval( 0x064B, 0x065E ), new Interval( 0x0670, 0x0670 ),
- new Interval( 0x06D6, 0x06E4 ), new Interval( 0x06E7, 0x06E8 ), new Interval( 0x06EA, 0x06ED ),
- new Interval( 0x070F, 0x070F ), new Interval( 0x0711, 0x0711 ), new Interval( 0x0730, 0x074A ),
- new Interval( 0x07A6, 0x07B0 ), new Interval( 0x07EB, 0x07F3 ), new Interval( 0x0901, 0x0902 ),
- new Interval( 0x093C, 0x093C ), new Interval( 0x0941, 0x0948 ), new Interval( 0x094D, 0x094D ),
- new Interval( 0x0951, 0x0954 ), new Interval( 0x0962, 0x0963 ), new Interval( 0x0981, 0x0981 ),
- new Interval( 0x09BC, 0x09BC ), new Interval( 0x09C1, 0x09C4 ), new Interval( 0x09CD, 0x09CD ),
- new Interval( 0x09E2, 0x09E3 ), new Interval( 0x0A01, 0x0A02 ), new Interval( 0x0A3C, 0x0A3C ),
- new Interval( 0x0A41, 0x0A42 ), new Interval( 0x0A47, 0x0A48 ), new Interval( 0x0A4B, 0x0A4D ),
- new Interval( 0x0A70, 0x0A71 ), new Interval( 0x0A81, 0x0A82 ), new Interval( 0x0ABC, 0x0ABC ),
- new Interval( 0x0AC1, 0x0AC5 ), new Interval( 0x0AC7, 0x0AC8 ), new Interval( 0x0ACD, 0x0ACD ),
- new Interval( 0x0AE2, 0x0AE3 ), new Interval( 0x0B01, 0x0B01 ), new Interval( 0x0B3C, 0x0B3C ),
- new Interval( 0x0B3F, 0x0B3F ), new Interval( 0x0B41, 0x0B43 ), new Interval( 0x0B4D, 0x0B4D ),
- new Interval( 0x0B56, 0x0B56 ), new Interval( 0x0B82, 0x0B82 ), new Interval( 0x0BC0, 0x0BC0 ),
- new Interval( 0x0BCD, 0x0BCD ), new Interval( 0x0C3E, 0x0C40 ), new Interval( 0x0C46, 0x0C48 ),
- new Interval( 0x0C4A, 0x0C4D ), new Interval( 0x0C55, 0x0C56 ), new Interval( 0x0CBC, 0x0CBC ),
- new Interval( 0x0CBF, 0x0CBF ), new Interval( 0x0CC6, 0x0CC6 ), new Interval( 0x0CCC, 0x0CCD ),
- new Interval( 0x0CE2, 0x0CE3 ), new Interval( 0x0D41, 0x0D43 ), new Interval( 0x0D4D, 0x0D4D ),
- new Interval( 0x0DCA, 0x0DCA ), new Interval( 0x0DD2, 0x0DD4 ), new Interval( 0x0DD6, 0x0DD6 ),
- new Interval( 0x0E31, 0x0E31 ), new Interval( 0x0E34, 0x0E3A ), new Interval( 0x0E47, 0x0E4E ),
- new Interval( 0x0EB1, 0x0EB1 ), new Interval( 0x0EB4, 0x0EB9 ), new Interval( 0x0EBB, 0x0EBC ),
- new Interval( 0x0EC8, 0x0ECD ), new Interval( 0x0F18, 0x0F19 ), new Interval( 0x0F35, 0x0F35 ),
- new Interval( 0x0F37, 0x0F37 ), new Interval( 0x0F39, 0x0F39 ), new Interval( 0x0F71, 0x0F7E ),
- new Interval( 0x0F80, 0x0F84 ), new Interval( 0x0F86, 0x0F87 ), new Interval( 0x0F90, 0x0F97 ),
- new Interval( 0x0F99, 0x0FBC ), new Interval( 0x0FC6, 0x0FC6 ), new Interval( 0x102D, 0x1030 ),
- new Interval( 0x1032, 0x1032 ), new Interval( 0x1036, 0x1037 ), new Interval( 0x1039, 0x1039 ),
- new Interval( 0x1058, 0x1059 ), new Interval( 0x1160, 0x11FF ), new Interval( 0x135F, 0x135F ),
- new Interval( 0x1712, 0x1714 ), new Interval( 0x1732, 0x1734 ), new Interval( 0x1752, 0x1753 ),
- new Interval( 0x1772, 0x1773 ), new Interval( 0x17B4, 0x17B5 ), new Interval( 0x17B7, 0x17BD ),
- new Interval( 0x17C6, 0x17C6 ), new Interval( 0x17C9, 0x17D3 ), new Interval( 0x17DD, 0x17DD ),
- new Interval( 0x180B, 0x180D ), new Interval( 0x18A9, 0x18A9 ), new Interval( 0x1920, 0x1922 ),
- new Interval( 0x1927, 0x1928 ), new Interval( 0x1932, 0x1932 ), new Interval( 0x1939, 0x193B ),
- new Interval( 0x1A17, 0x1A18 ), new Interval( 0x1B00, 0x1B03 ), new Interval( 0x1B34, 0x1B34 ),
- new Interval( 0x1B36, 0x1B3A ), new Interval( 0x1B3C, 0x1B3C ), new Interval( 0x1B42, 0x1B42 ),
- new Interval( 0x1B6B, 0x1B73 ), new Interval( 0x1DC0, 0x1DCA ), new Interval( 0x1DFE, 0x1DFF ),
- new Interval( 0x200B, 0x200F ), new Interval( 0x202A, 0x202E ), new Interval( 0x2060, 0x2063 ),
- new Interval( 0x206A, 0x206F ), new Interval( 0x20D0, 0x20EF ), new Interval( 0x302A, 0x302F ),
- new Interval( 0x3099, 0x309A ), new Interval( 0xA806, 0xA806 ), new Interval( 0xA80B, 0xA80B ),
- new Interval( 0xA825, 0xA826 ), new Interval( 0xFB1E, 0xFB1E ), new Interval( 0xFE00, 0xFE0F ),
- new Interval( 0xFE20, 0xFE23 ), new Interval( 0xFEFF, 0xFEFF ), new Interval( 0xFFF9, 0xFFFB ),
- new Interval( 0x10A01, 0x10A03 ), new Interval( 0x10A05, 0x10A06 ), new Interval( 0x10A0C, 0x10A0F ),
- new Interval( 0x10A38, 0x10A3A ), new Interval( 0x10A3F, 0x10A3F ), new Interval( 0x1D167, 0x1D169 ),
- new Interval( 0x1D173, 0x1D182 ), new Interval( 0x1D185, 0x1D18B ), new Interval( 0x1D1AA, 0x1D1AD ),
- new Interval( 0x1D242, 0x1D244 ), new Interval( 0xE0001, 0xE0001 ), new Interval( 0xE0020, 0xE007F ),
- new Interval( 0xE0100, 0xE01EF )
- };
-
- private static class Interval {
- public final int first;
- public final int last;
-
- public Interval(int first, int last) {
- this.first = first;
- this.last = last;
- }
- }
-
- /* auxiliary function for binary search in interval table */
- private static boolean bisearch(int ucs, Interval[] table, int max) {
- int min = 0;
- int mid;
-
- if (ucs < table[0].first || ucs > table[max].last)
- return false;
- while (max >= min) {
- mid = (min + max) / 2;
- if (ucs > table[mid].last)
- min = mid + 1;
- else if (ucs < table[mid].first)
- max = mid - 1;
- else
- return true;
- }
-
- return false;
- }
-
-
-}
diff --git a/kshell-console-jline2/src/main/java/lib/jline/console/completer/AggregateCompleter.java b/kshell-console-jline2/src/main/java/lib/jline/console/completer/AggregateCompleter.java
deleted file mode 100644
index 4e05637..0000000
--- a/kshell-console-jline2/src/main/java/lib/jline/console/completer/AggregateCompleter.java
+++ /dev/null
@@ -1,122 +0,0 @@
-/*
- * 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
- */
-package lib.jline.console.completer;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.LinkedList;
-import java.util.List;
-
-/**
- * Completer which contains multiple completers and aggregates them together.
- *
- * @author Jason Dillon
- * @since 2.3
- */
-public class AggregateCompleter
- implements Completer
-{
- private final List completers = new ArrayList();
-
- public AggregateCompleter() {
- // empty
- }
-
- /**
- * Construct an AggregateCompleter with the given collection of completers.
- * The completers will be used in the iteration order of the collection.
- *
- * @param completers the collection of completers
- */
- public AggregateCompleter(final Collection completers) {
- lib.jline.internal.Preconditions.checkNotNull(completers);
- this.completers.addAll(completers);
- }
-
- /**
- * Construct an AggregateCompleter with the given completers.
- * The completers will be used in the order given.
- *
- * @param completers the completers
- */
- public AggregateCompleter(final Completer... completers) {
- this(Arrays.asList(completers));
- }
-
- /**
- * Retrieve the collection of completers currently being aggregated.
- *
- * @return the aggregated completers
- */
- public Collection getCompleters() {
- return completers;
- }
-
- /**
- * Perform a completion operation across all aggregated completers.
- *
- * @see Completer#complete(String, int, java.util.List)
- * @return the highest completion return value from all completers
- */
- public int complete(final String buffer, final int cursor, final List candidates) {
- // buffer could be null
- lib.jline.internal.Preconditions.checkNotNull(candidates);
-
- List completions = new ArrayList(completers.size());
-
- // Run each completer, saving its completion results
- int max = -1;
- for (Completer completer : completers) {
- Completion completion = new Completion(candidates);
- completion.complete(completer, buffer, cursor);
-
- // Compute the max cursor position
- max = Math.max(max, completion.cursor);
-
- completions.add(completion);
- }
-
- // Append candidates from completions which have the same cursor position as max
- for (Completion completion : completions) {
- if (completion.cursor == max) {
- candidates.addAll(completion.candidates);
- }
- }
-
- return max;
- }
-
- /**
- * @return a string representing the aggregated completers
- */
- @Override
- public String toString() {
- return getClass().getSimpleName() + "{" +
- "completers=" + completers +
- '}';
- }
-
- private class Completion
- {
- public final List candidates;
-
- public int cursor;
-
- public Completion(final List candidates) {
- lib.jline.internal.Preconditions.checkNotNull(candidates);
- this.candidates = new LinkedList(candidates);
- }
-
- public void complete(final Completer completer, final String buffer, final int cursor) {
- lib.jline.internal.Preconditions.checkNotNull(completer);
- this.cursor = completer.complete(buffer, cursor, candidates);
- }
- }
-}
diff --git a/kshell-console-jline2/src/main/java/lib/jline/console/completer/AnsiStringsCompleter.java b/kshell-console-jline2/src/main/java/lib/jline/console/completer/AnsiStringsCompleter.java
deleted file mode 100644
index 2d61f17..0000000
--- a/kshell-console-jline2/src/main/java/lib/jline/console/completer/AnsiStringsCompleter.java
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * 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
- */
-package lib.jline.console.completer;
-
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.List;
-import java.util.Map;
-import java.util.SortedMap;
-import java.util.TreeMap;
-
-import lib.jline.internal.Ansi;
-
-/**
- * Completer for a set of strings.
- *
- * @author Jason Dillon
- * @since 2.3
- */
-public class AnsiStringsCompleter
- implements Completer
-{
- private final SortedMap strings = new TreeMap();
-
- public AnsiStringsCompleter() {
- // empty
- }
-
- public AnsiStringsCompleter(final Collection strings) {
- lib.jline.internal.Preconditions.checkNotNull(strings);
- for (String str : strings) {
- this.strings.put(Ansi.stripAnsi(str), str);
- }
- }
-
- public AnsiStringsCompleter(final String... strings) {
- this(Arrays.asList(strings));
- }
-
- public Collection getStrings() {
- return strings.values();
- }
-
- public int complete(String buffer, final int cursor, final List candidates) {
- // buffer could be null
- lib.jline.internal.Preconditions.checkNotNull(candidates);
-
- if (buffer == null) {
- candidates.addAll(strings.values());
- }
- else {
- buffer = Ansi.stripAnsi(buffer);
- for (Map.Entry match : strings.tailMap(buffer).entrySet()) {
- if (!match.getKey().startsWith(buffer)) {
- break;
- }
-
- candidates.add(match.getValue());
- }
- }
-
- return candidates.isEmpty() ? -1 : 0;
- }
-}
\ No newline at end of file
diff --git a/kshell-console-jline2/src/main/java/lib/jline/console/completer/ArgumentCompleter.java b/kshell-console-jline2/src/main/java/lib/jline/console/completer/ArgumentCompleter.java
deleted file mode 100644
index 4e9d72e..0000000
--- a/kshell-console-jline2/src/main/java/lib/jline/console/completer/ArgumentCompleter.java
+++ /dev/null
@@ -1,456 +0,0 @@
-/*
- * 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
- */
-package lib.jline.console.completer;
-
-import lib.jline.internal.Preconditions;
-import lib.jline.internal.Log;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.LinkedList;
-import java.util.List;
-
-/**
- * A {@link Completer} implementation that invokes a child completer using the appropriate separator argument.
- * This can be used instead of the individual completers having to know about argument parsing semantics.
- *
- * @author Marc Prud'hommeaux
- * @author Jason Dillon
- * @since 2.3
- */
-public class ArgumentCompleter
- implements Completer
-{
- private final ArgumentDelimiter delimiter;
-
- private final List completers = new ArrayList();
-
- private boolean strict = true;
-
- /**
- * Create a new completer with the specified argument delimiter.
- *
- * @param delimiter The delimiter for parsing arguments
- * @param completers The embedded completers
- */
- public ArgumentCompleter(final ArgumentDelimiter delimiter, final Collection completers) {
- this.delimiter = Preconditions.checkNotNull(delimiter);
- Preconditions.checkNotNull(completers);
- this.completers.addAll(completers);
- }
-
- /**
- * Create a new completer with the specified argument delimiter.
- *
- * @param delimiter The delimiter for parsing arguments
- * @param completers The embedded completers
- */
- public ArgumentCompleter(final ArgumentDelimiter delimiter, final Completer... completers) {
- this(delimiter, Arrays.asList(completers));
- }
-
- /**
- * Create a new completer with the default {@link WhitespaceArgumentDelimiter}.
- *
- * @param completers The embedded completers
- */
- public ArgumentCompleter(final Completer... completers) {
- this(new WhitespaceArgumentDelimiter(), completers);
- }
-
- /**
- * Create a new completer with the default {@link WhitespaceArgumentDelimiter}.
- *
- * @param completers The embedded completers
- */
- public ArgumentCompleter(final List completers) {
- this(new WhitespaceArgumentDelimiter(), completers);
- }
-
- /**
- * If true, a completion at argument index N will only succeed
- * if all the completions from 0-(N-1) also succeed.
- */
- public void setStrict(final boolean strict) {
- this.strict = strict;
- }
-
- /**
- * Returns whether a completion at argument index N will success
- * if all the completions from arguments 0-(N-1) also succeed.
- *
- * @return True if strict.
- * @since 2.3
- */
- public boolean isStrict() {
- return this.strict;
- }
-
- /**
- * @since 2.3
- */
- public ArgumentDelimiter getDelimiter() {
- return delimiter;
- }
-
- /**
- * @since 2.3
- */
- public List getCompleters() {
- return completers;
- }
-
- public int complete(final String buffer, final int cursor, final List candidates) {
- // buffer can be null
- Preconditions.checkNotNull(candidates);
-
- ArgumentDelimiter delim = getDelimiter();
- ArgumentList list = delim.delimit(buffer, cursor);
- int argpos = list.getArgumentPosition();
- int argIndex = list.getCursorArgumentIndex();
-
- if (argIndex < 0) {
- return -1;
- }
-
- List completers = getCompleters();
- Completer completer;
-
- // if we are beyond the end of the completers, just use the last one
- if (argIndex >= completers.size()) {
- completer = completers.get(completers.size() - 1);
- }
- else {
- completer = completers.get(argIndex);
- }
-
- // ensure that all the previous completers are successful before allowing this completer to pass (only if strict).
- for (int i = 0; isStrict() && (i < argIndex); i++) {
- Completer sub = completers.get(i >= completers.size() ? (completers.size() - 1) : i);
- String[] args = list.getArguments();
- String arg = (args == null || i >= args.length) ? "" : args[i];
-
- List subCandidates = new LinkedList();
-
- if (sub.complete(arg, arg.length(), subCandidates) == -1) {
- return -1;
- }
-
- if (!subCandidates.contains(arg)) {
- return -1;
- }
- }
-
- int ret = completer.complete(list.getCursorArgument(), argpos, candidates);
-
- if (ret == -1) {
- return -1;
- }
-
- int pos = ret + list.getBufferPosition() - argpos;
-
- // Special case: when completing in the middle of a line, and the area under the cursor is a delimiter,
- // then trim any delimiters from the candidates, since we do not need to have an extra delimiter.
- //
- // E.g., if we have a completion for "foo", and we enter "f bar" into the buffer, and move to after the "f"
- // and hit TAB, we want "foo bar" instead of "foo bar".
-
- if ((cursor != buffer.length()) && delim.isDelimiter(buffer, cursor)) {
- for (int i = 0; i < candidates.size(); i++) {
- CharSequence val = candidates.get(i);
-
- while (val.length() > 0 && delim.isDelimiter(val, val.length() - 1)) {
- val = val.subSequence(0, val.length() - 1);
- }
-
- candidates.set(i, val);
- }
- }
-
- Log.trace("Completing ", buffer, " (pos=", cursor, ") with: ", candidates, ": offset=", pos);
-
- return pos;
- }
-
- /**
- * The {@link ArgumentCompleter.ArgumentDelimiter} allows custom breaking up of a {@link String} into individual
- * arguments in order to dispatch the arguments to the nested {@link Completer}.
- *
- * @author Marc Prud'hommeaux
- */
- public static interface ArgumentDelimiter
- {
- /**
- * Break the specified buffer into individual tokens that can be completed on their own.
- *
- * @param buffer The buffer to split
- * @param pos The current position of the cursor in the buffer
- * @return The tokens
- */
- ArgumentList delimit(CharSequence buffer, int pos);
-
- /**
- * Returns true if the specified character is a whitespace parameter.
- *
- * @param buffer The complete command buffer
- * @param pos The index of the character in the buffer
- * @return True if the character should be a delimiter
- */
- boolean isDelimiter(CharSequence buffer, int pos);
- }
-
- /**
- * Abstract implementation of a delimiter that uses the {@link #isDelimiter} method to determine if a particular
- * character should be used as a delimiter.
- *
- * @author Marc Prud'hommeaux
- */
- public abstract static class AbstractArgumentDelimiter
- implements ArgumentDelimiter
- {
- private char[] quoteChars = {'\'', '"'};
-
- private char[] escapeChars = {'\\'};
-
- public void setQuoteChars(final char[] chars) {
- this.quoteChars = chars;
- }
-
- public char[] getQuoteChars() {
- return this.quoteChars;
- }
-
- public void setEscapeChars(final char[] chars) {
- this.escapeChars = chars;
- }
-
- public char[] getEscapeChars() {
- return this.escapeChars;
- }
-
- public ArgumentList delimit(final CharSequence buffer, final int cursor) {
- List args = new LinkedList();
- StringBuilder arg = new StringBuilder();
- int argpos = -1;
- int bindex = -1;
- int quoteStart = -1;
-
- for (int i = 0; (buffer != null) && (i < buffer.length()); i++) {
- // once we reach the cursor, set the
- // position of the selected index
- if (i == cursor) {
- bindex = args.size();
- // the position in the current argument is just the
- // length of the current argument
- argpos = arg.length();
- }
-
- if (quoteStart < 0 && isQuoteChar(buffer, i)) {
- // Start a quote block
- quoteStart = i;
- } else if (quoteStart >= 0) {
- // In a quote block
- if (buffer.charAt(quoteStart) == buffer.charAt(i) && !isEscaped(buffer, i)) {
- // End the block; arg could be empty, but that's fine
- args.add(arg.toString());
- arg.setLength(0);
- quoteStart = -1;
- } else if (!isEscapeChar(buffer, i)) {
- // Take the next character
- arg.append(buffer.charAt(i));
- }
- } else {
- // Not in a quote block
- if (isDelimiter(buffer, i)) {
- if (arg.length() > 0) {
- args.add(arg.toString());
- arg.setLength(0); // reset the arg
- }
- } else if (!isEscapeChar(buffer, i)) {
- arg.append(buffer.charAt(i));
- }
- }
- }
-
- if (cursor == buffer.length()) {
- bindex = args.size();
- // the position in the current argument is just the
- // length of the current argument
- argpos = arg.length();
- }
- if (arg.length() > 0) {
- args.add(arg.toString());
- }
-
- return new ArgumentList(args.toArray(new String[args.size()]), bindex, argpos, cursor);
- }
-
- /**
- * 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
- * returns true from {@link #isDelimiterChar}.
- *
- * @param buffer The complete command buffer
- * @param pos The index of the character in the buffer
- * @return True if the character should be a delimiter
- */
- public boolean isDelimiter(final CharSequence buffer, final int pos) {
- return !isQuoted(buffer, pos) && !isEscaped(buffer, pos) && isDelimiterChar(buffer, pos);
- }
-
- public boolean isQuoted(final CharSequence buffer, final int pos) {
- return false;
- }
-
- public boolean isQuoteChar(final CharSequence buffer, final int pos) {
- if (pos < 0) {
- return false;
- }
-
- for (int i = 0; (quoteChars != null) && (i < quoteChars.length); i++) {
- if (buffer.charAt(pos) == quoteChars[i]) {
- return !isEscaped(buffer, pos);
- }
- }
-
- return false;
- }
-
- /**
- * Check if this character is a valid escape char (i.e. one that has not been escaped)
- */
- public boolean isEscapeChar(final CharSequence buffer, final int pos) {
- if (pos < 0) {
- return false;
- }
-
- for (int i = 0; (escapeChars != null) && (i < escapeChars.length); i++) {
- if (buffer.charAt(pos) == escapeChars[i]) {
- return !isEscaped(buffer, pos); // escape escape
- }
- }
-
- return false;
- }
-
- /**
- * Check if a character is escaped (i.e. if the previous character is an escape)
- *
- * @param buffer
- * the buffer to check in
- * @param pos
- * the position of the character to check
- * @return true if the character at the specified position in the given buffer is an escape character and the character immediately preceding it is not an
- * escape character.
- */
- public boolean isEscaped(final CharSequence buffer, final int pos) {
- if (pos <= 0) {
- return false;
- }
-
- return isEscapeChar(buffer, pos - 1);
- }
-
- /**
- * 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
- * {@link #getEscapeChars}. To perform escaping manually, override {@link #isDelimiter} instead.
- */
- public abstract boolean isDelimiterChar(CharSequence buffer, int pos);
- }
-
- /**
- * {@link ArgumentCompleter.ArgumentDelimiter} implementation that counts all whitespace (as reported by
- * {@link Character#isWhitespace}) as being a delimiter.
- *
- * @author Marc Prud'hommeaux
- */
- public static class WhitespaceArgumentDelimiter
- extends AbstractArgumentDelimiter
- {
- /**
- * The character is a delimiter if it is whitespace, and the
- * preceding character is not an escape character.
- */
- @Override
- public boolean isDelimiterChar(final CharSequence buffer, final int pos) {
- return Character.isWhitespace(buffer.charAt(pos));
- }
- }
-
- /**
- * The result of a delimited buffer.
- *
- * @author Marc Prud'hommeaux
- */
- public static class ArgumentList
- {
- private String[] arguments;
-
- private int cursorArgumentIndex;
-
- private int argumentPosition;
-
- private int bufferPosition;
-
- /**
- * @param arguments The array of tokens
- * @param cursorArgumentIndex The token index of the cursor
- * @param argumentPosition The position of the cursor in the current token
- * @param bufferPosition The position of the cursor in the whole buffer
- */
- public ArgumentList(final String[] arguments, final int cursorArgumentIndex, final int argumentPosition, final int bufferPosition) {
- this.arguments = Preconditions.checkNotNull(arguments);
- this.cursorArgumentIndex = cursorArgumentIndex;
- this.argumentPosition = argumentPosition;
- this.bufferPosition = bufferPosition;
- }
-
- public void setCursorArgumentIndex(final int i) {
- this.cursorArgumentIndex = i;
- }
-
- public int getCursorArgumentIndex() {
- return this.cursorArgumentIndex;
- }
-
- public String getCursorArgument() {
- if ((cursorArgumentIndex < 0) || (cursorArgumentIndex >= arguments.length)) {
- return null;
- }
-
- return arguments[cursorArgumentIndex];
- }
-
- public void setArgumentPosition(final int pos) {
- this.argumentPosition = pos;
- }
-
- public int getArgumentPosition() {
- return this.argumentPosition;
- }
-
- public void setArguments(final String[] arguments) {
- this.arguments = arguments;
- }
-
- public String[] getArguments() {
- return this.arguments;
- }
-
- public void setBufferPosition(final int pos) {
- this.bufferPosition = pos;
- }
-
- public int getBufferPosition() {
- return this.bufferPosition;
- }
- }
-}
diff --git a/kshell-console-jline2/src/main/java/lib/jline/console/completer/CandidateListCompletionHandler.java b/kshell-console-jline2/src/main/java/lib/jline/console/completer/CandidateListCompletionHandler.java
deleted file mode 100644
index b1d2f60..0000000
--- a/kshell-console-jline2/src/main/java/lib/jline/console/completer/CandidateListCompletionHandler.java
+++ /dev/null
@@ -1,235 +0,0 @@
-/*
- * 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
- */
-package lib.jline.console.completer;
-
-import lib.jline.internal.Ansi;
-import lib.jline.console.ConsoleReader;
-
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Locale;
-import java.util.ResourceBundle;
-import java.util.Set;
-
-/**
- * A {@link CompletionHandler} that deals with multiple distinct completions
- * by outputting the complete list of possibilities to the console. This
- * mimics the behavior of the
- * readline library.
- *
- * @author Marc Prud'hommeaux
- * @author Jason Dillon
- * @since 2.3
- */
-public class CandidateListCompletionHandler
- implements CompletionHandler
-{
- private boolean printSpaceAfterFullCompletion = true;
- private boolean stripAnsi;
-
- public boolean getPrintSpaceAfterFullCompletion() {
- return printSpaceAfterFullCompletion;
- }
-
- public void setPrintSpaceAfterFullCompletion(boolean printSpaceAfterFullCompletion) {
- this.printSpaceAfterFullCompletion = printSpaceAfterFullCompletion;
- }
-
- public boolean isStripAnsi() {
- return stripAnsi;
- }
-
- public void setStripAnsi(boolean stripAnsi) {
- this.stripAnsi = stripAnsi;
- }
-
- // TODO: handle quotes and escaped quotes && enable automatic escaping of whitespace
-
- public boolean complete(final ConsoleReader reader, final List candidates, final int pos) throws
- IOException
- {
- lib.jline.console.CursorBuffer buf = reader.getCursorBuffer();
-
- // if there is only one completion, then fill in the buffer
- if (candidates.size() == 1) {
- String value = Ansi.stripAnsi(candidates.get(0).toString());
-
- if (buf.cursor == buf.buffer.length()
- && printSpaceAfterFullCompletion
- && !value.endsWith(" ")) {
- value += " ";
- }
-
- // fail if the only candidate is the same as the current buffer
- if (value.equals(buf.toString())) {
- return false;
- }
-
- setBuffer(reader, value, pos);
-
- return true;
- }
- else if (candidates.size() > 1) {
- String value = getUnambiguousCompletions(candidates);
- setBuffer(reader, value, pos);
- }
-
- printCandidates(reader, candidates);
-
- // redraw the current console buffer
- reader.drawLine();
-
- return true;
- }
-
- public static void setBuffer(final ConsoleReader reader, final CharSequence value, final int offset) throws
- IOException
- {
- while ((reader.getCursorBuffer().cursor > offset) && reader.backspace()) {
- // empty
- }
-
- reader.putString(value);
- reader.setCursorPosition(offset + value.length());
- }
-
- /**
- * Print out the candidates. If the size of the candidates is greater than the
- * {@link ConsoleReader#getAutoprintThreshold}, they prompt with a warning.
- *
- * @param candidates the list of candidates to print
- */
- public static void printCandidates(final ConsoleReader reader, Collection candidates) throws
- IOException
- {
- Set distinct = new HashSet(candidates);
-
- if (distinct.size() > reader.getAutoprintThreshold()) {
- //noinspection StringConcatenation
- reader.println();
- reader.print(Messages.DISPLAY_CANDIDATES.format(distinct.size()));
- reader.flush();
-
- int c;
-
- String noOpt = Messages.DISPLAY_CANDIDATES_NO.format();
- String yesOpt = Messages.DISPLAY_CANDIDATES_YES.format();
- char[] allowed = {yesOpt.charAt(0), noOpt.charAt(0)};
-
- while ((c = reader.readCharacter(allowed)) != -1) {
- String tmp = new String(new char[]{(char) c});
-
- if (noOpt.startsWith(tmp)) {
- reader.println();
- return;
- }
- else if (yesOpt.startsWith(tmp)) {
- break;
- }
- else {
- reader.beep();
- }
- }
- }
-
- // copy the values and make them distinct, without otherwise affecting the ordering. Only do it if the sizes differ.
- if (distinct.size() != candidates.size()) {
- Collection copy = new ArrayList();
-
- for (CharSequence next : candidates) {
- if (!copy.contains(next)) {
- copy.add(next);
- }
- }
-
- candidates = copy;
- }
-
- reader.println();
- reader.printColumns(candidates);
- }
-
- /**
- * Returns a root that matches all the {@link String} elements of the specified {@link List},
- * or null if there are no commonalities. For example, if the list contains
- * foobar, foobaz, foobuz, the method will return foob.
- */
- private String getUnambiguousCompletions(final List candidates) {
- if (candidates == null || candidates.isEmpty()) {
- return null;
- }
-
- if (candidates.size() == 1) {
- return candidates.get(0).toString();
- }
-
- // convert to an array for speed
- String first = null;
- String[] strings = new String[candidates.size() - 1];
- for (int i = 0; i < candidates.size(); i++) {
- String str = candidates.get(i).toString();
- if (stripAnsi) {
- str = Ansi.stripAnsi(str);
- }
- if (first == null) {
- first = str;
- } else {
- strings[i - 1] = str;
- }
- }
-
- StringBuilder candidate = new StringBuilder();
-
- for (int i = 0; i < first.length(); i++) {
- if (startsWith(first.substring(0, i + 1), strings)) {
- candidate.append(first.charAt(i));
- }
- else {
- break;
- }
- }
-
- return candidate.toString();
- }
-
- /**
- * @return true is all the elements of candidates start with starts
- */
- private static boolean startsWith(final String starts, final String[] candidates) {
- for (String candidate : candidates) {
- if (!candidate.toLowerCase().startsWith(starts.toLowerCase())) {
- return false;
- }
- }
-
- return true;
- }
-
- private static enum Messages
- {
- DISPLAY_CANDIDATES,
- DISPLAY_CANDIDATES_YES,
- DISPLAY_CANDIDATES_NO,;
-
- private static final
- ResourceBundle
- bundle =
- ResourceBundle.getBundle(CandidateListCompletionHandler.class.getName(), Locale.getDefault());
-
- public String format(final Object... args) {
- if (bundle == null)
- return "";
- else
- return String.format(bundle.getString(name()), args);
- }
- }
-}
diff --git a/kshell-console-jline2/src/main/java/lib/jline/console/completer/Completer.java b/kshell-console-jline2/src/main/java/lib/jline/console/completer/Completer.java
deleted file mode 100644
index a928a48..0000000
--- a/kshell-console-jline2/src/main/java/lib/jline/console/completer/Completer.java
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * 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
- */
-package lib.jline.console.completer;
-
-import java.util.List;
-
-/**
- * A completer is the mechanism by which tab-completion candidates will be resolved.
- *
- * @author Marc Prud'hommeaux
- * @author Jason Dillon
- * @since 2.3
- */
-public interface Completer
-{
- //
- // FIXME: Check if we can use CharSequece for buffer?
- //
-
- /**
- * Populates candidates with a list of possible completions for the buffer.
- *
- * The candidates list will not be sorted before being displayed to the user: thus, the
- * complete method should sort the {@link List} before returning.
- *
- * @param buffer The buffer
- * @param cursor The current position of the cursor in the buffer
- * @param candidates The {@link List} of candidates to populate
- * @return The index of the buffer for which the completion will be relative
- */
- int complete(String buffer, int cursor, List candidates);
-}
diff --git a/kshell-console-jline2/src/main/java/lib/jline/console/completer/CompletionHandler.java b/kshell-console-jline2/src/main/java/lib/jline/console/completer/CompletionHandler.java
deleted file mode 100644
index dc1dc52..0000000
--- a/kshell-console-jline2/src/main/java/lib/jline/console/completer/CompletionHandler.java
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * 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
- */
-package lib.jline.console.completer;
-
-import lib.jline.console.ConsoleReader;
-
-import java.io.IOException;
-import java.util.List;
-
-/**
- * Handler for dealing with candidates for tab-completion.
- *
- * @author Marc Prud'hommeaux
- * @author Jason Dillon
- * @since 2.3
- */
-public interface CompletionHandler
-{
- boolean complete(ConsoleReader reader, List candidates, int position) throws IOException;
-}
diff --git a/kshell-console-jline2/src/main/java/lib/jline/console/completer/EnumCompleter.java b/kshell-console-jline2/src/main/java/lib/jline/console/completer/EnumCompleter.java
deleted file mode 100644
index 44352f9..0000000
--- a/kshell-console-jline2/src/main/java/lib/jline/console/completer/EnumCompleter.java
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * 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
- */
-package lib.jline.console.completer;
-
-/**
- * {@link Completer} for {@link Enum} names.
- *
- * @author Jason Dillon
- * @since 2.3
- */
-public class EnumCompleter
- extends StringsCompleter
-{
- public EnumCompleter(Class extends Enum>> source) {
- this(source, true);
- }
-
- public EnumCompleter(Class extends Enum>> source, boolean toLowerCase) {
- lib.jline.internal.Preconditions.checkNotNull(source);
-
- for (Enum> n : source.getEnumConstants()) {
- this.getStrings().add(toLowerCase ? n.name().toLowerCase() : n.name());
- }
- }
-}
\ No newline at end of file
diff --git a/kshell-console-jline2/src/main/java/lib/jline/console/completer/FileNameCompleter.java b/kshell-console-jline2/src/main/java/lib/jline/console/completer/FileNameCompleter.java
deleted file mode 100644
index 113f6f9..0000000
--- a/kshell-console-jline2/src/main/java/lib/jline/console/completer/FileNameCompleter.java
+++ /dev/null
@@ -1,132 +0,0 @@
-/*
- * 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
- */
-package lib.jline.console.completer;
-
-import lib.jline.internal.Configuration;
-import lib.jline.internal.Preconditions;
-
-import java.io.File;
-import java.util.List;
-
-/**
- * A file name completer takes the buffer and issues a list of
- * potential completions.
- *
- * This completer tries to behave as similar as possible to
- * bash's file name completion (using GNU readline)
- * with the following exceptions:
- *
- *
- *
Candidates that are directories will end with "/"
- *
Wildcard regular expressions are not evaluated or replaced
- *
The "~" character can be used to represent the user's home,
- * but it cannot complete to other users' homes, since java does
- * not provide any way of determining that easily
- *
- *
- * @author Marc Prud'hommeaux
- * @author Jason Dillon
- * @since 2.3
- */
-public class FileNameCompleter
- implements Completer
-{
- // TODO: Handle files with spaces in them
-
- private static final boolean OS_IS_WINDOWS;
-
- static {
- String os = Configuration.getOsName();
- OS_IS_WINDOWS = os.contains("windows");
- }
-
- public int complete(String buffer, final int cursor, final List candidates) {
- // buffer can be null
- Preconditions.checkNotNull(candidates);
-
- if (buffer == null) {
- buffer = "";
- }
-
- if (OS_IS_WINDOWS) {
- buffer = buffer.replace('/', '\\');
- }
-
- String translated = buffer;
-
- File homeDir = getUserHome();
-
- // Special character: ~ maps to the user's home directory
- if (translated.startsWith("~" + separator())) {
- translated = homeDir.getPath() + translated.substring(1);
- }
- else if (translated.startsWith("~")) {
- translated = homeDir.getParentFile().getAbsolutePath();
- }
- else if (!(new File(translated).isAbsolute())) {
- String cwd = getUserDir().getAbsolutePath();
- translated = cwd + separator() + translated;
- }
-
- File file = new File(translated);
- final File dir;
-
- if (translated.endsWith(separator())) {
- dir = file;
- }
- else {
- dir = file.getParentFile();
- }
-
- File[] entries = dir == null ? new File[0] : dir.listFiles();
-
- return matchFiles(buffer, translated, entries, candidates);
- }
-
- protected String separator() {
- return File.separator;
- }
-
- protected File getUserHome() {
- return Configuration.getUserHome();
- }
-
- protected File getUserDir() {
- return new File(".");
- }
-
- protected int matchFiles(final String buffer, final String translated, final File[] files, final List candidates) {
- if (files == null) {
- return -1;
- }
-
- int matches = 0;
-
- // first pass: just count the matches
- for (File file : files) {
- if (file.getAbsolutePath().startsWith(translated)) {
- matches++;
- }
- }
- for (File file : files) {
- if (file.getAbsolutePath().startsWith(translated)) {
- CharSequence name = file.getName() + (matches == 1 && file.isDirectory() ? separator() : " ");
- candidates.add(render(file, name).toString());
- }
- }
-
- final int index = buffer.lastIndexOf(separator());
-
- return index + separator().length();
- }
-
- protected CharSequence render(final File file, final CharSequence name) {
- return name;
- }
-}
diff --git a/kshell-console-jline2/src/main/java/lib/jline/console/completer/NullCompleter.java b/kshell-console-jline2/src/main/java/lib/jline/console/completer/NullCompleter.java
deleted file mode 100644
index 8a2c89b..0000000
--- a/kshell-console-jline2/src/main/java/lib/jline/console/completer/NullCompleter.java
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * 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
- */
-package lib.jline.console.completer;
-
-import java.util.List;
-
-/**
- * Null completer.
- *
- * @author Marc Prud'hommeaux
- * @author Jason Dillon
- * @since 2.3
- */
-public final class NullCompleter
- implements Completer
-{
- public static final NullCompleter INSTANCE = new NullCompleter();
-
- public int complete(final String buffer, final int cursor, final List candidates) {
- return -1;
- }
-}
\ No newline at end of file
diff --git a/kshell-console-jline2/src/main/java/lib/jline/console/completer/StringsCompleter.java b/kshell-console-jline2/src/main/java/lib/jline/console/completer/StringsCompleter.java
deleted file mode 100644
index 1107611..0000000
--- a/kshell-console-jline2/src/main/java/lib/jline/console/completer/StringsCompleter.java
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * 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
- */
-package lib.jline.console.completer;
-
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.List;
-import java.util.SortedSet;
-import java.util.TreeSet;
-
-/**
- * Completer for a set of strings.
- *
- * @author Jason Dillon
- * @since 2.3
- */
-public class StringsCompleter
- implements Completer
-{
- private final SortedSet strings = new TreeSet();
-
- public StringsCompleter() {
- // empty
- }
-
- public StringsCompleter(final Collection strings) {
- lib.jline.internal.Preconditions.checkNotNull(strings);
- getStrings().addAll(strings);
- }
-
- public StringsCompleter(final String... strings) {
- this(Arrays.asList(strings));
- }
-
- public Collection getStrings() {
- return strings;
- }
-
- public int complete(final String buffer, final int cursor, final List candidates) {
- // buffer could be null
- lib.jline.internal.Preconditions.checkNotNull(candidates);
-
- if (buffer == null) {
- candidates.addAll(strings);
- }
- else {
- for (String match : strings.tailSet(buffer)) {
- if (!match.startsWith(buffer)) {
- break;
- }
-
- candidates.add(match);
- }
- }
-
- return candidates.isEmpty() ? -1 : 0;
- }
-}
\ No newline at end of file
diff --git a/kshell-console-jline2/src/main/java/lib/jline/console/completer/package-info.java b/kshell-console-jline2/src/main/java/lib/jline/console/completer/package-info.java
deleted file mode 100644
index 86795c5..0000000
--- a/kshell-console-jline2/src/main/java/lib/jline/console/completer/package-info.java
+++ /dev/null
@@ -1,14 +0,0 @@
-/*
- * 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
- */
-/**
- * Console completer support.
- *
- * @since 2.3
- */
-package lib.jline.console.completer;
\ No newline at end of file
diff --git a/kshell-console-jline2/src/main/java/lib/jline/console/history/FileHistory.java b/kshell-console-jline2/src/main/java/lib/jline/console/history/FileHistory.java
deleted file mode 100644
index 15e72ad..0000000
--- a/kshell-console-jline2/src/main/java/lib/jline/console/history/FileHistory.java
+++ /dev/null
@@ -1,113 +0,0 @@
-/*
- * 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
- */
-package lib.jline.console.history;
-
-import lib.jline.internal.Log;
-
-import java.io.BufferedOutputStream;
-import java.io.BufferedReader;
-import java.io.File;
-import java.io.FileOutputStream;
-import java.io.FileReader;
-import java.io.Flushable;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.io.PrintStream;
-import java.io.Reader;
-
-/**
- * {@link History} using a file for persistent backing.
- *
- * Implementers should install shutdown hook to call {@link FileHistory#flush}
- * to save history to disk.
- *
- * @author Jason Dillon
- * @since 2.0
- */
-public class FileHistory
- extends MemoryHistory
- implements lib.jline.console.history.PersistentHistory, Flushable
-{
- private final File file;
-
- public FileHistory(final File file) throws IOException {
- this.file = lib.jline.internal.Preconditions.checkNotNull(file).getAbsoluteFile();
- load(file);
- }
-
- public File getFile() {
- return file;
- }
-
- public void load(final File file) throws IOException {
- lib.jline.internal.Preconditions.checkNotNull(file);
- if (file.exists()) {
- Log.trace("Loading history from: ", file);
- FileReader reader = null;
- try{
- reader = new FileReader(file);
- load(reader);
- } finally{
- if(reader != null){
- reader.close();
- }
- }
- }
- }
-
- public void load(final InputStream input) throws IOException {
- lib.jline.internal.Preconditions.checkNotNull(input);
- load(new InputStreamReader(input));
- }
-
- public void load(final Reader reader) throws IOException {
- lib.jline.internal.Preconditions.checkNotNull(reader);
- BufferedReader input = new BufferedReader(reader);
-
- String item;
- while ((item = input.readLine()) != null) {
- internalAdd(item);
- }
- }
-
- public void flush() throws IOException {
- Log.trace("Flushing history");
-
- if (!file.exists()) {
- File dir = file.getParentFile();
- if (!dir.exists() && !dir.mkdirs()) {
- Log.warn("Failed to create directory: ", dir);
- }
- if (!file.createNewFile()) {
- Log.warn("Failed to create file: ", file);
- }
- }
-
- PrintStream out = new PrintStream(new BufferedOutputStream(new FileOutputStream(file)));
- try {
- for (Entry entry : this) {
- out.println(entry.value());
- }
- }
- finally {
- out.close();
- }
- }
-
- public void purge() throws IOException {
- Log.trace("Purging history");
-
- clear();
-
- if (!file.delete()) {
- Log.warn("Failed to delete history file: ", file);
- }
- }
-}
\ No newline at end of file
diff --git a/kshell-console-jline2/src/main/java/lib/jline/console/history/History.java b/kshell-console-jline2/src/main/java/lib/jline/console/history/History.java
deleted file mode 100644
index ed625a9..0000000
--- a/kshell-console-jline2/src/main/java/lib/jline/console/history/History.java
+++ /dev/null
@@ -1,106 +0,0 @@
-/*
- * 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
- */
-package lib.jline.console.history;
-
-import java.util.Iterator;
-import java.util.ListIterator;
-
-/**
- * Console history.
- *
- * @author Marc Prud'hommeaux
- * @author Jason Dillon
- * @since 2.3
- */
-public interface History
- extends Iterable
-{
- int size();
-
- boolean isEmpty();
-
- int index();
-
- void clear();
-
- CharSequence get(int index);
-
- void add(CharSequence line);
-
- /**
- * Set the history item at the given index to the given CharSequence.
- *
- * @param index the index of the history offset
- * @param item the new item
- * @since 2.7
- */
- void set(int index, CharSequence item);
-
- /**
- * Remove the history element at the given index.
- *
- * @param i the index of the element to remove
- * @return the removed element
- * @since 2.7
- */
- CharSequence remove(int i);
-
- /**
- * Remove the first element from history.
- *
- * @return the removed element
- * @since 2.7
- */
- CharSequence removeFirst();
-
- /**
- * Remove the last element from history
- *
- * @return the removed element
- * @since 2.7
- */
- CharSequence removeLast();
-
- void replace(CharSequence item);
-
- //
- // Entries
- //
-
- interface Entry
- {
- int index();
-
- CharSequence value();
- }
-
- ListIterator entries(int index);
-
- ListIterator entries();
-
- Iterator iterator();
-
- //
- // Navigation
- //
-
- CharSequence current();
-
- boolean previous();
-
- boolean next();
-
- boolean moveToFirst();
-
- boolean moveToLast();
-
- boolean moveTo(int index);
-
- void moveToEnd();
-}
diff --git a/kshell-console-jline2/src/main/java/lib/jline/console/history/MemoryHistory.java b/kshell-console-jline2/src/main/java/lib/jline/console/history/MemoryHistory.java
deleted file mode 100644
index 427ec79..0000000
--- a/kshell-console-jline2/src/main/java/lib/jline/console/history/MemoryHistory.java
+++ /dev/null
@@ -1,344 +0,0 @@
-/*
- * 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
- */
-package lib.jline.console.history;
-
-import java.util.Iterator;
-import java.util.LinkedList;
-import java.util.ListIterator;
-import java.util.NoSuchElementException;
-
-/**
- * Non-persistent {@link History}.
- *
- * @author Marc Prud'hommeaux
- * @author Jason Dillon
- * @since 2.3
- */
-public class MemoryHistory
- implements History
-{
- public static final int DEFAULT_MAX_SIZE = 500;
-
- private final LinkedList items = new LinkedList();
-
- private int maxSize = DEFAULT_MAX_SIZE;
-
- private boolean ignoreDuplicates = true;
-
- private boolean autoTrim = false;
-
- // NOTE: These are all ideas from looking at the Bash man page:
-
- // TODO: Add ignore space? (lines starting with a space are ignored)
-
- // TODO: Add ignore patterns?
-
- // TODO: Add history timestamp?
-
- // TODO: Add erase dups?
-
- private int offset = 0;
-
- private int index = 0;
-
- public void setMaxSize(final int maxSize) {
- this.maxSize = maxSize;
- maybeResize();
- }
-
- public int getMaxSize() {
- return maxSize;
- }
-
- public boolean isIgnoreDuplicates() {
- return ignoreDuplicates;
- }
-
- public void setIgnoreDuplicates(final boolean flag) {
- this.ignoreDuplicates = flag;
- }
-
- public boolean isAutoTrim() {
- return autoTrim;
- }
-
- public void setAutoTrim(final boolean flag) {
- this.autoTrim = flag;
- }
-
- public int size() {
- return items.size();
- }
-
- public boolean isEmpty() {
- return items.isEmpty();
- }
-
- public int index() {
- return offset + index;
- }
-
- public void clear() {
- items.clear();
- offset = 0;
- index = 0;
- }
-
- public CharSequence get(final int index) {
- return items.get(index - offset);
- }
-
- public void set(int index, CharSequence item) {
- items.set(index - offset, item);
- }
-
- public void add(CharSequence item) {
- lib.jline.internal.Preconditions.checkNotNull(item);
-
- if (isAutoTrim()) {
- item = String.valueOf(item).trim();
- }
-
- if (isIgnoreDuplicates()) {
- if (!items.isEmpty() && item.equals(items.getLast())) {
- return;
- }
- }
-
- internalAdd(item);
- }
-
- public CharSequence remove(int i) {
- return items.remove(i);
- }
-
- public CharSequence removeFirst() {
- return items.removeFirst();
- }
-
- public CharSequence removeLast() {
- return items.removeLast();
- }
-
- protected void internalAdd(CharSequence item) {
- items.add(item);
-
- maybeResize();
- }
-
- public void replace(final CharSequence item) {
- items.removeLast();
- add(item);
- }
-
- private void maybeResize() {
- while (size() > getMaxSize()) {
- items.removeFirst();
- offset++;
- }
-
- index = size();
- }
-
- public ListIterator entries(final int index) {
- return new EntriesIterator(index - offset);
- }
-
- public ListIterator entries() {
- return entries(offset);
- }
-
- public Iterator iterator() {
- return entries();
- }
-
- private static class EntryImpl
- implements Entry
- {
- private final int index;
-
- private final CharSequence value;
-
- public EntryImpl(int index, CharSequence value) {
- this.index = index;
- this.value = value;
- }
-
- public int index() {
- return index;
- }
-
- public CharSequence value() {
- return value;
- }
-
- @Override
- public String toString() {
- return String.format("%d: %s", index, value);
- }
- }
-
- private class EntriesIterator
- implements ListIterator
- {
- private final ListIterator source;
-
- private EntriesIterator(final int index) {
- source = items.listIterator(index);
- }
-
- public Entry next() {
- if (!source.hasNext()) {
- throw new NoSuchElementException();
- }
- return new EntryImpl(offset + source.nextIndex(), source.next());
- }
-
- public Entry previous() {
- if (!source.hasPrevious()) {
- throw new NoSuchElementException();
- }
- return new EntryImpl(offset + source.previousIndex(), source.previous());
- }
-
- public int nextIndex() {
- return offset + source.nextIndex();
- }
-
- public int previousIndex() {
- return offset + source.previousIndex();
- }
-
- public boolean hasNext() {
- return source.hasNext();
- }
-
- public boolean hasPrevious() {
- return source.hasPrevious();
- }
-
- public void remove() {
- throw new UnsupportedOperationException();
- }
-
- public void set(final Entry entry) {
- throw new UnsupportedOperationException();
- }
-
- public void add(final Entry entry) {
- throw new UnsupportedOperationException();
- }
- }
-
- //
- // Navigation
- //
-
- /**
- * This moves the history to the last entry. This entry is one position
- * before the moveToEnd() position.
- *
- * @return Returns false if there were no history entries or the history
- * index was already at the last entry.
- */
- public boolean moveToLast() {
- int lastEntry = size() - 1;
- if (lastEntry >= 0 && lastEntry != index) {
- index = size() - 1;
- return true;
- }
-
- return false;
- }
-
- /**
- * Move to the specified index in the history
- */
- public boolean moveTo(int index) {
- index -= offset;
- if (index >= 0 && index < size() ) {
- this.index = index;
- return true;
- }
- return false;
- }
-
- /**
- * Moves the history index to the first entry.
- *
- * @return Return false if there are no entries in the history or if the
- * history is already at the beginning.
- */
- public boolean moveToFirst() {
- if (size() > 0 && index != 0) {
- index = 0;
- return true;
- }
-
- return false;
- }
-
- /**
- * Move to the end of the history buffer. This will be a blank entry, after
- * all of the other entries.
- */
- public void moveToEnd() {
- index = size();
- }
-
- /**
- * Return the content of the current buffer.
- */
- public CharSequence current() {
- if (index >= size()) {
- return "";
- }
-
- return items.get(index);
- }
-
- /**
- * Move the pointer to the previous element in the buffer.
- *
- * @return true if we successfully went to the previous element
- */
- public boolean previous() {
- if (index <= 0) {
- return false;
- }
-
- index--;
-
- return true;
- }
-
- /**
- * Move the pointer to the next element in the buffer.
- *
- * @return true if we successfully went to the next element
- */
- public boolean next() {
- if (index >= size()) {
- return false;
- }
-
- index++;
-
- return true;
- }
-
- @Override
- public String toString() {
- StringBuilder sb = new StringBuilder();
- for (Entry e : this) {
- sb.append(e.toString() + "\n");
- }
- return sb.toString();
- }
-}
diff --git a/kshell-console-jline2/src/main/java/lib/jline/console/history/PersistentHistory.java b/kshell-console-jline2/src/main/java/lib/jline/console/history/PersistentHistory.java
deleted file mode 100644
index ebba200..0000000
--- a/kshell-console-jline2/src/main/java/lib/jline/console/history/PersistentHistory.java
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * 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
- */
-package lib.jline.console.history;
-
-import java.io.IOException;
-
-/**
- * Persistent {@link History}.
- *
- * @author Jason Dillon
- * @since 2.3
- */
-public interface PersistentHistory
- extends History
-{
- /**
- * Flush all items to persistent storage.
- *
- * @throws IOException Flush failed
- */
- void flush() throws IOException;
-
- /**
- * Purge persistent storage and {@link #clear}.
- *
- * @throws IOException Purge failed
- */
- void purge() throws IOException;
-}
\ No newline at end of file
diff --git a/kshell-console-jline2/src/main/java/lib/jline/console/history/package-info.java b/kshell-console-jline2/src/main/java/lib/jline/console/history/package-info.java
deleted file mode 100644
index ab18fb8..0000000
--- a/kshell-console-jline2/src/main/java/lib/jline/console/history/package-info.java
+++ /dev/null
@@ -1,14 +0,0 @@
-/*
- * 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
- */
-/**
- * Console history support.
- *
- * @since 2.0
- */
-package lib.jline.console.history;
\ No newline at end of file
diff --git a/kshell-console-jline2/src/main/java/lib/jline/console/internal/ConsoleReaderInputStream.java b/kshell-console-jline2/src/main/java/lib/jline/console/internal/ConsoleReaderInputStream.java
deleted file mode 100644
index 7328dfa..0000000
--- a/kshell-console-jline2/src/main/java/lib/jline/console/internal/ConsoleReaderInputStream.java
+++ /dev/null
@@ -1,121 +0,0 @@
-/*
- * 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
- */
-package lib.jline.console.internal;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.SequenceInputStream;
-import java.util.Enumeration;
-
-// FIXME: Clean up API and move to jline.console.runner package
-
-/**
- * An {@link InputStream} implementation that wraps a {@link lib.jline.console.ConsoleReader}.
- * It is useful for setting up the {@link System#in} for a generic console.
- *
- * @author Marc Prud'hommeaux
- * @since 2.7
- */
-class ConsoleReaderInputStream
- extends SequenceInputStream
-{
- private static InputStream systemIn = System.in;
-
- public static void setIn() throws IOException {
- setIn(new lib.jline.console.ConsoleReader());
- }
-
- public static void setIn(final lib.jline.console.ConsoleReader reader) {
- System.setIn(new ConsoleReaderInputStream(reader));
- }
-
- /**
- * Restore the original {@link System#in} input stream.
- */
- public static void restoreIn() {
- System.setIn(systemIn);
- }
-
- public ConsoleReaderInputStream(final lib.jline.console.ConsoleReader reader) {
- super(new ConsoleEnumeration(reader));
- }
-
- private static class ConsoleEnumeration
- implements Enumeration
- {
- private final lib.jline.console.ConsoleReader reader;
- private ConsoleLineInputStream next = null;
- private ConsoleLineInputStream prev = null;
-
- public ConsoleEnumeration(final lib.jline.console.ConsoleReader reader) {
- this.reader = reader;
- }
-
- public InputStream nextElement() {
- if (next != null) {
- InputStream n = next;
- prev = next;
- next = null;
-
- return n;
- }
-
- return new ConsoleLineInputStream(reader);
- }
-
- public boolean hasMoreElements() {
- // the last line was null
- if ((prev != null) && (prev.wasNull == true)) {
- return false;
- }
-
- if (next == null) {
- next = (ConsoleLineInputStream) nextElement();
- }
-
- return next != null;
- }
- }
-
- private static class ConsoleLineInputStream
- extends InputStream
- {
- private final lib.jline.console.ConsoleReader reader;
- private String line = null;
- private int index = 0;
- private boolean eol = false;
- protected boolean wasNull = false;
-
- public ConsoleLineInputStream(final lib.jline.console.ConsoleReader reader) {
- this.reader = reader;
- }
-
- public int read() throws IOException {
- if (eol) {
- return -1;
- }
-
- if (line == null) {
- line = reader.readLine();
- }
-
- if (line == null) {
- wasNull = true;
- return -1;
- }
-
- if (index >= line.length()) {
- eol = true;
- return '\n'; // lines are ended with a newline
- }
-
- return line.charAt(index++);
- }
- }
-}
\ No newline at end of file
diff --git a/kshell-console-jline2/src/main/java/lib/jline/console/internal/ConsoleRunner.java b/kshell-console-jline2/src/main/java/lib/jline/console/internal/ConsoleRunner.java
deleted file mode 100644
index c12c693..0000000
--- a/kshell-console-jline2/src/main/java/lib/jline/console/internal/ConsoleRunner.java
+++ /dev/null
@@ -1,93 +0,0 @@
-/*
- * 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
- */
-package lib.jline.console.internal;
-
-import lib.jline.console.completer.ArgumentCompleter;
-
-import java.io.File;
-import java.lang.reflect.Method;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
-import java.util.StringTokenizer;
-
-// FIXME: Clean up API and move to jline.console.runner package
-
-/**
- * A pass-through application that sets the system input stream to a
- * {@link lib.jline.console.ConsoleReader} and invokes the specified main method.
- *
- * @author Marc Prud'hommeaux
- * @since 2.7
- */
-public class ConsoleRunner
-{
- public static final String property = "jline.history";
-
- // FIXME: This is really ugly... re-write this
-
- public static void main(final String[] args) throws Exception {
- List argList = new ArrayList(Arrays.asList(args));
- if (argList.size() == 0) {
- usage();
- return;
- }
-
- String historyFileName = System.getProperty(ConsoleRunner.property, null);
-
- String mainClass = argList.remove(0);
- lib.jline.console.ConsoleReader reader = new lib.jline.console.ConsoleReader();
-
- if (historyFileName != null) {
- reader.setHistory(new lib.jline.console.history.FileHistory(new File(lib.jline.internal.Configuration.getUserHome(),
- String.format(".jline-%s.%s.history", mainClass, historyFileName))));
- }
- else {
- reader.setHistory(new lib.jline.console.history.FileHistory(new File(lib.jline.internal.Configuration.getUserHome(),
- String.format(".jline-%s.history", mainClass))));
- }
-
- String completors = System.getProperty(ConsoleRunner.class.getName() + ".completers", "");
- List completorList = new ArrayList();
-
- for (StringTokenizer tok = new StringTokenizer(completors, ","); tok.hasMoreTokens();) {
- Object obj = Class.forName(tok.nextToken()).newInstance();
- completorList.add((lib.jline.console.completer.Completer) obj);
- }
-
- if (completorList.size() > 0) {
- reader.addCompleter(new ArgumentCompleter(completorList));
- }
-
- ConsoleReaderInputStream.setIn(reader);
-
- try {
- Class> type = Class.forName(mainClass);
- Method method = type.getMethod("main", String[].class);
- String[] mainArgs = argList.toArray(new String[argList.size()]);
- method.invoke(null, (Object) mainArgs);
- }
- finally {
- // just in case this main method is called from another program
- ConsoleReaderInputStream.restoreIn();
- if (reader.getHistory() instanceof lib.jline.console.history.PersistentHistory) {
- ((lib.jline.console.history.PersistentHistory) reader.getHistory()).flush();
- }
- }
- }
-
- private static void usage() {
- System.out.println("Usage: \n java " + "[-Djline.history='name'] "
- + ConsoleRunner.class.getName()
- + " [args]"
- + "\n\nThe -Djline.history option will avoid history"
- + "\nmangling when running ConsoleRunner on the same application."
- + "\n\nargs will be passed directly to the target class name.");
- }
-}
diff --git a/kshell-console-jline2/src/main/java/lib/jline/console/package-info.java b/kshell-console-jline2/src/main/java/lib/jline/console/package-info.java
deleted file mode 100644
index 37cb80d..0000000
--- a/kshell-console-jline2/src/main/java/lib/jline/console/package-info.java
+++ /dev/null
@@ -1,14 +0,0 @@
-/*
- * 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
- */
-/**
- * Console support.
- *
- * @since 2.0
- */
-package lib.jline.console;
\ No newline at end of file
diff --git a/kshell-console-jline2/src/main/java/lib/jline/internal/Ansi.java b/kshell-console-jline2/src/main/java/lib/jline/internal/Ansi.java
deleted file mode 100644
index 22ae1e0..0000000
--- a/kshell-console-jline2/src/main/java/lib/jline/internal/Ansi.java
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * 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
- */
-package lib.jline.internal;
-
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-
-import org.fusesource.jansi.AnsiOutputStream;
-
-/**
- * Ansi support.
- *
- * @author Guillaume Nodet
- * @since 2.13
- */
-public class Ansi {
-
- public static String stripAnsi(String str) {
- if (str == null) return "";
- try {
- ByteArrayOutputStream baos = new ByteArrayOutputStream();
- AnsiOutputStream aos = new AnsiOutputStream(baos);
- aos.write(str.getBytes());
- aos.close();
- return baos.toString();
- } catch (IOException e) {
- return str;
- }
- }
-
-}
diff --git a/kshell-console-jline2/src/main/java/lib/jline/internal/Configuration.java b/kshell-console-jline2/src/main/java/lib/jline/internal/Configuration.java
deleted file mode 100644
index 9b22dad..0000000
--- a/kshell-console-jline2/src/main/java/lib/jline/internal/Configuration.java
+++ /dev/null
@@ -1,259 +0,0 @@
-/*
- * 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
- */
-package lib.jline.internal;
-
-import java.io.BufferedInputStream;
-import java.io.File;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.FileNotFoundException;
-import java.net.URL;
-import java.nio.charset.Charset;
-import java.nio.charset.IllegalCharsetNameException;
-import java.util.Map;
-import java.util.Properties;
-
-/**
- * Provides access to configuration values.
- *
- * @author Jason Dillon
- * @author Guillaume Nodet
- * @since 2.4
- */
-public class Configuration
-{
- /**
- * System property which can point to a file or URL containing configuration properties to load.
- *
- * @since 2.7
- */
- public static final String JLINE_CONFIGURATION = "jline.configuration";
-
- /**
- * Default configuration file name loaded from user's home directory.
- */
- public static final String JLINE_RC = ".jline.rc";
-
- private static volatile Properties properties;
-
- private static Properties initProperties() {
- URL url = determineUrl();
- Properties props = new Properties();
- try {
- loadProperties(url, props);
- }
- catch (FileNotFoundException e) {
- // debug here and no stack trace, as this can happen normally if default jline.rc file is missing
- Log.debug("Unable to read configuration: ", e.toString());
- }
- catch (IOException e) {
- Log.warn("Unable to read configuration from: ", url, e);
- }
- return props;
- }
-
- private static void loadProperties(final URL url, final Properties props) throws IOException {
- Log.debug("Loading properties from: ", url);
- InputStream input = url.openStream();
- try {
- props.load(new BufferedInputStream(input));
- }
- finally {
- try {
- input.close();
- }
- catch (IOException e) {
- // ignore
- }
- }
-
- if (Log.DEBUG) {
- Log.debug("Loaded properties:");
- for (Map.Entry