packages feed

elm-init-1.0.1.1: src/ElmInit/Interact.hs

{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE UnicodeSyntax     #-}

module ElmInit.Interact
  ( askChoicesWithOther
  , askChoices
  ) where


import           Control.Applicative         ((<$>), (<*>))
import           Control.Applicative.Unicode
import qualified Control.Arrow               as Arrow (first)
import           Control.Monad.Unicode
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, bool)
import           Prelude                     hiding (getLine, putStrLn)
import           Prelude.Unicode


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)