1{-# LANGUAGE DeriveDataTypeable #-}
5import qualified Data.Map as Map
6import qualified Data.List as List
7import qualified Data.Binary as Binary
8import Data.Version (showVersion)
9import System.Console.CmdArgs hiding (program)
10import System.Directory
15import qualified Text.Blaze.Html.Renderer.Pretty as Pretty
16import qualified Text.Blaze.Html.Renderer.String as Normal
17import qualified Text.Jasmine as JS
18import qualified Data.ByteString.Lazy.Char8 as BS
20import qualified Metadata.Prelude as Prelude
21import qualified Transform.Canonicalize as Canonical
22import SourceSyntax.Module
23import Initialize (buildFromSource, getSortedDependencies)
24import Generate.JavaScript (jsModule)
25import Generate.Html (createHtml, JSStyle(..), JSSource(..))
28import SourceSyntax.PrettyPrint (pretty, variable)
29import Text.PrettyPrint as P
30import qualified Type.Type as Type
31import qualified Data.Traversable as Traverse
36 , runtime :: Maybe FilePath
39 , print_program :: Bool
40 , scripts :: [FilePath]
43 , output_directory :: FilePath
45 deriving (Data,Typeable,Show,Eq)
49 &= help "automatically compile dependencies."
50 , files = def &= args &= typ "FILES"
51 , runtime = Nothing &= typFile
52 &= help "Specify a custom location for Elm's runtime system."
54 &= help "Compile only to JavaScript."
56 &= help "Print out infered types of top-level definitions."
57 , print_program = False
58 &= help "Print out an internal representation of a program."
59 , scripts = [] &= typFile
60 &= help "Load JavaScript files in generated HTML. Files will be included in the given order."
62 &= help "Do not import Prelude by default, used only when compiling standard libraries."
64 &= help "Minify generated JavaScript and HTML"
65 , output_directory = "ElmFiles" &= typFile
66 &= help "Output files to directory specified. Defaults to ElmFiles/ directory."
67 } &= help "Compile Elm programs to HTML, CSS, and JavaScript."
68 &= summary ("The Elm Compiler " ++ showVersion version ++ ", (c) Evan Czaplicki")
71main = do setNumCapabilities =<< getNumProcessors
72 compileArgs =<< cmdArgs flags
74compileArgs :: Flags -> IO ()
77 [] -> putStrLn "Usage: elm [OPTIONS] [FILES]\nFor more help: elm --help"
78 fs -> mapM_ (build flags) fs
81file :: Flags -> FilePath -> String -> FilePath
82file flags filePath ext = output_directory flags </> replaceExtension filePath ext
84elmo :: Flags -> FilePath -> FilePath
85elmo flags filePath = file flags filePath "elmo"
87elmi :: Flags -> FilePath -> FilePath
88elmi flags filePath = file flags filePath "elmi"
91buildFile :: Flags -> Int -> Int -> Interfaces -> FilePath -> IO ModuleInterface
92buildFile flags moduleNum numModules interfaces filePath =
93 do compiled <- alreadyCompiled
94 if not compiled then compile
95 else getInterface `fmap` Binary.decodeFile (elmi flags filePath)
97 getInterface :: (String, ModuleInterface) -> ModuleInterface
100 alreadyCompiled :: IO Bool
102 existsi <- doesFileExist (elmi flags filePath)
103 existso <- doesFileExist (elmo flags filePath)
104 if not existsi || not existso
106 else do tsrc <- getModificationTime filePath
107 tint <- getModificationTime (elmo flags filePath)
111 number = "[" ++ show moduleNum ++ " of " ++ show numModules ++ "]"
114 name = List.intercalate "." (splitDirectories (dropExtensions filePath))
116 compile :: IO ModuleInterface
118 putStrLn $ concat [ number, " Compiling ", name
119 , replicate (max 1 (20 - length name)) ' '
120 , "( " ++ filePath ++ " )" ]
121 source <- readFile filePath
122 createDirectoryIfMissing True (output_directory flags)
124 case buildFromSource (no_prelude flags) interfaces source of
125 Left err -> mapM print err >> exitFailure
127 case print_program flags of
129 True -> print . pretty $ program modul
132 if print_types flags then printTypes metaModule else return ()
133 tipes <- Traverse.traverse Type.toSrcType (types metaModule)
134 let interface = Canonical.interface name $ ModuleInterface {
136 iAdts = datatypes metaModule,
137 iAliases = aliases metaModule
139 createDirectoryIfMissing True . dropFileName $ elmi flags filePath
140 Binary.encodeFile (elmi flags filePath) (name,interface)
141 writeFile (elmo flags filePath) (jsModule metaModule)
144printTypes metaModule = do
146 forM_ (Map.toList $ types metaModule) $ \(n,t) -> do
147 pt <- Type.extraPretty t
148 print $ variable n <+> P.text ":" <+> pt
151getRuntime :: Flags -> IO FilePath
153 case runtime flags of
155 Nothing -> getDataFileName "elm-runtime.js"
157build :: Flags -> FilePath -> IO ()
158build flags rootFile = do
159 let noPrelude = no_prelude flags
160 files <- if make flags then getSortedDependencies noPrelude rootFile else return [rootFile]
161 let ifaces = if noPrelude then Map.empty else Prelude.interfaces
162 interfaces <- buildFiles flags (length files) ifaces files
163 js <- foldM appendToOutput "" files
164 case only_js flags of
166 putStr "Generating JavaScript ... "
167 writeFile (file flags rootFile "js") (genJs js)
170 putStr "Generating HTML ... "
171 runtime <- getRuntime flags
172 let html = genHtml $ createHtml runtime (takeBaseName rootFile) (sources js) ""
173 writeFile (file flags rootFile "html") html
177 appendToOutput :: String -> FilePath -> IO String
178 appendToOutput js filePath =
179 do src <- readFile (elmo flags filePath)
182 genHtml = if minify flags then Normal.renderHtml else Pretty.renderHtml
183 genJs = if minify flags then BS.unpack . JS.minify . BS.pack else id
184 sources js = map Link (scripts flags) ++
185 [ Source (if minify flags then Minified else Readable) js ]
188buildFiles :: Flags -> Int -> Interfaces -> [FilePath] -> IO Interfaces
189buildFiles _ _ interfaces [] = return interfaces
190buildFiles flags numModules interfaces (filePath:rest) = do
191 interface <- buildFile flags (numModules - length rest) numModules interfaces filePath
192 let moduleName = List.intercalate "." . splitDirectories $ dropExtensions filePath
193 interfaces' = Map.insert moduleName interface interfaces
194 buildFiles flags numModules interfaces' rest
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