8

我将JLine 2 (v2.13) 与 Socket IO 结合使用,为我的应用程序创建一个管理控制台,可以通过普通的 telnet 客户端进行访问。但是我发现它应该打印出换行符时会打印出奇怪的符号:

act.app.restart  restart app^Jact.job.list  List jobs

正确的输出应该是:

act.app.restart  restart app
act.job.list     List jobs

我追溯了代码,发现了导致问题的以下代码行:

在此处输入图像描述

另一个奇怪的事情是,当我按向上箭头获取历史记录时,控制台打印出来^[[A,没有其他任何反应。

有人有什么主意吗?

更新:添加了相关的源代码

  1. 接受传入 telnet 连接的代码:

在此处输入图像描述

  1. 创建ConsoleReader和调度命令的代码:

在此处输入图像描述

更新 2

对不起,我消失了一段时间。回来吧,因为我的项目让我呼吸到了新鲜空气。所以这就是发生的事情:我创建了一个PrintWriter并将其用作该^J问题的解决方法:

在此处输入图像描述

jline2但是,与 telnet 会话一起使用时还有许多其他问题:

  1. 类型<TAB>显示选项卡而不是激活完整列表。但是,在我按下回车键后,它会给我一个完整的列表和一条错误消息: 在此处输入图像描述
  2. 键入<UP>箭头,显示^[[A,按回车键它将执行我的最后一个命令。但是我失去了命令行编辑

问题仍然存在,我相信应该有办法解决它只需要一些指导......

4

1 回答 1

0

编辑: 我的错,我展示的方法是私有的。尽管如此,这不是一个错误——它是代码在做它应该做的事情。使用 rawPrint 的两个公共方法(我把它们放在最后)仅将它用于屏蔽输出,显然用于打印完成,因此 ConsoleReader 可能不支持您的用例 - 这可能是一个设计错误,但我认为它的意思成为那样。文档中提到了箭头键问题作为终端配置问题。

ConsoleReader.java 在这里:https ://github.com/jline/jline2/blob/master/src/main/java/jline/console/ConsoleReader.java

我认为这是最后一个版本,等等。

您正在做的是创建一个 ConsoleReader 调用 println() 。LF 显示为 ^J。这不是一个错误,因为该方法正在做它应该做的事情:

/*3478*/ public void println(final CharSequence s) throws IOException {
    print(s);
    println();
}

最终调用

/*3445*/private int print(final CharSequence buff, int start, int end, int cursorPos) throws IOException {
        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 + '@')); //LF -> ^J

这个函数做你想做的,但是是私有的:

/*3510*/ private void rawPrintln(final String s) throws IOException {
    rawPrint(s); //
    println();
}

/*3499*/ final void rawPrint(final String str) throws IOException {
    out.write(str);
    cursorOk = false;
}

可以通过第 895 行的公共方法 putString(final CharSequence str) 和第 3715 行的 printColumns(final Collection items) 调用它。 putString 仅在使用掩码输出时调用它,因此对您无用,而 printColumns 似乎用于完成.

也许您应该单独打印行并让 ConsoleReader 向它们添加换行符?从技术上讲,LF 是一个控制代码,禁止 ConsoleReader 按原样打印控制代码是有意义的。只需将您的输入分成几行,一一打印。

于 2016-01-03T11:01:02.800 回答