Использование отладчика Leksah с программами, использующими readLn и аналогичные - PullRequest
7 голосов
/ 15 сентября 2011

Я недавно установил Leksah (0.10.0.4 в 64-битной Windows 7), который кажется интересной IDE для Haskell.Тем не менее, я явно что-то упускаю из виду, когда речь заходит о пользовательском вводе программ при его использовании.

У меня в коде очень простой блок

do
    printStr "Prompt: "
    x <- readLn

.Когда отладчик нажимает на readLn, я ожидаю, что смогу где-нибудь предоставить ввод.Тем не менее, я не могу найти ни одного окна ввода.Сначала я ожидал, что окно журнала может быть включено, но я не могу найти где-нибудь взаимодействовать с программой.В GHCi все работает так, как ожидалось, поэтому я уверен, что это не код.

Далее, когда я просто делаю "Package-> Run", приглашение не становится видимым до тех пор, пока не поступит какой-либо другой вывод журнала (например, перестроение).

Используя Emacsв прошлом в Linux с режимом Haskell я надеялся на более удобный для пользователя опыт, чтобы я мог привлекать некоторых программистов Windows по темам Haskell.Я что-то упустил?

Ответы [ 3 ]

4 голосов
/ 15 сентября 2011

из этой темы http://groups.google.com/group/leksah/browse_thread/thread/7d3e3bf64e56f190/30278795c23b2168

Это известная проблема, которую мы еще не рассмотрели. Мы посылаем команды GCHi на его стандартный ввод, но у нас нет и хорошего способа отправить туда пользовательский ввод.

Я не уверен, как мы должны это исправить. Мы не можем отправить пользовательский ввод в процесс, который отлаживается с помощью нашего командного канала (наш код ожидает приглашения от ghci перед отправкой команд).

Если мы настроим какой-либо способ отправки данных на стандартный ввод без ожидания, это может помешать отправляемым нами командам GHCi (потому что они все еще идут по одному каналу).

Нам нужно выяснить, есть ли какой-нибудь способ, которым мы можем иметь отдельные каналы stdin / stdout / stderr для самого GHCi, и программа GHCi отлаживается.

В то же время вы можете сделать так, чтобы ваше приложение открывало сокет или именованный канал и записывало входные данные с другого терминала. Как то так (не проверено) ...

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 должен добавить необходимые операторы импорта.)

Это позволит взаимодействовать, но держите лекды в чистоте, чтобы лексы могли разговаривать с ghci. В идеале вы должны держать stdout и stderr в чистоте и вместо этого писать в этот сокет, но Leksah должен довольно хорошо справляться с произвольным выводом.

2 голосов
/ 19 марта 2013

Я столкнулся с той же проблемой, и я рассматриваю возможность использования препроцессора 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

Вы можете закомментировать строку, которая #defines FAKE_INPUT, когда вы хотите протестировать с реальными функциями (за пределами Leksah).Вы также можете получить фантазию и иметь несколько констант для нескольких входов, но это начинается с модульного тестирования, которое может оказаться лучшим решением в конце.

0 голосов
/ 15 сентября 2011

Я не использую Leksah, поэтому я не могу ответить на эту часть вашего вопроса, однако ваша проблема при использовании Package -> Run вызвана тем, что приглашение хранится в буфере, а не выводится немедленно.

Режим буферизации вывода по умолчанию определяется реализацией, но для терминалов обычно это буферизация строки, что означает, что буфер сбрасывается в выходной поток всякий раз, когда вы добавляете в него новую строку, тогда как в GHCi буферизация обычно отключена.

Поскольку после запроса нет строки для запуска сброса в режиме буферизации строки, вам нужно hFlush stdout самостоятельно или hSetBuffering stdout NoBuffering, чтобы вообще отключить буферизацию.

Подробнее см. Операции буферизации System.IO .

...