Jline是一个开源的Java控制台输入类库,最近的项目需要用到这个东东(
Zookeeper的命令行用的也是这个
),就是实现在命令行输入SQL语句,并解析它。不过它自带的自动补全功能有点弱,无法满足输入SQL时的TAB提示(提示SQL的关键字、表名、字段名之类的)的需求,下面贴出我的实现,本人使用的版本是0.9.94。
要实现TAB提示,需要实现Jline的Completor接口,其核心方法是complete方法,方法原型是这样的,
public int complete(final String buffer, final int cursor, final List clist)
参数解释:String buffer --- 在控制台按下tab键时已经输入的字符串
int cursor --- 在控制台按下tab键时光标的位置
List clist --- 返回的候选词
下面是我的代码
package client.shell;
import java.util.Arrays;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.SortedSet;
import java.util.TreeSet;
import jline.Completor;
public class MyCompletor implements Completor, Cloneable {
SortedSet candidates;
public MyCompletor(final String[] candidateStrings) {
candidates = new TreeSet();
for (String string : candidateStrings) {
candidates.add(string);
public int complete(final String buffer, final int cursor, final List clist) {
String start = (buffer == null) ? "" : buffer;
// 找到字符串中最后一个空格出现的位置
int index = start.lastIndexOf(" ");
// 把最后一个空格后面的词截出来
String tmp = start.substring(index + 1, start.length());
// candidates中存储的词都是按字典序排下来的
// 例如candidates中有如下三个词:insert select where
// 如果tmp是'se',则通过下面的tailSet方法,会返回select和where两个词
SortedSet matches = candidates.tailSet(tmp);
for (Iterator i = matches.iterator(); i.hasNext();) {
String can = (String) i.next();
// 过滤掉不是以tmp这个字符串开头的词
if (!(can.startsWith(tmp))) {
break;
clist.add(can);
if (clist.size() == 1) {
clist.set(0, ((String) clist.get(0)) + " ");
// the index of the completion is always from the beginning of the
// buffer.
// 如果没有从候选词中找到任何匹配的词,则返回-1
// 如果index为-1,即输入的字符串中没有空格,则返回0(起始位置)
// 如果index不是-1,则返回最后一个空格的位置加1
return (clist.size() == 0) ? (-1) : (index == -1 ? 0 : index + 1);
public void setCandidates(final SortedSet candidates) {
this.candidates = candidates;
public SortedSet getCandidates() {
return Collections.unmodifiableSortedSet(this.candidates);
public void setCandidateStrings(final String[] strings) {
setCandidates(new TreeSet(Arrays.asList(strings)));
public void addCandidateString(final String candidateString) {
candidates.add(candidateString);
public Object clone() throws CloneNotSupportedException {
return super.clone();
不过在使用中还是有几个问题还没解决,比如按HOME和END键没有返回行首或行尾,有时候按方向键上翻历史记录时,导致前面已经输出的多个字符被历史记录覆盖掉了,这两个问题都是用XShell远程连接时才有的,直接用键盘连机器还没有出现这些问题呀。。。如果哪位大神知晓其中缘由,请下方回复,不胜感激。
Overview
JLine 是一个用来处理控制台输入的Java类库,目前最新的版本是0.9.94。其官方网址是http://jline.sourceforge.net。在介绍JLine之前,首先还是介绍一下Java 6中的Console类,以便进行对比。
2 Java Console
通过调用System.console()方法可以得到与当前虚拟机对应的Co...
最近在用JLine开发的命令行客户端差不多快完工了,结果不符合需求,需要命令行格式的,幸好改动不大,哈哈,做成 Linux的命令即可。。
百度上关于JLine的帖子太少,目前Jline的版本已经到2.9.X了,JLine1和JLine2区别还是很大的,而且这个东西用途太强大(命令行界面终端很多,唯有这个发展的生机勃勃),还是需要好好学习下。
比如我们习惯在IDEA里打包用mvn clean package
在Scala IDEA for eclipse里出现mvn clean compile assembly:single
可能会出现Failed to execute goal org.scala-tools:maven...
[hadoop@mina0 hive]$ bin/hive
Logging initialized using configuration in jar:file:/home/hadoop/soft/hive/lib/hive-common-1.2.1.jar!/hive-log4j.properties
[ERROR] Terminal initialization failed;