credentials-cli-0.0.2: src/Credentials/CLI/Options.hs
{-# LANGUAGE OverloadedStrings #-}
-- |
-- Module : Credentials.CLI.Options
-- Copyright : (c) 2015-2016 Brendan Hay
-- License : Mozilla Public License, v. 2.0.
-- Maintainer : Brendan Hay <brendan.g.hay@gmail.com>
-- Stability : provisional
-- Portability : non-portable (GHC extensions)
--
module Credentials.CLI.Options where
import Credentials.CLI.Types
import Data.Bifunctor
import Data.List (foldl')
import Data.Maybe (isJust)
import Network.AWS.Data
import Network.AWS.Data.Text
import Options.Applicative hiding (optional)
import Options.Applicative.Help hiding (string)
import qualified Data.Text as Text
import qualified Options.Applicative as Opt
data Fact
= Required
| Optional
| Default
-- | Setup an option with formatted help text.
describe :: Text -- ^ The options' description.
-> Maybe Doc -- ^ The help body (title/footer in tabular).
-> Fact
-> Mod OptionFields a
describe title body r = helpDoc . Just $ wrap title <> doc <> line
where
doc | Just b <- body = pad (maybe b (b .$.) foot)
| otherwise = maybe mempty pad foot
foot = case r of
Required -> Just ("This is" <+> bold "required.")
Optional -> Just ("This is" <+> bold "optional.")
Default -> Nothing
pad = mappend line . indent 2
-- | Setup a tabular list of possible values for an option,
-- a default value, and an auto-completer.
completes :: ToText a
=> Text -- ^ The options' description.
-> Text -- ^ A title for the values.
-> [(a, String)] -- ^ Possible values and their documentation.
-> Maybe a -- ^ A default value.
-> Maybe Text -- ^ Footer contents.
-> Mod OptionFields a
completes title note xs x foot = doc <> completeWith (map fst ys)
where
doc = defaults title note ys x foot
ys = map (first string) xs
-- | Construct a tabular representation displaying the default values,
-- without using ToText for the tabular values.
defaults :: ToText a
=> Text
-> Text
-> [(String, String)]
-> Maybe a
-> Maybe Text
-> Mod OptionFields a
defaults title note xs x foot =
describe title (Just doc) Default <> maybe mempty value x
where
doc = maybe table (table .$.) (wrap <$> foot)
table = wrap note
.$. indent 2 rows
$$$ ( case x of
Nothing -> mempty
Just y -> "Defaults to " <> bold (text (string y)) <> "."
)
($$$) | isJust x = (.$.)
| otherwise = mappend
len = maximum (map (length . fst) xs)
rows | [r] <- xs = f r
| r:rs <- xs = foldl' (.$.) (f r) (map f rs)
| otherwise = mempty
where
f (k, v) = "-" <+> bold (text k) <+> indent (len - length k) ts
where
ts | null v = mempty
| otherwise = tupled [text v]
require :: (Fact -> a) -> a
require f = f Required
optional :: Alternative f => (Fact -> f a) -> f (Maybe a)
optional f = Opt.optional (f Optional)
textOption :: FromText a => Mod OptionFields a -> Parser a
textOption = option (eitherReader (fromText . Text.pack))
wrap :: Text -> Doc
wrap = extractChunk . paragraph . Text.unpack