forked from elm/compiler
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathMain.hs
338 lines (258 loc) · 10.1 KB
/
Main.hs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
{-# LANGUAGE OverloadedStrings #-}
module Main
( main
)
where
import Prelude hiding (init)
import qualified Data.List as List
import qualified Text.PrettyPrint.ANSI.Leijen as P
import Text.PrettyPrint.ANSI.Leijen ((<>))
import Text.Read (readMaybe)
import qualified Elm.Version as V
import Terminal
import Terminal.Helpers
import qualified Bump
import qualified Develop
import qualified Diff
import qualified Init
import qualified Install
import qualified Make
import qualified Publish
import qualified Repl
-- MAIN
main :: IO ()
main =
Terminal.app intro outro
[ repl
, init
, reactor
, make
, install
, bump
, diff
, publish
]
intro :: P.Doc
intro =
P.vcat
[ P.fillSep
["Hi,","thank","you","for","trying","out"
,P.green "Elm"
,P.green (P.text (V.toChars V.compiler)) <> "."
,"I hope you like it!"
]
, ""
, P.black "-------------------------------------------------------------------------------"
, P.black "I highly recommend working through <https://guide.elm-lang.org> to get started."
, P.black "It teaches many important concepts, including how to use `elm` in the terminal."
, P.black "-------------------------------------------------------------------------------"
]
outro :: P.Doc
outro =
P.fillSep $ map P.text $ words $
"Be sure to ask on the Elm slack if you run into trouble! Folks are friendly and\
\ happy to help out. They hang out there because it is fun, so be kind to get the\
\ best results!"
-- INIT
init :: Terminal.Command
init =
let
summary =
"Start an Elm project. It creates a starter elm.json file and\
\ provides a link explaining what to do from there."
details =
"The `init` command helps start Elm projects:"
example =
reflow
"It will ask permission to create an elm.json file, the one thing common\
\ to all Elm projects. It also provides a link explaining what to do from there."
in
Terminal.Command "init" (Common summary) details example noArgs noFlags Init.run
-- REPL
repl :: Terminal.Command
repl =
let
summary =
"Open up an interactive programming session. Type in Elm expressions\
\ like (2 + 2) or (String.length \"test\") and see if they equal four!"
details =
"The `repl` command opens up an interactive programming session:"
example =
reflow
"Start working through <https://guide.elm-lang.org> to learn how to use this!\
\ It has a whole chapter that uses the REPL for everything, so that is probably\
\ the quickest way to get started."
replFlags =
flags Repl.Flags
|-- flag "interpreter" interpreter "Path to a alternate JS interpreter, like node or nodejs."
|-- onOff "no-colors" "Turn off the colors in the REPL. This can help if you are having trouble reading the values. Some terminals use a custom color scheme that diverges significantly from the standard ANSI colors, so another path may be to pick a more standard color scheme."
in
Terminal.Command "repl" (Common summary) details example noArgs replFlags Repl.run
interpreter :: Parser String
interpreter =
Parser
{ _singular = "interpreter"
, _plural = "interpreters"
, _parser = Just
, _suggest = \_ -> return []
, _examples = \_ -> return ["node","nodejs"]
}
-- REACTOR
reactor :: Terminal.Command
reactor =
let
summary =
"Compile code with a click. It opens a file viewer in your browser, and\
\ when you click on an Elm file, it compiles and you see the result."
details =
"The `reactor` command starts a local server on your computer:"
example =
reflow
"After running that command, you would have a server at <http://localhost:8000>\
\ that helps with development. It shows your files like a file viewer. If you\
\ click on an Elm file, it will compile it for you! And you can just press\
\ the refresh button in the browser to recompile things."
reactorFlags =
flags Develop.Flags
|-- flag "port" port_ "The port of the server (default: 8000)"
in
Terminal.Command "reactor" (Common summary) details example noArgs reactorFlags Develop.run
port_ :: Parser Int
port_ =
Parser
{ _singular = "port"
, _plural = "ports"
, _parser = readMaybe
, _suggest = \_ -> return []
, _examples = \_ -> return ["3000","8000"]
}
-- MAKE
make :: Terminal.Command
make =
let
details =
"The `make` command compiles Elm code into JS or HTML:"
example =
stack
[ reflow
"For example:"
, P.indent 4 $ P.green "elm make src/Main.elm"
, reflow
"This tries to compile an Elm file named src/Main.elm, generating an index.html\
\ file if possible."
]
makeFlags =
flags Make.Flags
|-- onOff "debug" "Turn on the time-travelling debugger. It allows you to rewind and replay events. The events can be imported/exported into a file, which makes for very precise bug reports!"
|-- onOff "optimize" "Turn on optimizations to make code smaller and faster. For example, the compiler renames record fields to be as short as possible and unboxes values to reduce allocation."
|-- flag "output" Make.output "Specify the name of the resulting JS file. For example --output=assets/elm.js to generate the JS at assets/elm.js or --output=/dev/null to generate no output at all!"
|-- flag "report" Make.reportType "You can say --report=json to get error messages as JSON. This is only really useful if you are an editor plugin. Humans should avoid it!"
|-- flag "docs" Make.docsFile "Generate a JSON file of documentation for a package. Eventually it will be possible to preview docs with `reactor` because it is quite hard to deal with these JSON files directly."
in
Terminal.Command "make" Uncommon details example (zeroOrMore elmFile) makeFlags Make.run
-- INSTALL
install :: Terminal.Command
install =
let
details =
"The `install` command fetches packages from <https://package.elm-lang.org> for\
\ use in your project:"
example =
stack
[ reflow
"For example, if you want to get packages for HTTP and JSON, you would say:"
, P.indent 4 $ P.green $ P.vcat $
[ "elm install elm/http"
, "elm install elm/json"
]
, reflow
"Notice that you must say the AUTHOR name and PROJECT name! After running those\
\ commands, you could say `import Http` or `import Json.Decode` in your code."
, reflow
"What if two projects use different versions of the same package? No problem!\
\ Each project is independent, so there cannot be conflicts like that!"
]
installArgs =
oneOf
[ require0 Install.NoArgs
, require1 Install.Install package
]
in
Terminal.Command "install" Uncommon details example installArgs noFlags Install.run
-- PUBLISH
publish :: Terminal.Command
publish =
let
details =
"The `publish` command publishes your package on <https://package.elm-lang.org>\
\ so that anyone in the Elm community can use it."
example =
stack
[ reflow
"Think hard if you are ready to publish NEW packages though!"
, reflow
"Part of what makes Elm great is the packages ecosystem. The fact that\
\ there is usually one option (usually very well done) makes it way\
\ easier to pick packages and become productive. So having a million\
\ packages would be a failure in Elm. We do not need twenty of\
\ everything, all coded in a single weekend."
, reflow
"So as community members gain wisdom through experience, we want\
\ them to share that through thoughtful API design and excellent\
\ documentation. It is more about sharing ideas and insights than\
\ just sharing code! The first step may be asking for advice from\
\ people you respect, or in community forums. The second step may\
\ be using it at work to see if it is as nice as you think. Maybe\
\ it ends up as an experiment on GitHub only. Point is, try to be\
\ respectful of the community and package ecosystem!"
, reflow
"Check out <https://package.elm-lang.org/help/design-guidelines> for guidance on how to create great packages!"
]
in
Terminal.Command "publish" Uncommon details example noArgs noFlags Publish.run
-- BUMP
bump :: Terminal.Command
bump =
let
details =
"The `bump` command figures out the next version number based on API changes:"
example =
reflow
"Say you just published version 1.0.0, but then decided to remove a function.\
\ I will compare the published API to what you have locally, figure out that\
\ it is a MAJOR change, and bump your version number to 2.0.0. I do this with\
\ all packages, so there cannot be MAJOR changes hiding in PATCH releases in Elm!"
in
Terminal.Command "bump" Uncommon details example noArgs noFlags Bump.run
-- DIFF
diff :: Terminal.Command
diff =
let
details =
"The `diff` command detects API changes:"
example =
stack
[ reflow
"For example, to see what changed in the HTML package between\
\ versions 1.0.0 and 2.0.0, you can say:"
, P.indent 4 $ P.green $ "elm diff elm/html 1.0.0 2.0.0"
, reflow
"Sometimes a MAJOR change is not actually very big, so\
\ this can help you plan your upgrade timelines."
]
diffArgs =
oneOf
[ require0 Diff.CodeVsLatest
, require1 Diff.CodeVsExactly version
, require2 Diff.LocalInquiry version version
, require3 Diff.GlobalInquiry package version version
]
in
Terminal.Command "diff" Uncommon details example diffArgs noFlags Diff.run
-- HELPERS
stack :: [P.Doc] -> P.Doc
stack docs =
P.vcat $ List.intersperse "" docs
reflow :: String -> P.Doc
reflow string =
P.fillSep $ map P.text $ words string