{-# LANGUAGE NamedFieldPuns #-} {-# LANGUAGE ScopedTypeVariables #-} module Menu ( Menu(..) , Promptable(..) , formatTitle , select ) where import Control.Monad.IO.Class (MonadIO(..)) import Text.Printf (printf) import Utils (outputLn, prompt) data Menu a = Menu { title :: String , question :: String , invalidText :: String } formatTitle :: String -> [String] formatTitle aTitle = [line, formattedTitle, line] where formattedTitle = "==> " ++ aTitle line = const '-' <$> formattedTitle formatOption :: Promptable a => a -> String formatOption o = printf "%d. %s" (fromEnum o) (showOption o) class (Bounded a, Enum a) => Promptable a where menu :: Menu a showOption :: a -> String select :: forall a m. (MonadIO m, Promptable a) => m a select = toEnum <$> prompt (mapM_ outputLn (formatTitle title ++ options ++ [question])) (outputLn invalidText) (fromEnum (minBound :: a), fromEnum (maxBound :: a)) where Menu {title, question, invalidText} = (menu :: Menu a) options = formatOption <$> ([minBound .. maxBound] :: [a])