1-----------------------------------------------------------------------------
4-- Copyright : (c) Phil Freeman 2015
7-- Maintainer : Phil Freeman <paf31@cantab.net>
8-- Stability : experimental
11-- | Bundles compiled PureScript modules for the browser.
13-----------------------------------------------------------------------------
15{-# LANGUAGE PatternGuards #-}
16{-# LANGUAGE FlexibleContexts #-}
17{-# LANGUAGE ScopedTypeVariables #-}
18{-# LANGUAGE TupleSections #-}
19{-# LANGUAGE RecordWildCards #-}
21module Main (main) where
23import Data.Traversable (for)
24import Data.Version (showVersion)
26import Control.Applicative
28import Control.Monad.Error.Class
29import Control.Monad.Trans.Except
30import Control.Monad.IO.Class
32import System.FilePath (takeFileName, takeDirectory)
33import System.FilePath.Glob (glob)
34import System.Exit (exitFailure)
35import System.IO (stderr, hPutStrLn)
36import System.Directory (createDirectoryIfMissing)
38import Language.PureScript.Bundle
40import Options.Applicative as Opts
42import qualified Paths_purescript as Paths
44-- | Command line options.
46 { optionsInputFiles :: [FilePath]
47 , optionsOutputFile :: Maybe FilePath
48 , optionsEntryPoints :: [String]
49 , optionsMainModule :: Maybe String
50 , optionsNamespace :: String
53-- | Given a filename, assuming it is in the correct place on disk, infer a ModuleIdentifier.
54guessModuleIdentifier :: (Applicative m, MonadError ErrorMessage m) => FilePath -> m ModuleIdentifier
55guessModuleIdentifier filename = ModuleIdentifier (takeFileName (takeDirectory filename)) <$> (guessModuleType (takeFileName filename))
57 guessModuleType "index.js" = pure Regular
58 guessModuleType "foreign.js" = pure Foreign
59 guessModuleType name = throwError $ UnsupportedModulePath name
61-- | The main application function.
62-- This function parses the input files, performs dead code elimination, filters empty modules
63-- and generates and prints the final Javascript bundle.
64app :: forall m. (Applicative m, MonadError ErrorMessage m, MonadIO m) => Options -> m String
66 inputFiles <- concat <$> mapM (liftIO . glob) optionsInputFiles
67 when (null inputFiles) . liftIO $ do
68 hPutStrLn stderr "psc-bundle: No input files."
70 input <- for inputFiles $ \filename -> do
71 js <- liftIO (readFile filename)
72 mid <- guessModuleIdentifier filename
75 let entryIds = (map (`ModuleIdentifier` Regular) optionsEntryPoints)
77 bundle input entryIds optionsMainModule optionsNamespace
79-- | Command line options parser.
80options :: Parser Options
81options = Options <$> some inputFile
82 <*> optional outputFile
84 <*> optional mainModule
87 inputFile :: Parser FilePath
88 inputFile = strArgument $
90 <> help "The input .js file(s)"
92 outputFile :: Parser FilePath
93 outputFile = strOption $
96 <> help "The output .js file"
98 entryPoint :: Parser String
99 entryPoint = strOption $
102 <> help "Entry point module name(s). All code which is not a transitive dependency of an entry point module will be removed."
104 mainModule :: Parser String
105 mainModule = strOption $
107 <> help "Generate code to run the main method in the specified module."
109 namespace :: Parser String
110 namespace = strOption $
115 <> help "Specify the namespace that PureScript modules will be exported to when running in the browser."
120 opts <- execParser (info (version <*> helper <*> options) infoModList)
121 output <- runExceptT (app opts)
124 hPutStrLn stderr (unlines (printErrorMessage err))
127 case optionsOutputFile opts of
128 Just outputFile -> do
129 createDirectoryIfMissing True (takeDirectory outputFile)
130 writeFile outputFile js
131 Nothing -> putStrLn js
133 infoModList = fullDesc <> headerInfo <> footerInfo
134 headerInfo = header "psc-bundle - Bundles compiled PureScript modules for the browser"
135 footerInfo = footer $ "psc-bundle " ++ showVersion Paths.version
137 version :: Parser (a -> a)
138 version = abortOption (InfoMsg (showVersion Paths.version)) $ long "version" <> help "Show the version number" <> hidden
keysesc to close
- j k
- move down, up
- enter
- open
- esc
- back, or up a level
- 1 2 3 4
- readme, files, commits, refs
- /
- filter
- y
- copy the clone command
- c
- compare the chosen commit with another (or shift-click both)
- ?
- show or hide this list