module YJTools ( getLineP ) where import System.IO (stdin, stdout, hGetBuffering, hSetBuffering, BufferMode(NoBuffering)) import System.Posix.Terminal (getTerminalAttributes, setTerminalAttributes, TerminalState(Immediately), TerminalMode(EnableEcho), withoutMode) import System.Posix.IO (stdOutput) import Control.Exception (bracket) import Control.Monad.Tools (doWhile) getLineP :: IO String getLineP = bracket (do bi <- hGetBuffering stdin bo <- hGetBuffering stdout ta <- getTerminalAttributes stdOutput setTerminalAttributes stdOutput (withoutMode ta EnableEcho) Immediately hSetBuffering stdin NoBuffering hSetBuffering stdout NoBuffering return (bi, bo, ta)) (\(bi, bo, ta) -> do setTerminalAttributes stdOutput ta Immediately hSetBuffering stdin bi hSetBuffering stdout bo) (const $ do doWhile "" $ \s -> do c <- getChar case c of '\n' -> putChar '\n' >> return (reverse s, False) '\DEL' -> if null s then return ("", True) else do putChar '\b' >> putChar ' ' >> putChar '\b' return (tail s, True) _ -> putChar '*' >> return (c:s, True))