fortytwo-2.0.0: src/FortyTwo/Prompts/Password.hs
module FortyTwo.Prompts.Password (password) where
import Control.Monad.IO.Class
import System.Console.ANSI (cursorBackward, clearFromCursorToScreenEnd, setCursorColumn, clearFromCursorToLineEnd)
import Control.Monad (unless)
import FortyTwo.Renderers.Password (renderPassword, hideLetters)
import FortyTwo.Renderers.Question (renderQuestion)
import FortyTwo.Constants (emptyString, enterKey, delKey)
import FortyTwo.Utils
-- | Ask a user password
-- password "What your secret password?"
password :: MonadIO m => String -> m String
password question = liftIO $ do
putStrLn emptyString
renderQuestion question emptyString emptyString
putStr " "
flush
noBuffering
answer <- loop emptyString
restoreBuffering
-- for the password prompt we need to clear the prompt a bit differently
setCursorColumn 0
clearFromCursorToLineEnd
renderQuestion question emptyString $ hideLetters answer
return answer
-- | Loop to let the users select an single option
loop :: String -> IO String
loop pass = do
noEcho
renderPassword pass
key <- getKey
-- Cancel part of the password avoiding to cancel the question as well
-- the password and the question are located on the same line
unless (null pass) $ do
cursorBackward $ length pass
clearFromCursorToScreenEnd
-- Try to filter the control keys
res <- handleEvent pass (if length key > 1 then emptyString else key)
restoreEcho
return res
-- | Handle a user event
handleEvent ::String -> String -> IO String
handleEvent pass key
| key == enterKey = return pass
| key == delKey =
if null pass then return loop emptyString pass
else return loop emptyString (init pass)
| otherwise = loop $ pass ++ key