1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
#![forbid(unsafe_code, future_incompatible)]
#![deny(missing_debug_implementations, bad_style)]
#![warn(missing_docs)]
#![cfg_attr(test, deny(warnings))]

//! Command line argument paw-rser abstraction for main.
//!
//! Paw's goal is to show that C's idea of passing arguments into main wasn't that
//! bad at all, but just needed a bit of oxidation to make it work with Rust.
//!
//! Paw defines a trait, a proc macro, and an example implementation that when
//! combined allow you to pass fully parsed arguments to main. Gone is the need to
//! remember which methods to call in order to parse arguments in the CLI. Instead
//! paw makes command line parsing feel first-class
//!
//! ## Examples
//! __Create a parser from scratch__
//! ```rust
//! #[paw::main]
//! fn main(args: paw::Args) {
//!     for arg in args {
//!         println!("{:?}", arg);
//!     }
//! }
//! ```
//!
//! To start the server do:
//! ```sh
//! $ cargo run --example scratch -- localhost 8080
//! ```
//!
//! __More Examples__
//! - [Scratch](https://github.com/rust-cli/paw/tree/master/examples/scratch.rs)
//! - [Args](https://github.com/rust-cli/paw/tree/master/examples/args.rs)
//! - [Structopt](https://github.com/rust-cli/paw/tree/master/examples/structopt.rs)

use std::env::{Args as StdArgs, ArgsOs as StdArgsOs};
use std::ffi::OsString;
use std::fmt;
use std::iter::Iterator;

#[doc(inline)]
#[cfg(not(test))] // NOTE: exporting main breaks tests, we should file an issue.
pub use paw_attributes::main;

#[doc(inline)]
pub use paw_raw::ParseArgs;

/// An iterator over the arguments of a process, yielding an [`String`] value for each argument.
///
/// This is a wrapper over [`std::env::Args`] which is an iterator over the arguments to a process.
/// See its documentation for more.
///
/// [`String`]: ../string/struct.String.html
/// [`std::env::Args`]: https://doc.rust-lang.org/std/env/struct.Args.html
pub struct Args {
    inner: StdArgs,
}

impl fmt::Debug for Args {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        self.inner.fmt(f)
    }
}

impl Iterator for Args {
    type Item = String;

    fn next(&mut self) -> Option<Self::Item> {
        self.inner.next()
    }
}

impl ExactSizeIterator for Args {
    fn len(&self) -> usize {
        self.inner.len()
    }
}

impl DoubleEndedIterator for Args {
    fn next_back(&mut self) -> Option<String> {
        self.inner.next_back()
    }
}

impl ParseArgs for Args {
    type Error = std::io::Error;
    fn parse_args() -> Result<Self, Self::Error> {
        Ok(Self {
            inner: std::env::args(),
        })
    }
}

/// An iterator over the arguments of a process, yielding an [`OsString`] value for each argument.
///
/// This is a wrapper over [`std::env::ArgsOs`] which is an iterator over the arguments to a
/// process. See its documentation for more.
///
/// [`OsString`]: ../ffi/struct.OsString.html
/// [`std::env::ArgsOs`]: https://doc.rust-lang.org/std/env/struct.ArgsOs.html
pub struct ArgsOs {
    inner: StdArgsOs,
}

impl fmt::Debug for ArgsOs {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        self.inner.fmt(f)
    }
}

impl Iterator for ArgsOs {
    type Item = OsString;

    fn next(&mut self) -> Option<Self::Item> {
        self.inner.next()
    }
}

impl ExactSizeIterator for ArgsOs {
    fn len(&self) -> usize {
        self.inner.len()
    }
}

impl DoubleEndedIterator for ArgsOs {
    fn next_back(&mut self) -> Option<OsString> {
        self.inner.next_back()
    }
}

impl ParseArgs for ArgsOs {
    type Error = std::io::Error;
    fn parse_args() -> Result<Self, Self::Error> {
        Ok(Self {
            inner: std::env::args_os(),
        })
    }
}