src/args.bend
bolt@1.27.0.0 · 186 lines · 26 definitions
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19import Base
20import shake@0.6.0.0/main.bend as Shake
21import bolt@1.27.0.0/src/version.bend as Ver
22import bolt@1.27.0.0/src/build_rev.bend as Rev
23import bolt@1.27.0.0/src/lazy/lazy.bend as Lazy
24
25
26
27def widen(ss: List<&1, String>) -> List<&2, String>:
28 match ss:
29 case Nil{}:
30 Nil{}
31 case Con{s, t}:
32 s <> widen(t)
33
34
35
36def args_of(ss: List<&1, String>) -> List<&2, String>:
37 match ss:
38 case Nil{}:
39 Nil{}
40 case Con{_prog, t}:
41 widen(t)
42
43
44def argv() -> IO(List<&2, String>):
45 do IO<List<&2, String>>:
46 ss : List<&1, String> <- IO.args()
47 return args_of(ss)
48
49
50def is_cmd(+ww: String) -> Bool:
51 Bool.or(String.eq(ww, "lint"), Bool.or(String.eq(ww, "check"), String.eq(ww, "lsp")))
52
53
54
55def asks_help(ws: List<&2, String>) -> Bool:
56 match ws:
57 case Nil{}:
58 False{}
59 case Con{+ww, rest}:
60 Lazy.and_then(Bool.not(String.eq(ww, "--")), _u => Lazy.or_else(String.eq(ww, "--help"), _v => asks_help(rest)))
61
62
63
64def help_path(ws: List<&2, String>) -> List<&2, String>:
65 match ws:
66 case Nil{}:
67 Nil{}
68 case Con{+ww, rest}:
69 Lazy.either(List<&2, String>, String.eq(ww, "--help"), _u => help_path(rest),
70 _u => Bool.pick(List<&2, String>, is_cmd(ww), [ww], []))
71
72
73def line.at(ask: Bool, +ws: List<&2, String>) -> List<&2, String>:
74 match ask:
75 case True{}:
76 "help" <> help_path(ws)
77 case False{}:
78 ws
79
80
81
82def line(+ws: List<&2, String>) -> List<&2, String>:
83 line.at(asks_help(ws), ws)
84
85
86def spec.files(+help: String) -> Shake.Arg:
87 Shake.rest("files", help, False{}, None{}, [])
88
89
90def version.at(+rel: String, +rev: String) -> String:
91 Bool.pick(String, String.is_empty(rev), rel, rel ++ " (" ++ rev ++ ")")
92
93
94def version() -> String:
95 version.at(Ver.text(), Rev.text())
96
97
98def spec() -> Shake.Cli:
99 Shake.app("bolt", "A linter, checker and language server for Bend 2.", Some{version()},
100 [Shake.flag("version", None{}, Some{"version"}, "Print the version"),
101 spec.files("Files to lint")],
102 [Shake.sub("lint", "Lint files", [spec.files("Files to lint")], []),
103 Shake.sub("check", "Check files", [spec.files("Files to check")], []),
104 Shake.sub("lsp", "Serve an editor over stdio", [], [])])
105
106
107def parse(av: List<&2, String>) -> Result<&2, &2, Shake.ParseErr, Shake.Matched>:
108 Shake.parse(spec(), av)
109
110
111def help_text(path: List<&2, String>) -> String:
112 Shake.help(spec(), path)
113
114
115def err_text(ee: Shake.ParseErr) -> String:
116 Shake.err_text(spec(), ee)
117
118
119type Cmd is Data:
120 CLint{}
121 CCheck{}
122 CLsp{}
123
124
125def command(+name: String) -> Cmd:
126 Bool.pick(Cmd, String.eq(name, "check"), CCheck{},
127 Bool.pick(Cmd, String.eq(name, "lsp"), CLsp{}, CLint{}))
128
129
130type Stream is Data:
131 Line{}
132 Page{}
133 Err{}
134
135
136
137type Out is Data:
138 Stop{to: Stream, text: String, code: U32}
139 Go{cmd: Cmd, paths: List<&2, String>}
140
141
142
143
144def files.at(sel: Maybe<&2, Shake.Matched>, +mm: Shake.Matched) -> List<&2, String>:
145 match sel:
146 case Some{ss}:
147 Shake.get_all(ss, "files")
148 case None{}:
149 Shake.get_all(mm, "files")
150
151
152def files(+mm: Shake.Matched) -> List<&2, String>:
153 files.at(Shake.at(mm, Shake.path_of(mm)), mm)
154
155
156def out.run(ask: Bool, +mm: Shake.Matched) -> Out:
157 match ask:
158 case True{}:
159 Stop{Line{}, "bolt " ++ version(), 0}
160 case False{}:
161 Go{command(String.join(Shake.path_of(mm), "/")), files(mm)}
162
163
164
165def out.fail.at(asked: Maybe<&2, List<&2, String>>, +ee: Shake.ParseErr) -> Out:
166 match asked:
167 case Some{path}:
168 Stop{Page{}, help_text(path), 0}
169 case None{}:
170 Stop{Err{}, err_text(ee), 1}
171
172
173def out.fail(+ee: Shake.ParseErr) -> Out:
174 out.fail.at(Shake.help_path(ee), ee)
175
176
177def out.done(+mm: Shake.Matched) -> Out:
178 out.run(Shake.on(mm, "version"), mm)
179
180
181def out(rr: Result<&2, &2, Shake.ParseErr, Shake.Matched>) -> Out:
182 match rr:
183 case Fail{e}:
184 out.fail(e)
185 case Done{m}:
186 out.done(m)