将 Leksah 调试器与使用 readLn 和类似的程序一起使用

发布于 2024-12-04 10:03:49 字数 473 浏览 3 评论 0原文

我最近安装了 Leksah(Windows 7 64 位上的 0.10.0.4),这似乎是一个有趣的 Haskell IDE。然而,当涉及到使用程序时的用户输入时,我显然忽略了一些东西。

我的代码中有一个非常简单的

do
    printStr "Prompt: "
    x <- readLn

块。当调试器点击 readLn 时,我希望能够在某处提供输入。但是,我找不到任何输入窗口。我一开始预计日志窗口可能会被启用,但我找不到任何与程序交互的地方。在 GHCi 中运行一切都符合预期,所以我确定这不是代码。

此外,当我只是执行“Package->Run”时,提示直到其他日志输出到达(例如进行重建)才变得可见。

过去在 Linux 上使用带有 Haskell 模式的 Emacs,我希望获得更用户友好的体验,这样我就可以让一些 Windows 程序员参与 Haskell 主题。我错过了什么吗?

I recently installed Leksah (0.10.0.4 on Windows 7 64 bit), which seems like an interesting IDE for Haskell. However, I am clearly overlooking something when it comes to user input to programs when using it.

I have a very simple

do
    printStr "Prompt: "
    x <- readLn

block in my code. When the debugger hits the readLn, I would expect to be able to provide input somewhere. However, I can't find any input window. I expected at first that the log window might be enabled, but I can't find anywhere to interact with the program. Running in GHCi everything is as expected, so I'm certain it isn't the code.

Further, when I just do a "Package->Run", the prompt doesn't become visible until some other log output arrives (such as doing a rebuild).

Having used Emacs with Haskell mode in the past on Linux, I was hoping for a more user friendly experience so I could engage some Windows programmers on Haskell topics. Am I missing something?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

橘虞初梦 2024-12-11 10:03:49

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

这是我们尚未解决的已知问题。我们将 GCHi 命令发送到其标准输入,但我们也没有好方法在那里发送用户输入。

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

如果我们设置某种方式将数据发送到 stdin 而不等待,它可能会干扰我们发送的 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 应该添加所需的导入语句。)

这将允许交互,但保持标准输入清晰,以便 leksah 与之对话ghci。理想情况下,您也应保持 stdout 和 stderr 清晰,并改为写入此套接字,但 Leksah 应该可以很好地处理任意输出。

From this thread
http://groups.google.com/group/leksah/browse_thread/thread/7d3e3bf64e56f190/30278795c23b2168

This is a known issue we have not addressed yet. We send GCHi commands to its stdin, but we have no good way for sending user input there too.

I am not sure how we should fix this. We can't send user input to the process that is being debugged using our command channel (our code waits for the prompt from ghci before sending commands).

If we set up some way to send data to stdin without waiting it may interfere with the GHCi commands we send (because it is still all going down the same pipe).

We need to find out if there is some way we can have separate stdin/stdout/stderr pipes for GHCi itself and the program GHCi is debugging.

In the mean time you could have you app open a socket or named pipe and write input to that from another terminal. Something like this (not tested)...

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

(You will need to add process and network to your package dependancies. Then Ctrl+R should add the import statements needed.)

This will allow interaction, but keep stdin clear for leksah to talk to ghci. Ideally you would keep stdout and stderr clear too and write to this socket instead, but Leksah should cope fairly well with arbitrary output.

无所的.畏惧 2024-12-11 10:03:49

我遇到了同样的问题,我正在考虑使用 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 之外)进行测试时,您可以注释掉#defines FAKE_INPUT 行。您也可以幻想并为多个输入设置多个常量,但这从单元测试开始,这最终可能是最好的解决方案。

I have encountered the same problem and I'm considering using the C preprocessor to literally define whether I want fake input for testing or not. Something along these lines:

{-# 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

You can comment out the line that #defines FAKE_INPUT when you want to test with the real functions (outside of Leksah). You could also get fancy and have multiple constants for multiple inputs but that starts toward unit testing which may be the best solution in the end.

孤独难免 2024-12-11 10:03:49

我不使用 Leksah,所以我无法回答您问题的这一部分,但是您在使用 Package -> 时遇到的问题是Run 是由于提示符保存在缓冲区中而不是立即输出而引起的。

默认的输出缓冲模式是实现定义的,但对于终端来说,它通常是行缓冲,这意味着只要向其中添加换行符,缓冲区就会刷新到输出,而在 GHCi 中缓冲通常被禁用。

由于在行缓冲模式下触发刷新的提示后没有换行符,因此您需要自己 hFlush stdouthSetBuffering stdout NoBuffering 来完全禁用缓冲。

有关更多详细信息,请参阅 System.IO 缓冲操作。

I don't use Leksah, so I can't answer that part of your question, however your issue when using Package -> Run is caused by the prompt being kept in a buffer rather than being output immediately.

The default output buffering mode is implementation-defined, but for terminals it's usually line buffering, which means that the buffer is flushed to the ouput whenever you add a newline to it, whereas in GHCi buffering is usually disabled.

Since there is no newline after the prompt to trigger a flush in line buffering mode, you'll need to hFlush stdout yourself, or hSetBuffering stdout NoBuffering to disable the buffering altogether.

For more details, see System.IO buffering operations.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文