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
126 mapM print (List.intersperse (P.text " ") errors)
129 case print_program flags of
131 True -> print . pretty $ program modul
134 if print_types flags then printTypes metaModule else return ()
135 tipes <- Traverse.traverse Type.toSrcType (types metaModule)
136 let interface = Canonical.interface name $ ModuleInterface {
138 iAdts = datatypes metaModule,
139 iAliases = aliases metaModule
141 createDirectoryIfMissing True . dropFileName $ elmi flags filePath
142 Binary.encodeFile (elmi flags filePath) (name,interface)
143 writeFile (elmo flags filePath) (jsModule metaModule)
146printTypes metaModule = do
148 forM_ (Map.toList $ types metaModule) $ \(n,t) -> do
149 pt <- Type.extraPretty t
150 print $ variable n <+> P.text ":" <+> pt
153getRuntime :: Flags -> IO FilePath
155 case runtime flags of
157 Nothing -> getDataFileName "elm-runtime.js"
159build :: Flags -> FilePath -> IO ()
160build flags rootFile = do
161 let noPrelude = no_prelude flags
162 files <- if make flags then getSortedDependencies noPrelude rootFile else return [rootFile]
163 let ifaces = if noPrelude then Map.empty else Prelude.interfaces
164 interfaces <- buildFiles flags (length files) ifaces files
165 js <- foldM appendToOutput "" files
166 case only_js flags of
168 putStr "Generating JavaScript ... "
169 writeFile (file flags rootFile "js") (genJs js)
172 putStr "Generating HTML ... "
173 runtime <- getRuntime flags
174 let html = genHtml $ createHtml runtime (takeBaseName rootFile) (sources js) ""
175 writeFile (file flags rootFile "html") html
179 appendToOutput :: String -> FilePath -> IO String
180 appendToOutput js filePath =
181 do src <- readFile (elmo flags filePath)
184 genHtml = if minify flags then Normal.renderHtml else Pretty.renderHtml
185 genJs = if minify flags then BS.unpack . JS.minify . BS.pack else id
186 sources js = map Link (scripts flags) ++
187 [ Source (if minify flags then Minified else Readable) js ]
190buildFiles :: Flags -> Int -> Interfaces -> [FilePath] -> IO Interfaces
191buildFiles _ _ interfaces [] = return interfaces
192buildFiles flags numModules interfaces (filePath:rest) = do
193 interface <- buildFile flags (numModules - length rest) numModules interfaces filePath
194 let moduleName = List.intercalate "." . splitDirectories $ dropExtensions filePath
195 interfaces' = Map.insert moduleName interface interfaces
196 buildFiles flags numModules interfaces' rest
199exportInfo :: Module -> IO String
200exportInfo (Module names exs ims stmts) =
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