Merge branch 'ggonzalez/options2'

This commit is contained in:
Gabriel Gonzalez 2015-07-04 13:42:03 -07:00
commit ab15df5e32

View file

@ -9,8 +9,8 @@
-- > import Turtle -- > import Turtle
-- > -- >
-- > parser :: Parser (Text, Int) -- > parser :: Parser (Text, Int)
-- > parser = (,) <$> optText "name" "Your first name" -- > parser = (,) <$> optText "name" 'n' "Your first name"
-- > <*> optIntegral "age" "Your current age" -- > <*> optInt "age" 'a' "Your current age"
-- > -- >
-- > main = do -- > main = do
-- > (name, age) <- options "Greeting script" parser -- > (name, age) <- options "Greeting script" parser
@ -35,21 +35,24 @@ module Turtle.Options
( -- * Types ( -- * Types
Parser Parser
, ArgName , ArgName
, ShortName
, Description , Description
, HelpMessage , HelpMessage
-- * Flag-based option parsers -- * Flag-based option parsers
, switch , switch
, optText , optText
, optIntegral , optInt
, optFractional , optInteger
, optDouble
, optRead , optRead
, opt , opt
-- * Positional argument parsers -- * Positional argument parsers
, argText , argText
, argIntegral , argInt
, argFractional , argInteger
, argDouble
, argRead , argRead
, arg , arg
@ -80,13 +83,16 @@ options desc parser = liftIO
{-| The name of a command-line argument {-| The name of a command-line argument
This is used to infer the long name, short name, and metavariable for the This is used to infer the long name and metavariable for the command line
command line flag. For example, an `ArgName` of @\"name\"@ will create a flag. For example, an `ArgName` of @\"name\"@ will create a @--name@ flag
@--name@ flag with a @NAME@ metavariable and a short name of @-n@ with a @NAME@ metavariable
-} -}
newtype ArgName = ArgName { getArgName :: Text } newtype ArgName = ArgName { getArgName :: Text }
deriving (IsString) deriving (IsString)
-- | The short one-character abbreviation for a flag (i.e. @-n@)
type ShortName = Char
{-| A brief description of what your program does {-| A brief description of what your program does
This description will appear in the header of the @--help@ output This description will appear in the header of the @--help@ output
@ -106,12 +112,13 @@ newtype HelpMessage = HelpMessage { getHelpMessage :: Text }
-} -}
switch switch
:: ArgName :: ArgName
-> ShortName
-> Optional HelpMessage -> Optional HelpMessage
-> Parser Bool -> Parser Bool
switch argName helpMessage switch argName c helpMessage
= Opts.switch = Opts.switch
$ (Opts.long . Text.unpack . getArgName) argName $ (Opts.long . Text.unpack . getArgName) argName
<> foldMap (Opts.short . fst) (Text.uncons (getArgName argName)) <> Opts.short c
<> foldMap (Opts.help . Text.unpack . getHelpMessage) helpMessage <> foldMap (Opts.help . Text.unpack . getHelpMessage) helpMessage
{- | Build a flag-based option parser for any type by providing a `Text`-parsing {- | Build a flag-based option parser for any type by providing a `Text`-parsing
@ -119,38 +126,36 @@ switch argName helpMessage
-} -}
opt :: (Text -> Maybe a) opt :: (Text -> Maybe a)
-> ArgName -> ArgName
-> ShortName
-> Optional HelpMessage -> Optional HelpMessage
-> Parser a -> Parser a
opt argParse argName helpMessage opt argParse argName c helpMessage
= Opts.option (argParseToReadM argParse) = Opts.option (argParseToReadM argParse)
$ Opts.metavar (Text.unpack (Text.toUpper (getArgName argName))) $ Opts.metavar (Text.unpack (Text.toUpper (getArgName argName)))
<> Opts.long (Text.unpack (getArgName argName)) <> Opts.long (Text.unpack (getArgName argName))
<> foldMap (Opts.short . fst) (Text.uncons (getArgName argName)) <> Opts.short c
<> foldMap (Opts.help . Text.unpack . getHelpMessage) helpMessage <> foldMap (Opts.help . Text.unpack . getHelpMessage) helpMessage
-- | Parse any type that implements `Read` -- | Parse any type that implements `Read`
optRead :: Read a => ArgName -> Optional HelpMessage -> Parser a optRead :: Read a => ArgName -> ShortName -> Optional HelpMessage -> Parser a
optRead = opt (readMaybe . Text.unpack) optRead = opt (readMaybe . Text.unpack)
{-| Parse any type that implements `Integral` as n flag-based option -- | Parse an `Int` as a flag-based option
optInt :: ArgName -> ShortName -> Optional HelpMessage -> Parser Int
optInt = optRead
This is most commonly used to parse an `Int` or `Integer` -- | Parse an `Integer` as a flag-based option
-} optInteger :: ArgName -> ShortName -> Optional HelpMessage -> Parser Integer
optIntegral :: Integral n => ArgName -> Optional HelpMessage -> Parser n optInteger = optRead
optIntegral argName helpMessage = fmap fromInteger (optRead argName helpMessage)
-- | Parse a `Double` as a flag-based option
optDouble :: ArgName -> ShortName -> Optional HelpMessage -> Parser Double
optDouble = optRead
-- | Parse a `Text` value as a flag-based option -- | Parse a `Text` value as a flag-based option
optText :: ArgName -> Optional HelpMessage -> Parser Text optText :: ArgName -> ShortName -> Optional HelpMessage -> Parser Text
optText = opt Just optText = opt Just
{-| Parse any type that implements `Fractional` as a flag-based option
This is most commonly used to parse a `Double`
-}
optFractional :: Fractional n => ArgName -> Optional HelpMessage -> Parser n
optFractional argName helpMessage =
fmap fromRational (optRead argName helpMessage)
{- | Build a positional argument parser for any type by providing a {- | Build a positional argument parser for any type by providing a
`Text`-parsing function `Text`-parsing function
-} -}
@ -167,25 +172,22 @@ arg argParse argName helpMessage
argRead :: Read a => ArgName -> Optional HelpMessage -> Parser a argRead :: Read a => ArgName -> Optional HelpMessage -> Parser a
argRead = arg (readMaybe . Text.unpack) argRead = arg (readMaybe . Text.unpack)
{-| Parse any type that implements `Integral` as a positional argument -- | Parse an `Int` as a positional argument
argInt :: ArgName -> Optional HelpMessage -> Parser Int
argInt = argRead
This is most commonly used to parse an `Int` or `Integer` -- | Parse an `Integer` as a positional argument
-} argInteger :: ArgName -> Optional HelpMessage -> Parser Integer
argIntegral :: Integral n => ArgName -> Optional HelpMessage -> Parser n argInteger = argRead
argIntegral argName helpMessage = fmap fromInteger (argRead argName helpMessage)
-- | Parse a `Text` value as a positional argument -- | Parse a `Double` as a positional argument
argDouble :: ArgName -> Optional HelpMessage -> Parser Double
argDouble = argRead
-- | Parse a `Text` as a positional argument
argText :: ArgName -> Optional HelpMessage -> Parser Text argText :: ArgName -> Optional HelpMessage -> Parser Text
argText = arg Just argText = arg Just
{-| Parse any type that implements `Fractional` as a positional argument
This is most commonly used to parse a `Double`
-}
argFractional :: Fractional n => ArgName -> Optional HelpMessage -> Parser n
argFractional argName helpMessage =
fmap fromRational (argRead argName helpMessage)
argParseToReadM :: (Text -> Maybe a) -> Opts.ReadM a argParseToReadM :: (Text -> Maybe a) -> Opts.ReadM a
argParseToReadM f = do argParseToReadM f = do
s <- Opts.readerAsk s <- Opts.readerAsk