parseCabal :: IO [(String, String)]
parseCabal = go `fmap` lines `fmap` readProcess "cabal" ["list"] []
  where
    go [] = []
    go (('*':' ':name):rest) =
      let (meta, rest') = gm [] rest
      in (name, L.intercalate "\n" meta) : go rest'
    go l = error $ "Unexpected cabal output" ++ show l

    gm m [] = (m, [])
    gm m (rest@(('*':_):_)) = (m, rest)
    gm m (x:xs)
      | L.null x  = gm m xs
      | otherwise = gm (m ++ [x]) xs
parseCabal :: IO [(String, String)]
parseCabal = go `fmap` lines `fmap` readProcess "cabal" ["list"] []
  where
    go [] = []
    go (('*':' ':name):rest) =
      let (meta, rest') = gm [] rest
      in (name, L.intercalate "\n" meta) : go rest'
    go l = error $ "Unexpected cabal output" ++ show l

    gm m [] = (m, [])
    gm m (rest@(('*':_):_)) = (m, rest)
    gm m (x:xs)
      | L.null x  = gm m xs
      | otherwise = gm (m ++ [x]) xs
parseCabal = go `fmap` lines `fmap` readProcess "cabal" ["list"] []
  where
    go [] = []
    go (('*':' ':name):rest) =
      let (meta, rest') = gm [] rest
      in (name, L.intercalate "\n" meta) : go rest'
    go l = error $ "Unexpected cabal output" ++ show l

    gm m [] = (m, [])
    gm m (rest@(('*':_):_)) = (m, rest)
    gm m (x:xs)
      | L.null x  = gm m xs
      | otherwise = gm (m ++ [x]) xs