multiarg 0.22.0.0 → 0.24.0.0
raw patch · 5 files changed
+99/−134 lines, 5 filesPVP ok
version bump matches the API change (PVP)
API changes (from Hackage documentation)
- System.Console.MultiArg.Combinator: OneArgE :: (String -> Either InputError a) -> ArgSpec a
- System.Console.MultiArg.Combinator: OptionalArgE :: (Maybe String -> Either InputError a) -> ArgSpec a
- System.Console.MultiArg.Combinator: ThreeArgE :: (String -> String -> String -> Either InputError a) -> ArgSpec a
- System.Console.MultiArg.Combinator: TwoArgE :: (String -> String -> Either InputError a) -> ArgSpec a
- System.Console.MultiArg.Combinator: VariableArgE :: ([String] -> Either InputError a) -> ArgSpec a
- System.Console.MultiArg.Combinator: OneArg :: (String -> a) -> ArgSpec a
+ System.Console.MultiArg.Combinator: OneArg :: (String -> Either InputError a) -> ArgSpec a
- System.Console.MultiArg.Combinator: OptionalArg :: (Maybe String -> a) -> ArgSpec a
+ System.Console.MultiArg.Combinator: OptionalArg :: (Maybe String -> Either InputError a) -> ArgSpec a
- System.Console.MultiArg.Combinator: ThreeArg :: (String -> String -> String -> a) -> ArgSpec a
+ System.Console.MultiArg.Combinator: ThreeArg :: (String -> String -> String -> Either InputError a) -> ArgSpec a
- System.Console.MultiArg.Combinator: TwoArg :: (String -> String -> a) -> ArgSpec a
+ System.Console.MultiArg.Combinator: TwoArg :: (String -> String -> Either InputError a) -> ArgSpec a
- System.Console.MultiArg.Combinator: VariableArg :: ([String] -> a) -> ArgSpec a
+ System.Console.MultiArg.Combinator: VariableArg :: ([String] -> Either InputError a) -> ArgSpec a
Files
- NEWS +12/−0
- lib/System/Console/MultiArg/Combinator.hs +41/−113
- lib/System/Console/MultiArg/CommandLine.hs +27/−14
- lib/System/Console/MultiArg/SampleParser.hs +18/−6
- multiarg.cabal +1/−1
NEWS view
@@ -1,3 +1,15 @@+Release 0.24.0.0, September 12, 2013+Changes since release 0.20.0.0:++* Remove OneArgE, TwoArgE, etc. from Combinator module. These data+ constructors were renamed OneArg, TwoArg, etc. Having both OneArg+ and OneArgE was redundant.++* Improved error messages when the user enters an unrecognized option.+ Previously unrecognized options were passed through to client code+ as a positional argument; now they will be recognized as bad+ options.+ Release 0.20.0.0, August 30, 2013 Changes since release 0.18.0.0:
lib/System/Console/MultiArg/Combinator.hs view
@@ -22,7 +22,7 @@ import Data.Set ( Set ) import qualified Data.Set as Set import Control.Applicative- ((<$>), (<*>), optional, (<$), (*>), (<|>), many)+ ((<*>), optional, (<$), (*>), (<|>), many) import System.Console.MultiArg.Prim ( Parser, try, approxLongOpt,@@ -158,16 +158,17 @@ -- example that uses an algebraic data type, see -- "System.Console.MultiArg.SampleParser". ----- Some of these value constructors have names ending in @E@. Use--- these constructors when you want to parse option arguments that may--- fail to parse--for example, you want to parse an Int. The function--- passed as an argument to the value constructor indicates failure by--- returing an 'Exception'.+-- Most of these value constructors take as an argument a function+-- that returns an Either. The function should return a @Left+-- InputError@ if the parsing of the arguments failed--if, for+-- example, the user needs to enter an integer but she instead input a+-- letter. The functions should return a Right if parsing of the+-- arguments was successful. data ArgSpec a = NoArg a -- ^ This option takes no arguments - | OptionalArg (Maybe String -> a)+ | OptionalArg (Maybe String -> Either InputError a) -- ^ This option takes an optional argument. As noted in \"The Tao -- of Option Parsing\", optional arguments can result in some -- ambiguity. (Read it here:@@ -181,21 +182,21 @@ -- though, optional arguments lead to ambiguity, so if you don't -- like it, don't use them :) - | OneArg (String -> a)+ | OneArg (String -> Either InputError a) -- ^ This option takes one argument. Here, if option @a@ takes one -- argument, @-a -b@ will be parsed with @-b@ being an argument to -- option @a@, even though @-b@ starts with a hyphen and therefore -- \"looks like\" an option. - | TwoArg (String -> String -> a)+ | TwoArg (String -> String -> Either InputError a) -- ^ This option takes two arguments. Parsed similarly to -- 'OneArg'. - | ThreeArg (String -> String -> String -> a)+ | ThreeArg (String -> String -> String -> Either InputError a) -- ^ This option takes three arguments. Parsed similarly to -- 'OneArg'. - | VariableArg ([String] -> a)+ | VariableArg ([String] -> Either InputError a) -- ^ This option takes a variable number of arguments--zero or -- more. Option arguments continue until the command line contains -- a word that begins with a hyphen. For example, if option @a@@@ -215,56 +216,26 @@ -- option to GNU grep, which requires the user to supply one of -- three arguments: @always@, @never@, or @auto@. - | OptionalArgE (Maybe String -> Either InputError a)- -- ^ This option takes an optional argument, like- -- 'OptionalArg'. Parsing of the optional argument might fail. - | OneArgE (String -> Either InputError a)- -- ^ This option takes a single argument, like 'OneArg'. Parsing- -- of the argument might fail.-- | TwoArgE (String -> String -> Either InputError a)- -- ^ This option takes two arguments, like 'TwoArg'. Parsing of- -- the arguments might fail.-- | ThreeArgE (String -> String -> String -> Either InputError a)- -- ^ This option takes three arguments, like 'ThreeArg'. Parsing- -- of the arguments might fail.-- | VariableArgE ([String] -> Either InputError a)- -- ^ This option takes a variable number of arguments, like- -- 'VariableArg'. Parsing of the arguments might fail.-- instance Functor ArgSpec where fmap f a = case a of NoArg i -> NoArg $ f i- OptionalArg g ->- OptionalArg $ \ms -> f (g ms)- OneArg g ->- OneArg $ \s1 -> f (g s1)- TwoArg g ->- TwoArg $ \s1 s2 -> f (g s1 s2)- ThreeArg g ->- ThreeArg $ \s1 s2 s3 -> f (g s1 s2 s3)- VariableArg g ->- VariableArg $ \ls -> f (g ls) ChoiceArg gs -> ChoiceArg . map (\(s, r) -> (s, f r)) $ gs - OptionalArgE g -> OptionalArgE $ \ms -> fmap f (g ms)+ OptionalArg g -> OptionalArg $ \ms -> fmap f (g ms) - OneArgE g ->- OneArgE $ \s1 -> fmap f (g s1)+ OneArg g ->+ OneArg $ \s1 -> fmap f (g s1) - TwoArgE g ->- TwoArgE $ \s1 s2 -> fmap f (g s1 s2)+ TwoArg g ->+ TwoArg $ \s1 s2 -> fmap f (g s1 s2) - ThreeArgE g ->- ThreeArgE $ \s1 s2 s3 -> fmap f (g s1 s2 s3)+ ThreeArg g ->+ ThreeArg $ \s1 s2 s3 -> fmap f (g s1 s2 s3) - VariableArgE g ->- VariableArgE $ \ls -> fmap f (g ls)+ VariableArg g ->+ VariableArg $ \ls -> fmap f (g ls) -- | Parses a single command line option. Examines all the options@@ -318,15 +289,6 @@ Nothing -> return a Just _ -> fail $ "option " ++ unLongOpt lo ++ " does not take argument"- OptionalArg f -> return (f maybeArg)- OneArg f -> f <$> maybeNextArg- TwoArg f -> f <$> maybeNextArg <*> nextWord- ThreeArg f -> f <$> maybeNextArg <*> nextWord <*> nextWord- VariableArg f -> do- as <- many nonOptionPosArg- return . f $ case maybeArg of- Nothing -> as- Just a1 -> a1 : as ChoiceArg ls -> do s <- maybeNextArg case matchAbbrev ls s of@@ -335,32 +297,32 @@ ++ (concat . intersperse ", " . map fst $ ls) Just g -> return g - OptionalArgE f -> case maybeArg of+ OptionalArg f -> case maybeArg of Nothing -> either (fail . errorMsg (Left lo) []) return $ f Nothing Just s -> either (fail . errorMsg (Left lo) [s]) return $ f (Just s) - OneArgE f -> maybeNextArg >>= g+ OneArg f -> maybeNextArg >>= g where g a = either (fail . errorMsg (Left lo) [a]) return $ f a - TwoArgE f -> do+ TwoArg f -> do a1 <- maybeNextArg a2 <- nextWord either (fail . errorMsg (Left lo) [a1, a2]) return $ f a1 a2 - ThreeArgE f -> do+ ThreeArg f -> do a1 <- maybeNextArg a2 <- nextWord a3 <- nextWord either (fail . errorMsg (Left lo) [a1, a2, a3]) return $ f a1 a2 a3 - VariableArgE f -> do+ VariableArg f -> do as <- many nonOptionPosArg let args = case maybeArg of Nothing -> as@@ -376,17 +338,12 @@ let opt = unsafeShortOpt c in Just $ nextShort opt *> case argSpec o of NoArg a -> return a- OptionalArg f -> shortOptionalArg f- OneArg f -> shortOneArg f- TwoArg f -> shortTwoArg f- ThreeArg f -> shortThreeArg f- VariableArg f -> shortVariableArg f ChoiceArg ls -> shortChoiceArg opt ls- OptionalArgE f -> shortOptionalArgE opt f- OneArgE f -> shortOneArgE opt f- TwoArgE f -> shortTwoArgE opt f- ThreeArgE f -> shortThreeArgE opt f- VariableArgE f -> shortVariableArgE opt f+ OptionalArg f -> shortOptionalArg opt f+ OneArg f -> shortOneArg opt f+ TwoArg f -> shortTwoArg opt f+ ThreeArg f -> shortThreeArg opt f+ VariableArg f -> shortVariableArg opt f -- | Parses a short option without an argument, either pending or -- non-pending. Fails with a single error message rather than two.@@ -400,20 +357,11 @@ Nothing -> nonPendingShortOpt o -shortVariableArg :: ([String] -> a) -> Parser a-shortVariableArg f = do- maybeSameWordArg <- optional pendingShortOptArg- args <- many nonOptionPosArg- case maybeSameWordArg of- Nothing -> return (f args)- Just arg1 -> return (f (arg1:args))---shortVariableArgE+shortVariableArg :: ShortOpt -> ([String] -> Either InputError a) -> Parser a-shortVariableArgE so f = do+shortVariableArg so f = do maybeSameWordArg <- optional pendingShortOptArg args <- many nonOptionPosArg let as = case maybeSameWordArg of@@ -422,14 +370,11 @@ either (fail . errorMsg (Right so) as) return $ f as -shortOneArg :: (String -> a) -> Parser a-shortOneArg f = f <$> firstShortArg--shortOneArgE+shortOneArg :: ShortOpt -> (String -> Either InputError a) -> Parser a-shortOneArgE so f = do+shortOneArg so f = do a <- firstShortArg either (fail . errorMsg (Right so) [a]) return $ f a @@ -448,50 +393,33 @@ ++ (concat . intersperse " " . map fst $ ls) --shortTwoArg :: (String -> String -> a) -> Parser a-shortTwoArg f = f <$> firstShortArg <*> nextWord--shortTwoArgE+shortTwoArg :: ShortOpt -> (String -> String -> Either InputError a) -> Parser a-shortTwoArgE so f = do+shortTwoArg so f = do a1 <- firstShortArg a2 <- nextWord either (fail . errorMsg (Right so) [a1, a2]) return $ f a1 a2 -shortThreeArg :: (String -> String -> String -> a) -> Parser a-shortThreeArg f = f <$> firstShortArg <*> nextWord <*> nextWord -shortThreeArgE+shortThreeArg :: ShortOpt -> (String -> String -> String -> Either InputError a) -> Parser a-shortThreeArgE so f = do+shortThreeArg so f = do a1 <- firstShortArg a2 <- nextWord a3 <- nextWord either (fail . errorMsg (Right so) [a1, a2, a3]) return $ f a1 a2 a3 -shortOptionalArg :: (Maybe String -> a) -> Parser a-shortOptionalArg f = do- maybeSameWordArg <- optional pendingShortOptArg- case maybeSameWordArg of- Nothing -> do- maybeArg <- optional nonOptionPosArg- case maybeArg of- Nothing -> return (f Nothing)- Just a -> return (f (Just a))- Just a -> return (f (Just a))--shortOptionalArgE+shortOptionalArg :: ShortOpt -> (Maybe String -> Either InputError a) -> Parser a-shortOptionalArgE so f = do+shortOptionalArg so f = do maybeSameWordArg <- optional pendingShortOptArg case maybeSameWordArg of Nothing -> do
lib/System/Console/MultiArg/CommandLine.hs view
@@ -265,9 +265,9 @@ -- ^ This function processes the global options. If there are no -- shortcut options specified in the global options, it is applied -- to the result of processing the global options. This function- -- may return an Exception if there is something wrong with the+ -- may return a Left if there is something wrong with the -- global options (a nonsensical combination, perhaps.) Otherwise,- -- it returns an Either. Return a Left if there is no need to+ -- it returns a @Right Either@. Return a Left if there is no need to -- process any modes at all after seeing the global options. -- Otherwise, return a Right with a list of modes. @@ -275,9 +275,9 @@ -- ^ Command line arguments to parse -> Either P.Error (Either s r)- -- ^ If the command line arguments fail to parse, this will be an- -- Exception with the error. If the parser is successful, this- -- returns an Either. A Left indicates that the user entered a+ -- ^ If the command line arguments fail to parse, this will be a+ -- Left with the error. If the parser is successful, this+ -- returns a @Right Either@. A Left indicates that the user entered a -- shortcut option, either in the global options or in one of the -- mode-specific options. A Right indicates that the user selected -- a mode.@@ -340,9 +340,9 @@ -- ^ This function processes the global options. If there are no -- shortcut options specified in the global options, it is applied -- to the result of processing the global options. This function- -- may return an Exception if there is something wrong with the+ -- may return a Left if there is something wrong with the -- global options (a nonsensical combination, perhaps.) Otherwise,- -- it returns an Either. Return a Left if there is no need to+ -- it returns a @Right Either@. Return a Left if there is no need to -- process any modes at all after seeing the global options. -- Otherwise, return a Right with a list of modes. @@ -453,13 +453,21 @@ -- # Helpers --- | Parses positional arguments and handles errors with them.+-- | Handles positional arguments and errors with them. The parser for+-- the positional argument must be passed in (this way it can+-- be parsed with nonOptionPosArg or nextWord, as appropriate; when+-- parsing interpsersed command lines, you will want nonOptionPosArg;+-- when parsing non-interspersed command lines, you will need+-- nextWord.) parsePosArg- :: (String -> Either C.InputError a)+ :: P.Parser String+ -- ^ Parser for Word for next positional argument+ -> (String -> Either C.InputError a)+ -- ^ Function to handle positional arguments -> P.Parser a-parsePosArg p = do- a <- P.nextWord- case p a of+parsePosArg pa f = do+ a <- pa+ case f a of Left e -> let msg = "invalid positional argument: \"" ++ a ++ "\"" in case e of@@ -489,18 +497,23 @@ (++) <$> parseOptsNoIntersperse optParser <* optional P.stopper- <*> many (parsePosArg p)+ <*> many (parsePosArg P.nextWord p) -- | @parseIntersperse o p@ parses options and positional arguments, -- where o is a parser that parses options, and p is a function that, -- when applied to a string, returns the appropriate type.+--+-- If a stopper has not yet been seen, any word that begins with a+-- hyphen will not be parsed as a positional argument. Therefore, if+-- there is a word before a stopper and it begins with a hyphen, if it+-- is not a valid option then the parse will fail with an error. parseIntersperse :: P.Parser a -> (String -> Either C.InputError a) -> P.Parser [a] parseIntersperse optParser p =- let pa = Just <$> parsePosArg p+ let pa = Just <$> parsePosArg P.nonOptionPosArg p po = Just <$> optParser ps = Nothing <$ P.stopper parser = po <|> ps <|> pa
lib/System/Console/MultiArg/SampleParser.hs view
@@ -39,14 +39,26 @@ specs :: [C.OptSpec Flag] specs =- [ C.OptSpec ["bytes"] ['c'] (C.OneArg Bytes)- , C.OptSpec ["follow"] ['f'] (C.OptionalArg Follow)+ [ C.OptSpec ["bytes"] ['c']+ (C.OneArg (return . Bytes))++ , C.OptSpec ["follow"] ['f']+ (C.OptionalArg (return . Follow))+ , C.OptSpec ["follow-retry"] ['F'] (C.NoArg Retry)- , C.OptSpec ["lines"] ['n'] (C.OneArg Lines)- , C.OptSpec ["max-unchanged-stats"] [] (C.OneArg Stats)- , C.OptSpec ["pid"] [] (C.OneArg Pid)++ , C.OptSpec ["lines"] ['n']+ (C.OneArg (return . Lines))++ , C.OptSpec ["max-unchanged-stats"] []+ (C.OneArg (return . Stats))++ , C.OptSpec ["pid"] []+ (C.OneArg (return . Pid)) , C.OptSpec ["quiet"] ['q'] (C.NoArg Quiet)- , C.OptSpec ["sleep-interval"] ['s'] (C.OneArg Sleep)++ , C.OptSpec ["sleep-interval"] ['s']+ (C.OneArg (return . Sleep)) , C.OptSpec ["verbose"] ['v'] (C.NoArg Verbose) , C.OptSpec ["help"] [] (C.NoArg Help) , C.OptSpec ["version"] [] (C.NoArg Version)
multiarg.cabal view
@@ -1,5 +1,5 @@ Name: multiarg-Version: 0.22.0.0+Version: 0.24.0.0 Cabal-version: >=1.8 Build-Type: Simple License: BSD3