Skip to content

Commit

Permalink
Merge pull request #3 from ryanmiville/minimist
Browse files Browse the repository at this point in the history
minimist
  • Loading branch information
ryanmiville authored Nov 8, 2024
2 parents 6b0fb48 + 8cc4972 commit 2e25be6
Show file tree
Hide file tree
Showing 10 changed files with 509 additions and 896 deletions.
106 changes: 39 additions & 67 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,11 @@

Command line argument decoders for Gleam.

- Clad provides primitives to build a `dynamic.Decoder` for command line arguments.
- Arguments can be specified with long names (`--name`) or short names (`-n`).
- Values are decoded in the form `--name value` or `--name=value`.
- Boolean flags do not an explicit value. If the flag exists it is `True`, and if it is missing it is `False`. (i.e. `--verbose`)
Clad aims to make it as easy as possible to parse command line arguments in
Gleam. The goal is to support simple to medium complexity command line
interfaces while staying as minimal as possible. It is inspired by
[minimist](https://github.com/minimistjs/minimist) and
[gleam/json](https://hexdocs.pm/gleam_json/)


## Usage
Expand All @@ -24,80 +25,51 @@ This program is in the [examples directory](https://github.com/ryanmiville/clad/
```gleam
import argv
import clad
import gleam/bool
import gleam/dynamic
import gleam/int
import gleam/io
import gleam/string
type Order {
Order(flavors: List(String), scoops: Int, cone: Bool)
}
import decode/zero
fn order_decoder() {
use flavors <- clad.arg("flavor", "f", dynamic.list(dynamic.string))
use scoops <- clad.arg_with_default("scoops", "s", dynamic.int, default: 1)
use cone <- clad.toggle("cone", "c")
clad.decoded(Order(flavors:, scoops:, cone:))
pub type Student {
Student(name: String, age: Int, enrolled: Bool, classes: List(String))
}
pub fn main() {
let order =
order_decoder()
|> clad.decode(argv.load().arguments)
case order {
Ok(order) -> take_order(order)
_ ->
io.println(
"
Options:
-f, --flavor <FLAVOR> Flavors of ice cream
-s, --scoops <SCOOPS> Number of scoops per flavor [default: 1]
-c, --cone Put ice cream in a cone
",
)
let decoder = {
use name <- zero.field("name", zero.string)
use age <- zero.field("age", zero.int)
use enrolled <- zero.field("enrolled", zero.bool)
use classes <- clad.positional_arguments()
zero.success(Student(name:, age:, enrolled:, classes:))
}
}
fn take_order(order: Order) {
let scoops = bool.guard(order.scoops == 1, " scoop", fn() { " scoops" })
let container = bool.guard(order.cone, "cone", fn() { "cup" })
let flavs = string.join(order.flavors, " and ")
io.println(
int.to_string(order.scoops)
<> scoops
<> " of "
<> flavs
<> " in a "
<> container
<> ", coming right up!",
)
// args: --name Lucy --age 8 --enrolled true math science art
let result = clad.decode(argv.load().arguments, decoder)
let assert Ok(Student("Lucy", 8, True, ["math", "science", "art"])) = result
}
```

Run the program
Or, for more flexibility:

```sh
❯ gleam run -m examples/ice_cream -- -f vanilla
1 scoop of vanilla in a cup, coming right up!
❯ gleam run -m examples/ice_cream -- --flavor vanilla --flavor chocolate
1 scoop of vanilla and chocolate in a cup, coming right up!
❯ gleam run -m examples/ice_cream -- --flavor vanilla --flavor chocolate --scoops 2 --cone
2 scoops of vanilla and chocolate in a cone, coming right up!
❯ gleam run -m examples/ice_cream --

Options:
-f, --flavor <FLAVOR> Flavors of ice cream
-s, --scoops <SCOOPS> Number of scoops per flavor [default: 1]
-c, --cone Put ice cream in a cone
```
```gleam
import argv
import clad
import decode/zero
## Roadmap
pub type Student {
Student(name: String, age: Int, enrolled: Bool, classes: List(String))
}
pub fn main() {
let decoder = {
use name <- clad.opt("name", "n", zero.string)
use age <- clad.opt("age", "a", zero.int)
use enrolled <- clad.opt("enrolled", "e", clad.flag())
use classes <- clad.positional_arguments()
zero.success(Student(name:, age:, enrolled:, classes:))
}
- [ ] Settle on general API
- [ ] Add support for positional arguments
- [ ] Add support for subcommands
- [ ] Add support for environment variables
// args: --name=Lucy -ea8 math science art
let result = clad.decode(argv.load().arguments, decoder)
let assert Ok(Student("Lucy", 8, True, ["math", "science", "art"])) = result
}
```

Further documentation can be found at <https://hexdocs.pm/clad>.
4 changes: 3 additions & 1 deletion gleam.toml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
name = "clad"
version = "0.1.5"
version = "0.2.0"

# Fill out these fields if you intend to generate HTML documentation or publish
# your project to the Hex package manager.
Expand All @@ -14,7 +14,9 @@ repository = { type = "github", user = "ryanmiville", repo = "clad" }

[dependencies]
gleam_stdlib = ">= 0.34.0 and < 2.0.0"
decode = ">= 0.4.1 and < 1.0.0"

[dev-dependencies]
gleeunit = ">= 1.0.0 and < 2.0.0"
argv = ">= 1.0.2 and < 2.0.0"
gleam_json = ">= 2.0.0 and < 3.0.0"
4 changes: 4 additions & 0 deletions manifest.toml
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,15 @@

packages = [
{ name = "argv", version = "1.0.2", build_tools = ["gleam"], requirements = [], otp_app = "argv", source = "hex", outer_checksum = "BA1FF0929525DEBA1CE67256E5ADF77A7CDDFE729E3E3F57A5BDCAA031DED09D" },
{ name = "decode", version = "0.4.1", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "decode", source = "hex", outer_checksum = "90C83E830B380EAF64A0A20D0116C4C173AD753594AF1A37E692C1A699244244" },
{ name = "gleam_json", version = "2.0.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "gleam_json", source = "hex", outer_checksum = "CB10B0E7BF44282FB25162F1A24C1A025F6B93E777CCF238C4017E4EEF2CDE97" },
{ name = "gleam_stdlib", version = "0.40.0", build_tools = ["gleam"], requirements = [], otp_app = "gleam_stdlib", source = "hex", outer_checksum = "86606B75A600BBD05E539EB59FABC6E307EEEA7B1E5865AFB6D980A93BCB2181" },
{ name = "gleeunit", version = "1.2.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "gleeunit", source = "hex", outer_checksum = "F7A7228925D3EE7D0813C922E062BFD6D7E9310F0BEE585D3A42F3307E3CFD13" },
]

[requirements]
argv = { version = ">= 1.0.2 and < 2.0.0" }
decode = { version = ">= 0.4.1 and < 1.0.0" }
gleam_json = { version = ">= 2.0.0 and < 3.0.0" }
gleam_stdlib = { version = ">= 0.34.0 and < 2.0.0" }
gleeunit = { version = ">= 1.0.0 and < 2.0.0" }
Loading

0 comments on commit 2e25be6

Please sign in to comment.