当你按下enter键 - 当你按任何其他ke y - 它被打印到屏幕上。您可以关闭此行为与hSetEcho
:
main = do
hSetEcho stdin False
readEvalPrintLoop
但是,如果你这样做,你会发现这个有一些附带损害:在输入不再回荡,但也不是其他任何你的类型,所以它看起来就像你输入的所有东西都是隐形的!您可以通过手动实施修改后的回应策略来解决此问题。您需要做两件事:将输入流设置为无缓冲模式,使用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
@Bakuriu是的,它应该是你提到的输入缓冲。请注意,此缓冲区不存在于Haskell应用程序中,而是存在于终端中(OS内核或终端仿真程序中)。默认情况下,终端响应每个键并像往常一样移动光标,而不与应用程序进行任何交互。应用程序可以要求终端改变这种默认行为,实际上ncurses是一种常见的方式。 – chi
@Bakuriu缓冲只与切线相关:这里真正的问题是回声。在我的回答中,我还*关闭缓冲区,但不阻止换行符的出现;相反,它允许所有其他内容一次出现,而不是缓冲区大小的块! –
@Andrei如果你和我一样,这个问题可能导致你想知道到底发生了什么以及哪些行为是可配置的。你可以在[The TTY demystified](http://www.linusakesson.net/programming/tty/)上阅读更多关于它的内容,但我警告你:如果你只想完成任务,这将会是方式更多的信息比你想要的! –