gpt4 book ai didi

java - 将历史记录添加到自定义 Shell

转载 作者:搜寻专家 更新时间:2023-11-01 01:44:01 25 4
gpt4 key购买 nike

我正在用 Java 创建一个自定义 shell。我已经向它添加了历史记录,这样当按下向上箭头时它会转到上一个命令,但是向上箭头似乎不起作用

这是我的代码:

public class MyShell {

public static class JavaStringHistory
{
private List<String> history = new ArrayList<String>();
}

public static void main(String[] args) throws java.io.IOException {
JavaStringHistory javaStringHistory = new JavaStringHistory();
javaStringHistory.history.add("");

Integer indexOfHistory = 0;

String commandLine;
BufferedReader console = new BufferedReader
(new InputStreamReader(System.in));


//Break with Ctrl+C
while (true) {
//read the command
System.out.print("Shell>");
commandLine = console.readLine();
javaStringHistory.history.add(commandLine);

//if just a return, loop
if (commandLine.equals(""))
continue;
//history

if (commandLine.equals(KeyEvent.VK_UP))
{
System.out.println("up arrow");
}
//help command
if (commandLine.equals("help"))
{
System.out.println();
System.out.println();
System.out.println("Welcome to the shell");
System.out.println("Written by: Alex Frieden");
System.out.println("--------------------");
System.out.println();
System.out.println("Commands to use:");
System.out.println("1) cat");
System.out.println("2) exit");
System.out.println("3) clear");
System.out.println();
System.out.println();
System.out.println("---------------------");
System.out.println();
}

if (commandLine.equals("clear"))
{

for(int cls = 0; cls < 10; cls++ )
{
System.out.println();
}


}

if(commandLine.startsWith("cat"))
{
System.out.println("test");
//ProcessBuilder pb = new ProcessBuilder();
//pb = new ProcessBuilder(commandLine);
}

else
{
System.out.println("Incorrect Command");
}


if (commandLine.equals("exit"))
{

System.out.println("...Terminating the Virtual Machine");
System.out.println("...Done");
System.out.println("Please Close manually with Options > Close");
System.exit(0);
}

indexOfHistory++;

}
}
}

我得到的只是

Shell>^[[A
Incorrect Command
Shell>

有什么想法吗?

最佳答案

您的方法存在几个问题:

  • 用户 blackSmith 在我之前提到过,当涉及到光标键处理和类似主题时,系统控制台处理是平台相关的。
  • BufferedReader.readLine 不是用于在 shell 中循环历史记录的明智选择,因为您希望 shell 立即对光标键使用react,而不是强制用户按 Return 或 Enter。只有用户命令才需要读取整行。因此,您需要扫描每个单个字符或键码的键盘输入,并自行决定是否是,例如光标键(向上/向下用于循环历史记录,向左/向右用于在命令行内移动光标)或删除/退格键用于命令行编辑等。
  • 通过 readLine 读取控制字符创建的文本字符串可能取决于操作系统,甚至可能取决于 shell 和字符集(UTF-8、ISO-8859-1、US ASCII等)在控制台上。
  • 内置的 shell 编辑功能(如命令历史记录)可能会妨碍 readLine,例如在 Linux 上,我看到“^[[A”表示光标向上,在 Windows 上,光标键被传递到 cmd.exe 的内置命令历史记录功能。 IE。您需要将控制台置于原始模式(绕过行编辑并且不需要 Enter 键)而不是cooked 模式(需要使用 Enter 键进行行编辑)。

无论如何,要回答您最初的问题,即如何找出 BufferedReader.readLine 产生了哪些关键代码,其实很简单。像这样将字节转储到控制台:

commandLine = console.readLine();
System.out.println("Entered command text: " + commandLine);
System.out.print ("Entered command bytes: ");
for (byte b : commandLine.getBytes())
System.out.print(b + ", ");
System.out.println();

在 Linux 下,向上光标可能类似于“27、91、65”或只是“91、65”,具体取决于终端。在我的系统上,光标向下以“66”结尾。所以你可以这样做:

public class MyShell {
private static final String UP_ARROW_1 = new String(new byte[] {91, 65});
private static final String UP_ARROW_2 = new String(new byte[] {27, 91, 65});
private static final String DN_ARROW_1 = new String(new byte[] {91, 66});
private static final String DN_ARROW_2 = new String(new byte[] {27, 91, 66});

// (...)

public static void main(String[] args) throws IOException {
// (...)
// history
else if (commandLine.startsWith(UP_ARROW_1) || commandLine.startsWith(UP_ARROW_2)) {
System.out.println("up arrow");
}
else if (commandLine.startsWith(DN_ARROW_1) || commandLine.startsWith(DN_ARROW_2)) {
System.out.println("down arrow");
}
// (...)
}
}

但这一切只是为了解释或演示,以回答你的问题——我确实喜欢得到赏金。 ;-)

也许一种方法是不要重新发明轮子并使用他人的工作,例如像 JLine 这样的框架.据我所知,它也不是完美的,但比你在短时间内自己开发的任何东西都走得更远。有人写了一个简短的介绍blog post关于 JLine。该图书馆似乎可以满足您的需求。享受吧!


更新:我给了JLine 2.11尝试使用此代码示例(基本上是博客文章中的一个加上选项卡文件名完成:

import java.io.IOException;

import jline.TerminalFactory;
import jline.console.ConsoleReader;
import jline.console.completer.FileNameCompleter;

public class MyJLineShell {
public static void main(String[] args) {
try {
ConsoleReader console = new ConsoleReader();
console.addCompleter(new FileNameCompleter());
console.setPrompt("prompt> ");
String line = null;
while ((line = console.readLine()) != null) {
console.println(line);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
TerminalFactory.get().restore();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}

它在 Windows 和 Linux 上运行良好,但对我来说,制表符补全仅适用于 Linux,不适用于 Windows。无论如何,命令历史记录在两个平台上都运行良好。

关于java - 将历史记录添加到自定义 Shell,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17410895/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com