
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-Co...:
"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-Co...
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
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
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@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe