on master help sign in
Simplify "elm init"
2cd8509Evan Czaplicki
builder/src/Reporting/Exit/Init.hs+22−5
@@ -9,13 +9,16 @@ module Reporting.Exit.Init
9import qualified Reporting.Doc as D
9import qualified Reporting.Doc as D
10import qualified Reporting.Exit.Help as Help
10import qualified Reporting.Exit.Help as Help
11
11
12+import qualified Elm.Package as Pkg
13+
12
14
13
15
14-- EXITS
16-- EXITS
15
17
16
18
17data Exit
19data Exit
18− = ClashingFlags
20+ = NoSolution [Pkg.Name]
21+ | AlreadyStarted
19
22
20
23
21
24
@@ -25,8 +28,22 @@ data Exit
25toReport :: Exit -> Help.Report
28toReport :: Exit -> Help.Report
26toReport exit =
29toReport exit =
27 case exit of
30 case exit of
28− ClashingFlags ->
31+ NoSolution pkgs ->
29− Help.report "CLASHING FLAGS" Nothing
32+ Help.report "NO SOLUTION" Nothing
30− "Trim down to zero or one flag. If you are not sure which one you want, learn more about them with:"
33+ "I tried to create an elm.json with the following direct dependencies:"
31− [ D.indent 4 $ D.green $ "elm init --help"
34+ [ D.indent 4 $ D.vcat $
35+ map (D.dullyellow . D.fromString . Pkg.toString) pkgs
36+ , D.reflow $
37+ "I could not find compatible versions though! This should not happen, so please\
38+ \ ask around one of the community forums <http://elm-lang.org/community> to learn\
39+ \ what is going on!"
40+ ]
41+
42+ AlreadyStarted ->
43+ Help.report "EXISTING PROJECT" Nothing
44+ "You already have an elm.json file, so there is nothing for me to initialize!"
45+ [ D.fillSep
46+ ["Maybe",D.green (D.fromString (D.makeLink "init")),"can","help"
47+ ,"you","figure","out","what","to","do","next?"
48+ ]
32 ]
49 ]
ui/terminal/src/Init.hs+57−64
@@ -1,25 +1,26 @@
1{-# LANGUAGE OverloadedStrings #-}
1{-# LANGUAGE OverloadedStrings #-}
2module Init
2module Init
3− ( Flags(..)
4− , run
3+ ( run
5 )
4 )
6 where
5 where
7
6
8
7
9import Prelude hiding (init)
8import Prelude hiding (init)
10import Control.Monad.Trans (liftIO)
9import Control.Monad.Trans (liftIO)
11−import qualified Data.ByteString.Lazy as LBS
10+import qualified Data.Map as Map
12−import Data.Monoid ((<>))
13−import qualified Network.HTTP.Client as Client
14import qualified System.Directory as Dir
11import qualified System.Directory as Dir
15
12
13+import qualified Deps.Cache as Cache
14+import qualified Deps.Explorer as Explorer
15+import qualified Deps.Solver as Solver
16import qualified Elm.Compiler.Version as Compiler
16import qualified Elm.Compiler.Version as Compiler
17import qualified Elm.Package as Pkg
17import qualified Elm.Package as Pkg
18+import qualified Elm.Project.Constraint as Con
19+import qualified Elm.Project.Json as Project
18import qualified Reporting.Doc as D
20import qualified Reporting.Doc as D
19import qualified Reporting.Exit as Exit
21import qualified Reporting.Exit as Exit
20import qualified Reporting.Exit.Init as E
22import qualified Reporting.Exit.Init as E
21import qualified Reporting.Task as Task
23import qualified Reporting.Task as Task
22−import qualified Reporting.Task.Http as Http
23import qualified Reporting.Progress.Terminal as Terminal
24import qualified Reporting.Progress.Terminal as Terminal
24
25
25
26
@@ -27,81 +28,73 @@ import qualified Reporting.Progress.Terminal as Terminal
27-- RUN
28-- RUN
28
29
29
30
30−data Flags =
31− Flags
32− { _element :: Bool
33− , _document :: Bool
34− }
35−
36−
37−run :: () -> Flags -> IO ()
31+run :: () -> () -> IO ()
38−run () flags =
32+run () () =
39 do reporter <- Terminal.create
33 do reporter <- Terminal.create
34+ exists <- Dir.doesFileExist "elm.json"
40 Task.run reporter $
35 Task.run reporter $
36+ if exists then
37+ Task.throw (Exit.Init E.AlreadyStarted)
38+ else
41− do approved <- Task.getApproval question
39+ do approved <- Task.getApproval question
42− if approved
40+ if approved
43− then
41+ then
44− do init flags
42+ do init
45− liftIO $ putStrLn "Okay, I created them!"
43+ liftIO $ putStrLn "Okay, I created it. Now read that link!"
46− else
44+ else
47− liftIO $ putStrLn "Okay, I left everything the same!"
45+ liftIO $ putStrLn "Okay, I did not make any changes!"
48
46
49
47
50question :: D.Doc
48question :: D.Doc
51question =
49question =
52 D.stack
50 D.stack
53− [ "Hello! Elm projects are pretty simple. They include:"
51+ [ D.fillSep
54− , D.indent 2 $ D.vcat $
52+ ["Hello!"
55− [ "1. " <> D.green "elm.json" <> D.black " ------------ describes your dependencies"
53+ ,"Elm","projects","always","start","with","an",D.green "elm.json","file."
56− , "2. " <> D.green "src/Main.elm" <> D.black " ------ a small Elm program to expand"
54+ ,"I","can","create","them!"
57 ]
55 ]
58− , customReflow
56+ , D.reflow
59− "Now you may be wondering, what will be in these files? How do I see\
57+ "Now you may be wondering, what will be in this file? How do I add Elm files to\
60− \ it in the browser? How will my code grow? Do I need more\
58+ \ my project? How do I see it in the browser? How will my code grow? Do I need\
61− \ directories? What about tests? Etc. Check out"
59+ \ more directories? What about tests? Etc."
60+ , D.fillSep
62− (D.dullyellow (D.fromString (D.makeLink "init")))
61+ ["Check","out",D.cyan (D.fromString (D.makeLink "init"))
63− "for all the answers!"
62+ ,"for","all","the","answers!"
63+ ]
64− , "So, would you like me to create these two files now? [Y/n]: "
64+ , "Knowing all that, would you like me to create an elm.json file now? [Y/n]: "
65 ]
65 ]
66
66
67
67
68−customReflow :: String -> D.Doc -> String -> D.Doc
69−customReflow before doc after =
70− D.fillSep $
71− map D.fromString (words before) ++ [doc] ++ map D.fromString (words after)
72−
73−
74
68
75-- INIT
69-- INIT
76
70
77
71
78−init :: Flags -> Task.Task ()
72+init :: Task.Task ()
79−init flags =
73+init =
80− case flags of
74+ do registry <- Cache.optionalUpdate
81− Flags False False -> download "sandbox"
82− Flags True False -> download "element"
83− Flags False True -> download "document"
84− Flags _ _ -> Task.throw $ Exit.Init E.ClashingFlags
85−
86
75
87−download :: String -> Task.Task ()
76+ maybeSolution <-
88−download projectType =
77+ Explorer.run registry $ Solver.run $ Solver.solve defaults
89− do fetch projectType "elm.json" $ return ()
90− fetch projectType "src/Main.elm" $ Dir.createDirectoryIfMissing True "src"
91
78
79+ case maybeSolution of
80+ Just solution ->
81+ let
82+ directs = Map.intersection solution defaults
83+ indirects = Map.difference solution defaults
84+ in
85+ liftIO $
86+ do Dir.createDirectoryIfMissing True "src"
87+ Project.write "." $ Project.App $
88+ Project.AppInfo Compiler.version ["src"] directs indirects Map.empty Map.empty
92
89
93−fetch :: String -> FilePath -> IO () -> Task.Task ()
90+ Nothing ->
94−fetch projectType path setup =
91+ Task.throw (Exit.Init (E.NoSolution (Map.keys defaults)))
95− Http.run $
96− Http.anything
97− ("https://experiment.elm-lang.org/" ++ vsn ++ "/init/" ++ projectType ++ "/" ++ path)
98− (\request manager ->
99− do response <- Client.httpLbs request manager
100− setup
101− Right <$> LBS.writeFile path (Client.responseBody response)
102− )
103
92
104
93
105−vsn :: String
94+defaults :: Map.Map Pkg.Name Con.Constraint
106−vsn =
95+defaults =
107− Pkg.versionToString Compiler.version
96+ Map.fromList
97+ [ (Pkg.core, Con.anything)
98+ , (Pkg.browser, Con.anything)
99+ , (Pkg.html, Con.anything)
100+ ]
ui/terminal/src/Main.hs+5−11
@@ -81,24 +81,18 @@ init :: Interface
81init =
81init =
82 let
82 let
83 summary =
83 summary =
84− "Start an Elm project. It creates two files (elm.json and src/Main.elm)\
84+ "Start an Elm project. It creates a starter elm.json file and\
85− \ and provides a couple links that explain how to get going with Elm."
85+ \ provides a link explaining what to do from there."
86
86
87 details =
87 details =
88 "The `init` command helps start Elm projects:"
88 "The `init` command helps start Elm projects:"
89
89
90 example =
90 example =
91 reflow
91 reflow
92− "It asks permission to create two files (elm.json and src/Main.elm) that are\
92+ "It will ask permission to create an elm.json file, the one thing common\
93− \ common to all Elm projects. It also provides a couple links that explain what\
93+ \ to all Elm projects. It also provides a link explaining what to do from there."
94− \ to do from there."
95−
96− initFlags =
97− flags Init.Flags
98− |-- onOff "element" "Initialize a Browser.element program, making it easier to jump into making HTTP requests, generating random values, asking the time, etc."
99− |-- onOff "document" "Initialize a Browser.document program, allowing you to control the <title> and and <body> of the browser."
100 in
94 in
101− Interface "init" (Common summary) details example noArgs initFlags Init.run
95+ Interface "init" (Common summary) details example noArgs noFlags Init.run
102
96
103
97
104
98