[Haskell-cafe] Cmdargs and common flags

Neil Mitchell ndmitchell at gmail.com
Mon Jan 24 23:49:42 CET 2011


Hi Magnus,

What you want is actually easier than you think!

To quote from http://hackage.haskell.org/packages/archive/cmdargs/0.6.7/doc/html/System-Console-CmdArgs-Implicit.html:

"Missing Fields: If a field is shared by multiple modes, it may be
omitted in subsequent modes, and will default to the previous value."

Therefore you can just do:

   cmd1 = Cmd1 { foo = def &= help "..", ...}
   cmd2 = Cmd2 { ...} -- never mention foo in Cmd2

cmdArgs [cmd1,cmd2]

And foo in Cmd2 will act exactly like you duplicated the definition
from foo in Cmd1. I use this feature regularly - it's a big time
saver.

Alternatively, you can use the tricks described by Kevin.

Finally, you can switch to the pure annotations. I will document them
shortly and give an example in System.Console.CmdArgs.Implicit, but
for now the details can be found at
http://hackage.haskell.org/packages/archive/cmdargs/0.6.7/doc/html/System-Console-CmdArgs-Annotate.html

To translate your cmd1/cmd2:

cmd1 = record Cmd1{} [foo := def += help "..", ...]
cmd2 = record Cmd2{} [foo := def += help "..", ...]

And then call cmdArgs_ instead. Now you can do anything that
equational reasoning supports without any danger:

cmd1 = record Cmd1{} [myfoo, ...]
cmd2 = record Cmd2{} [myfoo, ...]
myfoo = foo := def += help ".."

Even when using the pure annotations, you can still use missing fields:

cmd1 = record Cmd1{} [foo := def += help "..", ...]
cmd2 = record Cmd2{} [...]

Thanks, Neil

On Mon, Jan 24, 2011 at 8:50 PM, Kevin Quick <quick at sparq.org> wrote:
> Magnus,
>
> I used the following technique, but it was a couple of iterations of CmdArgs
> ago:
>
>
> data UIMode = Normal | Batch | Query deriving (Data,Typeable,Show,Eq)
>
> uimode_arg :: forall t. t -> UIMode
> uimode_arg _ = enum Normal
>               [ Batch &= flag "B" & text "batch mode (no interaction)" &
> group grp
>               , Query &= flag "Q"
>                           & text "query mode (user verification solicited)"
>                           & group grp
>               ]
>    where grp = "Operating Mode"
>
>
> data Globalargs = CMD1 { ... , uimode :: UIMode , ... }
>                | CMD2 { ... , uimode :: UIMode , ... }
>
>
> cmd1mode :: Mode Globalargs
> cmd1mode = mode $ CMD1 { ... , uimode = uimode_arg "cmd1" }
>                  &= text (usage "...")
>
>
> cmd2mode :: Mode Globalargs
> cmd2mode = mode $ CMD1 { ... , uimode = uimode_arg "cmd2" }
>                  &= text (usage "...")
>
> modes :: [ Mode Globalargs ]
> modes = [ cmd1mode, cmd2mode ]
>
> main  = do cmdArgs progSummary modes
>           ...
>
>
> I've cut and pasted from my usage and perhaps pasted too little, so let me
> know if the above is unuseably brief.  And again, cmdargs has changed
> somewhat since this code was written and I haven't tried a recent
> compilation.
>
> -KQ
>
> P.S.  This often required {-# OPTIONS_GHC -fno-full-laziness -fno-strictness
> #-} because GHC (6.12? 6.10?) would complain about my uimode_arg type
> otherwise.
>
>
> On Thu, 20 Jan 2011 01:48:35 -0700, Magnus Therning <magnus at therning.org>
> wrote:
>
>> I'm looking for a good way of dealing with common flags in cmdargs.
>> Currently what I do requires a bit of repetition that I'd really like
>> to get rid of:
>>
>> 1. Data types
>>
>>    data Modes = Cmd1 { foo :: String, ... } | Cmd2 { foo :: String, ... }
>>
>> 2. Mode specifications
>>
>>    cmd1 = Cmd1 { foo = def &= help "..", ...}
>>    cmd2 = Cmd2 { foo = def &= help "..", ...}
>>
>> I have no idea how to deal with the repetition in the data types, so
>> all suggestions are welcome.
>>
>> For the repetition in the mode specifications I attempted to factor
>> the common bits into a "variable":
>>
>>    flagFoo = "" &= help ".."
>>
>> but that resulted in only the first command getting the proper
>> specification.  I suppose this comes down to the impurity, but how do
>> I work around that?  (Especially, are there any good examples of using
>> the pure part of the API?)
>>
>> /M
>>
>
>
> --
> -KQ
>
> _______________________________________________
> Haskell-Cafe mailing list
> Haskell-Cafe at haskell.org
> http://www.haskell.org/mailman/listinfo/haskell-cafe
>



More information about the Haskell-Cafe mailing list