如何在Haskell中读取而不转移到下一行?

时间:2016-11-21 09:41:13

标签: haskell io console readline

我试图在Haskell中使用readline而不将传输光标移到下一行。

例如,我编写了以下代码:

readEvalPrintLoop :: IO()
readEvalPrintLoop = do
    line <- getLine
    case line of
            "bye" -> return ()
            line   -> do putStrLn $ interpret line
                         readEvalPrintLoop

启动程序后:

> 1 2 + . <enter>
3

但我希望找到最简单的方法

> 1 2 + . <enter> 3

1 个答案:

答案 0 :(得分:1)

按Enter键时 - 按下任何其他键时 - 将其打印到屏幕上。您可以使用hSetEcho关闭此行为:

main = do
    hSetEcho stdin False
    readEvalPrintLoop

但是,如果你这样做,你会发现这有一些附带损害:输入不再回显,但你输入的其他内容都没有,所以看起来你输入的一切都是看不见的!您可以通过手动实施修改后的echo策略来解决此问题。您需要做两件事:将输入流设置为带有hSetBuffering的无缓冲模式(这样您可以立即接收输入,而不是在行尾),并打印您收到的每个非输入字符。所以:

myGetLine :: IO String
myGetLine = do
    c <- getChar
    case c of
        '\n' -> return "" -- don't echo newlines
        _ -> do
            putChar c -- do echo everything else
            fmap (c:) myGetLine

readEvalPrintLoop :: IO()
readEvalPrintLoop = do
    line <- myGetLine -- getLine changed to myGetLine
    case line of
            "bye" -> return ()
            line   -> do putStrLn $ interpret line
                         readEvalPrintLoop

main = do
    hSetEcho stdin False
    hSetBuffering stdin NoBuffering
    readEvalPrintLoop