使用Java命令提示符

时间:2016-04-18 04:12:43

标签: java haskell ghci

我正在使用Windows 7计算机。

我正在开发一个应用程序,它是Haskell的GHCi解释器的前端。用户将输入命令,然后Java将通过运行时的exec()方法执行命令,然后应用程序将显示如果用户刚刚使用命令提示符运行GHCi将显示的文本。

现在,我遇到了打印输出的循环问题。

这是我现在的代码。

public class GHCiTest {
public static Scanner rd, sc;

/**
 * @param args the command line arguments
 */
public static void main(String[] args) {

try {

  System.out.println("Starting... ");

  Process p = Runtime.getRuntime().exec("ghci");

  PrintStream hugsin  = new PrintStream(p.getOutputStream());
  InputStream hugsout = p.getInputStream();

  sc = new Scanner(hugsout);
  rd = new Scanner(System.in);

  String rdnextline;



  while (true){
    while (sc.hasNextLine()){
        System.out.println(sc.nextLine());

    }
      System.out.println("yay");
      rdnextline = rd.nextLine();
    if (rdnextline == "quit"){break;}
    hugsin.println(rdnextline);
    hugsin.flush();

  }
  System.out.println(" ... successful completion.");
}
catch(IOException e) {
  e.printStackTrace();
}
}

}

我知道GHCi的初始启动正在运行,因为该程序打印出“GHCi,版本7.10.3:http://www.haskell.org/ghc/ :?求助”。但是,问题似乎是while(sc.hasNextLine())循环,它应该读取命令提示符的输出并输出它直到没有任何东西,因为它不会突破循环并继续读取用户输入。我知道这是因为程序没有打印循环后输入的“yay”标志。

2 个答案:

答案 0 :(得分:2)

您的循环不会退出,直到到达流的末尾:

while (sc.hasNextLine()){
    System.out.println(sc.nextLine());
}

流的结尾是流程的结束。因此,您的Java程序正在等待子进程运行完成,并终止。一旦发生这种情况,循环将结束,Java程序将向进程发送所需的命令。

抱歉,我的意思是,尝试将所需的命令发送到进程;它不会成功,因为这个过程已经终止。

如果GHCi进程输出"提示"在某种程度上,你可以尝试在那一刻打破你的while(...) { print },从用户那里获得输入,将其发送到流程,然后循环返回并重新输入你的while(...) { print },等待下一个提示。

假设提示不以换行结束,而是出现在输入用户输入的行的开头,则不能使用while(sc.hasNextLine()) { ... }类型的循环,因为提示不是完整的行。您可能不得不求助于逐个字符地阅读,在最后一个" n"中寻找提示序列。字符。

看起来您可以更改GHCi中的提示。见here for details。如果您将提示更改为以换行符结尾,则仍可以按行读取流。

while (sc.hasNextLine()){
    String line = sc.nextLine();
    if (line.equals("YourPromptHere"))
         break;
    System.out.println(line);
}

(或者,您可以使用线程执行某些操作,以允许两个部分在不相互阻塞的情况下运行。当然,线程会带来自身的问题和复杂性。)

修改

我有一个明显的炫目闪光。假设GHC的提示看起来像这样......

GHCi, version 7.10.3
yada, yada, yada ...
Main> _

...您可以将扫描仪的分隔符设置为提示字符串Main>

// Set scanner delimiter to GHCi's Prompt string
sc = new Scanner(hugsout).setDelimiter("^Main> ");

while (sc.hasNext()) {

    // Echo GHCi's output upto the delimiter (prompt)
    System.out.println(sc.next());

    // Read user input & transfer to GHCi.
    System.out.print("Replacement Prompt> ");
    rdnextline = rd.nextLine();
    if (rdnextline == "quit") {
        break;
    }
    hugsin.println(rdnextline);
    hugsin.flush();
 }

注意:这没有考虑辅助提示,当GHCi需要更多输入来完成命令时使用。您可以使用匹配任一提示符的"^Main> |\bAlt> "之类的正则表达式,但是您无法分辨定界符匹配的提示符。 第一个子表达式"^Main> "匹配一行的开头,后跟" Main> ",其中第二个子表达式"\bAlt> "仅匹配字边界,后跟" Alt> &#34 ;.这是因为GHCi的输出流看起来像"\nMain> Alt> ",在Alt>之前有一段很长的停顿; "换行符" Alt>之前通常来自输入流上Enter键的回显。

答案 1 :(得分:2)

在另一个线程中接收ghci的输出。

System.out.println("Starting... ");

Process p = Runtime.getRuntime().exec("ghci");

PrintStream hugsin = new PrintStream(p.getOutputStream());
InputStream hugsout = p.getInputStream();
Scanner rd = new Scanner(System.in);
new Thread(() -> {
    try (Reader r = new InputStreamReader(hugsout)) {
        int ch;
        while ((ch = r.read()) != -1)
            System.out.print((char)ch);
    } catch (IOException e ) {}
}).start();
Scanner sc = new Scanner(hugsout);
String rdnextline;
while (true) {
    rdnextline = rd.nextLine();
    hugsin.println(rdnextline);
    hugsin.flush();
    if (rdnextline.equals("quit")) {
        break;
    }
}
System.out.println(" ... successful completion.");