2011-09-15 11 views
7

Niedawno zainstalowałem Leksah (0.10.0.4 na Windows 7 64 bit), który wydaje się interesującym IDE dla Haskella. Jednak wyraźnie coś przeoczyłem, jeśli chodzi o wprowadzanie danych przez użytkownika do programów podczas korzystania z niego.Używanie debuggera Leksah z programami, które używają ReadLn i podobnych

Mam bardzo prosty

do 
    printStr "Prompt: " 
    x <- readLn 

bloku w moim kodu. Kiedy debugger trafi do readLn, spodziewam się, że będę mógł gdzieś wprowadzić dane wejściowe. Jednak nie mogę znaleźć żadnego okna wejściowego. Z początku spodziewałem się, że okno dziennika może być włączone, ale nie mogę znaleźć nigdzie, aby wejść w interakcję z programem. Działając w GHCi wszystko jest zgodne z oczekiwaniami, więc jestem pewien, że to nie jest kod.

Co więcej, po prostu wykonuję "Pakiet-> Uruchom", monit nie staje się widoczny, dopóki nie pojawi się inne wyjście dziennika (na przykład wykonanie przebudowy).

Używając Emacsa z trybem Haskella w przeszłości na Linuksie, liczyłem na bardziej przyjazne dla użytkownika doświadczenie, dzięki czemu mogłem zaangażować niektórych programistów Windows w tematykę Haskell. Czy czegoś brakuje?

+0

+1 Mogę replikować to zachowanie (lub raczej nie-zachowanie), Windows 7 32-bitowy, GHC 7.0.3, Leksah 0.10.0.4. Nic nie wychodzi podczas oczekiwania na 'getLine' lub coś podobnego, a kiedy zmienię plik, przerwie program, powodując, że ostatecznie wydrukuje" Monit: ". –

Odpowiedz

4

Od tego wątku http://groups.google.com/group/leksah/browse_thread/thread/7d3e3bf64e56f190/30278795c23b2168

Jest to znany problem, że nie zostały jeszcze rozwiązane. Wysyłamy komendy GCHi do standardowego wejścia, ale nie mamy również dobrego sposobu na wysyłanie danych przez użytkownika.

Nie jestem pewien, jak powinniśmy to naprawić. Nie możemy wysłać danych użytkownika do procesu, który jest debugowany za pomocą naszego kanału poleceń (nasz kod czeka na żądanie od ghci przed wysłaniem poleceń).

Jeśli założyć jakiś sposób, aby przesłać dane do standardowego wejścia bez czekania może to kolidować z poleceń GHCi wysyłamy (ponieważ jest ciągle schodząc tą samą rurę).

Musimy dowiedzieć się, czy istnieje sposób, w jaki możemy mieć oddzielne stdin/stdout/stderr dla samego GHCi, a program GHCi debuguje.

W tym czasie można mieć Państwo app otworzyć gniazda lub nazwanego potoku i napisać, że wejście do innego terminala. Coś jak to (nie testowane) ...

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 

(trzeba będzie dodać proces i sieci do zależnościami pakietów. Potem Ctrl + R należy dodać oświadczenia importowe potrzebne.)

To pozwoli interakcja, ale utrzymuj stdin jasne dla leksah, aby porozmawiać z ghci.Najlepiej byłoby, gdybyś utrzymywał stdout i stderr również jasne i pisał do tego gniazda, ale Leksah powinna radzić sobie całkiem dobrze z arbitralnym wyjściem.

+0

Dziękuję za to ... Zrobiłem sporo Googling przed pytaniem, ale przegapiłem to, ponieważ kontekst był getChar(). Szkoda, że ​​klient telnet nie jest załadowany domyślnie w systemie Windows 7, ale to drobnostka. – Godeke

0

Nie używam Leksah, więc nie mogę odpowiedzieć na tę część twojego pytania, jednak twoja emisja podczas używania Package -> Run jest spowodowana tym, że podpowiedź jest przechowywana w buforze, a nie natychmiast.

Domyślny tryb buforowania wyjściowego jest definiowany przez implementację, ale w przypadku terminali zwykle jest to buforowanie liniowe, co oznacza, że ​​bufor jest przepłukiwany do wyjścia zawsze, gdy dodaje się do niego nową linię, podczas gdy buforowanie GHCi jest zwykle wyłączone.

Ponieważ po znaku zachęty do uruchomienia trybu buforowania linii nie ma znaku nowej linii, należy samodzielnie wykonać hFlush stdout lub całkowicie wyłączyć buforowanie. Aby uzyskać więcej informacji, zobacz System.IO buffering operations.

2

Napotkałem ten sam problem i rozważam użycie procesora C, aby dosłownie określić, czy chcę wprowadzić fałszywy sygnał wejściowy do testowania, czy nie. Coś wzdłuż tych linii:

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

Można wykomentuj wiersz #defines FAKE_INPUT gdy chcesz przetestować z funkcji rzeczywistych (poza Leksah). Można również uzyskać fantazyjne i mieć wiele stałych dla wielu wejść, ale to zaczyna się w kierunku testów jednostkowych, które mogą być najlepszym rozwiązaniem w końcu.

Powiązane problemy