{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE OverloadedStrings #-}
module Hie.Cabal.Parser where
import Control.Applicative
import Control.Monad
import Data.Attoparsec.Text
import Data.Char
import Data.Functor
import Data.Maybe
import Data.Text (Text)
import qualified Data.Text as T
import System.FilePath.Posix ((</>))
type Name = Text
type Path = Text
type Indent = Int
data Package = Package Name [Component]
deriving (Int -> Package -> ShowS
[Package] -> ShowS
Package -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Package] -> ShowS
$cshowList :: [Package] -> ShowS
show :: Package -> String
$cshow :: Package -> String
showsPrec :: Int -> Package -> ShowS
$cshowsPrec :: Int -> Package -> ShowS
Show, Package -> Package -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Package -> Package -> Bool
$c/= :: Package -> Package -> Bool
== :: Package -> Package -> Bool
$c== :: Package -> Package -> Bool
Eq, Eq Package
Package -> Package -> Bool
Package -> Package -> Ordering
Package -> Package -> Package
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
min :: Package -> Package -> Package
$cmin :: Package -> Package -> Package
max :: Package -> Package -> Package
$cmax :: Package -> Package -> Package
>= :: Package -> Package -> Bool
$c>= :: Package -> Package -> Bool
> :: Package -> Package -> Bool
$c> :: Package -> Package -> Bool
<= :: Package -> Package -> Bool
$c<= :: Package -> Package -> Bool
< :: Package -> Package -> Bool
$c< :: Package -> Package -> Bool
compare :: Package -> Package -> Ordering
$ccompare :: Package -> Package -> Ordering
Ord)
data CompType = Lib | Exe | Test | Bench
deriving (Int -> CompType -> ShowS
[CompType] -> ShowS
CompType -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [CompType] -> ShowS
$cshowList :: [CompType] -> ShowS
show :: CompType -> String
$cshow :: CompType -> String
showsPrec :: Int -> CompType -> ShowS
$cshowsPrec :: Int -> CompType -> ShowS
Show, CompType -> CompType -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: CompType -> CompType -> Bool
$c/= :: CompType -> CompType -> Bool
== :: CompType -> CompType -> Bool
$c== :: CompType -> CompType -> Bool
Eq, Eq CompType
CompType -> CompType -> Bool
CompType -> CompType -> Ordering
CompType -> CompType -> CompType
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
min :: CompType -> CompType -> CompType
$cmin :: CompType -> CompType -> CompType
max :: CompType -> CompType -> CompType
$cmax :: CompType -> CompType -> CompType
>= :: CompType -> CompType -> Bool
$c>= :: CompType -> CompType -> Bool
> :: CompType -> CompType -> Bool
$c> :: CompType -> CompType -> Bool
<= :: CompType -> CompType -> Bool
$c<= :: CompType -> CompType -> Bool
< :: CompType -> CompType -> Bool
$c< :: CompType -> CompType -> Bool
compare :: CompType -> CompType -> Ordering
$ccompare :: CompType -> CompType -> Ordering
Ord)
data Component
= Comp CompType Name Path
deriving (Int -> Component -> ShowS
[Component] -> ShowS
Component -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Component] -> ShowS
$cshowList :: [Component] -> ShowS
show :: Component -> String
$cshow :: Component -> String
showsPrec :: Int -> Component -> ShowS
$cshowsPrec :: Int -> Component -> ShowS
Show, Component -> Component -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Component -> Component -> Bool
$c/= :: Component -> Component -> Bool
== :: Component -> Component -> Bool
$c== :: Component -> Component -> Bool
Eq, Eq Component
Component -> Component -> Bool
Component -> Component -> Ordering
Component -> Component -> Component
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
min :: Component -> Component -> Component
$cmin :: Component -> Component -> Component
max :: Component -> Component -> Component
$cmax :: Component -> Component -> Component
>= :: Component -> Component -> Bool
$c>= :: Component -> Component -> Bool
> :: Component -> Component -> Bool
$c> :: Component -> Component -> Bool
<= :: Component -> Component -> Bool
$c<= :: Component -> Component -> Bool
< :: Component -> Component -> Bool
$c< :: Component -> Component -> Bool
compare :: Component -> Component -> Ordering
$ccompare :: Component -> Component -> Ordering
Ord)
parsePackage' :: Text -> Either String Package
parsePackage' :: Text -> Either String Package
parsePackage' = forall a. Parser a -> Text -> Either String a
parseOnly Parser Package
parsePackage
skipFreeformField :: Parser ()
skipFreeformField :: Parser ()
skipFreeformField =
forall (f :: * -> *) a. Alternative f => [f a] -> f a
choice forall a b. (a -> b) -> a -> b
$
forall a b c. (a -> b -> c) -> b -> a -> c
flip (forall a. Int -> Text -> (Int -> Parser a) -> Parser a
field Int
0) Int -> Parser ()
skipBlock
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [ Text
"author",
Text
"bug-reports",
Text
"category",
Text
"copyright",
Text
"description",
Text
"homepage",
Text
"maintainer",
Text
"package-url",
Text
"stability",
Text
"synopsis"
]
parsePackage :: Parser Package
parsePackage :: Parser Package
parsePackage =
( do
Text
n <- forall a. Int -> Text -> (Int -> Parser a) -> Parser a
field Int
0 Text
"name" forall a b. (a -> b) -> a -> b
$ forall a b. a -> b -> a
const Parser Text Text
parseString
(Package Text
_ [Component]
t) <- Parser Package
parsePackage
forall (f :: * -> *) a. Applicative f => a -> f a
pure forall a b. (a -> b) -> a -> b
$ Text -> [Component] -> Package
Package Text
n [Component]
t
)
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> (Parser ()
skipFreeformField forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> Parser Package
parsePackage)
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> ( do
[Component]
h <- Int -> Parser [Component]
parseComponent Int
0
(Package Text
n [Component]
t) <- Parser Package
parsePackage
forall (f :: * -> *) a. Applicative f => a -> f a
pure forall a b. (a -> b) -> a -> b
$ Text -> [Component] -> Package
Package Text
n ([Component]
h forall a. Semigroup a => a -> a -> a
<> [Component]
t)
)
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> (Parser ()
skipToNextLine forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> Parser Package
parsePackage)
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> forall (f :: * -> *) a. Applicative f => a -> f a
pure (Text -> [Component] -> Package
Package Text
"" [])
componentHeader :: Indent -> Text -> Parser Name
Int
i Text
t = do
Int
_ <- Int -> Parser Int
indent Int
i
Text
_ <- Text -> Parser Text Text
asciiCI Text
t
forall (f :: * -> *) a. Alternative f => f a -> f ()
skipMany Parser Char
tabOrSpace
Text
n <- Parser Text Text
parseString forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> forall (f :: * -> *) a. Applicative f => a -> f a
pure Text
""
Parser ()
skipToNextLine
forall (f :: * -> *) a. Applicative f => a -> f a
pure Text
n
parseComponent :: Indent -> Parser [Component]
parseComponent :: Int -> Parser [Component]
parseComponent Int
i =
Int -> Parser [Component]
parseExe Int
i
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> Int -> Parser [Component]
parseLib Int
i
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> Int -> Parser [Component]
parseBench Int
i
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> Int -> Parser [Component]
parseTestSuite Int
i
parseLib :: Indent -> Parser [Component]
parseLib :: Int -> Parser [Component]
parseLib Int
i =
(Int -> Text -> (Text -> Text -> Component) -> Parser [Component]
parseSec Int
i Text
"library" forall a b. (a -> b) -> a -> b
$ CompType -> Text -> Text -> Component
Comp CompType
Lib)
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> (Int -> Text -> (Text -> Text -> Component) -> Parser [Component]
parseSec Int
i Text
"foreign-library" forall a b. (a -> b) -> a -> b
$ CompType -> Text -> Text -> Component
Comp CompType
Lib)
parseTestSuite :: Indent -> Parser [Component]
parseTestSuite :: Int -> Parser [Component]
parseTestSuite Int
i = Int -> Text -> (Text -> Text -> Component) -> Parser [Component]
parseSec Int
i Text
"test-suite" forall a b. (a -> b) -> a -> b
$ CompType -> Text -> Text -> Component
Comp CompType
Test
parseExe :: Indent -> Parser [Component]
parseExe :: Int -> Parser [Component]
parseExe = (Text -> Text -> Component) -> Text -> Int -> Parser [Component]
parseSecMain (CompType -> Text -> Text -> Component
Comp CompType
Exe) Text
"executable"
parseBench :: Indent -> Parser [Component]
parseBench :: Int -> Parser [Component]
parseBench = (Text -> Text -> Component) -> Text -> Int -> Parser [Component]
parseSecMain (CompType -> Text -> Text -> Component
Comp CompType
Bench) Text
"benchmark"
parseSecMain :: (Name -> Path -> Component) -> Text -> Indent -> Parser [Component]
parseSecMain :: (Text -> Text -> Component) -> Text -> Int -> Parser [Component]
parseSecMain Text -> Text -> Component
c Text
s Int
i = do
Text
n <- Int -> Text -> Parser Text Text
componentHeader Int
i Text
s
[Text]
p <- Int -> [Text] -> Text -> [Text] -> [Text] -> Parser [Text]
pathMain (Int
i forall a. Num a => a -> a -> a
+ Int
1) [Text
"./"] Text
"" [] []
forall (f :: * -> *) a. Applicative f => a -> f a
pure forall a b. (a -> b) -> a -> b
$ forall a b. (a -> b) -> [a] -> [b]
map (Text -> Text -> Component
c Text
n) [Text]
p
parseQuoted :: Parser Text
parseQuoted :: Parser Text Text
parseQuoted = do
Char
q <- Char -> Parser Char
char Char
'"' forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> Char -> Parser Char
char Char
'\''
Text
s <- (Char -> Bool) -> Parser Text Text
takeTill (forall a. Eq a => a -> a -> Bool
== Char
q)
Char
_ <- Char -> Parser Char
char Char
q
forall (f :: * -> *) a. Applicative f => a -> f a
pure Text
s
parseString :: Parser Name
parseString :: Parser Text Text
parseString = Parser Text Text
parseQuoted forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> Parser Text Text
unqualName
unqualName :: Parser Text
unqualName :: Parser Text Text
unqualName = (Char -> Bool) -> Parser Text Text
takeWhile1 (Bool -> Bool
not forall b c a. (b -> c) -> (a -> b) -> a -> c
. (\Char
c -> Char -> Bool
isSpace Char
c Bool -> Bool -> Bool
|| Char
c forall a. Eq a => a -> a -> Bool
== Char
','))
parseList :: Indent -> Parser [Text]
parseList :: Int -> Parser [Text]
parseList Int
i = forall (f :: * -> *) a. Alternative f => f a -> f [a]
many (Parser Text Text
nl forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> Parser Text Text
sl)
where
sep :: Parser ()
sep = forall (f :: * -> *) a. Alternative f => f a -> f ()
skipMany (Char -> Parser Char
char Char
',' forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> Parser Char
tabOrSpace)
com :: Parser ()
com = forall (f :: * -> *) a. Alternative f => f a -> f ()
skipMany Parser Char
tabOrSpace forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> Parser Text Text
"--" forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> (Char -> Bool) -> Parser ()
skipWhile (Bool -> Bool
not forall b c a. (b -> c) -> (a -> b) -> a -> c
. Char -> Bool
isEndOfLine)
sl :: Parser Text Text
sl = do
Parser ()
sep
Text
x <- Parser Text Text
parseString
Parser ()
sep
forall (f :: * -> *) a. Alternative f => f a -> f ()
skipMany Parser ()
com
forall (f :: * -> *) a. Applicative f => a -> f a
pure Text
x
nl :: Parser Text Text
nl = do
forall (f :: * -> *) a. Alternative f => f a -> f ()
skipMany Parser ()
emptyOrComLine forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> Parser ()
endOfLine
Int
_ <- Int -> Parser Int
indent Int
i
Parser ()
sep
forall (f :: * -> *) a. Alternative f => f a -> f ()
skipMany Parser ()
com
Text
x <- Parser Text Text
parseString
Parser ()
sep
forall (f :: * -> *) a. Alternative f => f a -> f ()
skipMany Parser ()
com
forall (f :: * -> *) a. Applicative f => a -> f a
pure Text
x
pathMain :: Indent -> [Text] -> Text -> [Text] -> [Text] -> Parser [Text]
pathMain :: Int -> [Text] -> Text -> [Text] -> [Text] -> Parser [Text]
pathMain Int
i [Text]
p Text
m [Text]
o [Text]
a =
(Int -> Parser [Text]
hsSourceDir Int
i forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= (\[Text]
p' -> Int -> [Text] -> Text -> [Text] -> [Text] -> Parser [Text]
pathMain Int
i [Text]
p' Text
m [Text]
o [Text]
a))
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> (forall a. Int -> Text -> (Int -> Parser a) -> Parser a
field Int
i Text
"main-is" (forall a b. a -> b -> a
const Parser Text Text
parseString) forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= (\Text
m' -> Int -> [Text] -> Text -> [Text] -> [Text] -> Parser [Text]
pathMain Int
i [Text]
p Text
m' [Text]
o [Text]
a))
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> (forall a. Int -> Text -> (Int -> Parser a) -> Parser a
field Int
i Text
"other-modules" Int -> Parser [Text]
parseList forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= forall a b c. (a -> b -> c) -> b -> a -> c
flip (Int -> [Text] -> Text -> [Text] -> [Text] -> Parser [Text]
pathMain Int
i [Text]
p Text
m) [Text]
a)
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> (forall a. Int -> Text -> (Int -> Parser a) -> Parser a
field Int
i Text
"autogen-modules" Int -> Parser [Text]
parseList forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= Int -> [Text] -> Text -> [Text] -> [Text] -> Parser [Text]
pathMain Int
i [Text]
p Text
m [Text]
o)
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> (Int -> Parser ()
skipBlockLine Int
i forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> Int -> [Text] -> Text -> [Text] -> [Text] -> Parser [Text]
pathMain Int
i [Text]
p Text
m [Text]
o [Text]
a)
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> forall (f :: * -> *) a. Applicative f => a -> f a
pure
( forall a b. (a -> b) -> [a] -> [b]
map (Text -> Text -> Text
<//> Text
m) [Text]
p
forall a. Semigroup a => a -> a -> a
<> [ Text
p' Text -> Text -> Text
<//> (Text
o'' forall a. Semigroup a => a -> a -> a
<> Text
".hs")
| Text
p' <- [Text]
p,
Text
o' <- forall a. (a -> Bool) -> [a] -> [a]
filter (forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`notElem` [Text]
a) [Text]
o,
let o'' :: Text
o'' = Text -> Text -> Text -> Text
T.replace Text
"." Text
"/" Text
o'
]
)
(<//>) :: Text -> Text -> Text
Text
a <//> :: Text -> Text -> Text
<//> Text
b = String -> Text
T.pack (Text -> String
T.unpack Text
a String -> ShowS
</> Text -> String
T.unpack Text
b)
infixr 5 <//>
parseSec :: Indent -> Text -> (Name -> Path -> Component) -> Parser [Component]
parseSec :: Int -> Text -> (Text -> Text -> Component) -> Parser [Component]
parseSec Int
i Text
compType Text -> Text -> Component
compCon = do
Text
n <- Int -> Text -> Parser Text Text
componentHeader Int
i Text
compType
[Text]
p <- Int -> [Text] -> Parser [Text]
extractPath (Int
i forall a. Num a => a -> a -> a
+ Int
1) []
let p' :: [Text]
p' = if forall (t :: * -> *) a. Foldable t => t a -> Bool
null [Text]
p then [Text
"./"] else [Text]
p
forall (f :: * -> *) a. Applicative f => a -> f a
pure forall a b. (a -> b) -> a -> b
$ forall a b. (a -> b) -> [a] -> [b]
map (Text -> Text -> Component
compCon Text
n) [Text]
p'
skipToNextLine :: Parser ()
skipToNextLine :: Parser ()
skipToNextLine = (Char -> Bool) -> Parser ()
skipWhile (Bool -> Bool
not forall b c a. (b -> c) -> (a -> b) -> a -> c
. Char -> Bool
isEndOfLine) forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> Parser ()
endOfLine
skipBlock :: Indent -> Parser ()
skipBlock :: Int -> Parser ()
skipBlock Int
i = forall (f :: * -> *) a. Alternative f => f a -> f ()
skipMany forall a b. (a -> b) -> a -> b
$ Int -> Parser ()
skipBlockLine Int
i
comment :: Parser ()
= forall (f :: * -> *) a. Alternative f => f a -> f ()
skipMany Parser Char
tabOrSpace forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> Parser Text Text
"--" forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> Parser ()
skipToNextLine
skipBlockLine :: Indent -> Parser ()
skipBlockLine :: Int -> Parser ()
skipBlockLine Int
i = (Int -> Parser Int
indent Int
i forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> Parser ()
skipToNextLine) forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> Parser ()
emptyOrComLine
emptyOrComLine :: Parser ()
emptyOrComLine :: Parser ()
emptyOrComLine = (forall (f :: * -> *) a. Alternative f => f a -> f ()
skipMany Parser Char
tabOrSpace forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> Parser ()
endOfLine) forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> Parser ()
comment
tabOrSpace :: Parser Char
tabOrSpace :: Parser Char
tabOrSpace = Char -> Parser Char
char Char
' ' forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> Char -> Parser Char
char Char
'\t'
hsSourceDir :: Indent -> Parser [Text]
hsSourceDir :: Int -> Parser [Text]
hsSourceDir Int
i = forall a. Int -> Text -> (Int -> Parser a) -> Parser a
field Int
i Text
"hs-source-dirs" Int -> Parser [Text]
parseList
field ::
Indent ->
Text ->
(Indent -> Parser a) ->
Parser a
field :: forall a. Int -> Text -> (Int -> Parser a) -> Parser a
field Int
i Text
f Int -> Parser a
p =
do
Int
i' <- Int -> Parser Int
indent Int
i
Text
_ <- Text -> Parser Text Text
asciiCI Text
f
forall (f :: * -> *) a. Alternative f => f a -> f ()
skipMany Parser Char
tabOrSpace
Char
_ <- Char -> Parser Char
char Char
':'
forall (f :: * -> *) a. Alternative f => f a -> f ()
skipMany Parser Char
tabOrSpace
a
p' <- Int -> Parser a
p forall a b. (a -> b) -> a -> b
$ Int
i' forall a. Num a => a -> a -> a
+ Int
1
Parser ()
skipToNextLine
forall (f :: * -> *) a. Applicative f => a -> f a
pure a
p'
extractPath :: Indent -> [Path] -> Parser [Path]
Int
i [Text]
ps =
(forall a. Int -> Text -> (Int -> Parser a) -> Parser a
field Int
i Text
"hs-source-dirs" Int -> Parser [Text]
parseList forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= (\[Text]
p -> Int -> [Text] -> Parser [Text]
extractPath Int
i forall a b. (a -> b) -> a -> b
$ [Text]
ps forall a. Semigroup a => a -> a -> a
<> [Text]
p))
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> (Int -> Parser ()
skipBlockLine Int
i forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> Int -> [Text] -> Parser [Text]
extractPath Int
i [Text]
ps)
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> (Parser ()
comment forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> Int -> [Text] -> Parser [Text]
extractPath Int
i [Text]
ps)
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> forall (f :: * -> *) a. Applicative f => a -> f a
pure [Text]
ps
indent :: Indent -> Parser Int
indent :: Int -> Parser Int
indent Int
i = do
Int
c <- forall (t :: * -> *) a. Foldable t => t a -> Int
length forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall (m :: * -> *) a. MonadPlus m => m a -> m [a]
many' Parser Char
tabOrSpace
if Int
c forall a. Ord a => a -> a -> Bool
>= Int
i then forall (f :: * -> *) a. Applicative f => a -> f a
pure Int
c else forall (m :: * -> *) a. MonadFail m => String -> m a
fail String
"insufficient indent"
extractPkgs :: Parser [T.Text]
= forall (m :: * -> *) a. Monad m => m (m a) -> m a
join forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. [Maybe a] -> [a]
catMaybes forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall (m :: * -> *) a. MonadPlus m => m a -> m [a]
many' (forall a. a -> Maybe a
Just forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall a. Int -> Text -> (Int -> Parser a) -> Parser a
field Int
0 Text
"packages" Int -> Parser [Text]
parseList forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> (Parser ()
skipToNextLine forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> forall (f :: * -> *) a. Applicative f => a -> f a
pure forall a. Maybe a
Nothing))