module GHCi.History.Parse.Common
where
import Parsing as P
import GHCi.History (
HistoryItem(..)
, FilePos(..)
)
someSpace = skipSome space
num :: Parser Int
num = read <$> many1 digit
negNum :: Parser Int
negNum = negate <$> (char '-' *> num)
numSpan:: Parser (Int, Int)
numSpan = (,) <$> num <*> (char '-' *> num)
filePos :: Parser FilePos
filePos = FilePos <$> (char '(' *> num) <*> (char ',' *> num <* char ')')
unabbrevPosRange :: Parser (FilePos , FilePos )
unabbrevPosRange = (,) <$> filePos <*> (char '-' *> filePos)
abbrevPosRange :: Parser (FilePos , FilePos )
abbrevPosRange =
let
lineAndStartCol = try $ ( (,) :: Int -> Int -> (Int, Int)) <$> num <*> (char ':' *> num) <* (char '-')
in
mkRange <$> lineAndStartCol <*> num
where
mkRange (ln, stCol) endCol = (FilePos ln stCol, FilePos ln endCol)
pointRange :: Parser (FilePos, FilePos )
pointRange = mkRange <$> num <*> (char ':' *> num)
where
mkRange ln stCol = (FilePos ln stCol, FilePos ln stCol)
posRange = abbrevPosRange <|> pointRange <|> unabbrevPosRange
filename :: Parser String
filename = many1 $ noneOf ":"
funcname :: Parser String
funcname = someSpace *> option "" (string "\ESC[1m") *> many1 (noneOf " \ESC") <* option "" (string "\ESC[0m") <* someSpace
histLine :: Parser HistoryItem
histLine =
mkHistLine <$> (negNum <* someSpace <* char ':') <*> funcname <*> (char '(' *> filename <* char ':') <*> posRange <* char ')'
where
mkHistLine n func file (startPos, endPos) = HistoryItem n func file startPos endPos
emptyHistory :: Parser [HistoryItem]
emptyHistory = const [] <$> string "Empty history." <* manyTill anyChar eof
nonEmptyHistory = manyTill (histLine <* endOfLine) (string "<end of history>" <|> string "..." )
history = emptyHistory <|> nonEmptyHistory