2011-09-15 25 views
7

的程序我最近安装了Leksah(0.10.0.4在Windows 7 64位),这看起来像是一个有趣的Haskell IDE。然而,当使用它的用户输入到程序时,我清楚地忽略了一些东西。使用Leksah调试器与使用readLn和类似

我有一个非常简单的

do 
    printStr "Prompt: " 
    x <- readLn 

块在我的代码。当调试器击中readLn时,我希望能够在某处提供输入。但是,我找不到任何输入窗口。我首先期望可以启用日志窗口,但我找不到任何地方与程序交互。在GHCi中运行一切都如预期,所以我确信它不是代码。此外,当我只做一个“Package-> Run”时,只有等到其他日志输出到达时(例如重建),提示才会变得可见。

以前在Linux上使用过Haskell模式的Emacs,我希望有一个更加用户友好的体验,所以我可以让一些Windows程序员参与Haskell主题。我错过了什么吗?

+0

+1我可以复制此行为(或更确切地说,非行为),Windows 7 32位,GHC 7.0.3,Leksah 0.10.0.4。在等待getLine或类似的时候什么都不输出,然后当我改变文件时它会中断程序,导致它最终打印出“Prompt:”。 –

回答

4

从这个线程 http://groups.google.com/group/leksah/browse_thread/thread/7d3e3bf64e56f190/30278795c23b2168

这是一个已知的问题,我们还没有解决。我们将GCHi命令发送到它的标准输入,但是我们也没有好的方法来发送用户输入。

我不知道我们应该如何解决这个问题。我们无法将用户输入发送到正在使用我们的命令通道进行调试的进程(我们的代码在发送命令之前等待ghci的提示)。

如果我们设置某种方式将数据发送到标准输入不经等待,它可能会干扰我们发送的GHCi命令(因为它仍然在同一根管道中)。

我们需要了解是否有某种方式可以让GHCi本身和GHCi正在调试的程序分开stdin/stdout/stderr管道。

同时,您可能需要打开一个套接字或命名管道,然后将输入写入另一个终端。事情是这样的(未测试)...

main = do 
    sock <- listenOn (PortNumber 8000) 
    -- Start a new terminal window (this command needs to be changed for OS X or Windows) 
    forkIO $ system "gnome-terminal -e \"telnet localhost 8000\"" 
    (handle, _, _) <- accept sock -- Wait for the new terminal to connect 
    -- You might want to add a call to hSetBuffering here 
    line <- hGetLine handle 
    print line 
    sClose sock 

(您将需要添加工艺和网络软件包的依赖关系,然后按Ctrl + R应该添加import语句需要。)

这将使互动,但保持stdin明确leksah与ghci交谈。理想情况下,你应该保持stdout和stderr清晰,然后写入这个套接字,但Leksah应该可以很好地处理任意输出。

+0

非常感谢您......在询问之前,我做了相当多的Google搜索,但由于上下文是getChar()而错过了。可惜的是,在Windows 7上,默认情况下telnet客户端并未加载,但这是次要的。 – Godeke

0

我不使用雷克萨,所以我不能回答你的问题的部分,但使用Package -> Run时,你的问题是由于提示被保存在缓冲区而不是立即输出引起的。

默认的输出缓冲模式是实现定义的,但是对于终端来说,它通常是线缓冲,这意味着无论何时添加一个换行符,缓冲区都会刷新到输出,而在GHCi缓冲通常是禁用的。

由于在行缓冲模式下触发刷新提示后没有换行符,您需要自己或hSetBuffering stdout NoBuffering才能完全禁用缓冲。

有关更多详细信息,请参阅System.IO buffering operations

2

我遇到了同样的问题,我正在考虑使用C预处理器来从字面上定义我是否想要用于测试的假输入。沿着这些路线的东西:

{-# LANGUAGE CPP, TemplateHaskell #-} 

module Main (
    main 
) where 

#define FAKE_INPUT 

main :: IO() 
main = do 
    putStrLn "Prompt: " 
    x <- myReadLn 
    putStrLn x 

#ifdef FAKE_INPUT 
myReadLn = return "fake string" 
#else 
myReadLn = readLn 
#endif 

您可以注释掉当你想与真正的功能测试(Leksah之外),其#define语句FAKE_INPUT行。你也可以看中并且有多个常量用于多个输入,但是开始向单元测试,这可能是最终的最佳解决方案。