module Main where
import Options.Applicative
import Control.Monad
import Control.Monad.State
main :: IO ()
main = join . customExecParser (prefs showHelpOnError) $
info (helper <*> parser) fullDesc
parser =
example <$> strOption (long "aaa")
<|>
example2 <$> strOption (long "aaa")
<*> strOption (long "bbb")
example :: String -> IO ()
example x = do
print "example..."
print x
example2 :: String -> String -> IO ()
example2 x y = do
print "example2..."
print x
print y
With the above code and the following arguments: :set args --aaa test --bbb test2
results in:
Invalid option `--bbb'
Usage: <interactive> (--aaa ARG | --aaa ARG --bbb ARG)
Available options:
-h,--help Show this help text
*** Exception: ExitFailure 1
How can I successfully parse the second case (relating to example2
)?
The issue seems to be relating to the parser code strOption (long "aaa")
which is present in both parsers. Is there an alternative to (<|>)
that can achieve the desired behavior perhaps?
The problem here is in the (<|>)
operator. It only tried the second parser when the first parser didn't consume any input. But in your exaple it did. You can verify this by specifying the arguments in reverse order. Then the first parser will not consume any input and fail and the second parser will be run with success result.
You can solve this issue like this way:
parser =
(\a -> maybe (example a) (example2 a))
<$> strOption (long "aaa")
<*> optional (strOption (long "bbb"))