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