Skip to content

Instantly share code, notes, and snippets.

@max630
Created January 25, 2017 21:40
Show Gist options
  • Save max630/5d64247eff2e1fc0a112d1008d8f134b to your computer and use it in GitHub Desktop.
Save max630/5d64247eff2e1fc0a112d1008d8f134b to your computer and use it in GitHub Desktop.
optparse-applicative question
> {-# LANGUAGE TupleSections #-}
> import Control.Applicative
> import Data.List (isPrefixOf)
> import Options.Applicative
> prefixReader expect = eitherReader $ prefixReader' expect
> prefixReader' expect s = if expect `isPrefixOf` s
> then Right s
> else Left ("not(\"" ++ s ++ "\" `isPrefixOf` \"" ++ expect ++ "\")")
> notPrefixReader expect = eitherReader $ notPrefixReader' expect
> notPrefixReader' expect s = if not (expect `isPrefixOf` s)
> then Right s
> else Left ("\"" ++ s ++ "\" `isPrefixOf` \"" ++ expect ++ "\"")
> test o = execParserPure (prefs mempty) (info o mempty)
The needed syntax to parse is "program [A] [B]", so user can specify
either both A B, or only A, or only B, or none. "A" has some complicated
syntax which canot be mistaken with "B". It would seem that it is
straightforward:
> op = (,)
> <$> optional (argument (notPrefixReader "b") (metavar "A"))
> <*> optional (argument (prefixReader "b") (metavar "B"))
but here is an issue: I do not want blindly assume that any argument
which does not has correct "A" format is decided to be "B". Because it
can be just some mistype. I would rather accept it for A roughly and
then fail overall parsing if I cannot match it specifically. Apparently,
optparse-applicative doe not seem to allow me that - if I accepted
argument in reader it is returned succesfully. I can only check it again
after parsing is done, which makes me construct the failed parsing
manually if I want to print nice "Usage"
So I tried to do this:
> op2 = ((Nothing,) . Just) <$> argument (notPrefixReader "a") (metavar "B")
> <|> (,)
> <$> optional (argument (prefixReader "a") (metavar "A"))
> <*> optional (argument (prefixReader "b") (metavar "B"))
That is, I try to explicitly check the case of "prog B" with some rough
check and if it fails resort to the full case. But the failure of first
branch seems to fail the whole parsing. How could I treat the failure to
parse argument as "mempty" to try another branch?
Or, alternatively, how could I make "op" fail whole parsing if first
argument pass rough check 'notPrefixReader "b"' but fails correct check
'prefixReader "a"'?
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment