Skip to content

Commit

Permalink
Improved macro docs
Browse files Browse the repository at this point in the history
  • Loading branch information
Kyllingene committed Nov 23, 2023
1 parent 74c4cd3 commit 68d1d4d
Show file tree
Hide file tree
Showing 2 changed files with 90 additions and 0 deletions.
1 change: 1 addition & 0 deletions src/macros/const_exprs.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
/// Compile-time string replacement. Can only substitute
/// bytes for bytes (to simplify code).
#[macro_export]
#[doc(hidden)]
macro_rules! __replace {
( $input:expr, $from:expr, $to:expr ) => {{
const OUTPUT_LEN: usize = $input.len();
Expand Down
89 changes: 89 additions & 0 deletions src/macros/mod.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
pub mod const_exprs;

#[macro_export]
#[doc(hidden)]
macro_rules! __parse_arg {
( err => $parser:expr, $name:ident ) => {
let $name = $name.get();
Expand All @@ -19,6 +20,7 @@ macro_rules! __parse_arg {
}

#[macro_export]
#[doc(hidden)]
macro_rules! __arg_typ {
( err , $typ:ty ) => {
$crate::ArgResult<$typ>
Expand All @@ -34,6 +36,7 @@ macro_rules! __arg_typ {
}

#[macro_export]
#[doc(hidden)]
macro_rules! __var_tag {
( $long:ident ) => {
$crate::tag::long($crate::__replace!(stringify!($long), '_', '-'))
Expand All @@ -51,6 +54,92 @@ macro_rules! __var_tag {
}

#[macro_export]
/// A macro to quickly define your CLI interface with struct-like syntax.
///
/// # Example
///
/// ```
/// # use sarge::prelude::*;
/// // This is a normal, non-proc macro. That means sarge is still
/// // zero-dependency! The syntax may seem a little strange at first, but it
/// // should help greatly when defining your CLI interface.
/// sarge! {
/// // This is the name of our struct.
/// Args,
///
/// // These are our arguments. Each will have a long variant matching the
/// // field name one-to-one, with one exception: all underscores are
/// // replaced by dashes at compile-time.
/// //
/// // The hashtags denote the arg 'wrapper'. No wrapper means it will be
/// // unwrapped; if the argument wasn't passed, or it failed to parse, this
/// // will panic. Thankfully, `bool` arguments are immune to both, and
/// // `String` arguments are immune to the latter.
///
/// first: bool, // true if `--first` is passed, false otherwise
///
/// // If you want a short variant (e.g. '-s'), you can specify one with a char
/// // literal before the name (but after the wrapper, if any):
/// 's' second: String,
///
/// // You can also specify an environment variable counterpart. If an argument
/// // has values for both an environment variable and a CLI argument, the CLI
/// // argument takes precedence.
/// @ENV_VAR env_var: i32,
///
/// // `#err` makes the argument an `Option<Result<T, _>>`.
/// #err foo: f32,
///
/// // `#ok` makes the argument an `Option<T>`, discarding any parsing errors.
/// #ok bar: f64,
///
/// // Here's every feature in one argument:
/// // an `Option<Result<T, _>>` that can be set via `-b`, `--baz`, or `BAZ=`.
/// #err 'b' @BAZ baz: Vec<u64>,
/// }
///
/// # macro_rules! create_args {
/// # ( $( $arg:expr ),* $(,)? ) => {
/// # [ $( $arg.to_string(), )* ]
/// # };
/// # }
/// #
/// # macro_rules! create_env {
/// # ( $( $name:expr, $val:expr ),* $(,)? ) => {
/// # [ $( ($name.to_string(), $val.to_string()), )* ]
/// # };
/// # }
///
/// fn main() {
/// let args = create_args![
/// "test", // The name of the executable.
/// "--first",
/// "-s", "Hello, World!",
/// "--bar=badnum", // The syntax `--arg=val` is valid for long tags.
/// "foobar", // This value isn't part of an argument.
/// "--baz", "1,2,3", // Remember this value...
/// ];
///
/// let env = create_env![
/// "ENV_VAR", "42",
/// "BAZ", "4,5,6", // ...and this one.
/// ];
///
/// // Normally, you would use `::parse()` here. However, since this gets run
/// // as a test, we'll manually pass the arguments along.
/// let (args, remainder) = Args::parse_provided(&args, env.into_iter())
/// .expect("Failed to parse arguments");
///
/// assert_eq!(remainder, vec!["foobar"]);
///
/// assert!(args.first);
/// assert_eq!(args.second, "Hello, World!");
/// assert_eq!(args.env_var, 42);
/// assert_eq!(args.foo, None);
/// assert_eq!(args.bar, None);
/// assert_eq!(args.baz, Some(Ok(vec![1, 2, 3])));
/// }
/// ```
macro_rules! sarge {
( $v:vis $name:ident, $( $( # $spec:ident )? $( $short:literal )? $( @ $env:ident )? $av:vis $long:ident : $typ:ty ),* $(,)? ) => {
$v struct $name {
Expand Down

0 comments on commit 68d1d4d

Please sign in to comment.