私はこれを試しました:
main = do
hSetBuffering stdin NoBuffering
c <- getChar
しかし、Enterキーが押されるまで待機します。これは私が望んでいることではありません。ユーザーが押した直後に文字を読みたい。
私はWindows7でghcv6.12.1を使用しています。
編集:私にとっての回避策は、これを正しくサポートするGHCからWinHugsに移行することでした。
はい、それはバグです。クリックしてスクロールする人を節約するための回避策は次のとおりです。
{-# LANGUAGE ForeignFunctionInterface #-}
import Data.Char
import Foreign.C.Types
getHiddenChar = fmap (chr.fromEnum) c_getch
foreign import ccall unsafe "conio.h getch"
c_getch :: IO CInt
getChar
したがって、への呼び出しをへの呼び出しに置き換えることができますgetHiddenChar
。
これは、Windows上のghc/ghciの回避策であることに注意してください。たとえば、winhugsにはバグがなく、このコードはwinhugsでは機能しません。
バグの可能性があります:
http://hackage.haskell.org/trac/ghc/ticket/2189
次のプログラムは、Escキーが押されるまで入力された文字を繰り返します。
import IO import Monad import Char main :: IO () main = do hSetBuffering stdin NoBuffering inputLoop inputLoop :: IO () inputLoop = do i <- getContents mapM_ putChar $ takeWhile ((/= 27) . ord) i
hSetBuffering stdin NoBuffering行があるため、キーストロークの間にEnterキーを押す必要はありません。このプログラムは、WinHugs(2006年9月バージョン)で正しく動作します。ただし、GHC 6.8.2は、Enterキーが押されるまで文字を繰り返しません。この問題は、Windows XP Professionalでcmd.exeとcommand.comの両方を使用して、すべてのGHC実行可能ファイル(ghci、ghc、runghc、runhaskell)で再現されました...
うーん..実際、この機能がバグであるとは思えません。あなたが読むときstdin
、それはあなたが「ファイル」で働きたいことを意味します、そしてあなたがバッファリングをやめるとき、あなたは読み取りバッファの必要がないと言っています。しかし、それは、その「ファイル」をエミュレートしているアプリケーションが書き込みバッファを使用してはならないという意味ではありません。Linuxの場合、端末が「icanon」モードの場合、特別なイベント(Enterキーの押下やCtrl + Dなど)が発生するまで入力は送信されません。おそらくWindowsのコンソールにはいくつかの同様のモードがあります。
Haskelineパッケージは私のために働いた。
個々のキャラクターに必要な場合は、サンプルを少し変更してください。
getInputLine
になりますgetInputChar
"quit"
になります'q'
++ input
になります++ [input]
main = runInputT defaultSettings loop
where
loop :: InputT IO ()
loop = do
minput <- getInputChar "% "
case minput of
Nothing -> return ()
Just 'q' -> return ()
Just input -> do outputStrLn $ "Input was: " ++ [input]
loop
hidden-charを使用:クロスプラットフォームのgetHiddenChar関数を提供します。