I am using optparse-applicative and I would like to parse the command line arguments, for example:
$ ./program -a file1 file2 -b filea fileb
ie, two switches, both of which can take multiple arguments.
So, I have a data type for my parameters that looks like this:
data MyOptions = MyOptions { aFiles :: [String] , bFiles :: [String] }
And then a Parser as follows:
config :: Parser MyOptions config = MyOptions <$> option (str >>= parseStringList) ( short 'a' <> long "aFiles" ) <*> option (str >>= parseStringList) ( short 'b' <> long "bFiles" ) parseStringList :: Monad m => String -> m [String] parseStringList = return . words
This approach fails in that it will give the expected result when only one argument is provided for each switch, but if you specify the second argument, you will get an "Invalid argument" for this second argument.
I wondered if I could shy away from it, pretending that I needed four options: a Boolean switch (ie -a ); list of lines; another logical switch (i.e. -b ); and another list of lines. So I changed my data type:
data MyOptions = MyOptions { isA :: Bool , aFiles :: [String] , isB :: Bool , bFiles :: [String] }
And then changed the parser as follows:
config :: Parser MyOptions config = MyOptions <$> switch ( short 'a' <> long "aFiles" ) <*> many (argument str (metavar "FILE")) <*> switch ( short 'b' <> long "bFiles" ) <*> many (argument str (metavar "FILE"))
This time using the many and argument combinators instead of explicit parsing for the list of strings.
But now the first many (argument str (metavar "FILE")) consumes all arguments, including those that follow the -b switch.
So how can I write this argument parser?