2

I would like to use cmdargs to pass arguments to my Haskell program. For some reasons, I would like some options to be hidden (not shown but usable) in the cmdargs help message.

Is there a way to do to that?

I'm using cmdargs 0.10.9.

Vigo
  • 131
  • 6

1 Answers1

1

The idea here is to intercept the --help processing and edit the help text to remove any references to hidden options before displaying it. Options we wish to hide can be marked with special help text (e.g. &= help "HIDDEN OPTION") and those lines can be removed from the help output.

Consider this simple main program:

main = cmdArgs sampleArgs >>= print

The path taken when --help is present is as follows:

cmdArgs = cmdArgsRun . cmdArgsMode

cmdArgs m = cmdArgsApply =<< processArgs m

cmdArgsApply :: CmdArgs a -> IO a
cmdArgsApply CmdArgs{..}
    | Just x <- cmdArgsHelp = do putStr x; exitSuccess
    | Just x <- cmdArgsVersion = ...
    | otherwise =  ...

To intercept help processing we can write our main like this:

main = do
  b <- processArgs (cmdArgsMode sampleArgs)
  a <- myApply b
  print a

where myApply is a version of cmdArgsApply which emits the edited version of the help text.

Here is working example. The options -s and --secret will not be shown in the help text. Try it with these arguments:

prog
prog --help
prog --version
prog -s1234

Program:

 {-# LANGUAGE DeriveDataTypeable, RecordWildCards #-}

 import Data.List                       (isInfixOf)
 import System.Console.CmdArgs
 import System.Console.CmdArgs.Explicit (processArgs)
 import System.Exit                     (exitSuccess)

 data MyArgs = MyArgs { file :: String, dest :: String, secret :: String }
   deriving (Show, Data)

 sample  = MyArgs { file = "input.txt"  &= help "the input file" &= opt "input"
                  , dest = "output.txt" &= help "the output file"
                  , secret = "3l33t"    &= help "HIDDEN OPTION"  &= opt "someflag" 
                  }

 main = do
   b <- processArgs (cmdArgsMode sample)
   a <- myApply b
   putStrLn $ "running program with " ++ show a

 myApply :: CmdArgs a -> IO a
 myApply b@CmdArgs{..}
   | Just x <- cmdArgsHelp = do putStr (fixupHelp x); exitSuccess
   | otherwise             = cmdArgsApply b

 fixupHelp = unlines
               . filter (not . ("HIDDEN OPTION" `isInfixOf`))
               . lines
ErikR
  • 51,541
  • 9
  • 73
  • 124
  • This seems to mostly do the trick, except you have to be careful since the help can be laid out in multiple lines. In that case you might end up with stray lines in the output. This should really be supported by cmdargs.. – alias Nov 20 '20 at 06:52