module UI.Butcher.Monadic.Param
( Param(..)
, paramHelp
, paramHelpStr
, paramDefault
, paramSuggestions
, paramFile
, paramDirectory
, addParamRead
, addParamReadOpt
, addParamString
, addParamStringOpt
, addParamStrings
, addParamNoFlagString
, addParamNoFlagStringOpt
, addParamNoFlagStrings
, addParamRestOfInput
, addParamRestOfInputRaw
,
addReadParam
, addReadParamOpt
, addStringParam
, addStringParamOpt
, addStringParams
, addRestOfInputStringParam
)
where
#include "prelude.inc"
import Control.Monad.Free
import qualified Control.Monad.Trans.MultiRWS.Strict as MultiRWSS
import qualified Control.Monad.Trans.MultiState.Strict as MultiStateS
import qualified Text.PrettyPrint as PP
import Data.HList.ContainsType
import UI.Butcher.Monadic.Internal.Types
import UI.Butcher.Monadic.Internal.Core
data Param p = Param
{ _param_default :: Maybe p
, _param_help :: Maybe PP.Doc
, _param_suggestions :: Maybe [CompletionItem]
}
appendParam :: Param p -> Param p -> Param p
appendParam (Param a1 b1 c1) (Param a2 b2 c2) = Param (a1 `f` a2)
(b1 <> b2)
(c1 <> c2)
where
f Nothing x = x
f x _ = x
instance Semigroup (Param p) where
(<>) = appendParam
instance Monoid (Param p) where
mempty = Param Nothing Nothing Nothing
mappend = (<>)
paramHelpStr :: String -> Param p
paramHelpStr s = mempty { _param_help = Just $ PP.text s }
paramHelp :: PP.Doc -> Param p
paramHelp h = mempty { _param_help = Just h }
paramDefault :: p -> Param p
paramDefault d = mempty { _param_default = Just d }
paramSuggestions :: [String] -> Param p
paramSuggestions ss =
mempty { _param_suggestions = Just $ CompletionString <$> ss }
paramFile :: Param p
paramFile = mempty { _param_suggestions = Just [CompletionFile] }
paramDirectory :: Param p
paramDirectory = mempty { _param_suggestions = Just [CompletionDirectory] }
addParamRead :: forall f out a
. (Applicative f, Typeable a, Show a, Text.Read.Read a)
=> String
-> Param a
-> CmdParser f out a
addParamRead = addReadParam
addReadParam :: forall f out a
. (Applicative f, Typeable a, Show a, Text.Read.Read a)
=> String
-> Param a
-> CmdParser f out a
addReadParam name par = addCmdPart desc parseF
where
desc :: PartDesc
desc = addSuggestion (_param_suggestions par)
$ (maybe id PartWithHelp $ _param_help par)
$ (maybe id (PartDefault . show) $ _param_default par)
$ PartVariable name
parseF :: String -> Maybe (a, String)
parseF s = case Text.Read.reads s of
((x, ' ':r):_) -> Just (x, dropWhile Char.isSpace r)
((x, []):_) -> Just (x, [])
_ -> _param_default par <&> \x -> (x, s)
addParamReadOpt :: forall f out a
. (Applicative f, Typeable a, Text.Read.Read a)
=> String
-> Param a
-> CmdParser f out (Maybe a)
addParamReadOpt = addReadParamOpt
addReadParamOpt :: forall f out a
. (Applicative f, Typeable a, Text.Read.Read a)
=> String
-> Param a
-> CmdParser f out (Maybe a)
addReadParamOpt name par = addCmdPart desc parseF
where
desc :: PartDesc
desc = addSuggestion (_param_suggestions par)
$ PartOptional
$ (maybe id PartWithHelp $ _param_help par)
$ PartVariable name
parseF :: String -> Maybe (Maybe a, String)
parseF s = case Text.Read.reads s of
((x, ' ':r):_) -> Just (Just x, dropWhile Char.isSpace r)
((x, []):_) -> Just (Just x, [])
_ -> Just (Nothing, s)
addParamString
:: forall f out . (Applicative f)
=> String
-> Param String
-> CmdParser f out String
addParamString = addStringParam
addStringParam
:: forall f out . (Applicative f)
=> String
-> Param String
-> CmdParser f out String
addStringParam name par = addCmdPartInp desc parseF
where
desc :: PartDesc
desc = addSuggestion (_param_suggestions par)
$ (maybe id PartWithHelp $ _param_help par)
$ PartVariable name
parseF :: Input -> Maybe (String, Input)
parseF (InputString str)
= case break Char.isSpace $ dropWhile Char.isSpace str of
("", rest) -> _param_default par <&> \x -> (x, InputString rest)
(x, rest) -> Just (x, InputString rest)
parseF (InputArgs args) = case args of
(s1:sR) -> Just (s1, InputArgs sR)
[] -> _param_default par <&> \x -> (x, InputArgs args)
addParamStringOpt
:: forall f out . (Applicative f)
=> String
-> Param Void
-> CmdParser f out (Maybe String)
addParamStringOpt = addStringParamOpt
addStringParamOpt
:: forall f out . (Applicative f)
=> String
-> Param Void
-> CmdParser f out (Maybe String)
addStringParamOpt name par = addCmdPartInp desc parseF
where
desc :: PartDesc
desc = addSuggestion (_param_suggestions par)
$ PartOptional
$ (maybe id PartWithHelp $ _param_help par)
$ PartVariable name
parseF :: Input -> Maybe (Maybe String, Input)
parseF (InputString str)
= case break Char.isSpace $ dropWhile Char.isSpace str of
("", rest) -> Just (Nothing, InputString rest)
(x, rest) -> Just (Just x, InputString rest)
parseF (InputArgs args) = case args of
(s1:sR) -> Just (Just s1, InputArgs sR)
[] -> Just (Nothing, InputArgs [])
addParamStrings
:: forall f out
. (Applicative f)
=> String
-> Param Void
-> CmdParser f out [String]
addParamStrings = addStringParams
addStringParams
:: forall f out
. (Applicative f)
=> String
-> Param Void
-> CmdParser f out [String]
addStringParams name par = addCmdPartManyInp ManyUpperBoundN desc parseF
where
desc :: PartDesc
desc =
addSuggestion (_param_suggestions par)
$ (maybe id PartWithHelp $ _param_help par)
$ PartVariable name
parseF :: Input -> Maybe (String, Input)
parseF (InputString str) =
case break Char.isSpace $ dropWhile Char.isSpace str of
("", _ ) -> Nothing
(x , rest) -> Just (x, InputString rest)
parseF (InputArgs args) = case args of
(s1:sR) -> Just (s1, InputArgs sR)
[] -> Nothing
addParamNoFlagString
:: forall f out . (Applicative f)
=> String
-> Param String
-> CmdParser f out String
addParamNoFlagString name par = addCmdPartInp desc parseF
where
desc :: PartDesc
desc =
addSuggestion (_param_suggestions par)
$ (maybe id PartWithHelp $ _param_help par)
$ PartVariable name
parseF :: Input -> Maybe (String, Input)
parseF (InputString str) =
case break Char.isSpace $ dropWhile Char.isSpace str of
("" , rest) -> _param_default par <&> \x -> (x, InputString rest)
('-':_, _ ) -> _param_default par <&> \x -> (x, InputString str)
(x , rest) -> Just (x, InputString rest)
parseF (InputArgs args) = case args of
[] -> _param_default par <&> \x -> (x, InputArgs args)
(('-':_):_ ) -> _param_default par <&> \x -> (x, InputArgs args)
(s1 :sR) -> Just (s1, InputArgs sR)
addParamNoFlagStringOpt
:: forall f out
. (Applicative f)
=> String
-> Param Void
-> CmdParser f out (Maybe String)
addParamNoFlagStringOpt name par = addCmdPartInp desc parseF
where
desc :: PartDesc
desc =
PartOptional $ (maybe id PartWithHelp $ _param_help par) $ PartVariable name
parseF :: Input -> Maybe (Maybe String, Input)
parseF (InputString str) =
case break Char.isSpace $ dropWhile Char.isSpace str of
("" , rest) -> Just (Nothing, InputString rest)
('-':_, _ ) -> Just (Nothing, InputString str)
(x , rest) -> Just (Just x, InputString rest)
parseF (InputArgs args) = case args of
[] -> Just (Nothing, InputArgs [])
(('-':_):_ ) -> Just (Nothing, InputArgs args)
(s1 :sR) -> Just (Just s1, InputArgs sR)
addParamNoFlagStrings
:: forall f out
. (Applicative f)
=> String
-> Param Void
-> CmdParser f out [String]
addParamNoFlagStrings name par = addCmdPartManyInp ManyUpperBoundN desc parseF
where
desc :: PartDesc
desc =
addSuggestion (_param_suggestions par)
$ (maybe id PartWithHelp $ _param_help par)
$ PartVariable name
parseF :: Input -> Maybe (String, Input)
parseF (InputString str) =
case break Char.isSpace $ dropWhile Char.isSpace str of
("" , _ ) -> Nothing
('-':_, _ ) -> Nothing
(x , rest) -> Just (x, InputString rest)
parseF (InputArgs args) = case args of
[] -> Nothing
(('-':_):_ ) -> Nothing
(s1 :sR) -> Just (s1, InputArgs sR)
addParamRestOfInput
:: forall f out . (Applicative f)
=> String
-> Param Void
-> CmdParser f out String
addParamRestOfInput = addRestOfInputStringParam
addRestOfInputStringParam
:: forall f out
. (Applicative f)
=> String
-> Param Void
-> CmdParser f out String
addRestOfInputStringParam name par = addCmdPartInp desc parseF
where
desc :: PartDesc
desc =
addSuggestion (_param_suggestions par)
$ (maybe id PartWithHelp $ _param_help par)
$ PartVariable name
parseF :: Input -> Maybe (String, Input)
parseF (InputString str ) = Just (str, InputString "")
parseF (InputArgs args) = Just (List.unwords args, InputArgs [])
addParamRestOfInputRaw
:: forall f out . (Applicative f)
=> String
-> Param Void
-> CmdParser f out Input
addParamRestOfInputRaw name par = addCmdPartInp desc parseF
where
desc :: PartDesc
desc =
addSuggestion (_param_suggestions par)
$ (maybe id PartWithHelp $ _param_help par)
$ PartVariable name
parseF :: Input -> Maybe (Input, Input)
parseF i@InputString{} = Just (i, InputString "")
parseF i@InputArgs{} = Just (i, InputArgs [])