[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