module Fixme.Comment
(
Comment
, Located
, parseComments
, commentText
, startLine
, endLine
, newComment
, parseComments'
, Language
, languageForFile
, highlightCode
) where
import Protolude
import qualified Data.Text as Text
import Text.Highlighting.Kate
( SourceLine
, Token
, TokenType(..)
, highlightAs
, languagesByFilename
)
parseComments :: Language -> Text -> [Comment]
parseComments language = parseComments' . highlightCode language
parseComments' :: [SourceLine] -> [Comment]
parseComments' =
coalesce appendComment . mapMaybe getComment . locateTokens
where
coalesce :: (a -> a -> Maybe a) -> [a] -> [a]
coalesce maybeAppend (x:y:ys) =
case x `maybeAppend` y of
Nothing -> x:(coalesce maybeAppend (y:ys))
Just z -> (coalesce maybeAppend (z:ys))
coalesce _ xs = xs
data Located a = Located { startLine :: Int
, value :: a
} deriving (Eq, Show)
type LocatedToken = Located Token
locateTokens :: [SourceLine] -> [LocatedToken]
locateTokens lines = [Located i x | (i, xs) <- zip [0..] lines, x <- xs]
type Comment = Located Text
commentText :: Comment -> Text
commentText = value
newComment :: Int -> Text -> Comment
newComment i text = Located i text
endLine :: Comment -> Int
endLine (Located startLine c) = startLine + (Text.count "\n" c)
appendComment :: Comment -> Comment -> Maybe Comment
appendComment x y
| startLine y endLine x > 1 = Nothing
| startLine y endLine x == 1 = Just (newComment (startLine x) (commentText x <> "\n" <> commentText y))
| otherwise = Just (newComment (startLine x) (commentText x <> commentText y))
getComment :: LocatedToken -> Maybe Comment
getComment (Located lineNum token) =
case getComment' token of
Nothing -> Nothing
Just comment -> Just $ Located lineNum comment
getComment' :: Token -> Maybe Text
getComment' (AlertTok, value) = Just (toS value)
getComment' (CommentTok, value) = Just (toS value)
getComment' _ = Nothing
type Language = Text
languageForFile :: Text -> Maybe Language
languageForFile = fmap toS . head . languagesByFilename . toS
highlightCode :: Language -> Text -> [SourceLine]
highlightCode language code =
let highlighted = highlightAs (toS language) (toS code)
in case Text.toLower language of
"haskell" -> map fixupHaskellComments highlighted
_ -> highlighted
where
fixupHaskellComments = map (\t -> if t == (FunctionTok, "--") then (CommentTok, "--") else t)