2

Wenn ich die folgenden Arten und Parser:Haskell optparse-applicative: eine Liste der Datensätze Parsen, die mehrere Felder haben

data Mode = 
    Mode1 
    | Mode2 
    deriving (Show, Eq, Read) 

data ThingINeedMulitpleOf = 
    Thing { _name :: String, _mode :: Mode } 
    deriving (Show, Eq) 

thingParser :: Parser ThingINeedMulitpleOf 
thingParser = Thing <$> strArgument (metavar "NAME") 
        <*> option auto (long "mode" <> metavar "MODE") 

und ich bauen einen Parser auf folgende Weise:

data Config = 
    Config ThingINeedMulitpleOf ThingINeedMulitpleOf 
    deriving (Show, Eq) 

loadConfig = execParser $ info (Config <$> thingParser <*> thingParser) fullDesc 

dann kann ich my-exe Thing1 --mode Mode1 Thing2 --mode Mode2 erfolgreich parsen, aber das ist nur nützlich, wenn ich genau zwei Things will. ich in Probleme laufen, wenn die Config zu ändern versuchen nThing s zu unterstützen, das heißt:

data Config = 
    Config [ThingINeedMulitpleOf] 
    deriving (Show, Eq) 

loadConfig = execParser $ info (Config <$> many thingParser) fullDesc 

aber ich kann jetzt nicht analysieren mehr my-exe Thing1 --mode Mode1 Thing2 --mode Mode2, mir den Fehler Invalid argument 'Thing1'

geben Interessanterweise das funktioniert, wenn die nur ein Feld enthält.

Antwort

3

Wenn Sie einen Subparser mit Alternative typeclass some Funktion verwenden, können Sie den gewünschten Effekt bekommen, zugegeben mit einer etwas anderen Befehlszeilensyntax.

thingSubparser :: Parser ThingINeedMulitpleOf 
thingSubparser = subparser $ command "thing" (info thingParser mempty) 

loadConfig :: IO Config 
loadConfig = execParser $ info (Config <$> some thingSubparser) fullDesc 

Damit Sie Befehlszeilen wie schreiben:

my-exe thing test --mode Mode1 thing test2 --mode Mode2 

, die die Config Objekt ergeben:

Config [Thing {_name = "test", _mode = Mode1},Thing {_name = "test2", _mode = Mode2}] 

Ich bin mir nicht ganz sicher, warum Sie die subparser müssen und können‘ t einfach some gegen die thingParser, aber wenn ich raten müsste, wäre es, weil der Befehl dem Parser einen Begrenzer gibt (das "Ding" Argument/Befehlsname).