add docs for Value trait and derive

This commit is contained in:
Terts Diepraam
2023-12-19 13:22:39 +01:00
parent 50cd4b1494
commit 88019ffe4b
3 changed files with 95 additions and 16 deletions
+5 -15
View File
@@ -1,6 +1,9 @@
// For the full copyright and license information, please view the LICENSE
// file that was distributed with this source code.
//! Derive macros for `uutils_args`. All items here are documented in that
//! crate.
mod argument;
mod attributes;
mod complete;
@@ -18,21 +21,7 @@ use proc_macro::TokenStream;
use quote::quote;
use syn::{parse_macro_input, Data::Enum, DeriveInput};
/// Derive `Arguments`
///
/// ## Argument specifications
///
/// | specification | kind | value |
/// | -------------- | ---------- | -------- |
/// | `VAL` | positional | n.a. |
/// | `-s` | short | none |
/// | `-s VAL` | short | required |
/// | `-s[VAL]` | short | optional |
/// | `--long` | long | none |
/// | `--long=VAL` | long | required |
/// | `--long[=VAL]` | long | optional |
/// | `long=VAL` | dd | required |
///
/// Documentation for this can be found in `uutils_args`.
#[proc_macro_derive(Arguments, attributes(arg, arguments))]
pub fn arguments(input: TokenStream) -> TokenStream {
let input = parse_macro_input!(input as DeriveInput);
@@ -125,6 +114,7 @@ pub fn arguments(input: TokenStream) -> TokenStream {
TokenStream::from(expanded)
}
/// Documentation for this can be found in `uutils_args`.
#[proc_macro_derive(Value, attributes(value))]
pub fn value(input: TokenStream) -> TokenStream {
let input = parse_macro_input!(input as DeriveInput);
+56
View File
@@ -1 +1,57 @@
# Value trait
Any field on the enum implementing [`Arguments`](trait@crate::Arguments) has to implement the [`Value`](trait@crate::Value) trait, which determines how it is derive from the text value. Normally, [`Value`](trait@crate::Value) only requires one method: [`from_value`](crate::Value::from_value), which takes an `&OsStr` and returns a `Result` with either `Self` or some boxed error.
This trait is implemented for common types, such as integers, [`OsString`](std::ffi::OsString), [`PathBuf`](std::path::PathBuf), [`String`] and [`Option<T>`] where `T` implements `Value`.
There is also a [`Value` derive macro](derive@crate::Value), which provides parsing string values into an `enum`. The name of each variant (lowercased) with a `#[value]` attribute is parsed automatically. Additionally, if the string is an unambiguous prefix, it is also parsed. For example, if we have the values `"yes"` and `"no"` then `"y"`, `"ye"`, `"yes"` are all valid for `"yes"`, because no other values start with those substrings.
```rust
use uutils_args::Value;
use std::ffi::OsStr;
#[derive(Value, Debug, PartialEq, Eq)]
enum YesOrNo {
#[value]
Yes,
#[value]
No,
}
assert_eq!(YesOrNo::from_value(OsStr::new("yes")).unwrap(), YesOrNo::Yes);
assert_eq!(YesOrNo::from_value(OsStr::new("no")).unwrap(), YesOrNo::No);
assert_eq!(YesOrNo::from_value(OsStr::new("y")).unwrap(), YesOrNo::Yes);
assert_eq!(YesOrNo::from_value(OsStr::new("n")).unwrap(), YesOrNo::No);
assert!(YesOrNo::from_value(OsStr::new("YES")).is_err());
assert!(YesOrNo::from_value(OsStr::new("NO")).is_err());
assert!(YesOrNo::from_value(OsStr::new("maybe")).is_err());
```
We can also provide custom names for the variants. This is useful if there are multiple strings that should parse to one variant.
```rust
use uutils_args::Value;
use std::ffi::OsStr;
#[derive(Value, Debug, PartialEq, Eq)]
enum Color {
#[value("yes", "always")]
Always,
#[value("auto")]
Auto,
#[value("no", "never")]
Never,
}
assert_eq!(Color::from_value(&OsStr::new("yes")).unwrap(), Color::Always);
assert_eq!(Color::from_value(&OsStr::new("always")).unwrap(), Color::Always);
assert_eq!(Color::from_value(&OsStr::new("auto")).unwrap(), Color::Auto);
assert_eq!(Color::from_value(&OsStr::new("no")).unwrap(), Color::Never);
assert_eq!(Color::from_value(&OsStr::new("never")).unwrap(), Color::Never);
// The prefixes here are interesting:
// - "a" is ambiguous because it is a prefix of "auto" and "always"
// - "n" is not ambiguous because "no" and "never" map to the same variant
assert!(Color::from_value(&OsStr::new("a")).is_err());
assert_eq!(Color::from_value(&OsStr::new("n")).unwrap(), Color::Never);
```
+34 -1
View File
@@ -12,7 +12,40 @@ mod value;
pub mod docs;
pub use lexopt;
pub use uutils_args_derive::*;
// The documentation for the derive macros is written here instead of in
// `uutils_args_derive`, because we need to be able to link to items and the
// documentation in this crate.
/// Derive macro for [`Value`](trait@crate::Value)
///
/// [See also the chapter on this trait in the guide](crate::docs::guide::value)
///
/// This macro only works on `enums` and will error at compile time when it is
/// used on a `struct`.
pub use uutils_args_derive::Value;
/// Derive macro for [`Arguments`](trait@crate::Arguments)
///
/// [See also the chapter on this trait in the guide](crate::docs::guide::quick)
///
/// This macro only works on `enums` and will error at compile time when it is
/// used on a `struct`.
///
/// /// ## Argument specifications
///
/// | specification | kind | value |
/// | -------------- | ---------- | -------- |
/// | `VAL` | positional | n.a. |
/// | `-s` | short | none |
/// | `-s VAL` | short | required |
/// | `-s[VAL]` | short | optional |
/// | `--long` | long | none |
/// | `--long=VAL` | long | required |
/// | `--long[=VAL]` | long | optional |
/// | `long=VAL` | dd | required |
///
pub use uutils_args_derive::Arguments;
pub use error::{Error, ErrorKind};
pub use value::{Value, ValueError, ValueResult};