Your question turned out to be more complicated than you think. Current optparse-applicative
API is not supposed to be used with such cases. So you probably may want to change the way you handle CLI arguments or switch to another CLI parsing library. But I will describe most closest way of achieving your goal.
First, you need to read other two SO questions:
1. How to parse Maybe with optparse-applicative
2. Is it possible to have a optparse-applicative option with several parameters?
From first question you know how to parse optional arguments using optional
function. From second you learn some problems with parsing multiple arguments. So I will write here several approaches how you can workaround this problem.
1. Naive and ugly
You can represent pair of strings as pair of String
type and use just naive show
of this pair. Here is code:
mainParser :: Parser Arguments
mainParser = Arguments
<$> switch (long "someflag" <> help "Some argument flag")
<*> optional (uncurry SubArguments <$>
(option auto $ long "subarguments" <> help "some desc"))
getArguments :: IO Arguments
getArguments = do
(res, ()) <- simpleOptions "main example" "" "desc" mainParser empty
return res
main :: IO ()
main = getArguments >>= print
Here is result in ghci
:
ghci> :run main --someflag --subarguments "(\"a\",\"b\")"
Arguments True (Just (SubArguments "a" "b"))
2. Less naive
From answer to second question you should learn how pass multiple arguments inside one string. Here is code for parsing:
subArgParser :: ReadM SubArguments
subArgParser = do
input <- str
-- no error checking, don't actually do this
let [a,b] = words input
pure $ SubArguments a b
mainParser :: Parser Arguments
mainParser = Arguments
<$> switch (long "someflag" <> help "Some argument flag")
<*> optional (option subArgParser $ long "subarguments" <> help "some desc")
And here is ghci
output:
ghci> :run main --someflag --subarguments "x yyy"
Arguments True (Just (SubArguments "x" "yyy"))
The only bad thing in second solution is that error checking is absent. Thus you can use another general purpose parsing library, for example megaparsec
, instead of just let [a,b] = words input
.