[Haskell-cafe] Cmdargs and common flags
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 -- Magnus Therning OpenPGP: 0xAB4DFBA4 email: mag...@therning.org jabber: mag...@therning.org twitter: magthe http://therning.org/magnus ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Cmdargs and common flags
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
Re: [Haskell-cafe] Cmdargs and common flags
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 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 > 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 > ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Cmdargs and common flags
Hi Magnus, > 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 I've added more details in: http://hackage.haskell.org/packages/archive/cmdargs/0.6.8/doc/html/System-Console-CmdArgs-Annotate.html http://hackage.haskell.org/packages/archive/cmdargs/0.6.8/doc/html/System-Console-CmdArgs-Implicit.html The first link includes comparisons for pure/impure, and the second gives a set of equivalences for converting between the two forms. Thanks, Neil ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Cmdargs and common flags
On Mon, Feb 14, 2011 at 19:11, Neil Mitchell wrote: > Hi Magnus, > >> 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 > > I've added more details in: > http://hackage.haskell.org/packages/archive/cmdargs/0.6.8/doc/html/System-Console-CmdArgs-Annotate.html > http://hackage.haskell.org/packages/archive/cmdargs/0.6.8/doc/html/System-Console-CmdArgs-Implicit.html > > The first link includes comparisons for pure/impure, and the second > gives a set of equivalences for converting between the two forms. > > Thanks, Neil I noticed that the form "record Ctor {} [...]" leads to a warning that Ctor isn't initialised. The obvious way to remove the warning is to call the constructor with all the arguments, but is there a more convenient/terse way of achieving the same? /M -- Magnus Therning OpenPGP: 0xAB4DFBA4 email: mag...@therning.org jabber: mag...@therning.org twitter: magthe http://therning.org/magnus ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Cmdargs and common flags
{-# OPTIONS_GHC -fno-warn-missing-fields #-} That's what I did in my CmdArgs test suite - if you have all your CmdArgs bit in a separate file then missing this warning will be fine. I don't know of any way to rewrite the code to indicate to GHC that you know what you are doing. Thanks, Neil On Sat, Mar 12, 2011 at 8:02 AM, Magnus Therning wrote: > On Mon, Feb 14, 2011 at 19:11, Neil Mitchell wrote: >> Hi Magnus, >> >>> 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 >> >> I've added more details in: >> http://hackage.haskell.org/packages/archive/cmdargs/0.6.8/doc/html/System-Console-CmdArgs-Annotate.html >> http://hackage.haskell.org/packages/archive/cmdargs/0.6.8/doc/html/System-Console-CmdArgs-Implicit.html >> >> The first link includes comparisons for pure/impure, and the second >> gives a set of equivalences for converting between the two forms. >> >> Thanks, Neil > > I noticed that the form "record Ctor {} [...]" leads to a warning that > Ctor isn't initialised. The obvious way to remove the warning is to > call the constructor with all the arguments, but is there a more > convenient/terse way of achieving the same? > > /M > > -- > Magnus Therning OpenPGP: 0xAB4DFBA4 > email: mag...@therning.org jabber: mag...@therning.org > twitter: magthe http://therning.org/magnus > ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe