From ce207617f5d71f82926a1b1335f62d6ddd93b4aa Mon Sep 17 00:00:00 2001
From: Iustin Pop <iustin@google.com>
Date: Tue, 25 Sep 2012 11:33:13 +0200
Subject: [PATCH] Annotate options with completion information

This is a quite boring patch, just adding annotation information to
all existing options. Some of the annotations are not very good; but
we don't have support for more precise completion in
build-bash-completion, so this is good enough.

Signed-off-by: Iustin Pop <iustin@google.com>
Reviewed-by: Agata Murawska <agatamurawska@google.com>
---
 htest/Test/Ganeti/Common.hs |   4 +-
 htools/Ganeti/Common.hs     |  16 +-
 htools/Ganeti/Daemon.hs     |  60 +++---
 htools/Ganeti/HTools/CLI.hs | 377 +++++++++++++++++++++---------------
 4 files changed, 272 insertions(+), 185 deletions(-)

diff --git a/htest/Test/Ganeti/Common.hs b/htest/Test/Ganeti/Common.hs
index 6c2e3f29a..37d975d3c 100644
--- a/htest/Test/Ganeti/Common.hs
+++ b/htest/Test/Ganeti/Common.hs
@@ -58,7 +58,7 @@ checkOpt :: (StandardOptions b) =>
                                           -- from the options
          -> c
 checkOpt repr defaults failfn eqcheck valfn
-         (val, opt@(GetOpt.Option _ longs _ _), fn) =
+         (val, opt@(GetOpt.Option _ longs _ _, _), fn) =
   case longs of
     [] -> failfn "no long options?"
     cmdarg:_ ->
@@ -79,7 +79,7 @@ passFailOpt :: (StandardOptions b) =>
             -- ^ The list of enabled options, fail value and pass value
             -> c
 passFailOpt defaults failfn passfn
-              (opt@(GetOpt.Option _ longs _ _), bad, good) =
+              (opt@(GetOpt.Option _ longs _ _, _), bad, good) =
   let prefix = "--" ++ head longs ++ "="
       good_cmd = prefix ++ good
       bad_cmd = prefix ++ bad in
diff --git a/htools/Ganeti/Common.hs b/htools/Ganeti/Common.hs
index 379e63f1d..f300205d2 100644
--- a/htools/Ganeti/Common.hs
+++ b/htools/Ganeti/Common.hs
@@ -76,7 +76,7 @@ optComplYesNo :: OptCompletion
 optComplYesNo = OptComplChoices ["yes", "no"]
 
 -- | Abrreviation for the option type.
-type GenericOptType a = OptDescr (a -> Result a)
+type GenericOptType a = (OptDescr (a -> Result a), OptCompletion)
 
 -- | Type class for options which support help and version.
 class StandardOptions a where
@@ -87,18 +87,20 @@ class StandardOptions a where
 
 -- | Options to request help output.
 oShowHelp :: (StandardOptions a) => GenericOptType a
-oShowHelp = Option "h" ["help"] (NoArg (Ok . requestHelp))
-            "show help"
+oShowHelp = (Option "h" ["help"] (NoArg (Ok . requestHelp)) "show help",
+             OptComplNone)
 
+-- | Option to request version information.
 oShowVer :: (StandardOptions a) => GenericOptType a
-oShowVer = Option "V" ["version"] (NoArg (Ok . requestVer))
-           "show the version of the program"
+oShowVer = (Option "V" ["version"] (NoArg (Ok . requestVer))
+            "show the version of the program",
+            OptComplNone)
 
 -- | Usage info.
 usageHelp :: String -> [GenericOptType a] -> String
 usageHelp progname =
   usageInfo (printf "%s %s\nUsage: %s [OPTION...]"
-             progname Version.version progname)
+             progname Version.version progname) . map fst
 
 -- | Show the program version info.
 versionInfo :: String -> String
@@ -155,7 +157,7 @@ parseOptsInner :: (StandardOptions a) =>
                -> [GenericOptType a]
                -> Either (ExitCode, String) (a, [String])
 parseOptsInner defaults argv progname options  =
