elm-init-1.0.1.0: src/ElmInit/Interact.hs
{-# LANGUAGE OverloadedStrings #-}
module ElmInit.Interact
( askChoicesWithOther
, askChoices
) where
import Control.Applicative ((<$>), (<*>))
import qualified Control.Arrow as Arrow (first)
import Data.Bool (bool)
import Data.Text (append)
import Data.Text as Text (Text, intercalate, pack)
import Data.Text.IO as TextIO (getLine, putStrLn)
import ElmInit.Util (enumerate, getOr)
import Prelude hiding (getLine, putStrLn)
askChoices :: Text -> Int -> [Text] -> IO Text
askChoices =
((fmap <$> (!!) <*>) .) . askChoices'
askChoices' :: Text -> Int -> [Text] -> IO Int
askChoices' message selected choices =
putStrLn message >>
ask out
where
(l1, selectedElem : l2tail) = splitAt selected choices
out =
intercalate
"\n"
(normFormat 1 l1
++ (selectedFormat selected selectedElem : normFormat (selected + 1) l2tail))
enumF = flip append " ) " . pack . show
enumFn = append " " . enumF
enumFs = append " * " . enumF
normFormat = (map (uncurry append . Arrow.first enumFn) .) . enumerate
selectedFormat x y = (flip append y . enumFs) x
ask a =
putStrLn a >>
getOr selected >>=
(bool
(putStrLn "invalid choice, please choose again" >>
ask a)
<$> return
<*> (<= length choices))
askChoicesWithOther :: Text -> Int -> (Text -> Either Text a) -> [Text] -> IO a
askChoicesWithOther m s trans l =
askChoices' m s (l ++ ["other (specify)"])
>>= (flip bool getAlternative
<$> either (const $ error "No parse") return . trans . (l !!)
<*> (== length l))
where
getAlternative =
putStrLn "please enter an alternative" >>
getLine >>=
(either
(\message ->
putStrLn "Invalid input:" >>
putStrLn message >>
getAlternative
)
return
. trans)