packages feed

proteome-0.9.9.9: lib/Proteome/Grep/Parse.hs

module Proteome.Grep.Parse where

import Chiasma.Data.Ident (generateIdent, identText)
import Data.Attoparsec.Text (parseOnly)
import qualified Data.Text as Text (strip)
import Exon (exon)
import qualified Log
import Path (Abs, Dir, Path, parseAbsFile, parseRelFile, stripProperPrefix, (</>))
import Ribosome (pathText)
import Ribosome.Menu.Data.MenuItem (MenuItem (MenuItem))
import Text.Parser.Char (anyChar, char, noneOf)
import Text.Parser.Combinators (manyTill)
import Text.Parser.Token (TokenParsing, natural)

import Proteome.Data.GrepOutputLine (GrepOutputLine (GrepOutputLine))
import Proteome.Grep.Syntax (lineNumber)

grepParser ::
  MonadFail m =>
  TokenParsing m =>
  Path Abs Dir ->
  m GrepOutputLine
grepParser cwd =
  GrepOutputLine <$> path <*> (subtract 1 <$> number) <*> optional number <*> (toText <$> many anyChar)
  where
    path = do
      s <- manyTill (noneOf ":") (char ':')
      maybe (fail "not a path") pure (parseAbsFile s <|> ((cwd </>) <$> parseRelFile s))
    number =
      (fromInteger <$> natural) <* char ':'

formatGrepLine :: Path Abs Dir -> GrepOutputLine -> Text
formatGrepLine cwd (GrepOutputLine path line col text) =
  [exon|#{relativePath} #{lineNumber} #{show line}:#{show (fromMaybe 1 col)} #{Text.strip text}|]
  where
    relativePath =
      maybe (pathText path) pathText (stripProperPrefix cwd path)

parseGrepOutput ::
  Members [Log, Embed IO] r =>
  Path Abs Dir ->
  Text ->
  Sem r (Maybe (MenuItem GrepOutputLine))
parseGrepOutput cwd =
  item . parseOnly (grepParser cwd)
  where
    item (Right a) = do
      ident <- identText <$> generateIdent
      pure (Just (convert ident a))
    item (Left err) =
      Nothing <$ Log.debug [exon|parsing grep output failed: #{toText err}|]
    convert _ file =
      MenuItem file text [exon| * #{text}|]
      where
        text =
          formatGrepLine cwd file