hgrep-0.1: main/hgrep.hs
{-# LANGUAGE NoImplicitPrelude #-}
{-# LANGUAGE OverloadedStrings #-}
module Main where
import qualified Language.Haskell.HGrep as HGrep
import Language.Haskell.HGrep.Prelude
import qualified Options.Applicative as O
import qualified System.Console.ANSI as ANSI
import System.Exit (ExitCode (..), exitWith)
import qualified System.IO as IO
main :: IO ()
main = do
IO.hSetBuffering IO.stdout IO.LineBuffering
IO.hSetBuffering IO.stderr IO.LineBuffering
opts <- parseOpts
colour <- detectColour
case parseQuery (cmdQuery opts) (cmdRegex opts) of
Left er -> do
IO.hPutStrLn IO.stderr er
exitWith (ExitFailure 2)
Right q -> do
found <-
fmap sum $
for (cmdFiles opts) $ \fp ->
hgrep (HGrep.PrintOpts colour) q fp
exitWith (exitCode found)
exitCode :: Integer -> ExitCode
exitCode found
| found == 0 = ExitFailure 1
| otherwise = ExitSuccess
detectColour :: IO HGrep.ColourOpts
detectColour = do
out <- ANSI.hSupportsANSI IO.stdout
err <- ANSI.hSupportsANSI IO.stderr
pure $ case out && err of
True ->
HGrep.DefaultColours
False ->
HGrep.NoColours
hgrep :: HGrep.PrintOpts -> HGrep.Query -> FilePath -> IO Integer
hgrep popts q fp = do
esrc <- HGrep.parseModule fp
case esrc of
Left err -> do
IO.hPutStrLn IO.stderr (HGrep.printParseError err)
pure 0
Right src -> do
let results = HGrep.queryModule q src
HGrep.printResults popts results
pure $ fromIntegral (length results)
parseQuery :: [Char] -> Bool -> Either [Char] HGrep.Query
parseQuery str regex =
case regex of
True ->
HGrep.MatchRegex <$> HGrep.compileRegex str
False ->
pure $ HGrep.MatchSimple str
-- -----------------------------------------------------------------------------
data CmdOpts = CmdOpts {
cmdQuery :: [Char]
, cmdRegex :: Bool
, cmdFiles :: [FilePath]
} deriving (Eq, Ord, Show)
parseOpts :: IO CmdOpts
parseOpts =
O.execParser $
O.info
(parser <**> O.helper)
(O.header "hgrep - search Haskell source code from the command line")
parser :: O.Parser CmdOpts
parser =
CmdOpts
<$> O.argument O.str (O.metavar "QUERY")
<*> O.switch
(O.short 'e' <> O.long "regex" <> O.help "Match a regular expression")
<*> many (O.argument O.str (O.metavar "FILE"))