Safe Haskell | None |
---|---|
Language | Haskell2010 |
- withCli :: WithCli main => main -> IO ()
- class WithCli main
- class HasArguments a where
- atomicArgumentsParser :: forall a. Argument a => Modifiers -> Maybe String -> Result (Parser Unnormalized a)
- class Argument a where
- withCliModified :: WithCli main => [Modifier] -> main -> IO ()
- data Modifier
- class Generic a
- class Typeable k (a :: k)
- data Proxy k (t :: k) :: forall k. k -> * = Proxy
Documentation
withCli :: WithCli main => main -> IO () Source #
withCli
converts an IO operation into a program with a proper CLI.
Retrieves command line arguments through withArgs
.
main
(the given IO operation) can have arbitrarily many parameters
provided all parameters have instances for HasArguments
.
May throw the following exceptions:
in case of invalid options. Error messages are written toExitFailure
1stderr
.
in caseExitSuccess
--help
is given. (
behaves like a normal exception, except that -- if uncaught -- the process will exit with exit-codeExitSuccess
0
.) Help output is written tostdout
.
Example:
import WithCli main :: IO () main = withCli run run :: String -> Int -> Bool -> IO () run s i b = print (s, i, b)
Using the above program in a shell:
$ program foo 42 true ("foo",42,True) $ program --help program [OPTIONS] STRING INTEGER BOOL -h --help show help and exit $ program foo 42 bar cannot parse as BOOL: bar # exit-code 1 $ program missing argument of type STRING missing argument of type INTEGER missing argument of type BOOL # exit-code 1 $ program foo 42 yes bar unknown argument: bar # exit-code 1
Everything that can be used as a main
function with withCli
needs to
have an instance of WithCli
. You shouldn't need to implement your own
instances.
run
class HasArguments a where Source #
Everything that can be used as an argument to your main
function
(see withCli
) needs to have a HasArguments
instance.
HasArguments
also allows to conjure up instances for record types
to create more complex command line interfaces. Here's an example:
{-# LANGUAGE DeriveAnyClass #-} {-# LANGUAGE DeriveGeneric #-} import WithCli data Options = Options { port :: Int, daemonize :: Bool, config :: Maybe FilePath } deriving (Show, Generic, HasArguments) main :: IO () main = withCli run run :: Options -> IO () run = print
In a shell this program behaves like this:
$ program --port 8080 --config some/path Options {port = 8080, daemonize = False, config = Just "some/path"} $ program --port 8080 --daemonize Options {port = 8080, daemonize = True, config = Nothing} $ program --port foo cannot parse as INTEGER: foo # exit-code 1 $ program missing option: --port=INTEGER # exit-code 1 $ program --help program [OPTIONS] --port=INTEGER --daemonize --config=STRING (optional) -h --help show help and exit
argumentsParser :: Modifiers -> Maybe String -> Result (Parser Unnormalized a) Source #
argumentsParser :: (Generic a, GTo a, GDatatypeInfo a, All2 HasArguments (GCode a)) => Modifiers -> Maybe String -> Result (Parser Unnormalized a) Source #
HasArguments Bool Source # | |
HasArguments Double Source # | |
HasArguments Float Source # | |
HasArguments Int Source # | |
HasArguments String Source # | |
Argument a => HasArguments [a] Source # | |
Argument a => HasArguments (Maybe a) Source # | |
(HasArguments a, HasArguments b) => HasArguments (a, b) Source # | |
(HasArguments a, HasArguments b, HasArguments c) => HasArguments (a, b, c) Source # | |
atomicArgumentsParser :: forall a. Argument a => Modifiers -> Maybe String -> Result (Parser Unnormalized a) Source #
Useful for implementing your own instances of HasArguments
on top
of a custom Argument
instance.
class Argument a where Source #
Argument
is a typeclass for things that can be parsed as atomic values from
single command line arguments, e.g. strings (and filenames) and numbers.
Occasionally you might want to declare your own instance for additional type safety and for providing a more informative command argument type. Here's an example:
{-# LANGUAGE DeriveDataTypeable #-} import WithCli data File = File FilePath deriving (Show, Typeable) instance Argument File where argumentType Proxy = "custom-file-type" parseArgument f = Just (File f) instance HasArguments File where argumentsParser = atomicArgumentsParser main :: IO () main = withCli run run :: File -> IO () run = print
And this is how the above program behaves:
$ program --help program [OPTIONS] custom-file-type -h --help show help and exit $ program some/file File "some/file"
argumentType :: Proxy a -> String Source #
parseArgument :: String -> Maybe a Source #
Modifiers
Modifier
s can be used to customize the command line parser.
AddShortOption String Char |
|
RenameOption String String |
|
RenameOptions (String -> Maybe String) |
Can be used together with |
UseForPositionalArguments String String |
|
AddOptionHelp String String |
|
AddVersionFlag String |
|
Useful Re-exports
Representable types of kind *. This class is derivable in GHC with the DeriveGeneric flag on.
Generic Bool | |
Generic Ordering | |
Generic () | |
Generic Version | |
Generic ExitCode | |
Generic Fixity | |
Generic Associativity | |
Generic SourceUnpackedness | |
Generic SourceStrictness | |
Generic DecidedStrictness | |
Generic [a] | |
Generic (Maybe a) | |
Generic (Par1 p) | |
Generic (I a) | |
Generic (Either a b) | |
Generic (V1 k p) | |
Generic (U1 k p) | |
Generic (a, b) | |
Generic (Proxy k t) | |
Generic (Rec1 k f p) | |
Generic (URec k (Ptr ()) p) | |
Generic (URec k Char p) | |
Generic (URec k Double p) | |
Generic (URec k Float p) | |
Generic (URec k Int p) | |
Generic (URec k Word p) | |
Generic (a, b, c) | |
Generic (K k a b) | |
Generic (K1 k i c p) | |
Generic ((:+:) k f g p) | |
Generic ((:*:) k f g p) | |
Generic (a, b, c, d) | |
Generic (M1 k i c f p) | |
Generic ((:.:) k2 k1 f g p) | |
Generic (a, b, c, d, e) | |
Generic ((:.:) l k f g p) | |
Generic (a, b, c, d, e, f) | |
Generic (a, b, c, d, e, f, g) | |
The class Typeable
allows a concrete representation of a type to
be calculated.
typeRep#
data Proxy k (t :: k) :: forall k. k -> * #
A concrete, poly-kinded proxy type
Generic1 k (Proxy k) | |
Monad (Proxy *) | Since: 4.7.0.0 |
Functor (Proxy *) | Since: 4.7.0.0 |
Applicative (Proxy *) | Since: 4.7.0.0 |
Foldable (Proxy *) | Since: 4.7.0.0 |
Traversable (Proxy *) | Since: 4.7.0.0 |
Alternative (Proxy *) | Since: 4.9.0.0 |
MonadPlus (Proxy *) | Since: 4.9.0.0 |
Bounded (Proxy k t) | |
Enum (Proxy k s) | Since: 4.7.0.0 |
Eq (Proxy k s) | Since: 4.7.0.0 |
Ord (Proxy k s) | Since: 4.7.0.0 |
Read (Proxy k s) | Since: 4.7.0.0 |
Show (Proxy k s) | Since: 4.7.0.0 |
Ix (Proxy k s) | Since: 4.7.0.0 |
Generic (Proxy k t) | |
Monoid (Proxy k s) | Since: 4.7.0.0 |
type Rep1 k (Proxy k) | |
type Rep (Proxy k t) | |
type Code (Proxy * t) | |
type DatatypeInfoOf (Proxy * t) | |