1
1
//// This module encodes a list of command line arguments as a `dynamic.Dynamic` and
2
- //// provides functions to decode those arguments using a `decode/zero .Decoder`.
2
+ //// provides functions to decode those arguments using a `dynamic/decode .Decoder`.
3
3
////
4
4
//// # Encoding
5
5
////
24
24
////
25
25
//// # Decoding
26
26
////
27
- //// Arguments can be decoded with a normal `zero .Decoder`
27
+ //// Arguments can be decoded with a normal `dynamic/decode .Decoder`
28
28
////
29
29
//// ```gleam
30
30
//// // args: --name Lucy --age 8 --enrolled true --class math --class art
31
31
////
32
32
//// let decoder = {
33
- //// use name <- zero .field("name", zero .string)
34
- //// use age <- zero .field("age", zero .int)
35
- //// use enrolled <- zero .field("enrolled", zero .bool)
36
- //// use classes <- zero .field("class", zero .list(zero .string))
37
- //// zero .success(Student(name:, age:, enrolled:, classes:))
33
+ //// use name <- decode .field("name", decode .string)
34
+ //// use age <- decode .field("age", decode .int)
35
+ //// use enrolled <- decode .field("enrolled", decode .bool)
36
+ //// use classes <- decode .field("class", decode .list(decode .string))
37
+ //// decode .success(Student(name:, age:, enrolled:, classes:))
38
38
//// }
39
39
////
40
40
//// let result = clad.decode(args, decoder)
55
55
//// // args: --name Lucy --age 8 --enrolled true --class math
56
56
////
57
57
//// let decoder = {
58
- //// use name <- zero .field("name", zero .string)
59
- //// use age <- zero .field("age", zero .int)
60
- //// use enrolled <- zero .field("enrolled", zero .bool)
61
- //// use classes <- zero .field("class", clad.list(zero .string))
62
- //// zero .success(Student(name:, age:, enrolled:, classes:))
58
+ //// use name <- decode .field("name", decode .string)
59
+ //// use age <- decode .field("age", decode .int)
60
+ //// use enrolled <- decode .field("enrolled", decode .bool)
61
+ //// use classes <- decode .field("class", clad.list(decode .string))
62
+ //// decode .success(Student(name:, age:, enrolled:, classes:))
63
63
//// }
64
64
////
65
65
//// let result = clad.decode(args, decoder)
66
66
//// assert result == Ok(Student("Lucy", 8, True, ["math"]))
67
67
//// ```
68
- //// ## Boolean Flags
69
- ////
70
- //// CLI's commonly represent boolean flags just by the precense or absence of the
71
- //// option. Since Clad has no knowledge of your target record, it cannot encode
72
- //// missing flags as False.
73
- ////
74
- //// Clad provides the `flag()` decoder to handle this case.
75
- ////
76
- //// ```gleam
77
- //// // args1: --name Lucy --age 8 --class math --class art --enrolled
78
- //// // args2: --name Bob --age 3 --class math
79
- ////
80
- //// let decoder = {
81
- //// use name <- zero.field("name", zero.string)
82
- //// use age <- zero.field("age", zero.int)
83
- //// use enrolled <- zero.field("enrolled", clad.flag())
84
- //// use classes <- zero.field("class", clad.list(zero.string))
85
- //// zero.success(Student(name:, age:, enrolled:, classes:))
86
- //// }
87
- ////
88
- //// let result = clad.decode(args1, decoder)
89
- //// assert result == Ok(Student("Lucy", 8, True, ["math", "art"]))
90
- ////
91
- //// let result = clad.decode(args2, decoder)
92
- //// assert result == Ok(Student("Bob", 3, False, ["math"]))
93
- //// ```
94
- ////
95
68
//// ## Alternate Names
96
69
////
97
70
//// It is also common for CLI's to support long names and short names for options
100
73
//// Clad provides the `opt()` function for this.
101
74
////
102
75
//// ```gleam
103
- //// // args1: -n Lucy -a 8 -e -c math -c art
104
- //// // args2: --name Bob --age 3 --class math
76
+ //// // args1: -n Lucy -a 8 -e true -c math -c art
77
+ //// // args2: --name Bob --age 3 --enrolled false -- class math
105
78
////
106
79
//// let decoder = {
107
- //// use name <- clad.opt(long_name: "name", short_name: "n", zero .string)
108
- //// use age <- clad.opt(long_name: "age", short_name: "a", zero .int)
109
- //// use enrolled <- clad.opt(long_name: "enrolled", short_name: "e" clad.flag() )
110
- //// use classes <- clad.opt(long_name: "class", short_name: "c", clad.list(zero .string))
111
- //// zero .success(Student(name:, age:, enrolled:, classes:))
80
+ //// use name <- clad.opt(long_name: "name", short_name: "n", decode .string)
81
+ //// use age <- clad.opt(long_name: "age", short_name: "a", decode .int)
82
+ //// use enrolled <- clad.opt(long_name: "enrolled", short_name: "e", decode.bool )
83
+ //// use classes <- clad.opt(long_name: "class", short_name: "c", clad.list(decode .string))
84
+ //// decode .success(Student(name:, age:, enrolled:, classes:))
112
85
//// }
113
86
////
114
87
//// let result = clad.decode(args1, decoder)
117
90
//// let result = clad.decode(args2, decoder)
118
91
//// assert result == Ok(Student("Bob", 3, False, ["math"]))
119
92
//// ```
93
+ //// ## Boolean Flags
120
94
////
121
- //// ## Positional Arguments
95
+ //// CLI's commonly represent boolean flags just by the precense or absence of the
96
+ //// option. Since Clad has no knowledge of your target record, it cannot encode
97
+ //// missing flags as False.
122
98
////
123
- //// A CLI may also support positional arguments. These are any arguments that are
124
- //// not attributed to a named option. Clad provides the `positional_arguments()` decoder to
125
- //// retrieve these values. All arguments followed by a `--` will be added to the positional arguemnts.
99
+ //// Clad provides the `flag()` decoder to handle this case.
126
100
////
127
101
//// ```gleam
128
- //// // args1: -n Lucy -ea8 -c math -c art -- Lucy is a star student!
129
- //// // args2: --name Bob who is --age 3 --class math Bob -- -idk
102
+ //// // args1: --name Lucy --age 8 --class math --class art --enrolled
103
+ //// // args2: --name Bob --age 3 --class math
130
104
////
131
105
//// let decoder = {
132
- //// use name <- clad.opt("name", "n", zero.string)
133
- //// use age <- clad.opt("age", "a", zero.int)
134
- //// use enrolled <- clad.opt("enrolled", "e" clad.flag())
135
- //// use classes <- clad.opt(long_name: "class", short_name: "c", clad.list(zero.string))
136
- //// use notes <- clad.positional_arguments()
137
- //// let notes = string.join(notes, " ")
138
- //// zero.success(Student(name:, age:, enrolled:, classes:, notes:))
106
+ //// use name <- clad.opt(long_name: "name", short_name: "n", decode.string)
107
+ //// use age <- clad.opt(long_name: "age", short_name: "a", decode.int)
108
+ //// use enrolled <- clad.flag(long_name: "enrolled", short_name: "e")
109
+ //// use classes <- clad.opt(long_name: "class", short_name: "c", clad.list(decode.string))
110
+ //// decode.success(Student(name:, age:, enrolled:, classes:))
139
111
//// }
140
112
////
141
113
//// let result = clad.decode(args1, decoder)
142
- //// let assert Ok(Student(
143
- //// "Lucy",
144
- //// 8,
145
- //// True,
146
- //// ["math", "art"],
147
- //// "Lucy is a star student!",
148
- //// )) = result
114
+ //// assert result == Ok(Student("Lucy", 8, True, ["math", "art"]))
149
115
////
150
116
//// let result = clad.decode(args2, decoder)
151
- //// assert result == Ok(Student("Bob", 3, False, ["math"], "who is Bob -idk" ))
117
+ //// assert result == Ok(Student("Bob", 3, False, ["math"]))
152
118
//// ```
153
119
154
- import decode/zero . { type Decoder }
155
120
import gleam/dict . { type Dict }
156
- import gleam/dynamic . { type Dynamic }
121
+ import gleam/dynamic
122
+ import gleam/dynamic/decode . { type DecodeError , type Decoder , type Dynamic }
157
123
import gleam/float
158
124
import gleam/int
159
125
import gleam/list
@@ -182,8 +148,8 @@ type State {
182
148
/// // args: --name Lucy [email protected]
183
149
///
184
150
/// let decoder = {
185
- /// use name <- zero .field("name", dynamic.string)
186
- /// use email <- zero .field("email", dynamic.string),
151
+ /// use name <- decode .field("name", dynamic.string)
152
+ /// use email <- decode .field("email", dynamic.string),
187
153
/// clad.decoded(SignUp(name:, email:))
188
154
/// }
189
155
///
@@ -193,10 +159,10 @@ type State {
193
159
pub fn decode (
194
160
args : List ( String ) ,
195
161
decoder : Decoder ( t) ,
196
- ) -> Result ( t, List ( dynamic . DecodeError ) ) {
162
+ ) -> Result ( t, List ( DecodeError ) ) {
197
163
parse ( args )
198
164
|> to_dynamic
199
- |> zero . run ( decoder )
165
+ |> decode . run ( decoder )
200
166
}
201
167
202
168
/// Get all of the unnamed, positional arguments
@@ -205,7 +171,7 @@ pub fn decode(
205
171
/// ```gleam
206
172
/// let decoder = {
207
173
/// use positional <- clad.positional_arguments
208
- /// zero .success(positional)
174
+ /// decode .success(positional)
209
175
/// }
210
176
/// let result = clad.decode(["-a1", "hello", "-b", "2", "world"], decoder)
211
177
/// assert result == Ok(["hello", "world"])
@@ -219,15 +185,15 @@ pub fn decode(
219
185
pub fn positional_arguments (
220
186
next : fn ( List ( String ) ) -> Decoder ( final) ,
221
187
) -> Decoder ( final) {
222
- use args <- zero . field ( positional_arg_name , zero . list ( zero . string ) )
188
+ use args <- decode . field ( positional_arg_name , decode . list ( decode . string ) )
223
189
next ( args )
224
190
}
225
191
226
192
/// Decode a command line flag as a Bool. Returns False if value is not present
227
193
/// ```gleam
228
194
/// let decoder = {
229
- /// use verbose <- clad.flag("verbose", "v", clad.flag() )
230
- /// zero .success(verbose)
195
+ /// use verbose <- clad.flag("verbose", "v", decode.bool )
196
+ /// decode .success(verbose)
231
197
/// }
232
198
/// let result = clad.decode(["-v"], decoder)
233
199
/// assert result == Ok(True)
@@ -243,10 +209,10 @@ pub fn flag(
243
209
short_name : String ,
244
210
next : fn ( Bool ) -> Decoder ( final) ,
245
211
) -> Decoder ( final) {
246
- use value <- optional_field ( long_name , zero . bool )
212
+ use value <- optional_field ( long_name , decode . bool )
247
213
case value {
248
214
Some ( v ) -> next ( v )
249
- None -> zero . optional_field ( short_name , False , zero . bool , next )
215
+ None -> decode . optional_field ( short_name , False , decode . bool , next )
250
216
}
251
217
}
252
218
@@ -255,14 +221,14 @@ fn optional_field(
255
221
field_decoder : Decoder ( t) ,
256
222
next : fn ( Option ( t) ) -> Decoder ( final) ,
257
223
) -> Decoder ( final) {
258
- zero . optional_field ( field_name , None , zero . optional ( field_decoder ) , next )
224
+ decode . optional_field ( field_name , None , decode . optional ( field_decoder ) , next )
259
225
}
260
226
261
227
/// Decode a command line option by either a long name or short name
262
228
/// ```gleam
263
229
/// let decoder = {
264
- /// use name <- clad.opt("name", "n", zero .string)
265
- /// zero .success(name)
230
+ /// use name <- clad.opt("name", "n", decode .string)
231
+ /// decode .success(name)
266
232
/// }
267
233
///
268
234
/// let result = clad.decode(["--name", "Lucy"], decoder)
@@ -280,7 +246,7 @@ pub fn opt(
280
246
use value <- optional_field ( long_name , field_decoder )
281
247
case value {
282
248
Some ( v ) -> next ( v )
283
- None -> zero . field ( short_name , field_decoder , next )
249
+ None -> decode . field ( short_name , field_decoder , next )
284
250
}
285
251
}
286
252
@@ -289,15 +255,15 @@ pub fn opt(
289
255
/// encoded as the inner type rather than a list.
290
256
/// ```gleam
291
257
/// let decoder = {
292
- /// use classes <- zero .field("class", clad.list(zero .string))
293
- /// zero .success(classes)
258
+ /// use classes <- decode .field("class", clad.list(decode .string))
259
+ /// decode .success(classes)
294
260
/// }
295
261
/// let result = clad.decode(["--class", "art"], decoder)
296
262
/// assert result == Ok(["art"])
297
263
/// ```
298
264
pub fn list ( of inner : Decoder ( a) ) -> Decoder ( List ( a) ) {
299
- let single = inner |> zero . map ( list . wrap )
300
- zero . one_of ( zero . list ( inner ) , [ single ] )
265
+ let single = inner |> decode . map ( list . wrap )
266
+ decode . one_of ( decode . list ( inner ) , [ single ] )
301
267
}
302
268
303
269
fn parse ( args : List ( String ) ) -> State {
0 commit comments