10

I'm pretty new to Haskell, so I'm looking for a simple-ish way to detect keypresses, rather than using getLine.

If anyone knows any libraries, or some trick to doing this, it would be great!

And if there is a better place to ask this, please direct me there, I'd appreciate it.

Don Stewart
  • 137,316
  • 36
  • 365
  • 468
TaslemGuy
  • 594
  • 5
  • 13
  • There is a similar thread here http://stackoverflow.com/questions/2983974/haskell-read-input-character-from-console-immediately-not-after-newline – Pedro Rodrigues Oct 09 '10 at 01:17
  • Most GUI libraries (ex: gtk2hs) have a onKeyPress type operation - if you're doing anything large or for distribution then consider those. – Thomas M. DuBuisson Oct 09 '10 at 04:59

2 Answers2

16

If you don't want blocking you can use hReady to detect whether a key has been pressed yet. This is useful for games where you want the program to run and pick up a key press whenever it has happened without pausing the game.

Here's a convenience function I use for this:

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

Which can be used like this:

stdin `ifReadyDo` getChar

Returning a Maybe that is Just if a key was pressed and Nothing otherwise.

Ollie Saunders
  • 7,787
  • 3
  • 29
  • 37
9
import System.IO

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

I don't know when this is guaranteed to work. Putting the terminal into a "raw" mode is a system-dependent process. But it works for me with GHC 6.12.1 on Linux.

keegan
  • 1,617
  • 10
  • 13
  • That's the issue I've found, it works rather poorly on Windows, and requires a newline before it is submitted. – TaslemGuy Oct 12 '10 at 22:26