Skip to content
This repository has been archived by the owner on Apr 26, 2021. It is now read-only.

Commit

Permalink
Fix #41
Browse files Browse the repository at this point in the history
  • Loading branch information
felixSchl committed Jun 3, 2016
1 parent dbec1a0 commit 89e874d
Show file tree
Hide file tree
Showing 2 changed files with 87 additions and 7 deletions.
28 changes: 21 additions & 7 deletions src/Language/Docopt/Parser/Desc.purs
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,12 @@ import Data.Function (on)
import Data.String as Str
import Control.Lazy (defer)
import Control.Bind ((>=>))
import Control.Monad (when)
import Control.Alt ((<|>))
import Control.Apply ((*>), (<*))
import Control.MonadPlus (guard)
import Data.List (List, (:), many, some, head, length, filter, catMaybes)
import Data.List (List(..), (:), many, some, head, length, filter, catMaybes,
reverse)
import Text.Parsing.Parser (ParseError, fail) as P
import Text.Parsing.Parser.Combinators ((<?>), try, choice, lookAhead, manyTill,
option, optionMaybe, notFollowedBy,
Expand Down Expand Up @@ -193,8 +195,19 @@ parse :: (List L.PositionedToken) -> Either P.ParseError (List Desc)
parse = flip L.runTokenParser descParser

descParser :: L.TokenParser (List Desc)
descParser = markIndent do many desc <* L.eof
descParser = markIndent do
reverse <$> go Nil
<* L.eof
where
go vs = do
v <- (Just <$> desc) <|> (descContent true $> Nothing)
case v of
Just v' -> go (v' : vs)
Nothing ->
P.choice [
desc >>= \v' -> go (v' : vs)
, pure vs
]

anyName :: L.TokenParser String
anyName = L.angleName <|> L.shoutName <|> L.name
Expand All @@ -205,8 +218,8 @@ descParser = markIndent do many desc <* L.eof
, positionalsDesc
]

descContent :: L.TokenParser (List Content)
descContent = do
descContent :: Boolean -> L.TokenParser (List Content)
descContent toplevel = do
markIndent do
catMaybes <$> (flip P.manyTill descEnd do
P.choice $ P.try <$> [
Expand All @@ -221,7 +234,8 @@ descParser = markIndent do many desc <* L.eof
L.eof
, void $ P.lookAhead do
L.newline
lessIndented
when (not toplevel)
lessIndented
P.choice [
void L.sopt
, void L.lopt
Expand All @@ -234,14 +248,14 @@ descParser = markIndent do many desc <* L.eof
positionalsDesc = do
L.angleName <|> L.shoutName
repeatable <- P.option false $ L.tripleDot $> true
descContent
descContent false
pure CommandDesc

optionDesc :: L.TokenParser Desc
optionDesc = do

xopt <- opt
description <- descContent
description <- descContent false

let defaults = getDefaultValue <$> filter isDefaultTag description
envs = getEnvKey <$> filter isEnvTag description
Expand Down
66 changes: 66 additions & 0 deletions test/Test/Spec/DescParserSpec.purs
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,72 @@ descParserSpec = \_ ->
, fail
"-f=BAZ, --foo=qux"
"Option-arguments mismatch: \"BAZ\" and \"qux\""
, pass (dedent
-- Fix #41
-- Should allow non-empty option sections that contain no options.
"""
foo bar
"""
) []
, pass (dedent
-- Fix #41
-- Should allow non-empty option sections that contain no options.
"""
foo bar
-f=BAZ, --foo=BAZ [default: 100]
-q=BAZ, --qux=BAZ [default: 200]
"""
) [ o { name: Desc.Full 'f' "foo"
, arg: Just $ arg "BAZ" (int 100)
, env: Nothing
, repeatable: false
}
, o { name: Desc.Full 'q' "qux"
, arg: Just $ arg "BAZ" (int 200)
, env: Nothing
, repeatable: false
}
]
, pass (dedent
-- Fix #41
-- Should allow non-empty option sections that contain no options.
"""
-f=BAZ, --foo=BAZ [default: 100]
foo bar
-q=BAZ, --qux=BAZ [default: 200]
"""
) [ o { name: Desc.Full 'f' "foo"
, arg: Just $ arg "BAZ" (int 100)
, env: Nothing
, repeatable: false
}
, o { name: Desc.Full 'q' "qux"
, arg: Just $ arg "BAZ" (int 200)
, env: Nothing
, repeatable: false
}
]
, pass (dedent
-- Fix #41
-- Should allow non-empty option sections that contain no options.
"""
foo bar
-f=BAZ, --foo=BAZ [default: 100]
foo bar
-q=BAZ, --qux=BAZ [default: 200]
foo bar
"""
) [ o { name: Desc.Full 'f' "foo"
, arg: Just $ arg "BAZ" (int 100)
, env: Nothing
, repeatable: false
}
, o { name: Desc.Full 'q' "qux"
, arg: Just $ arg "BAZ" (int 200)
, env: Nothing
, repeatable: false
}
]
, pass (dedent
-- if an option is indented past the start of the description
-- block for the previous option, it's considered part of the
Expand Down

0 comments on commit 89e874d

Please sign in to comment.