----------------------------------------------------------------------------- -- -- Module : Main -- Copyright : (c) Hardy Jones 2014 -- License : MIT (http://opensource.org/licenses/MIT) -- -- Maintainer : Hardy Jones -- Stability : experimental -- Portability : -- -- | -- Generate Directed Graphs of PureScript TypeClasses -- ----------------------------------------------------------------------------- module Command.Hierarchy (command) where import Prelude import Protolude (catMaybes) import Control.Applicative (optional) import Data.Foldable (for_) import Data.Text qualified as T import Data.Text.IO qualified as T import Options.Applicative (Parser) import Options.Applicative qualified as Opts import System.Directory (createDirectoryIfMissing) import System.FilePath (()) import System.FilePath.Glob (glob) import System.Exit (exitFailure, exitSuccess) import System.IO (hPutStr, stderr) import System.IO.UTF8 (readUTF8FilesT) import Language.PureScript qualified as P import Language.PureScript.CST qualified as CST import Language.PureScript.Hierarchy (Graph(..), _unDigraph, _unGraphName, typeClasses) data HierarchyOptions = HierarchyOptions { _hierarchyInput :: FilePath , _hierarchyOutput :: Maybe FilePath } parseInput :: [FilePath] -> IO (Either P.MultipleErrors [P.Module]) parseInput paths = do content <- readUTF8FilesT paths return $ map (snd . snd) <$> CST.parseFromFiles id content compile :: HierarchyOptions -> IO () compile (HierarchyOptions inputGlob mOutput) = do input <- glob inputGlob modules <- parseInput input case modules of Left errs -> hPutStr stderr (P.prettyPrintMultipleErrors P.defaultPPEOptions errs) >> exitFailure Right ms -> do for_ (catMaybes $ typeClasses ms) $ \(Graph name graph) -> case mOutput of Just output -> do createDirectoryIfMissing True output T.writeFile (output T.unpack (_unGraphName name)) (_unDigraph graph) Nothing -> T.putStrLn (_unDigraph graph) exitSuccess inputFile :: Parser FilePath inputFile = Opts.strArgument $ Opts.metavar "FILE" <> Opts.value "main.purs" <> Opts.showDefault <> Opts.help "The input file to generate a hierarchy from" outputFile :: Parser (Maybe FilePath) outputFile = optional . Opts.strOption $ Opts.short 'o' <> Opts.long "output" <> Opts.help "The output directory" pscOptions :: Parser HierarchyOptions pscOptions = HierarchyOptions <$> inputFile <*> outputFile command :: Opts.Parser (IO ()) command = compile <$> (Opts.helper <*> pscOptions)