2010-10-08 17 views
9

Soy bastante nuevo para Haskell, así que estoy buscando una forma simple de detectar pulsaciones de teclas, en lugar de usar getLine.¿Cuál es una forma sencilla de esperar y detectar las pulsaciones de teclas en Haskell?

¡Si alguien conoce alguna biblioteca, o algún truco para hacer esto, sería genial!

Y si hay un lugar mejor para preguntar esto, por favor dirígeme allí, lo agradecería.

+0

Hay un hilo similar aquí http://stackoverflow.com/questions/2983974/haskell-read-input-character-from-console-immediately-not-after-newline –

+0

La mayoría de las bibliotecas de GUI (por ejemplo, gtk2hs) tienen una operación de tipo onKeyPress - si está haciendo algo grande o para distribución, entonces considere eso. –

Respuesta

14

Si no desea que el bloqueo se puede utilizar hReady para detectar si una tecla ha sido presionada todavía. Esto es útil para los juegos en los que deseas que se ejecute el programa y presionar una tecla siempre que haya sucedido sin detener el juego.

Aquí hay una función de conveniencia que uso para esto:

ifReadyDo :: Handle -> IO a -> IO (Maybe a) 
ifReadyDo hnd x = hReady hnd >>= f 
    where f True = x >>= return . Just 
     f _ = return Nothing 

que puede ser utilizado como esto:

stdin `ifReadyDo` getChar 

Devolución de una Maybe que es Just si se pulsa una tecla y Nothing lo contrario.

+2

También mencionaría la función' hSetEcho', que permite suprimir el eco de caracteres en ' stdout', mientras usa 'getChar'. –

8
import System.IO 

main :: IO() 
main = do 
    hSetBuffering stdin NoBuffering 
    x <- getChar 
    putStrLn ("You pressed: " ++ [x]) 

No sé cuándo se garantiza que esto funcione. Poner el terminal en un modo "en bruto" es un proceso dependiente del sistema. Pero funciona para mí con GHC 6.12.1 en Linux.

+1

Pero no funciona en Windows usando GHC. –

+0

Ese es el problema que he encontrado, funciona bastante mal en Windows y requiere una nueva línea antes de enviarlo. – TaslemGuy

-1

Puede usar getChar en lugar de getLine. Esto probablemente no es lo que estás buscando, pero es la manera más simple.

pressKey :: IO() 
pressKey = do x <- getChar 
       return x 

Pero hay una manera aún más simple. Sólo tiene que escribir getChar:

pressKey :: IO() 
pressKey = getChar >> putStr "I am a String" 

pressKey = putStrLn "Hi" >> getChar >> putStrLn "Bye" 
+1

Su primera 'pressKey' es exactamente equivalente a' getChar' aquí. –

+0

Bueno, lo sé. Mi punto era que x se podía usar, por ejemplo, "do {x <- getCbar; dosomething (read x :: Int)} o no. – danportin

Cuestiones relacionadas