2010-10-08 42 views
9

Je suis un nouveau venu chez Haskell, donc je cherche un moyen simple de détecter les touches au lieu d'utiliser getLine.Qu'est-ce qu'un moyen simple d'attendre puis de détecter les touches dans Haskell?

Si quelqu'un connaît des bibliothèques, ou un truc pour faire cela, ce serait génial!

Et s'il y a un meilleur endroit pour poser cette question, s'il vous plaît me diriger là, je l'apprécierais.

+0

Il existe un fil similaire ici http://stackoverflow.com/questions/2983974/haskell-read-input-character-from-console-immediately-not-after-newline –

+0

La plupart des bibliothèques GUI (ex: gtk2hs) ont une opération de type onKeyPress - si vous faites quelque chose de grand ou pour la distribution, alors considérez ceux-ci. –

Répondre

14

Si vous ne voulez pas bloquer, vous pouvez utiliser hReady pour détecter si une clé est encore enfoncée. Ceci est utile pour les jeux où vous voulez que le programme s'exécute et ramasse une touche lorsque cela s'est produit sans interrompre la partie.

est ici une fonction de commodité, je l'utilise pour cela:

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

qui peut être utilisé comme ceci:

stdin `ifReadyDo` getChar 

De retour d'un Maybe qui est Just si une touche a été pressée et Nothing autrement.

+2

Je mentionnerais aussi à propos de la fonction' hSetEcho', qui permet de supprimer les caractères d'écho dans ' stdout', en utilisant 'getChar'. –

8
import System.IO 

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

Je ne sais pas quand cela fonctionnera. Mettre le terminal dans un mode «brut» est un processus dépendant du système. Mais ça marche pour moi avec GHC 6.12.1 sous Linux.

+1

Mais cela ne fonctionne pas sur Windows en utilisant GHC. –

+0

C'est le problème que j'ai trouvé, il fonctionne plutôt mal sur Windows, et nécessite un retour à la ligne avant qu'il ne soit soumis. – TaslemGuy

-1

Vous pouvez utiliser getChar au lieu de getLine. Ce n'est probablement pas ce que vous cherchez, mais c'est le moyen le plus simple.

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

Mais il existe un moyen encore plus simple. Il suffit d'écrire getChar:

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

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

Votre premier 'pressKey' est exactement équivalent à' getChar' ici. –

+0

Eh bien, je le sais. Mon point était que x pourrait être utilisé, par exemple, "do {x <- getCbar; dosomething (lire x :: Int)} ou non – danportin