packages feed

krank-0.1.0: app/Main.hs

{-# LANGUAGE QuasiQuotes #-}
{-# LANGUAGE TemplateHaskell #-}

import System.Environment (getArgs)
import System.Exit (exitFailure)
import System.IO (hPutStrLn, stderr)

import Control.Exception.Safe
import Control.Applicative (optional)
import Data.Semigroup ((<>))
import Data.Text (unpack)
import qualified Options.Applicative as Opt
import Options.Applicative ((<**>), many)
import Control.Monad.Reader
import PyF

import Krank
import Krank.Formatter
import Krank.Types

data KrankOpts = KrankOpts {
  codeFilePaths :: [FilePath],
  krankConfig :: KrankConfig
}

filesToParse :: Opt.Parser [FilePath]
filesToParse = many (Opt.argument Opt.str (Opt.metavar "FILES..."))

githubKeyToParse :: Opt.Parser (Maybe GithubKey)
githubKeyToParse = optional (
  GithubKey <$> (
    Opt.strOption $
      Opt.long "issuetracker-githubkey"
      <> Opt.metavar "DEVELOPER_KEY"
      <> Opt.help "A github developer key to allow for more API calls for the IssueTracker checker"))

optionsParser :: Opt.Parser KrankOpts
optionsParser = KrankOpts
  <$> filesToParse
  <*> (KrankConfig
       <$> githubKeyToParse
       <*> (Opt.switch $ Opt.long "dry-run"
        <> Opt.help "Perform a dry run. Parse file, but do not execute HTTP requests")
      )

opts :: Opt.ParserInfo KrankOpts
opts = Opt.info (optionsParser <**> Opt.helper)
  ( Opt.fullDesc
  <> Opt.progDesc "Checks the comments in FILES"
  <> Opt.header "krank - a comment linter / analytics tool" )

runKrank :: FilePath -> KrankConfig -> IO ()
runKrank path options = do
  violations <- runReaderT (processFile path) options
  putStr . unpack . showViolations $ violations

main :: IO ()
main = do
  options <- Opt.execParser opts
  (flip mapM_) (codeFilePaths options) $ \path -> do
    (runKrank path (krankConfig options))
    `catchAnyDeep` (\(SomeException e) -> hPutStrLn stderr [fmt|Error when processing {path}: {show e}|])