packages feed

cmdlib 0.2.1 → 0.3

raw patch · 4 files changed

+103/−35 lines, 4 filesdep ~basePVP ok

version bump matches the API change (PVP)

Dependency ranges changed: base

API changes (from Hackage documentation)

- System.Console.CmdLib: RecordMode :: String -> Constr -> RecordMode cmd
- System.Console.CmdLib: data RecordMode cmd
- System.Console.CmdLib: rec_cmdname :: RecordMode cmd -> String
- System.Console.CmdLib: rec_initial :: RecordMode cmd -> Constr
+ System.Console.CmdLib: commandNames :: Bool -> [CommandWrap] -> [String]
+ System.Console.CmdLib: data CommandWrap
+ System.Console.CmdLib: dispatchOr :: (String -> IO ()) -> [DispatchOpt] -> [CommandWrap] -> [String] -> IO ()
+ System.Console.CmdLib: mode_help :: RecordCommand cmd => cmd -> String
- System.Console.CmdLib: (<%) :: (Keys keys) => Attribute -> keys -> AttributeMap Key
+ System.Console.CmdLib: (<%) :: Keys keys => Attribute -> keys -> AttributeMap Key
- System.Console.CmdLib: attributes :: (Attributes a) => a -> AttributeMap Key
+ System.Console.CmdLib: attributes :: Attributes a => a -> AttributeMap Key
- System.Console.CmdLib: class (Typeable a) => Data a
+ System.Console.CmdLib: class Typeable a => Data a
- System.Console.CmdLib: class (Data cmd) => RecordCommand cmd
+ System.Console.CmdLib: class Data cmd => RecordCommand cmd
- System.Console.CmdLib: cmd :: (Command cmd flag) => cmd
+ System.Console.CmdLib: cmd :: Command cmd flag => cmd
- System.Console.CmdLib: cmd_flag_empty :: (Command cmd flag) => cmd -> Folded flag
+ System.Console.CmdLib: cmd_flag_empty :: Command cmd flag => cmd -> Folded flag
- System.Console.CmdLib: cmdname :: (Command cmd flag) => cmd -> String
+ System.Console.CmdLib: cmdname :: Command cmd flag => cmd -> String
- System.Console.CmdLib: commandGroup :: (Commands a) => String -> a -> [CommandWrap]
+ System.Console.CmdLib: commandGroup :: Commands a => String -> a -> [CommandWrap]
- System.Console.CmdLib: data (Attributes adt) => ADT adt
+ System.Console.CmdLib: data Attributes adt => ADT adt
- System.Console.CmdLib: data (Attributes rec) => Record rec
+ System.Console.CmdLib: data Attributes rec => Record rec
- System.Console.CmdLib: dispatchR :: (Eq (Record cmd), Attributes cmd, RecordCommand cmd, Command (RecordMode cmd) f, (Folded f) ~ cmd) => [DispatchOpt] -> cmd -> [String] -> IO cmd
+ System.Console.CmdLib: dispatchR :: (Eq cmd, Eq (Record cmd), Attributes cmd, RecordCommand cmd, Command (RecordMode cmd) f, (Folded f) ~ cmd) => [DispatchOpt] -> [String] -> IO cmd
- System.Console.CmdLib: everywhere :: (Eq k) => Attribute -> AttributeMap k
+ System.Console.CmdLib: everywhere :: Eq k => Attribute -> AttributeMap k
- System.Console.CmdLib: execute :: (Command cmd f) => cmd -> [String] -> IO ()
+ System.Console.CmdLib: execute :: Command cmd f => cmd -> [String] -> IO ()
- System.Console.CmdLib: executeR :: (Eq (Record cmd), Attributes cmd, RecordCommand cmd) => cmd -> [String] -> IO cmd
+ System.Console.CmdLib: executeR :: (Eq cmd, Eq (Record cmd), Attributes cmd, RecordCommand cmd) => cmd -> [String] -> IO cmd
- System.Console.CmdLib: globalFlag :: a -> (a -> IO (), IO a)
+ System.Console.CmdLib: globalFlag :: Typeable a => a -> (a -> IO (), IO a)
- System.Console.CmdLib: group :: (AttributeMapLike k a) => String -> a -> AttributeMap k
+ System.Console.CmdLib: group :: AttributeMapLike k a => String -> a -> AttributeMap k
- System.Console.CmdLib: help :: (Command cmd flag) => cmd -> String
+ System.Console.CmdLib: help :: Command cmd flag => cmd -> String
- System.Console.CmdLib: helpOptions :: (Command cmd f) => cmd -> String
+ System.Console.CmdLib: helpOptions :: Command cmd f => cmd -> String
- System.Console.CmdLib: mode_summary :: (RecordCommand cmd) => cmd -> String
+ System.Console.CmdLib: mode_summary :: RecordCommand cmd => cmd -> String
- System.Console.CmdLib: optionStyle :: (Command cmd flag) => cmd -> OptionStyle
+ System.Console.CmdLib: optionStyle :: Command cmd flag => cmd -> OptionStyle
- System.Console.CmdLib: options :: (Command cmd flag) => cmd -> AttributeMap Key
+ System.Console.CmdLib: options :: Command cmd flag => cmd -> AttributeMap Key
- System.Console.CmdLib: readCommon :: (Data a) => String -> a
+ System.Console.CmdLib: readCommon :: Data a => String -> a
- System.Console.CmdLib: rec_options :: (RecordCommand cmd) => cmd -> AttributeMap Key
+ System.Console.CmdLib: rec_options :: RecordCommand cmd => cmd -> AttributeMap Key
- System.Console.CmdLib: recordCommands :: (Eq (Record cmd), Data cmd, RecordCommand cmd, Attributes cmd) => cmd -> [CommandWrap]
+ System.Console.CmdLib: recordCommands :: (Eq cmd, Eq (Record cmd), Data cmd, RecordCommand cmd, Attributes cmd) => cmd -> [CommandWrap]
- System.Console.CmdLib: run :: (Command cmd flag) => cmd -> Folded flag -> [String] -> IO ()
+ System.Console.CmdLib: run :: Command cmd flag => cmd -> Folded flag -> [String] -> IO ()
- System.Console.CmdLib: run' :: (RecordCommand cmd) => cmd -> [String] -> IO ()
+ System.Console.CmdLib: run' :: RecordCommand cmd => cmd -> [String] -> IO ()
- System.Console.CmdLib: summary :: (Command cmd flag) => cmd -> String
+ System.Console.CmdLib: summary :: Command cmd flag => cmd -> String
- System.Console.CmdLib: supercommand :: (Command cmd flag) => cmd -> Bool
+ System.Console.CmdLib: supercommand :: Command cmd flag => cmd -> Bool
- System.Console.CmdLib: synopsis :: (Command cmd flag) => cmd -> String
+ System.Console.CmdLib: synopsis :: Command cmd flag => cmd -> String

