-
Notifications
You must be signed in to change notification settings - Fork 16
/
Copy pathMain.elm
151 lines (111 loc) · 4 KB
/
Main.elm
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
module Main where
import Json.Encode as Encode
import Json.Decode as Decode
import Task exposing (Task, andThen, onError)
import Console
import File
import Http
import Path
import Process
import Url
import Oracle
port main : Task String ()
port main =
case parsedArgs of
Help ->
Console.log usage
Warn message ->
emitError message
Search sourceFile query ->
tryCatch emitError <|
loadSource sourceFile
`andThen` \source -> loadDeps
`andThen` \deps -> Task.fromResult (parseDeps deps)
`andThen` \docPaths -> downloadDocs docPaths
`andThen` \_ -> loadDocs docPaths
--`andThen` \depsDocs -> getProjectDocs
--`andThen` \projectDocs -> Task.succeed (projectDocs ++ depsDocs)
`andThen` \docs -> Console.log (Oracle.search query source docs)
usage : String
usage = """elm-oracle 1.1.0
Usage: elm-oracle FILE query
Query for information about a token in an Elm file.
Available options:
-h,--help Show this help text."""
type Command = Help | Search String String | Warn String
parsedArgs : Command
parsedArgs =
case Process.args of
"-h" :: xs -> Help
"--help" :: xs -> Help
x1 :: x2 :: xs -> Search x1 x2
x :: [] -> Warn "You did not supply a query."
[] -> Warn "You did not supply a source file or query."
loadSource : String -> Task String String
loadSource path =
File.read (Path.normalize path)
`withError` ("Could not find the give source file: " ++ path)
loadDeps : Task String String
loadDeps =
File.read (Path.resolve ["elm-stuff", "exact-dependencies.json"])
`withError` "Dependencies file is missing. Perhaps you need to run `elm-package install`?"
type alias DocPaths = List { local : String, network : String, name : String }
parseDeps : String -> Result String DocPaths
parseDeps json =
let deps = Decode.decodeString (Decode.keyValuePairs Decode.string) json
buildDocPath (name, version) =
let docFile = "documentation.json"
local = Path.resolve ["elm-stuff", "packages", name, version, docFile]
network = Url.join ["http://package.elm-lang.org", "packages", name, version, docFile]
in
{ local = local, network = network, name = name }
in
case deps of
Ok packages -> Ok <| List.map buildDocPath packages
Err _ -> Err "Could not decode the dependencies file."
downloadDocs : DocPaths -> Task String (List ())
downloadDocs =
let test path =
(File.lstat path `andThen` \_ -> Task.succeed ()) `withError` path
pull path =
Http.get path `withError` ("Could not download docs from " ++ path)
write path data =
File.write path data `withError` ("Could not download docs to " ++ path)
download path =
test path.local
`onError` \_ -> pull path.network `andThen` write path.local
in
Task.sequence << List.map download
loadDocs : DocPaths -> Task String (List (String, String))
loadDocs =
let load path =
(File.read path.local `andThen` (Task.succeed << (,) path.name))
`withError` ("Could not load docs from " ++ path.local)
in
Task.sequence << List.map load
getProjectDocs : Task String (List (String, String))
getProjectDocs =
let path = Path.resolve ["elm-stuff", "documentation.json"]
generate =
Process.exec ("elm-make Main.elm --docs " ++ path)
`withError` "Failed to generate local project docs."
load =
File.read path
`withError` "Failed to load local project docs."
in
generate
`andThen` \_ -> load
`andThen` \docs -> Task.succeed [(path, docs)]
emitError : String -> Task x ()
emitError message =
let json =
[Encode.object [ ("error", Encode.string (message)) ]]
|> Encode.list
|> Encode.encode 0
in
Console.fatal json
withError : Task x a -> y -> Task y a
withError task error =
Task.mapError (\_ -> error) task
tryCatch : (x -> Task y a) -> Task x a -> Task y a
tryCatch = flip Task.onError