Skip to content

Commit

Permalink
release: 0.9.0
Browse files Browse the repository at this point in the history
  • Loading branch information
joshstoik1 committed Oct 15, 2024
2 parents 2d97404 + 44e8884 commit e421e9a
Show file tree
Hide file tree
Showing 16 changed files with 933 additions and 248 deletions.
28 changes: 28 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,34 @@



## [0.9.0](https://github.com/Blobfolio/argyle/releases/tag/v0.9.0) - 2024-10-14

This release introduces a brand new streaming version of the argument parser `Argue`. It is simpler and cleaner, but works completely differently than the original.

Sorry about that!

Old and new are both present in this release to ease the transition, but projects should migrate to the new version (or another crate) when convenient as the duality won't last.

### New

* `argyle::stream::args`
* `argyle::stream::Argue`
* `argyle::stream::Argument`
* `argyle::stream::ArgyleError`

### Changed

* Bump MSRV to `1.81`
* Update lints

### Deprecated

* `argyle::Argue`
* `argyle::ArgyleError`
* `argyle::KeyKind`



## [0.8.1](https://github.com/Blobfolio/argyle/releases/tag/v0.8.1) - 2024-09-05

### Changed
Expand Down
4 changes: 2 additions & 2 deletions CREDITS.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Project Dependencies
Package: argyle
Version: 0.8.1
Generated: 2024-09-05 18:45:10 UTC
Version: 0.9.0
Generated: 2024-10-14 21:16:53 UTC

This package has no dependencies.
20 changes: 2 additions & 18 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
[package]
name = "argyle"
version = "0.8.1"
version = "0.9.0"
authors = ["Blobfolio, LLC. <[email protected]>"]
edition = "2021"
rust-version = "1.70"
rust-version = "1.81"
description = "A lightweight, agnostic CLI argument parser."
license = "WTFPL"
repository = "https://github.com/Blobfolio/argyle"
Expand Down Expand Up @@ -31,24 +31,8 @@ bash-dir = "./"
man-dir = "./"
credits-dir = "./"

[dev-dependencies]
brunch = "0.5.*"

[[bench]]
name = "fm_keykind"
harness = false

[[bench]]
name = "fm_argue"
harness = false

[features]
default = []

# Enables ArgyleError::WantsDynamicHelp variant.
dynamic-help = []

