我们都知道,软件的用户界面无非分为 GUI (图形用户界面)和 CLI (命令行用户界面)。对于我们经常使用 Linux 的人来说,命令行界面一定非常熟悉。无论是 Shell 里输入命令的界面,还是如 GDB 等软件的内部交互界面,都是命令行界面。而当我们开发自己的软件,要写认真写一个 CLI 的时候,却发现要手写做出一个好用的命令行界面其实非常困难。因为一个好的命令行界面,在输入/输出之外,还要支持一些常见的命令行功能。
JLine3是一个用于处理控制台输入的Java库,可实现如下功能:
自动补全:当按下 TAB 键时,在当前光标处进行内容补全。根据上下文信息,补全可能是对命令的补全,也可能是对文件路径的补全。
命令历史:当按上/下方向键时,可以显示上一条/下一条命令。
行编辑 (line editing):可以使用 Emacs 快捷键进行行内的编辑功能,例如 Ctrl+A 移动光标至行首,Ctrl+E 移动光标至行尾。
本文主要讲解运行环境的搭建。先上maven依赖:
<dependency> <groupId>org.jline</groupId> <artifactId>jline</artifactId> <version>3.20.0</version> </dependency> <dependency> <groupId>org.fusesource.jansi</groupId> <artifactId>jansi</artifactId> <version>2.4.0</version> </dependency>
jline3和jansi的版本也可以是其他版本,这两个版本都测试通过,都可以从阿里云仓库中自动加载。
接下来是代码部分,以下代码已通过测试,上完整java代码:
import org.jline.builtins.Completers; import org.jline.reader.Completer; import org.jline.reader.LineReader; import org.jline.reader.LineReaderBuilder; import org.jline.reader.impl.completer.ArgumentCompleter; import org.jline.reader.impl.completer.StringsCompleter; import org.jline.terminal.Terminal; import org.jline.terminal.TerminalBuilder; import java.io.*; public class Jline3Demo { public static void main(String[] args) { Terminal terminal = null; try { terminal = TerminalBuilder.builder() .system(true) .name("xterm") .type("xterm") .build(); } catch (IOException e) { e.printStackTrace(); } Completer createCompleter = new ArgumentCompleter( new StringsCompleter("help","look"), new Completers.FileNameCompleter() ); LineReader lineReader = LineReaderBuilder.builder() .terminal(terminal) .completer(createCompleter) .build(); String prompt = ">>"; while (true) { String command; command = lineReader.readLine(prompt); System.out.println("已输入:"+command); if(command.startsWith("exit")){ System.out.println("程序已退出"); break; } } } }
以上代码可以实现按方向键查看历史命令,且不会出现乱码,输入look或help命令并按tab键后,实现命令补全,并可以在后面通过输入路径例如"/"等实现文件路径补全。
terminal = TerminalBuilder.builder() .system(true) .name("xterm") .type("xterm")这句代码中的.name("xterm")和.type("xterm")在linux上运行是必须 的,否则会报:Cannot run program "infocmp": error=0, Failed to exec spawn helper错误,虽然不影响运行,但十分影响观感,这是因为系统环境变量配置错误或者系统缺少必要的执行程序导致的。"infocmp"是用来显示不同终端类型之间的信息差异的,它是"ncurses"库的一部分,通常在类Unix系统中可以找到。
以下是可能的解决步骤:确认你的系统是否安装了 "ncurses" 库。在Linux系统中,你可以使用包管理器(如apt-get,yum等)来检查和安装。但要在linux服务器上安装"ncurses" 库,显然就不优雅了。
好在有chatgpt,chatgpt3.5给出了解决方案:通过显式地指定终端类型为"xterm",而不是依赖于系统默认值,从而解决了这个问题。