Using Leksah debugger with programs that use readLn and similar
Asked Answered
Z

3

7

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?

Zia answered 15/9, 2011 at 2:21 Comment(1)
+1 I can replicate this behavior (or rather, non-behavior), Windows 7 32 bit, GHC 7.0.3, Leksah 0.10.0.4. Outputs nothing when waiting for a getLine or similar, then when I change the file it will interrupt the program, causing it to finally print "Prompt:".Stanfill
C
4

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.

Compiler answered 15/9, 2011 at 6:46 Comment(1)
Thank you for that... I did quite a bit of Googling before asking, but missed this because the context was getChar(). It is a shame that the telnet client isn't loaded by default on Windows 7, but that is a minor thing.Zia
N
2

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.

Nazario answered 19/3, 2013 at 7:36 Comment(0)
P
0

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.

Postliminy answered 15/9, 2011 at 4:55 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.