[profile.bench]
lto = false
codegen-units = 1
opt-level = 3
85 changes: 50 additions & 35 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,13 @@
[![license](https://img.shields.io/badge/license-wtfpl-ff1493?style=flat-square)](https://en.wikipedia.org/wiki/WTFPL)
[![contributions welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg?style=flat-square&label=contributions)](https://github.com/Blobfolio/argyle/issues)

This crate contains an agnostic CLI argument parser for Unix platforms called `Argue`. Unlike more robust libraries like [clap](https://crates.io/crates/clap), `Argue` does not hold information about expected or required arguments; it merely parses the raw arguments (`std::env::args_os`) into a consistent state so the implementor can query them as needed.
This crate provides a simple streaming CLI argument parser/iterator called `Argue`, offering a middle ground between the standard library's barebones `std::env::args_os` helper and full-service crates like [clap](https://crates.io/crates/clap).

Post-processing is an exercise largely left to the implementing library to do in its own way, in its own time. [`Argue`] exposes several methods for quickly querying the individual pieces of the set, but it can also be dereferenced to a slice or consumed into an owned vector for fully manual processing if desired.
`Argue` performs some basic normalization — it handles string conversion in a non-panicking way, recognizes shorthand value assignments like `-kval`, `-k=val`, `--key=val`, and handles end-of-command (`--`) arguments — and will help identify any special subcommands and/or keys/values expected by your app.

Arguments are processed and held as owned bytes rather than (os)strings, again leaving the choice of later conversion entirely up to the implementor.
The subsequent validation and handling, however, are left _entirely up to you_. Loop, match, and proceed however you see fit.

For simple applications, this agnostic approach can significantly reduce the overhead of processing CLI arguments, but because handling is left to the implementing library, it might be too tedious or limiting for more complex use cases.
If that sounds terrible, just use [clap](https://crates.io/crates/clap) instead. Haha.



Expand All @@ -24,53 +24,68 @@ Add `argyle` to your `dependencies` in `Cargo.toml`, like:

```
[dependencies]
argyle = "0.8.*"
argyle = "0.9.*"
```



## Example

A general setup might look something like the following. Refer to the documentation for `Argue` for more information, caveats, etc.
A general setup might look something like the following.

Refer to the documentation for `Argue` for more information, caveats, etc.

```rust
use argyle::{
Argue,
ArgyleError,
FLAG_HELP,
FLAG_REQUIRED,
FLAG_VERSION,
};
use argyle::stream::Argument;
use std::path::PathBuf;

#[derive(Debug, Clone, Default)]
/// # Configuration.
struct Settings {
threads: usize,
verbose: bool,
paths: Vec<PathBuf>,
}

fn main() {
if let Err(e) = _main() {
match(e) {
// A "-V" or "--version" flag was present.
Err(ArgyleError::WantsVersion) => {
println!("MyApp v{}", env!("CARGO_PKG_VERSION"));
let args = argyle::stream::args()
.with_keys([
("-h", false), // Boolean flag.
("--help", false), // Boolean flag.
("--threads", true), // Expects a value.
("--verbose", false), // Boolean flag.
])
.unwrap(); // An error will only occur if a
// duplicate or invalid key is declared.

// Loop and handle!
let mut settings = Settings::default();
for arg in args {
match arg {
Argument::Key("-h" | "--help") => {
println!("Help Screen Goes Here.");
return;
},
Argument::Key("--verbose") => {
settings.verbose = true;
},
Argument::KeyWithValue("--threads", threads) => {
settings.threads = threads.parse().expect("Threads must be a number!");
},
// A "-h" or "--help" flag was present.
Err(ArgyleError::WantsHelp) => {
println!("Help stuff goes here...");
// Something else… maybe you want to assume it's a path?
Argument::Other(v) => {
settings.paths.push(PathBuf::from(v));
},
// An actual error!
Err(e) => {
eprintln!("{}", e);
std::process::exit(1);
// Also something else, but not String-able. Paths don't care,
// though, so for this example maybe you just keep it?
Argument::InvalidUtf8(v) => {
settings.paths.push(PathBuf::from(v));
},
_ => {}, // Not relevant here.
}
}
}

fn _main() -> Result<(), ArgyleError> {
// Parse CLI arguments.
let args = Argue::new(FLAG_HELP | FLAG_REQUIRED | FLAG_VERSION)?;

// Pull the pieces you want.
let clean: bool = args.switch(b"--clean");
let prefix: Option<&[u8]> = args.option2(b"-p", b"--prefix");

...
// Do something with those settings…
}
```

Expand Down
37 changes: 0 additions & 37 deletions benches/fm_argue.rs

This file was deleted.

23 changes: 0 additions & 23 deletions benches/fm_keykind.rs

This file was deleted.

32 changes: 4 additions & 28 deletions examples/debug.rs
Original file line number Diff line number Diff line change
@@ -1,36 +1,12 @@
/*!
# Argyle: Argue
# Argyle: Streaming Argue
This example parses any arbitrary arguments fed to it and displays the results.
*/

use std::ffi::OsStr;
use std::mem::size_of;
use std::os::unix::ffi::OsStrExt;



fn main() {
println!("Struct size: {}", size_of::<argyle::Argue>());
println!();

let args = argyle::Argue::new(argyle::FLAG_REQUIRED);
match args {
Ok(a) => {
println!("\x1b[2mRAW:\x1b[0m");
println!("{:?}", a);

println!();
println!("\x1b[2mPRETTY:\x1b[0m");

a.take().iter().for_each(|b| {
println!("{}", OsStr::from_bytes(b).to_str().unwrap_or("[Invalid UTF-8]"));
});

println!();
},
Err(e) => {
println!("Error: {}", e);
},
for arg in argyle::stream::args() {
println!("\x1b[2m-----\x1b[0m\n{arg:?}");
}
println!("\x1b[2m-----\x1b[0m");
}
31 changes: 0 additions & 31 deletions examples/list.rs

This file was deleted.

30 changes: 0 additions & 30 deletions justfile
Original file line number Diff line number Diff line change
Expand Up @@ -23,25 +23,6 @@ doc_dir := justfile_directory() + "/doc"



# Bench it!
bench BENCH="":
#!/usr/bin/env bash
clear
if [ -z "{{ BENCH }}" ]; then
cargo bench \
--benches \
--all-features \
--target-dir "{{ cargo_dir }}"
else
cargo bench \
--bench "{{ BENCH }}" \
--all-features \
--target-dir "{{ cargo_dir }}"
fi
exit 0


# Clean Cargo crap.
@clean:
# Most things go here.
Expand Down Expand Up @@ -84,17 +65,6 @@ bench BENCH="":
-- {{ ARGS }}


# Build and Run Example.
@debug-args:
clear
find . -name '*.rs' -type f -exec realpath {} + | cargo run \
-q \
--release \
--example "list" \
--target-dir "{{ cargo_dir }}" \
-- -l - "foo/bar"


# Build Docs.
@doc:
# Make sure nightly is installed; this version generates better docs.
Expand Down
Loading

0 comments on commit e421e9a

Please sign in to comment.