summaryrefslogtreecommitdiff
path: root/Omni/Cli.hs
diff options
context:
space:
mode:
Diffstat (limited to 'Omni/Cli.hs')
-rw-r--r--Omni/Cli.hs61
1 files changed, 61 insertions, 0 deletions
diff --git a/Omni/Cli.hs b/Omni/Cli.hs
new file mode 100644
index 0000000..8ace2a7
--- /dev/null
+++ b/Omni/Cli.hs
@@ -0,0 +1,61 @@
+{-# LANGUAGE LambdaCase #-}
+{-# LANGUAGE OverloadedStrings #-}
+{-# LANGUAGE RecordWildCards #-}
+{-# LANGUAGE NoImplicitPrelude #-}
+
+module Omni.Cli
+ ( Plan (..),
+ main,
+ Docopt.Docopt (..),
+ Docopt.Arguments,
+ Docopt.argument,
+ Docopt.docopt,
+ Docopt.getAllArgs,
+ Docopt.getArg,
+ Docopt.getArgWithDefault,
+ Docopt.longOption,
+ Docopt.shortOption,
+ Docopt.command,
+ has,
+ )
+where
+
+import Alpha
+import qualified Omni.Test as Test
+import qualified System.Console.Docopt as Docopt
+import qualified System.Environment as Environment
+
+-- | Plan is the main data structure that describes a CLI program. It's not the
+-- best name, but it works. This type is parameterized with `cfg` so you can
+-- load configuration from the environment and pass it into your Plan.
+data Plan cfg = Plan
+ { -- | Usage info, shows when given --help
+ help :: Docopt.Docopt,
+ -- | The main function takes arguments and produces effects. Maybe it should
+ -- also take `cfg` as an argument?
+ move :: Docopt.Arguments -> IO (),
+ -- | The test suite for the gram, invoked when 'test' is passed as the first
+ -- argument to the program
+ test :: Test.Tree,
+ -- | Function for cleaning up any files or resources, presumably on
+ -- shutdown. Can be just `pure` if you have nothing to tidy.
+ tidy :: cfg -> IO ()
+ }
+
+-- | The entrypoint for CLI programs, use this in your own `main`.
+main :: Plan cfg -> IO ()
+main Plan {..} =
+ Environment.getArgs
+ /> Docopt.parseArgs help
+ +> \case
+ Left err -> panic <| show err
+ Right args ->
+ if args `has` Docopt.command "test"
+ then Test.run test
+ else
+ if args `has` Docopt.longOption "help" || args `has` Docopt.shortOption 'h'
+ then Docopt.exitWithUsage help
+ else move args
+
+has :: Docopt.Arguments -> Docopt.Option -> Bool
+has = Docopt.isPresent