]> gitweb.michael.orlitzky.com - haeredes.git/blobdiff - src/CommandLine.hs
test/Doctests.hs: support new Cabal autogen path in doctests.
[haeredes.git] / src / CommandLine.hs
index b489c7eb686670f7bfa7d515be99d3ff509513dc..5539605df406d64e428aed128a388418fd0c8f6a 100644 (file)
@@ -2,26 +2,27 @@
 
 module CommandLine (
   Args(..),
-  get_args
-  )
+  get_args )
 where
 
 import System.Console.CmdArgs (
+  Ann,
+  Annotate( (:=) ),
   Data,
-  Typeable,
-  (&=),
+  (+=),
   args,
   auto,
-  cmdArgs,
+  cmdArgs_,
   def,
   details,
   explicit,
   groupname,
   help,
   helpArg,
-  modes,
+  modes_,
   name,
   program,
+  record,
   summary,
   typ,
   versionArg )
@@ -30,92 +31,135 @@ import System.Console.CmdArgs (
 import Paths_haeredes (version)
 import Data.Version (showVersion)
 
+import Timeout (Timeout(seconds))
+
+
 -- | Description of the 'NS' mode.
+--
 ns_description :: String
 ns_description =
   "Confirm delegation of NS records. " ++
   "This is the default mode."
 
+
 -- | Description of the 'MX' mode.
+--
 mx_description :: String
 mx_description = "Confirm delegation of MX records."
 
+
+-- | The name of the program, appears in the \"help\" output.
+--
 program_name :: String
 program_name = "haeredes"
 
+
+-- | A short summary (program name and version) that are output
+--   as part of the help.
+--
 my_summary :: String
 my_summary = program_name ++ "-" ++ (showVersion version)
 
+
+-- | Description of the --no-append-root flag.
+--
 no_append_root_help :: String
 no_append_root_help =
   "Don't append a trailing dot to DNS names"
 
--- | Help string for the --server flag.
+
+-- | Description of the --server flag.
+--
 server_help :: String
 server_help =
   "IP address or hostname of server to query " ++
   "(will use resolv.conf if not specified)"
 
--- | The Args type represents the possible command-line options. The
---   duplication here seems necessary; CmdArgs' magic requires us to
+
+-- | Description of the --timeout flag.
+--
+timeout_help :: String
+timeout_help =
+  "Query timeout, in seconds (default: " ++ defstr ++ ")"
+  where
+    defstr = show $ seconds (def :: Timeout)
+
+
+-- | The 'Args' type represents the possible command-line options. The
+--   duplication here seems necessary; CmdArgs's magic requires us to
 --   define some things explicitly.
+--
 data Args =
   NS { no_append_root :: Bool,
        server :: Maybe String,
+       timeout :: Timeout,
        delegates :: [String] } |
   MX { no_append_root :: Bool,
        server :: Maybe String,
+       timeout :: Timeout,
        delegates :: [String] }
-  deriving (Data, Show, Typeable)
+  deriving (Data, Show)
 
-arg_spec :: Args
+
+
+-- | The big argument specification. We use explicit annotation here
+--   because otherwise there's come CmdArgs magic going on that
+--   requires us to specify /all/ of the arguments for /each/ mode;
+--   i.e. we have to duplicate all of them for both 'NS' and 'MX.
+--
+--   This is slightly arcane but at least it doesn't repeat yoself.
+--
+arg_spec :: Annotate Ann
 arg_spec =
-  modes [ns &= auto, mx]
-    &= program program_name
-    &= summary my_summary
-    &= helpArg [explicit,
+  modes_ [ns += auto, mx]
+    += program program_name
+    += summary my_summary
+    += helpArg [explicit,
                 name "help",
                 name "h",
                 groupname "Common flags"]
-    &= versionArg [explicit,
+    += versionArg [explicit,
                    name "version",
                    name "v",
                    groupname "Common flags"]
   where
-    -- The repetition here is necessary, some CmdArgs magic going on.
-    ns :: Args
-    ns = NS {
-           no_append_root = def
-                         &= groupname "Common flags"
-                         &= help no_append_root_help,
-
-           server = def
-                 &= groupname "Common flags"
-                 &= typ "IP"
-                 &= help server_help,
-
-           delegates = def
-                    &= args
-                    &= typ "DELEGATES" }
-
-            &= details [ns_description]
-
-    mx :: Args
-    mx = MX {
-           no_append_root = def
-                         &= groupname "Common flags"
-                         &= help no_append_root_help,
-
-           server = def
-                 &= groupname "Common flags"
-                 &= typ "IP"
-                 &= help server_help,
-
-           delegates = def
-                    &= args
-                    &= typ "DELEGATES" }
-
-            &= details [mx_description]
-
+    -- | Create a mode, adding all of the common flags to it
+    --   automatically. The big ugly type of the first argument is
+    --   simply the type of our NS/MX constructors.
+    --
+    make_mode :: (Bool -> Maybe String -> Timeout -> [String] -> Args)
+              -> String
+              -> (Annotate Ann)
+    make_mode ctor desc =
+      record (ctor def def def def) [
+        no_append_root := def
+                       += groupname "Common flags"
+                       += help no_append_root_help,
+
+        server := def
+               += groupname "Common flags"
+               += typ "IP"
+               += help server_help,
+
+        timeout := def
+                += groupname "Common flags"
+                += typ "SECONDS"
+                += help timeout_help,
+
+        delegates := def
+                  += args
+                  += typ "DELEGATES" ]
+        += details ["  " ++ desc]
+
+
+    -- Here we just create the NS/MX modes using our make_mode from above.
+    ns = make_mode NS ns_description
+    mx = make_mode MX mx_description
+
+
+
+-- | This is the public interface; i.e. what 'main' should use to get
+--   the command-line arguments.
+--
 get_args :: IO Args
-get_args = cmdArgs arg_spec
+get_args = cmdArgs_ arg_spec