Files

System/Console/CmdLib.hs view
@@ -44,6 +44,14 @@ module System.Console.CmdLib (   -- * News   --+  -- | Since version 0.3: "dispatchR" no longer takes a cmd argument, as it was+  -- never used for anything and was simply confusing. A new function,+  -- "dispatchOr" has been added to allow the program to continue despite+  -- otherwise fatal errors (unknown command, unknown flags).  New function,+  -- "commandNames", has been added, to go from [CommandWrap] to [String]. The+  -- "CommandWrap" type is now exported (opaque).  The "RecordCommand" class+  -- now has a mode_help method. "RecordMode" is no longer exported.+  --   -- | Since version 0.2: The Positional arguments are no longer required to be   -- strings. A default (fallback) command may be provided to   -- "dispatch"/"dispatchR" (this has also incompatibly changed their@@ -66,21 +74,21 @@    -- | Flags (commandline options) can be represented in two basic styles,   -- either as a plain ADT (algebraic data type) or as a record type. These two-  -- styles are implemented using "ADTFlag" and "ADT" for the former and-  -- "RecordFlag" and "Record" for the latter. The *Flag classes can be used to-  -- attach attributes to flags and to override the parser for option-  -- arguments. However, an empty instance is valid for both cases. The "ADT"-  -- and "Record" newtype wrappers are then used in a "Command" or-  -- "RecordCommand" instance declaration.+  -- styles are implemented using the "ADT" wrapper for the former and and a+  -- "Record" wrapper for the latter. You need to make your type an instance of+  -- the "Attributes" class, which can be used to attach attributes to the+  -- flags.    , ADT, Record, Attributes(..)    -- * Commands-  , (%:), commandGroup, Command(..), dispatch, execute, helpCommands, helpOptions+  , (%:), commandGroup, Command(..), dispatch, dispatchOr, execute, helpCommands, helpOptions   , noHelp, defaultCommand, OptionStyle(..)+  , CommandWrap -- just the type (for signatures in users code)+  , commandNames    -- * Record-based commands-  , RecordCommand(..), RecordMode(..), recordCommands, dispatchR, executeR+  , RecordCommand(..), recordCommands, dispatchR, executeR    -- * Utilities   , globalFlag, readCommon, (<+<), HelpCommand(..), die@@ -109,11 +117,11 @@ -- > data Flag = Wibblify Int | Verbose Bool -- > (setVerbose, isVerbose) = globalFlag False -- >--- > instance ADTFlag Flag where--- >     adt_attrs _ = Verbose %> Global setVerbose+-- > instance Attributes Flag where+-- >     attributes _ = Verbose %> Global setVerbose -- > -- > putVerbose str = isVerbose >>= flip when (putStrLn str)-globalFlag :: a -> (a -> IO (), IO a)+globalFlag :: Typeable a => a -> (a -> IO (), IO a) globalFlag def = unsafePerformIO $ do ref <- newIORef def                                       return (writeIORef ref, readIORef ref) {-# NOINLINE globalFlag #-}
System/Console/CmdLib/Command.hs view
@@ -114,6 +114,16 @@         one (CommandGroup name l) = "\n" ++ name ++ ":\n" ++ helpCommands l         pad str = (take 15 $ str ++ replicate 15 ' ') ++ " " +-- | This could be used to implement a disambiguation function+--+-- Note that there isn't presently a notion of hidden commands,+-- but we're taking them into account now for future API stability+commandNames :: Bool -- ^ show hidden commands too+             -> [CommandWrap] -> [String]+commandNames _ x = concatMap one x+  where one (CommandWrap c) = [cmdname c]+        one (CommandGroup _ cs) = concatMap one cs+ execute' :: forall cmd f. (Command cmd f) => cmd -> [String] -> IO (Maybe (Folded f, [String])) execute' cmd opts   | "--help" `elem` opts && not (supercommand cmd) = printHelp cmd >> return Nothing@@ -191,11 +201,12 @@ printHelp c = putStr $ helpOptions c printCommands comms = putStr $ helpCommands comms -dispatch' :: [DispatchOpt] -> [CommandWrap] -> [String] -> IO (Maybe (CommandWrap, [String]))-dispatch' dopt comms' args = case args of+dispatch' :: (String -> IO ()) -- ^ fail+          -> [DispatchOpt] -> [CommandWrap] -> [String] -> IO (Maybe (CommandWrap, [String]))+dispatch' diefn dopt comms' args = case args of   [] | isNothing def -> dieHelp "Command required."      | otherwise -> return $ Just (fromJust def, [])-  ("--help":_) -> printCommands comms >> return Nothing+  ("--help":x) -> dispatch' diefn dopt comms' ("help":x)   (cmd:args') -> case findCommand cmd comms of     Nothing -> case def of       Nothing -> dieHelp $ "No such command " ++ cmd@@ -203,7 +214,7 @@     Just x -> return $ Just (x, args')   where comms | null [ () | NoHelp <- dopt ] = HelpCommand comms %: comms'               | otherwise = comms'-        dieHelp msg = printCommands comms >> die msg >> return Nothing+        dieHelp msg = printCommands comms >> diefn msg >> return Nothing         def | (DefaultCommand n:_) <- [ o | o@(DefaultCommand _) <- dopt ] = Just n             | otherwise = Nothing @@ -217,9 +228,16 @@ -- and transfer control to the command.  This function also implements the -- @help@ pseudocommand. dispatch :: [DispatchOpt] -> [CommandWrap] -> [String] -> IO ()-dispatch dopt comms opts = dispatch' dopt comms opts >>= \c -> case c of+dispatch = dispatchOr die++-- | Like 'dispatch' but with the ability to control what happens when there+--   is an error on user input+dispatchOr :: (String -> IO ()) -- ^ eg. 'die'+           -> [DispatchOpt] -> [CommandWrap] -> [String] -> IO ()+dispatchOr die dopt comms opts = dispatch' die dopt comms opts >>= \c -> case c of   Nothing -> return ()   Just (CommandWrap c, opts') -> execute c opts'+  -- | Helper for dying with an error message (nicely, at least compared to -- "fail" in IO).
System/Console/CmdLib/Record.hs view
@@ -38,7 +38,7 @@ -- TODO: List-based option types should be accumulated instead of overriden. data (Attributes rec) => Record rec = Record rec String deriving Eq -instance (Eq (Record rec), Data rec, Attributes rec) => FlagType (Record rec) where+instance (Eq rec, Eq (Record rec), Data rec, Attributes rec) => FlagType (Record rec) where   type Folded (Record rec) = rec    flag_attrkey (Record _ f) = KeyF (typeOf (undefined :: rec)) f@@ -68,7 +68,8 @@    flag_value (Record _ field) folded = getField field folded   flag_set (Record _ field) v = \x -> setField field x (errcast v)-     where errcast x = case cast x of+     where errcast :: (Typeable a, Typeable b) => a -> b+           errcast x = case cast x of                            Just x -> x                            Nothing -> error "BUG: flag_set in Record used with wrong value type" @@ -112,21 +113,26 @@   rec_options :: cmd -> AttributeMap Key   rec_options _ = EmptyMap -  -- | Provide a help string for each mode. Used in help output. Again, pattern-  -- match like in @run'@.+  -- | Provide a summary help string for each mode. Used in help output. Again,+  -- pattern match like in @run'@.   mode_summary :: cmd -> String   mode_summary _ = "" +  -- | Provide a help blurb for each mode. Use patterns like in @run'@.+  mode_help :: cmd -> String+  mode_help _ = ""+ data RecordMode cmd = RecordMode { rec_cmdname :: String                                  , rec_initial :: Constr }                     deriving (Typeable) -instance (Eq (Record cmd), RecordCommand cmd, Data cmd, Attributes cmd)+instance (Eq cmd, Eq (Record cmd), RecordCommand cmd, Data cmd, Attributes cmd)          => Command (RecordMode cmd) (Record cmd) where   cmdname = rec_cmdname   run _ = run'    summary cmd = mode_summary $ (fromConstr $ rec_initial cmd :: cmd)+  help cmd = mode_help $ (fromConstr $ rec_initial cmd :: cmd)    options cmd = rec_options ctor %% available %% everywhere disable     where available = [ (KeyF (typeOf (undefined :: cmd)) opt, [enable])@@ -136,8 +142,10 @@   cmd_flag_empty cmd = fromConstr $ rec_initial cmd  -- | Construct a command list (for "dispatch"/"helpCommands") from a--- multi-constructor record data type. See also "RecordCommand".-recordCommands :: forall cmd. (Eq (Record cmd), Data cmd, RecordCommand cmd, Attributes cmd) => cmd -> [CommandWrap]+-- multi-constructor record data type. See also "RecordCommand". Alternatively,+-- you can use "dispatchR" directly.+recordCommands :: forall cmd. (Eq cmd, Eq (Record cmd), Data cmd, RecordCommand cmd, Attributes cmd)+               => cmd -> [CommandWrap] recordCommands _ = go $ dataTypeConstrs $ dataTypeOf (undefined :: cmd)     where go = map $ CommandWrap . rec_cmd           rec_cmd :: Constr -> RecordMode cmd@@ -166,10 +174,16 @@           errcast :: forall a b. (Typeable a, Typeable b) => a -> b           errcast = fromMaybe (error $ "BUG: getField used with wrong type on " ++ field) . cast -dispatchR :: forall cmd f. (Eq (Record cmd), Attributes cmd, RecordCommand cmd,+-- | A command parsing & dispatch entry point for record-based+-- commands. Ex. (see "RecordCommand"):+--+-- > main = getArgs >>= dispatchR [] >>= \x -> case x of+-- >   Foo {} -> putStrLn $ "You asked for foo. Wibble = " ++ show (wibble x)+-- >   Bar {} -> putStrLn $ "You asked for bar. ..."+dispatchR :: forall cmd f. (Eq cmd, Eq (Record cmd), Attributes cmd, RecordCommand cmd,                             Command (RecordMode cmd) f,-                            Folded f ~ cmd) => [DispatchOpt] -> cmd -> [String] -> IO cmd-dispatchR dopt _ opts = dispatch' dopt (recordCommands (undefined :: cmd)) opts >>= \c -> case c of+                            Folded f ~ cmd) => [DispatchOpt] -> [String] -> IO cmd+dispatchR dopt opts = dispatch' die dopt (recordCommands (undefined :: cmd)) opts >>= \c -> case c of   Nothing -> exitWith ExitSuccess >> return undefined   Just (CommandWrap x, opts') -> execute' x opts' >>= \c -> case c of     Just (command, opts') -> case (cast command) of@@ -177,7 +191,17 @@       Nothing -> execute x opts' >> exitWith ExitSuccess >> return undefined     Nothing -> exitWith ExitSuccess >> return undefined -executeR :: forall cmd. (Eq (Record cmd), Attributes cmd, RecordCommand cmd) => cmd -> [String] -> IO cmd+-- | Like "execute", but you get the flags as a return value. This is useful to+-- implement non-modal applications with record-based flags, eg.:+--+-- > data Main = Main { greeting :: String, again :: Bool }+-- >     deriving (Typeable, Data, Eq)+-- > instance Attributes Main where -- (...)+-- > instance RecordCommand Main+-- > main = getArgs >>= executeR Main {} >>= \opts -> do+-- >    putStrLn (greeting opts) -- (...)+executeR :: forall cmd. (Eq cmd, Eq (Record cmd), Attributes cmd, RecordCommand cmd)+         => cmd -> [String] -> IO cmd executeR cmd opts = execute' cmd' opts >>= \c -> case c of   Just (command, _) -> return command   Nothing -> exitWith ExitSuccess >> return undefined
cmdlib.cabal view
@@ -1,12 +1,30 @@-name:                cmdlib-version:             0.2.1-synopsis:            a library for command line parsing & online help+name:        cmdlib+version:     0.3+synopsis:    a library for command line parsing & online help -description: An alternative to cmdargs, based on getopt. Comes with a powerful-             attribute system. Supports complex interfaces with many options-             and commands, with option & command grouping, while at the same-             time keeping simple things simple.+description: A commandline parsing library, based on getopt. Comes with a+             powerful attribute system. Supports complex interfaces with many+             options and commands, with option & command grouping, with simple+             and convenient API. Even though quite powerful, it strives to keep+             simple things simple. The library uses "System.Console.GetOpt" as+             its backend.+             .+             In comparison to the other commandline handling libraries:+             .+             Compared to cmdargs, cmdlib has a pure attribute system and is+             based on GetOpt for help formatting & argument parsing. Cmdlib may+             also be more extendable due to typeclass design, and can use+             user-supplied types for option arguments.+             .+             Cmdargs >= 0.4 can optionally use a pure attribute system,+             although this is clearly an add-on and the API is a second-class+             citizen in relation to the impure version.+             .+             GetOpt and parseargs both require explicit flag representation, so+             they live a level below cmdlib. GetOpt is in fact used as a+             backend by cmdlib. + -- The license under which the package is released. -- copyright: license:             BSD3@@ -35,7 +53,7 @@                  System.Console.CmdLib.ADTs                  System.Console.CmdLib.Record -  build-depends: base < 5, syb, mtl, split+  build-depends: base >= 4 && < 5, syb, mtl, split  flag test   default:     False