packages feed

optparse-applicative 0.10.0 → 0.11.0

raw patch · 10 files changed

+103/−65 lines, 10 filesdep ~base

Dependency ranges changed: base

Files

CHANGELOG.md view
@@ -1,3 +1,16 @@+## Version 0.11.0 (4 Oct 2014)++- Added Alternative instances for `Chunk` and `ReadM`.++- The `ReadM` monad is now a `ReaderT` for the argument being parsed.  User+  defined readers do not need to handle their argument explicitly, but can+  always access it using `readerAsk`.++- Argument builders now take a `ReadM` parameter, just like options.++- Fixed bugs+    * \#106 - argument should perhaps use `ReadM`+ ## Version 0.10.0 (1 Sep 2014)  - Parser execution and help text generation are now more modular, and allow for@@ -168,8 +181,8 @@          foo --out -  will match an option called `--output`, as long as its the only one starting-  with the string `out`.+    will match an option called `--output`, as long as its the only one starting+    with the string `out`.  - Added `briefDesc` modifier. 
Options/Applicative/BashCompletion.hs view
@@ -71,9 +71,7 @@         w:_ -> isPrefixOf w         _ -> const True -    compl = do-      setParser Nothing (infoParser pinfo)-      runParserInfo pinfo (drop 1 ws')+    compl = runParserInfo pinfo (drop 1 ws')  bashCompletionScript :: String -> String -> IO [String] bashCompletionScript prog progn = return
Options/Applicative/Builder.hs view
@@ -111,18 +111,18 @@ -- readers --  -- | 'Option' reader based on the 'Read' type class.-auto :: Monad m => Read a => String -> m a-auto arg = case reads arg of+auto :: Read a => ReadM a+auto = eitherReader $ \arg -> case reads arg of   [(r, "")] -> return r-  _         -> fail $ "cannot parse value `" ++ arg ++ "'"+  _         -> Left $ "cannot parse value `" ++ arg ++ "'"  -- | String 'Option' reader.-str :: Monad m => String -> m String-str = return+str :: ReadM String+str = readerAsk  -- | Null 'Option' reader. All arguments will fail validation.-disabled :: Monad m => String -> m a-disabled = const . fail $ "disabled option"+disabled :: ReadM a+disabled = readerError "disabled option"  -- modifiers -- @@ -156,8 +156,8 @@ helpDoc doc = optionMod $ \p -> p { propHelp = Chunk doc }  -- | Convert a function in the 'Either' monad to a reader.-eitherReader :: (String -> Either String a) -> String -> ReadM a-eitherReader f = either readerError return . f+eitherReader :: (String -> Either String a) -> ReadM a+eitherReader f = readerAsk >>= either readerError return . f  -- | Specify the error to display when no argument is provided to this option. noArgError :: ParseError -> Mod OptionFields a@@ -209,7 +209,7 @@     rdr = uncurry CmdReader (mkCommand m)  -- | Builder for an argument parser.-argument :: (String -> Maybe a) -> Mod ArgumentFields a -> Parser a+argument :: ReadM a -> Mod ArgumentFields a -> Parser a argument p (Mod f d g) = mkParser d g (ArgReader rdr)   where     ArgumentFields compl = f (ArgumentFields mempty)@@ -260,7 +260,7 @@ -- the given parse error.  If you simply want to output a message, use -- 'infoOption' instead. abortOption :: ParseError -> Mod OptionFields (a -> a) -> Parser (a -> a)-abortOption err m = option (const (ReadM (Left err))) . (`mappend` m) $ mconcat+abortOption err m = option (readerAbort err) . (`mappend` m) $ mconcat   [ noArgError err   , value id   , metavar "" ]@@ -275,11 +275,11 @@  -- | Same as 'option'. {-# DEPRECATED nullOption "Use 'option' instead" #-}-nullOption :: (String -> ReadM a) -> Mod OptionFields a -> Parser a+nullOption :: ReadM a -> Mod OptionFields a -> Parser a nullOption = option  -- | Builder for an option using the 'auto' reader.-option :: (String -> ReadM a) -> Mod OptionFields a -> Parser a+option :: ReadM a -> Mod OptionFields a -> Parser a option r m = mkParser d g rdr   where     Mod f d g = metavar "ARG" `mappend` m
Options/Applicative/Common.hs view
@@ -51,7 +51,7 @@   ) where  import Control.Applicative (pure, (<*>), (<$>), (<|>), (<$))-import Control.Monad (guard, mzero, msum, when, liftM, MonadPlus)+import Control.Monad (guard, mzero, msum, when, liftM) import Control.Monad.Trans.Class (lift) import Control.Monad.Trans.State (StateT(..), get, put, runStateT) import Data.List (isPrefixOf)@@ -91,9 +91,9 @@ argMatches :: MonadP m => OptReader a -> String            -> Maybe (StateT Args m a) argMatches opt arg = case opt of-  ArgReader rdr -> do-    result <- crReader rdr arg-    Just $ return result+  ArgReader rdr -> Just $ do+    result <- lift $ runReadM (crReader rdr) arg+    return result   CmdReader _ f ->     flip fmap (f arg) $ \subp -> StateT $ \args -> do       setContext (Just arg) subp@@ -116,18 +116,14 @@       let missing_arg = lift $ missingArgP no_arg_err (crCompleter rdr)       (arg', args') <- maybe missing_arg return mb_args       put args'-      case runReadM (crReader rdr arg') of-        Left e -> lift $ errorFor arg1 e-        Right r -> return r+      lift $ runReadM (withReadM (errorFor arg1) (crReader rdr)) arg'   FlagReader names x -> do     guard $ has_name arg1 names     guard $ isNothing val     Just $ return x   _ -> Nothing   where-    errorFor name (ErrorMsg msg) =-      errorP (ErrorMsg ("option " ++ showOption name ++ ": " ++ msg))-    errorFor _ e = errorP e+    errorFor name msg = "option " ++ showOption name ++ ": " ++ msg      has_name a       | disambiguate = any (isOptionPrefix a)
Options/Applicative/Help/Chunk.hs view
@@ -37,6 +37,10 @@   pure = Chunk . pure   Chunk f <*> Chunk x = Chunk (f <*> x) +instance Alternative Chunk where+  empty = Chunk Control.Applicative.empty+  a <|> b = Chunk $ unChunk a <|> unChunk b+ instance Monad Chunk where   return = pure   m >>= f = Chunk $ unChunk m >>= unChunk . f
Options/Applicative/Help/Core.hs view
@@ -9,13 +9,13 @@   bodyHelp,   footerHelp,   parserHelp,-  parserUsage+  parserUsage,   ) where  import Control.Monad (guard) import Data.List (intersperse, sort) import Data.Maybe (maybeToList, catMaybes)-import Data.Monoid (Monoid, mempty, mappend)+import Data.Monoid (mempty, mappend)  import Options.Applicative.Common import Options.Applicative.Types
Options/Applicative/Internal.hs view
@@ -8,6 +8,8 @@   , uncons   , hoistMaybe   , hoistEither+  , runReadM+  , withReadM    , runP @@ -30,9 +32,9 @@ import Control.Monad (MonadPlus(..), liftM, ap, guard) import Control.Monad.Trans.Class (MonadTrans, lift) import Control.Monad.Trans.Except-  (runExceptT, ExceptT(..), throwE, catchE)+  (runExcept, runExceptT, withExcept, ExceptT(..), throwE, catchE) import Control.Monad.Trans.Reader-  (runReader, runReaderT, Reader, ReaderT, ask)+  (mapReaderT, runReader, runReaderT, Reader, ReaderT, ask) import Control.Monad.Trans.Writer (runWriterT, WriterT, tell) import Control.Monad.Trans.State (StateT, get, put, evalStateT) import Data.Maybe (maybeToList)@@ -42,7 +44,6 @@  class (Alternative m, MonadPlus m) => MonadP m where   setContext :: Maybe String -> ParserInfo a -> m ()-  setParser :: Maybe String -> Parser a -> m ()   getPrefs :: m ParserPrefs    missingArgP :: ParseError -> Completer -> m a@@ -87,7 +88,6 @@  instance MonadP P where   setContext name = P . lift . tell . Context (maybeToList name)-  setParser _ _ = return ()   getPrefs = P . lift . lift $ ask    missingArgP e _ = errorP e@@ -108,6 +108,15 @@ uncons [] = Nothing uncons (x : xs) = Just (x, xs) +runReadM :: MonadP m => ReadM a -> String -> m a+runReadM (ReadM r) s = hoistEither . runExcept $ runReaderT r s++withReadM :: (String -> String) -> ReadM a -> ReadM a+withReadM f = ReadM . mapReaderT (withExcept f') . unReadM+  where+    f' (ErrorMsg err) = ErrorMsg (f err)+    f' e = e+ data SomeParser = forall a . SomeParser (Parser a)  data ComplError@@ -157,7 +166,6 @@  instance MonadP Completion where   setContext _ _ = return ()-  setParser _ _ = return ()   getPrefs = Completion $ lift ask    missingArgP _ = Completion . lift . lift . ComplOption
Options/Applicative/Types.hs view
@@ -10,6 +10,7 @@   OptProperties(..),   OptVisibility(..),   ReadM(..),+  readerAsk,   readerAbort,   readerError,   CReader(..),@@ -41,6 +42,9 @@ import Control.Applicative   (Applicative(..), Alternative(..), (<$>), optional) import Control.Monad (ap, liftM, MonadPlus, mzero, mplus)+import Control.Monad.Trans.Except (Except, throwE)+import Control.Monad.Trans.Class (lift)+import Control.Monad.Trans.Reader (ReaderT, ask) import Data.Monoid (Monoid(..)) import System.Exit (ExitCode(..)) @@ -57,8 +61,8 @@  instance Monoid ParseError where   mempty = UnknownError-  mappend UnknownError m = m-  mappend m _ = m+  mappend m UnknownError = m+  mappend _ m = m  -- | A full description for a runnable 'Parser' for a program. data ParserInfo a = ParserInfo@@ -117,51 +121,54 @@ instance Functor Option where   fmap f (Option m p) = Option (fmap f m) p -data CReader m a = CReader-  { crCompleter :: Completer-  , crReader :: String -> m a }--instance Functor m => Functor (CReader m) where-  fmap f (CReader c r) = CReader c (fmap f . r)---- | A newtype over the 'Either' monad used by option readers.+-- | A newtype over 'ReaderT String Except', used by option readers. newtype ReadM a = ReadM-  { runReadM :: Either ParseError a }+  { unReadM :: ReaderT String (Except ParseError) a }  instance Functor ReadM where-  fmap f (ReadM m) = ReadM (fmap f m)+  fmap f (ReadM r) = ReadM (fmap f r)  instance Applicative ReadM where-  pure = ReadM . Right-  ReadM b <*> ReadM a = ReadM (b <*> a)+  pure = ReadM . pure+  ReadM x <*> ReadM y = ReadM $ x <*> y +instance Alternative ReadM where+  empty = mzero+  (<|>) = mplus+ instance Monad ReadM where-  return = ReadM . Right-  ReadM m >>= f = ReadM $ m >>= runReadM . f-  fail = ReadM . Left . ErrorMsg+  return = pure+  ReadM r >>= f = ReadM $ r >>= unReadM . f+  fail = readerError  instance MonadPlus ReadM where-  mzero = ReadM $ Left UnknownError-  mplus m1 m2 = case runReadM m1 of-    Left _ -> m2-    Right r -> return r+  mzero = ReadM mzero+  mplus (ReadM x) (ReadM y) = ReadM $ mplus x y +-- | Return the value being read.+readerAsk :: ReadM String+readerAsk = ReadM ask+ -- | Abort option reader by exiting with a 'ParseError'. readerAbort :: ParseError -> ReadM a-readerAbort = ReadM . Left+readerAbort = ReadM . lift . throwE  -- | Abort option reader by exiting with an error message. readerError :: String -> ReadM a readerError = readerAbort . ErrorMsg -type OptCReader = CReader ReadM-type ArgCReader = CReader Maybe+data CReader a = CReader+  { crCompleter :: Completer+  , crReader :: ReadM a } +instance Functor CReader where+  fmap f (CReader c r) = CReader c (fmap f r)+ -- | An 'OptReader' defines whether an option matches an command line argument. data OptReader a-  = OptReader [OptName] (OptCReader a) ParseError       -- ^ option reader+  = OptReader [OptName] (CReader a) ParseError          -- ^ option reader   | FlagReader [OptName] !a                             -- ^ flag reader-  | ArgReader (ArgCReader a)                            -- ^ argument reader+  | ArgReader (CReader a)                               -- ^ argument reader   | CmdReader [String] (String -> Maybe (ParserInfo a)) -- ^ command reader  instance Functor OptReader where
README.md view
@@ -4,9 +4,20 @@ parsers.  [![Continuous Integration status][status-png]][status]+[![Hackage page (downloads and API reference)][hackage-png]][hackage] -[Hackage page (downloads and documentation)][hackage]+**Table of Contents** +- [Getting started](#getting-started)+- [Supported options](#supported-options)+    - [Regular options](#regular-options)+    - [Flags](#flags)+    - [Arguments](#arguments)+    - [Commands](#commands)+- [Option builders](#option-builders)+- [Advanced features](#advanced-features)+- [How it works](#how-it-works)+ ## Getting started  Here is a simple example of an applicative option parser:@@ -336,8 +347,9 @@ See [this blog post][blog] for a more detailed explanation based on a simplified implementation. - [status-png]: https://secure.travis-ci.org/pcapriotti/optparse-applicative.png?branch=master+ [status-png]: https://api.travis-ci.org/pcapriotti/optparse-applicative.svg  [status]: http://travis-ci.org/pcapriotti/optparse-applicative?branch=master  [blog]: http://paolocapriotti.com/blog/2012/04/27/applicative-option-parser/  [builder-documentation]: http://hackage.haskell.org/package/optparse-applicative/docs/Options-Applicative-Builder.html- [hackage]: http://hackage.haskell.org/package/optparse-applicative-0.9.0+ [hackage-png]: http://img.shields.io/hackage/v/optparse-applicative.svg+ [hackage]: http://hackage.haskell.org/package/optparse-applicative
optparse-applicative.cabal view
@@ -1,5 +1,5 @@ name:                optparse-applicative-version:             0.10.0+version:             0.11.0 synopsis:            Utilities and combinators for parsing command line options description:     Here is a simple example of an applicative option parser: