Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Preventing input characters appearing in terminal

I'm making a silly terminal game, that uses keyboard input to control a character moving around a board. When the user presses a key, my code responds correctly, using getChar, but the character that the users presses also appears in the terminal. Is there a way to receive keyboard input in a terminal app, without displaying what the user typed?

Edit: I'm on Mac, but would be good to know on all platforms.

like image 268
Peter Hall Avatar asked Apr 06 '13 09:04

Peter Hall


1 Answers

Basically there are two things you have to do in order to reach your goal:

  1. You have to disable any buffering in the terminal, so that your program gets the pressed keys at once (and you don't have to confirm with ENTER).

    hSetBuffering stdin NoBuffering
    
  2. Then you have to ensure the character isn't echoed back to the terminal.

    hSetEcho stdin False
    

Please note that just before your program exits it has to restore the previous settings in order to allow further usage of the terminal.

Putting everything together the code will look like this:

import System.IO
import Control.Exception (bracket)

withHiddenTerminalInput :: IO a -> IO a
withHiddenTerminalInput io = bracket
   (do prevBuff <- hGetBuffering stdin
       prevEcho <- hGetEcho stdin

       hSetBuffering stdin NoBuffering
       hSetEcho stdin False

       return (prevBuff, prevEcho)
   )

   (\(prevBuff, prevEcho) -> do
       hSetBuffering stdin prevBuff
       hSetEcho stdin prevEcho
   )

   (const io)
like image 159
Jakub Avatar answered Oct 13 '22 13:10

Jakub