-
Notifications
You must be signed in to change notification settings - Fork 9
/
hello.gleam
300 lines (285 loc) · 9.78 KB
/
hello.gleam
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
//// This module demonstrates a simple glint app with 2 commands
////
//// ## Usage
////
//// ### Running the application
////
//// You can run this example with `gleam run -m examples/hello -- <NAMES>` from the root of the repo
////
//// The application prints: `Hello, <NAMES>!`
//// The `hello` application accepts at least one argument, being the names of people to say hello to.
//// - No input: `gleam run` -> prints "Hello, Joe!"
//// - One input: `gleam run Joe` -> prints "Hello, Joe!"
//// - Two inputs: `gleam run Rob Louis` -> prints "Hello, Rob and Louis!"
//// - \>2 inputs: `gleam run Rob Louis Hayleigh` -> prints "Hello, Rob, Louis and Hayleigh!"
////
//// ### Flags
////
//// All commands accepts two flags:
//// - `--caps`: capitalizes the output, so if output would be "Hello, Joe!" it prints "HELLO, JOE!"
//// - `--repeat=N`: repeats the output N times separated , so with N=2 if output would be "Hello, Joe!" it prints "Hello, Joe!\nHello, Joe!"
////
//// ### Help Text
////
//// Here is the help text for the root command:
////
//// ```txt
//// This module demonstrates a simple glint app with 2 commands
////
//// ## Usage
////
//// ### Running the application
////
//// You can run this example with `gleam run -m examples/hello -- <NAMES>` from the root of the repo
////
//// The application prints: `Hello, <NAMES>!`
//// The `hello` application accepts at least one argument, being the names of people to say hello to.
//// - No input: `gleam run` -> prints "Hello, Joe!"
//// - One input: `gleam run Joe` -> prints "Hello, Joe!"
//// - Two inputs: `gleam run Rob Louis` -> prints "Hello, Rob and Louis!"
//// - \>2 inputs: `gleam run Rob Louis Hayleigh` -> prints "Hello, Rob, Louis and Hayleigh!"
////
//// ### Flags
////
//// All commands accepts two flags:
//// - `--caps`: capitalizes the output, so if output would be "Hello, Joe!" it prints "HELLO, JOE!"
//// - `--repeat=N`: repeats the output N times separated , so with N=2 if output would be "Hello, Joe!" it prints "Hello, Joe!\nHello, Joe!"
////
//// ### Help Text
////
//// Here is the help text for the root command:
////
//// ```txt
//// This module demonstrates a simple glint app with 2 commands
////
//// ## Usage
////
//// ### Running the application
////
//// You can run this example with `gleam run -m examples/hello -- <NAMES>` from the root of the repo
////
//// The application prints: `Hello, <NAMES>!`
//// The `hello` application accepts at least one argument, being the names of people to say hello to.
//// - No input: `gleam run` -> prints "Hello, Joe!"
//// - One input: `gleam run Joe` -> prints "Hello, Joe!"
//// - Two inputs: `gleam run Rob Louis` -> prints "Hello, Rob and Louis!"
//// - \>2 inputs: `gleam run Rob Louis Hayleigh` -> prints "Hello, Rob, Louis and Hayleigh!"
////
//// ### Flags
////
//// All commands accepts two flags:
//// - `--caps`: capitalizes the output, so if output would be "Hello, Joe!" it prints "HELLO, JOE!"
//// - `--repeat=N`: repeats the output N times separated , so with N=2 if output would be "Hello, Joe!" it prints "Hello, Joe!\nHello, Joe!"
////
//// ### Help Text
////
//// Here is the help text for the root command:
////
//// ```txt
//// This module demonstrates a simple glint app with 2 commands
////
//// ## Usage
////
//// ### Running the application
////
//// You can run this example with `gleam run -m examples/hello -- <NAMES>` from the root of the repo
////
//// The application prints: `Hello, <NAMES>!`
//// The `hello` application accepts at least one argument, being the names of people to say hello to.
//// - No input: `gleam run` -> prints "Hello, Joe!"
//// - One input: `gleam run Joe` -> prints "Hello, Joe!"
//// - Two inputs: `gleam run Rob Louis` -> prints "Hello, Rob and Louis!"
//// - \>2 inputs: `gleam run Rob Louis Hayleigh` -> prints "Hello, Rob, Louis and Hayleigh!"
////
//// ### Flags
////
//// All commands accepts two flags:
//// - `--caps`: capitalizes the output, so if output would be "Hello, Joe!" it prints "HELLO, JOE!"
//// - `--repeat=N`: repeats the output N times separated , so with N=2 if output would be "Hello, Joe!" it prints "Hello, Joe!\nHello, Joe!"
////
//// ### Help Text
////
//// Here is the help text for the root command:
////
//// ```txt
//// This module demonstrates a simple glint app with 2 commands
////
//// ## Usage
////
//// ### Running the application
////
//// You can run this example with `gleam run -m examples/hello -- <NAMES>` from the root of the repo
////
//// The application prints: `Hello, <NAMES>!`
//// The `hello` application accepts at least one argument, being the names of people to say hello to.
//// - No input: `gleam run` -> prints "Hello, Joe!"
//// - One input: `gleam run Joe` -> prints "Hello, Joe!"
//// - Two inputs: `gleam run Rob Louis` -> prints "Hello, Rob and Louis!"
//// - \>2 inputs: `gleam run Rob Louis Hayleigh` -> prints "Hello, Rob, Louis and Hayleigh!"
////
//// ### Flags
////
//// All commands accepts two flags:
//// - `--caps`: capitalizes the output, so if output would be "Hello, Joe!" it prints "HELLO, JOE!"
//// - `--repeat=N`: repeats the output N times separated , so with N=2 if output would be "Hello, Joe!" it prints "Hello, Joe!\nHello, Joe!"
////
//// ### Help Text
////
//// Here is the help text for the root command:
////
//// ```txt
//// It's time to say hello!
////
//// Prints Hello, <names>!
////
//// USAGE:
//// gleam run -m examples/hello ( single ) [ 1 or more arguments ] [
//// --caps=<BOOL> --repeat=<INT> ]
////
//// FLAGS:
//// --caps=<BOOL> Capitalize the hello message
//// --help Print help information
//// --repeat=<INT> Repeat the message n-times
////
//// SUBCOMMANDS:
//// single Prints Hello, <name>!
//// ```
////
//// Here is the help text for the `single` command:
////
//// ```
//// It's time to say hello!
////
//// Command: single
////
//// Prints Hello, <name>!
////
//// USAGE:
//// gleam run -m examples/hello single <name> [ --caps=<BOOL> --repeat=<INT> ]
////
//// FLAGS:
//// --caps=<BOOL> Capitalize the hello message
//// --help Print help information
//// --repeat=<INT> Repeat the message n-times
//// ```
// stdlib imports
import gleam/io
import gleam/list
import gleam/string.{uppercase}
// external dep imports
import snag
// glint imports
import argv
import glint
// ----- APPLICATION LOGIC -----
/// a helper function to join a list of names
fn join_names(names: List(String)) -> String {
case names {
[] -> ""
_ -> do_join_names(names, "")
}
}
// tail-recursive implementation of join_naemes
fn do_join_names(names: List(String), acc: String) {
case names {
[] -> acc
[a] -> acc <> " and " <> a
[a, ..b] -> do_join_names(b, acc <> ", " <> a)
}
}
pub fn capitalize(msg, caps) -> String {
case caps {
True -> uppercase(msg)
False -> msg
}
}
/// hello is a function that says hello
pub fn hello(
primary: String,
rest: List(String),
caps: Bool,
repeat: Int,
) -> String {
{ "Hello, " <> primary <> join_names(rest) <> "!" }
|> capitalize(caps)
|> list.repeat(repeat)
|> string.join("\n")
}
// ----- CLI SETUP -----
/// a boolean flag with default False to control message capitalization.
///
pub fn caps_flag() -> glint.Flag(Bool) {
glint.bool_flag("caps")
|> glint.flag_default(False)
|> glint.flag_help("Capitalize the hello message")
}
/// an int flag with default 1 to control how many times to repeat the message.
/// this flag is constrained to values greater than 0.
///
pub fn repeat_flag() -> glint.Flag(Int) {
use n <- glint.flag_constraint(
glint.int_flag("repeat")
|> glint.flag_default(1)
|> glint.flag_help("Repeat the message n-times"),
)
case n {
_ if n > 0 -> Ok(n)
_ -> snag.error("Value must be greater than 0.")
}
}
/// the command function that will be executed as the root command
///
pub fn hello_cmd() -> glint.Command(String) {
use <- glint.command_help("Prints Hello, <names>!")
use <- glint.unnamed_args(glint.MinArgs(1))
use _, args, flags <- glint.command()
let assert Ok(caps) = glint.get_flag(flags, caps_flag())
let assert Ok(repeat) = glint.get_flag(flags, repeat_flag())
let assert [name, ..rest] = args
hello(name, rest, caps, repeat)
}
/// the command function that will be executed as the "single" command
///
pub fn hello_single_cmd() -> glint.Command(String) {
use <- glint.command_help("Prints Hello, <name>!")
use <- glint.unnamed_args(glint.EqArgs(0))
use name <- glint.named_arg("name")
use named_args, _, flags <- glint.command()
let assert Ok(caps) = glint.get_flag(flags, caps_flag())
let assert Ok(repeat) = glint.get_flag(flags, repeat_flag())
let name = name(named_args)
hello(name, [], caps, repeat)
}
// the function that describes our cli structure
pub fn app() {
// create a new glint instance
glint.new()
// with an app name of "hello", this is used when printing help text
|> glint.with_name("examples/hello")
// apply global help text to all commands
|> glint.global_help("It's time to say hello!")
// show in usage text that the current app is run as a gleam module
|> glint.as_module
// with pretty help enabled, using the built-in colours
|> glint.pretty_help(glint.default_pretty_help())
// with group level flags
// with flag `caps` for all commands (equivalent of using glint.global_flag)
|> glint.group_flag([], caps_flag())
// // with flag `repeat` for all commands (equivalent of using glint.global_flag)
|> glint.group_flag([], repeat_flag())
// with a root command that executes the `hello` function
|> glint.add(
// add the hello command to the root
at: [],
do: hello_cmd(),
)
|> glint.add(
// add the hello single command
at: ["single"],
do: hello_single_cmd(),
)
}
pub fn main() {
// run with a handler that prints the command output
glint.run_and_handle(app(), argv.load().arguments, io.println)
}