-  case getOpt Permute options argv of
+  case getOpt Permute (map fst options) argv of
     (opts, args, []) ->
       case foldM (flip id) defaults opts of
            Bad msg -> Left (ExitFailure 1,
diff --git a/htools/Ganeti/Daemon.hs b/htools/Ganeti/Daemon.hs
index a3330d784..852e59538 100644
--- a/htools/Ganeti/Daemon.hs
+++ b/htools/Ganeti/Daemon.hs
@@ -114,40 +114,52 @@ type OptType = GenericOptType DaemonOptions
 -- * Command line options
 
 oNoDaemonize :: OptType
-oNoDaemonize = Option "f" ["foreground"]
-               (NoArg (\ opts -> Ok opts { optDaemonize = False}))
-               "Don't detach from the current terminal"
+oNoDaemonize =
+  (Option "f" ["foreground"]
+   (NoArg (\ opts -> Ok opts { optDaemonize = False}))
+   "Don't detach from the current terminal",
+   OptComplNone)
 
 oDebug :: OptType
-oDebug = Option "d" ["debug"]
-         (NoArg (\ opts -> Ok opts { optDebug = True }))
-         "Enable debug messages"
+oDebug =
+  (Option "d" ["debug"]
+   (NoArg (\ opts -> Ok opts { optDebug = True }))
+   "Enable debug messages",
+   OptComplNone)
 
 oNoUserChecks :: OptType
-oNoUserChecks = Option "" ["no-user-checks"]
-         (NoArg (\ opts -> Ok opts { optNoUserChecks = True }))
-         "Ignore user checks"
+oNoUserChecks =
+  (Option "" ["no-user-checks"]
+   (NoArg (\ opts -> Ok opts { optNoUserChecks = True }))
+   "Ignore user checks",
+   OptComplNone)
 
 oPort :: Int -> OptType
-oPort def = Option "p" ["port"]
-            (reqWithConversion (tryRead "reading port")
-             (\port opts -> Ok opts { optPort = Just port }) "PORT")
-            ("Network port (default: " ++ show def ++ ")")
+oPort def =
+  (Option "p" ["port"]
+   (reqWithConversion (tryRead "reading port")
+    (\port opts -> Ok opts { optPort = Just port }) "PORT")
+   ("Network port (default: " ++ show def ++ ")"),
+   OptComplNumeric)
 
 oBindAddress :: OptType
-oBindAddress = Option "b" ["bind"]
-               (ReqArg (\addr opts -> Ok opts { optBindAddress = Just addr })
-                "ADDR")
-               "Bind address (default depends on cluster configuration)"
+oBindAddress =
+  (Option "b" ["bind"]
+   (ReqArg (\addr opts -> Ok opts { optBindAddress = Just addr })
+    "ADDR")
+   "Bind address (default depends on cluster configuration)",
+   OptComplInetAddr)
 
 oSyslogUsage :: OptType
-oSyslogUsage = Option "" ["syslog"]
-               (reqWithConversion syslogUsageFromRaw
-                (\su opts -> Ok opts { optSyslogUsage = Just su })
-                "SYSLOG")
-               ("Enable logging to syslog (except debug \
-                \messages); one of 'no', 'yes' or 'only' [" ++ C.syslogUsage ++
-                "]")
+oSyslogUsage =
+  (Option "" ["syslog"]
+   (reqWithConversion syslogUsageFromRaw
+    (\su opts -> Ok opts { optSyslogUsage = Just su })
+    "SYSLOG")
+   ("Enable logging to syslog (except debug \
+    \messages); one of 'no', 'yes' or 'only' [" ++ C.syslogUsage ++
+    "]"),
+   OptComplChoices ["yes", "no", "only"])
 
 -- | Generic options.
 genericOpts :: [OptType]
diff --git a/htools/Ganeti/HTools/CLI.hs b/htools/Ganeti/HTools/CLI.hs
index 4c03c25b3..e10a43b8c 100644
--- a/htools/Ganeti/HTools/CLI.hs
+++ b/htools/Ganeti/HTools/CLI.hs
@@ -211,229 +211,302 @@ parseISpecString descr inp = do
     [dsk, ram, cpu] -> return $ RSpec cpu ram dsk
     _ -> err
 
+-- | Disk template choices.
+optComplDiskTemplate :: OptCompletion
+optComplDiskTemplate = OptComplChoices $
+                       map diskTemplateToRaw [minBound..maxBound]
+
 -- * Command line options
 
 oDataFile :: OptType
-oDataFile = Option "t" ["text-data"]
-            (ReqArg (\ f o -> Ok o { optDataFile = Just f }) "FILE")
-            "the cluster data FILE"
+oDataFile =
+  (Option "t" ["text-data"]
+   (ReqArg (\ f o -> Ok o { optDataFile = Just f }) "FILE")
+   "the cluster data FILE",
+   OptComplFile)
 
 oDiskMoves :: OptType
-oDiskMoves = Option "" ["no-disk-moves"]
-             (NoArg (\ opts -> Ok opts { optDiskMoves = False}))
-             "disallow disk moves from the list of allowed instance changes,\
-             \ thus allowing only the 'cheap' failover/migrate operations"
+oDiskMoves =
+  (Option "" ["no-disk-moves"]
+   (NoArg (\ opts -> Ok opts { optDiskMoves = False}))
+   "disallow disk moves from the list of allowed instance changes,\
+   \ thus allowing only the 'cheap' failover/migrate operations",
+   OptComplNone)
 
 oDiskTemplate :: OptType
-oDiskTemplate = Option "" ["disk-template"]
-                (reqWithConversion diskTemplateFromRaw
-                 (\dt opts -> Ok opts { optDiskTemplate = Just dt })
-                 "TEMPLATE") "select the desired disk template"
+oDiskTemplate =
+  (Option "" ["disk-template"]
+   (reqWithConversion diskTemplateFromRaw
+    (\dt opts -> Ok opts { optDiskTemplate = Just dt })
+    "TEMPLATE") "select the desired disk template",
+   optComplDiskTemplate)
 
 oSpindleUse :: OptType
-oSpindleUse = Option "" ["spindle-use"]
-              (reqWithConversion (tryRead "parsing spindle-use")
-               (\su opts -> do
-                  when (su < 0) $
-                       fail "Invalid value of the spindle-use\
-                            \ (expected >= 0)"
-                  return $ opts { optSpindleUse = Just su })
-               "SPINDLES") "select how many virtual spindle instances use\
-                           \ [default read from cluster]"
+oSpindleUse =
+  (Option "" ["spindle-use"]
+   (reqWithConversion (tryRead "parsing spindle-use")
+    (\su opts -> do
+       when (su < 0) $
+            fail "Invalid value of the spindle-use (expected >= 0)"
+       return $ opts { optSpindleUse = Just su })
+    "SPINDLES") "select how many virtual spindle instances use\
+                \ [default read from cluster]",
+   OptComplNumeric)
 
 oSelInst :: OptType
-oSelInst = Option "" ["select-instances"]
-          (ReqArg (\ f opts -> Ok opts { optSelInst = sepSplit ',' f }) "INSTS")
-          "only select given instances for any moves"
+oSelInst =
+  (Option "" ["select-instances"]
+   (ReqArg (\ f opts -> Ok opts { optSelInst = sepSplit ',' f }) "INSTS")
+   "only select given instances for any moves",
+   OptComplManyInstances)
 
 oInstMoves :: OptType
-oInstMoves = Option "" ["no-instance-moves"]
-             (NoArg (\ opts -> Ok opts { optInstMoves = False}))
-             "disallow instance (primary node) moves from the list of allowed,\
-             \ instance changes, thus allowing only slower, but sometimes\
-             \ safer, drbd secondary changes"
+oInstMoves =
+  (Option "" ["no-instance-moves"]
+   (NoArg (\ opts -> Ok opts { optInstMoves = False}))
+   "disallow instance (primary node) moves from the list of allowed,\
+   \ instance changes, thus allowing only slower, but sometimes\
+   \ safer, drbd secondary changes",
+   OptComplNone)
 
 oDynuFile :: OptType
-oDynuFile = Option "U" ["dynu-file"]
-            (ReqArg (\ f opts -> Ok opts { optDynuFile = Just f }) "FILE")
-            "Import dynamic utilisation data from the given FILE"
+oDynuFile =
+  (Option "U" ["dynu-file"]
+   (ReqArg (\ f opts -> Ok opts { optDynuFile = Just f }) "FILE")
+   "Import dynamic utilisation data from the given FILE",
+   OptComplFile)
 
 oEvacMode :: OptType
-oEvacMode = Option "E" ["evac-mode"]
-            (NoArg (\opts -> Ok opts { optEvacMode = True }))
-            "enable evacuation mode, where the algorithm only moves \
-            \ instances away from offline and drained nodes"
+oEvacMode =
+  (Option "E" ["evac-mode"]
+   (NoArg (\opts -> Ok opts { optEvacMode = True }))
+   "enable evacuation mode, where the algorithm only moves \
+   \ instances away from offline and drained nodes",
+   OptComplNone)
 
 oExInst :: OptType
-oExInst = Option "" ["exclude-instances"]
-          (ReqArg (\ f opts -> Ok opts { optExInst = sepSplit ',' f }) "INSTS")
-          "exclude given instances from any moves"
+oExInst =
+  (Option "" ["exclude-instances"]
+   (ReqArg (\ f opts -> Ok opts { optExInst = sepSplit ',' f }) "INSTS")
+   "exclude given instances from any moves",
+   OptComplManyInstances)
 
 oExTags :: OptType
-oExTags = Option "" ["exclusion-tags"]
-            (ReqArg (\ f opts -> Ok opts { optExTags = Just $ sepSplit ',' f })
-             "TAG,...") "Enable instance exclusion based on given tag prefix"
+oExTags =
+  (Option "" ["exclusion-tags"]
+   (ReqArg (\ f opts -> Ok opts { optExTags = Just $ sepSplit ',' f })
+    "TAG,...") "Enable instance exclusion based on given tag prefix",
+   OptComplString)
 
 oExecJobs :: OptType
-oExecJobs = Option "X" ["exec"]
-             (NoArg (\ opts -> Ok opts { optExecJobs = True}))
-             "execute the suggested moves via Luxi (only available when using\
-             \ it for data gathering)"
+oExecJobs =
+  (Option "X" ["exec"]
+   (NoArg (\ opts -> Ok opts { optExecJobs = True}))
+   "execute the suggested moves via Luxi (only available when using\
+   \ it for data gathering)",
+   OptComplNone)
 
 oGroup :: OptType
-oGroup = Option "G" ["group"]
-            (ReqArg (\ f o -> Ok o { optGroup = Just f }) "ID")
-            "the ID of the group to balance"
+oGroup =
+  (Option "G" ["group"]
+   (ReqArg (\ f o -> Ok o { optGroup = Just f }) "ID")
+   "the ID of the group to balance",
+   OptComplOneGroup)
 
 oIAllocSrc :: OptType
-oIAllocSrc = Option "I" ["ialloc-src"]
-             (ReqArg (\ f opts -> Ok opts { optIAllocSrc = Just f }) "FILE")
-             "Specify an iallocator spec as the cluster data source"
+oIAllocSrc =
+  (Option "I" ["ialloc-src"]
+   (ReqArg (\ f opts -> Ok opts { optIAllocSrc = Just f }) "FILE")
+   "Specify an iallocator spec as the cluster data source",
+   OptComplFile)
 
 oLuxiSocket :: OptType
-oLuxiSocket = Option "L" ["luxi"]
-              (OptArg ((\ f opts -> Ok opts { optLuxi = Just f }) .
-                       fromMaybe Path.defaultLuxiSocket) "SOCKET")
-              "collect data via Luxi, optionally using the given SOCKET path"
+oLuxiSocket =
+  (Option "L" ["luxi"]
+   (OptArg ((\ f opts -> Ok opts { optLuxi = Just f }) .
+            fromMaybe Path.defaultLuxiSocket) "SOCKET")
+   "collect data via Luxi, optionally using the given SOCKET path",
+   OptComplFile)
 
 oMachineReadable :: OptType
-oMachineReadable = Option "" ["machine-readable"]
-                   (OptArg (\ f opts -> do
-                     flag <- parseYesNo True f
-                     return $ opts { optMachineReadable = flag }) "CHOICE")
-          "enable machine readable output (pass either 'yes' or 'no' to\
-          \ explicitly control the flag, or without an argument defaults to\
-          \ yes"
+oMachineReadable =
+  (Option "" ["machine-readable"]
+   (OptArg (\ f opts -> do
+              flag <- parseYesNo True f
+              return $ opts { optMachineReadable = flag }) "CHOICE")
+   "enable machine readable output (pass either 'yes' or 'no' to\
+   \ explicitly control the flag, or without an argument defaults to\
+   \ yes",
+   optComplYesNo)
 
 oMaxCpu :: OptType
-oMaxCpu = Option "" ["max-cpu"]
-          (reqWithConversion (tryRead "parsing max-cpu")
-           (\mcpu opts -> do
-              when (mcpu <= 0) $
-                   fail "Invalid value of the max-cpu ratio,\
-                        \ expected >0"
-              return $ opts { optMcpu = Just mcpu }) "RATIO")
-          "maximum virtual-to-physical cpu ratio for nodes (from 0\
-          \ upwards) [default read from cluster]"
+oMaxCpu =
+  (Option "" ["max-cpu"]
+   (reqWithConversion (tryRead "parsing max-cpu")
+    (\mcpu opts -> do
+       when (mcpu <= 0) $
+            fail "Invalid value of the max-cpu ratio, expected >0"
+       return $ opts { optMcpu = Just mcpu }) "RATIO")
+   "maximum virtual-to-physical cpu ratio for nodes (from 0\
+   \ upwards) [default read from cluster]",
+   OptComplNumeric)
 
 oMaxSolLength :: OptType
-oMaxSolLength = Option "l" ["max-length"]
-                (reqWithConversion (tryRead "max solution length")
-                 (\i opts -> Ok opts { optMaxLength = i }) "N")
-                "cap the solution at this many balancing or allocation \
-                \ rounds (useful for very unbalanced clusters or empty \
-                \ clusters)"
+oMaxSolLength =
+  (Option "l" ["max-length"]
+   (reqWithConversion (tryRead "max solution length")
+    (\i opts -> Ok opts { optMaxLength = i }) "N")
+   "cap the solution at this many balancing or allocation \
+   \ rounds (useful for very unbalanced clusters or empty \
+   \ clusters)",
+   OptComplNumeric)
 
 oMinDisk :: OptType
-oMinDisk = Option "" ["min-disk"]
-           (reqWithConversion (tryRead "min free disk space")
-            (\n opts -> Ok opts { optMdsk = n }) "RATIO")
-           "minimum free disk space for nodes (between 0 and 1) [0]"
+oMinDisk =
+  (Option "" ["min-disk"]
+   (reqWithConversion (tryRead "min free disk space")
+    (\n opts -> Ok opts { optMdsk = n }) "RATIO")
+   "minimum free disk space for nodes (between 0 and 1) [0]",
+   OptComplNumeric)
 
 oMinGain :: OptType
-oMinGain = Option "g" ["min-gain"]
-           (reqWithConversion (tryRead "min gain")
-            (\g opts -> Ok opts { optMinGain = g }) "DELTA")
-            "minimum gain to aim for in a balancing step before giving up"
+oMinGain =
+  (Option "g" ["min-gain"]
+   (reqWithConversion (tryRead "min gain")
+    (\g opts -> Ok opts { optMinGain = g }) "DELTA")
+   "minimum gain to aim for in a balancing step before giving up",
+   OptComplNumeric)
 
 oMinGainLim :: OptType
-oMinGainLim = Option "" ["min-gain-limit"]
-            (reqWithConversion (tryRead "min gain limit")
-             (\g opts -> Ok opts { optMinGainLim = g }) "SCORE")
-            "minimum cluster score for which we start checking the min-gain"
+oMinGainLim =
+  (Option "" ["min-gain-limit"]
+   (reqWithConversion (tryRead "min gain limit")
+    (\g opts -> Ok opts { optMinGainLim = g }) "SCORE")
+   "minimum cluster score for which we start checking the min-gain",
+   OptComplNumeric)
 
 oMinScore :: OptType
-oMinScore = Option "e" ["min-score"]
-            (reqWithConversion (tryRead "min score")
-             (\e opts -> Ok opts { optMinScore = e }) "EPSILON")
-            "mininum score to aim for"
+oMinScore =
+  (Option "e" ["min-score"]
+   (reqWithConversion (tryRead "min score")
+    (\e opts -> Ok opts { optMinScore = e }) "EPSILON")
+   "mininum score to aim for",
+   OptComplNumeric)
 
 oNoHeaders :: OptType
-oNoHeaders = Option "" ["no-headers"]
-             (NoArg (\ opts -> Ok opts { optNoHeaders = True }))
-             "do not show a header line"
+oNoHeaders =
+  (Option "" ["no-headers"]
+   (NoArg (\ opts -> Ok opts { optNoHeaders = True }))
+   "do not show a header line",
+   OptComplNone)
 
 oNoSimulation :: OptType
-oNoSimulation = Option "" ["no-simulation"]
-                (NoArg (\opts -> Ok opts {optNoSimulation = True}))
-                "do not perform rebalancing simulation"
+oNoSimulation =
+  (Option "" ["no-simulation"]
+   (NoArg (\opts -> Ok opts {optNoSimulation = True}))
+   "do not perform rebalancing simulation",
+   OptComplNone)
 
 oNodeSim :: OptType
-oNodeSim = Option "" ["simulate"]
-            (ReqArg (\ f o -> Ok o { optNodeSim = f:optNodeSim o }) "SPEC")
-            "simulate an empty cluster, given as\
-            \ 'alloc_policy,num_nodes,disk,ram,cpu'"
+oNodeSim =
+  (Option "" ["simulate"]
+   (ReqArg (\ f o -> Ok o { optNodeSim = f:optNodeSim o }) "SPEC")
+   "simulate an empty cluster, given as\
+   \ 'alloc_policy,num_nodes,disk,ram,cpu'",
+   OptComplString)
 
 oOfflineNode :: OptType
-oOfflineNode = Option "O" ["offline"]
-               (ReqArg (\ n o -> Ok o { optOffline = n:optOffline o }) "NODE")
-               "set node as offline"
+oOfflineNode =
+  (Option "O" ["offline"]
+   (ReqArg (\ n o -> Ok o { optOffline = n:optOffline o }) "NODE")
+   "set node as offline",
+   OptComplOneNode)
 
 oOutputDir :: OptType
-oOutputDir = Option "d" ["output-dir"]
-             (ReqArg (\ d opts -> Ok opts { optOutPath = d }) "PATH")
-             "directory in which to write output files"
+oOutputDir =
+  (Option "d" ["output-dir"]
+   (ReqArg (\ d opts -> Ok opts { optOutPath = d }) "PATH")
+   "directory in which to write output files",
+   OptComplDir)
 
 oPrintCommands :: OptType
-oPrintCommands = Option "C" ["print-commands"]
-                 (OptArg ((\ f opts -> Ok opts { optShowCmds = Just f }) .
-                          fromMaybe "-")
-                  "FILE")
-                 "print the ganeti command list for reaching the solution,\
-                 \ if an argument is passed then write the commands to a\
-                 \ file named as such"
+oPrintCommands =
+  (Option "C" ["print-commands"]
+   (OptArg ((\ f opts -> Ok opts { optShowCmds = Just f }) .
+            fromMaybe "-")
+    "FILE")
+   "print the ganeti command list for reaching the solution,\
+   \ if an argument is passed then write the commands to a\
+   \ file named as such",
+   OptComplNone)
 
 oPrintInsts :: OptType
-oPrintInsts = Option "" ["print-instances"]
-              (NoArg (\ opts -> Ok opts { optShowInsts = True }))
-              "print the final instance map"
+oPrintInsts =
+  (Option "" ["print-instances"]
+   (NoArg (\ opts -> Ok opts { optShowInsts = True }))
+   "print the final instance map",
+   OptComplNone)
 
 oPrintNodes :: OptType
-oPrintNodes = Option "p" ["print-nodes"]
-              (OptArg ((\ f opts ->
-                          let (prefix, realf) = case f of
-                                                  '+':rest -> (["+"], rest)
-                                                  _ -> ([], f)
-                              splitted = prefix ++ sepSplit ',' realf
-                          in Ok opts { optShowNodes = Just splitted }) .
-                       fromMaybe []) "FIELDS")
-              "print the final node list"
+oPrintNodes =
+  (Option "p" ["print-nodes"]
+   (OptArg ((\ f opts ->
+               let (prefix, realf) = case f of
+                                       '+':rest -> (["+"], rest)
+                                       _ -> ([], f)
+                   splitted = prefix ++ sepSplit ',' realf
+               in Ok opts { optShowNodes = Just splitted }) .
+            fromMaybe []) "FIELDS")
+   "print the final node list",
+   OptComplNone)
 
 oQuiet :: OptType
-oQuiet = Option "q" ["quiet"]
-         (NoArg (\ opts -> Ok opts { optVerbose = optVerbose opts - 1 }))
-         "decrease the verbosity level"
+oQuiet =
+  (Option "q" ["quiet"]
+   (NoArg (\ opts -> Ok opts { optVerbose = optVerbose opts - 1 }))
+   "decrease the verbosity level",
+   OptComplNone)
 
 oRapiMaster :: OptType
-oRapiMaster = Option "m" ["master"]
-              (ReqArg (\ m opts -> Ok opts { optMaster = m }) "ADDRESS")
-              "collect data via RAPI at the given ADDRESS"
+oRapiMaster =
+  (Option "m" ["master"]
+   (ReqArg (\ m opts -> Ok opts { optMaster = m }) "ADDRESS")
+   "collect data via RAPI at the given ADDRESS",
+   OptComplHost)
 
 oSaveCluster :: OptType
-oSaveCluster = Option "S" ["save"]
-            (ReqArg (\ f opts -> Ok opts { optSaveCluster = Just f }) "FILE")
-            "Save cluster state at the end of the processing to FILE"
+oSaveCluster =
+  (Option "S" ["save"]
+   (ReqArg (\ f opts -> Ok opts { optSaveCluster = Just f }) "FILE")
+   "Save cluster state at the end of the processing to FILE",
+   OptComplNone)
 
 oStdSpec :: OptType
-oStdSpec = Option "" ["standard-alloc"]
-             (ReqArg (\ inp opts -> do
-                        tspec <- parseISpecString "standard" inp
-                        return $ opts { optStdSpec = Just tspec } )
-              "STDSPEC")
-             "enable standard specs allocation, given as 'disk,ram,cpu'"
+oStdSpec =
+  (Option "" ["standard-alloc"]
+   (ReqArg (\ inp opts -> do
+              tspec <- parseISpecString "standard" inp
+              return $ opts { optStdSpec = Just tspec } )
+    "STDSPEC")
+   "enable standard specs allocation, given as 'disk,ram,cpu'",
+   OptComplString)
 
 oTieredSpec :: OptType
-oTieredSpec = Option "" ["tiered-alloc"]
-             (ReqArg (\ inp opts -> do
-                        tspec <- parseISpecString "tiered" inp
-                        return $ opts { optTieredSpec = Just tspec } )
-              "TSPEC")
-             "enable tiered specs allocation, given as 'disk,ram,cpu'"
+oTieredSpec =
+  (Option "" ["tiered-alloc"]
+   (ReqArg (\ inp opts -> do
+              tspec <- parseISpecString "tiered" inp
+              return $ opts { optTieredSpec = Just tspec } )
+    "TSPEC")
+   "enable tiered specs allocation, given as 'disk,ram,cpu'",
+   OptComplString)
 
 oVerbose :: OptType
-oVerbose = Option "v" ["verbose"]
-           (NoArg (\ opts -> Ok opts { optVerbose = optVerbose opts + 1 }))
-           "increase the verbosity level"
+oVerbose =
+  (Option "v" ["verbose"]
+   (NoArg (\ opts -> Ok opts { optVerbose = optVerbose opts + 1 }))
+   "increase the verbosity level",
+   OptComplNone)
 
 -- | Generic options.
 genericOpts :: [GenericOptType Options]
-- 
GitLab