module Highlight.Hrep.Run where
import Prelude ()
import Prelude.Compat
import Control.Exception (IOException)
import Data.ByteString (ByteString)
import Data.Maybe (maybeToList)
import Data.Monoid ((<>))
import Pipes (Producer)
import Text.RE.PCRE (RE, (*=~), anyMatches)
import Text.RE.Replace (replaceAll)
import Highlight.Common.Color
(colorForFileNumber, colorReset, colorVividRedBold,
colorVividWhiteBold)
import Highlight.Common.Error (handleErr)
import Highlight.Common.Options (CommonOptions(..))
import Highlight.Hrep.Monad
(FilenameHandlingFromFiles(..), HrepM, Output,
compileHighlightRegexWithErr, createInputData, getInputFilenamesM,
getRecursiveM, handleInputData, runHrepM, runOutputProducer)
import Highlight.Pipes (stdinLines)
run :: CommonOptions -> IO ()
run opts = do
eitherRes <- runHrepM opts prog
either handleErr return eitherRes
prog :: HrepM ()
prog = do
outputProducer <- hrepOutputProducer stdinLines
runOutputProducer outputProducer
hrepOutputProducer
:: Producer ByteString HrepM ()
-> HrepM (Producer Output HrepM ())
hrepOutputProducer stdinProducer = do
regex <- compileHighlightRegexWithErr
inputFilenames <- getInputFilenamesM
recursive <- getRecursiveM
inputData <- createInputData recursive inputFilenames stdinProducer
let outputProducer =
handleInputData
(handleStdinInput regex)
(handleFileInput regex)
handleError
inputData
return outputProducer
handleStdinInput
:: Monad m
=> RE -> ByteString -> m [ByteString]
handleStdinInput regex input =
return $ formatNormalLine regex input
formatNormalLine :: RE -> ByteString -> [ByteString]
formatNormalLine regex =
maybeToList . highlightMatchInRed regex
handleFileInput
:: Monad m
=> RE
-> FilenameHandlingFromFiles
-> ByteString
-> Int
-> ByteString
-> m [ByteString]
handleFileInput regex NoFilename _ _ input =
return $ formatNormalLine regex input
handleFileInput regex PrintFilename filePath fileNumber input =
return $ formatLineWithFilename regex fileNumber filePath input
formatLineWithFilename
:: RE -> Int -> ByteString -> ByteString -> [ByteString]
formatLineWithFilename regex fileNumber filePath input =
case highlightMatchInRed regex input of
Nothing -> []
Just line ->
[ colorForFileNumber fileNumber
, filePath
, colorVividWhiteBold
, ": "
, colorReset
, line
]
handleError
:: Monad m
=> ByteString
-> IOException
-> Maybe IOException
-> m [ByteString]
handleError filePath _ (Just _) =
return ["Error when trying to read file or directory \"", filePath, "\""]
handleError filePath _ Nothing =
return ["Error when trying to read file \"", filePath, "\""]
highlightMatchInRed :: RE -> ByteString -> Maybe ByteString
highlightMatchInRed regex input =
let matches = input *=~ regex
didMatch = anyMatches matches
in if didMatch
then Just $ replaceAll replaceInRedByteString matches
else Nothing
replaceInRedByteString :: ByteString
replaceInRedByteString = colorVividRedBold <> "$0" <> colorReset