packages feed

sarsi-0.0.5.1: src/Codec/Sarsi/SBT.hs

{-# LANGUAGE OverloadedStrings #-}

module Codec.Sarsi.SBT where

import Codec.Sarsi (Level (..), Location (..), Message (..))
import Data.Attoparsec.Combinator (lookAhead)
import Data.Attoparsec.Text
import qualified Data.Attoparsec.Text as AttoText
import Data.Text (Text)
import qualified Data.Text as Text

data SBTEvent = CompileStart Text | TaskFinish Bool Text | Throw Message
  deriving (Show)

cleaningCursesSBT :: Parser Text
cleaningCursesSBT = choice [silent, empty, keep]
  where
    silent = "  | =>" >> untilLineBreak >> "\n" >> return Text.empty
    empty = do
      _ <- AttoText.takeWhile1 $ \w -> w == '\n'
      return Text.empty
    keep = do
      content <- (AttoText.takeWhile1 $ \w -> w /= '\n') <* end
      return $ content `Text.snoc` '\n'

eventParser :: Parser SBTEvent
eventParser = choice [compile, finish, Throw <$> messageParser]
  where
    compile = do
      txt <- string "[info] " *> choice ["Build triggered", "Compiling"] *> untilLineBreak <* end
      return $ CompileStart txt
    finish = do
      res <- status <* space
      txt <- string "Total time: " *> untilLineBreak <* end
      _ <- end
      return $ TaskFinish res txt
      where
        status = choice [string "[success]" *> return True, string "[error]" *> return False]

messageParser :: Parser Message
messageParser = do
  lvl <- lineStart
  fp <- takeWhile1 (\c -> c /= sepChar && c /= '\n') <* char sepChar
  ln <- decimal <* char sepChar
  col <- decimal <* char sepChar
  t <- space *> (untilLineBreak <* "\n")
  ts <- manyTill' (lineStart *> (untilLineBreak <* "\n")) (lookAhead $ column')
  _ <- column' -- ignored as it was parsed above
  _ <- end
  return $ Message (Location fp col ln) lvl $ formatTxts t ts
  where
    level = choice [string "[error]" *> return Error, string "[warn]" *> return Warning]
    lineStart = level <* space
    sepChar = ':'
    formatTxts t [] = [t]
    formatTxts t ts = t : init ts
    column' = level *> ((length <$> many1 space) <* "^\n")

untilLineBreak :: Parser Text
untilLineBreak = takeWhile1 $ \w -> w /= '\n'

end :: Parser ()
end = choice [const () <$> "\n", endOfInput, return ()]