purescript-0.15.9: app/Command/Graph.hs
module Command.Graph (command) where
import Prelude
import Control.Applicative (many)
import Control.Monad (unless, when)
import Data.Aeson qualified as Json
import Data.Bool (bool)
import Data.ByteString.Lazy qualified as LB
import Data.ByteString.Lazy.UTF8 qualified as LBU8
import Language.PureScript qualified as P
import Language.PureScript.Errors.JSON (JSONResult(..), toJSONErrors)
import Options.Applicative qualified as Opts
import System.Console.ANSI qualified as ANSI
import System.Exit (exitFailure)
import System.Directory (getCurrentDirectory)
import System.FilePath.Glob (glob)
import System.IO (hPutStr, hPutStrLn, stderr)
data GraphOptions = GraphOptions
{ graphInput :: [FilePath]
, graphJSONErrors :: Bool
}
graph :: GraphOptions -> IO ()
graph GraphOptions{..} = do
input <- globWarningOnMisses (unless graphJSONErrors . warnFileTypeNotFound) graphInput
when (null input && not graphJSONErrors) $ do
hPutStr stderr $ unlines
[ "purs graph: No input files."
, "Usage: For basic information, try the `--help' option."
]
exitFailure
(makeResult, makeWarnings) <- P.graph input
printWarningsAndErrors graphJSONErrors makeWarnings makeResult
>>= (LB.putStr . Json.encode)
where
warnFileTypeNotFound :: String -> IO ()
warnFileTypeNotFound =
hPutStrLn stderr . ("purs graph: No files found using pattern: " <>)
command :: Opts.Parser (IO ())
command = graph <$> (Opts.helper <*> graphOptions)
where
graphOptions :: Opts.Parser GraphOptions
graphOptions =
GraphOptions <$> many inputFile
<*> jsonErrors
inputFile :: Opts.Parser FilePath
inputFile =
Opts.strArgument $
Opts.metavar "FILE" <>
Opts.help "The input .purs file(s)."
jsonErrors :: Opts.Parser Bool
jsonErrors =
Opts.switch $
Opts.long "json-errors" <>
Opts.help "Print errors to stderr as JSON"
-- | Arguments: use JSON, warnings, errors
printWarningsAndErrors :: Bool -> P.MultipleErrors -> Either P.MultipleErrors a -> IO a
printWarningsAndErrors False warnings errors = do
pwd <- getCurrentDirectory
cc <- bool Nothing (Just P.defaultCodeColor) <$> ANSI.hSupportsANSI stderr
let ppeOpts = P.defaultPPEOptions { P.ppeCodeColor = cc, P.ppeFull = True, P.ppeRelativeDirectory = pwd }
when (P.nonEmpty warnings) $
hPutStrLn stderr (P.prettyPrintMultipleWarnings ppeOpts warnings)
case errors of
Left errs -> do
hPutStrLn stderr (P.prettyPrintMultipleErrors ppeOpts errs)
exitFailure
Right res -> pure res
printWarningsAndErrors True warnings errors = do
let verbose = True
hPutStrLn stderr . LBU8.toString . Json.encode $
JSONResult (toJSONErrors verbose P.Warning [] warnings)
(either (toJSONErrors verbose P.Error []) (const []) errors)
case errors of
Left _errs -> exitFailure
Right res -> pure res
globWarningOnMisses :: (String -> IO ()) -> [FilePath] -> IO [FilePath]
globWarningOnMisses warn = concatMapM globWithWarning
where
globWithWarning :: String -> IO [FilePath]
globWithWarning pattern' = do
paths <- glob pattern'
when (null paths) $ warn pattern'
return paths
concatMapM :: (a -> IO [b]) -> [a] -> IO [b]
concatMapM f = fmap concat . mapM f