1use std::error::Error as StdError;
2
3pub use type_cli_derive::CLI;
4
5mod args;
6pub use args::{Argument, Flag, OptionalArg};
7
8pub trait CLI: Sized {
9 fn parse(args: impl std::iter::Iterator<Item = String>) -> Result<Parse<Self>, Error>;
15 fn process() -> Self {
23 match Self::parse(std::env::args()) {
24 Ok(Parse::Success(val)) => val,
25 Ok(Parse::Help(help)) => {
26 eprintln!("{}", help);
27 std::process::exit(1);
28 }
29 Err(e) => {
30 eprintln!("{}", e);
31 std::process::exit(101);
32 }
33 }
34 }
35}
36
37pub enum Parse<T: CLI> {
43 Success(T),
44 Help(HelpInfo),
45}
46
47pub struct HelpInfo(pub &'static str);
48
49impl std::fmt::Display for HelpInfo {
50 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
51 write!(f, "{}", self.0)
52 }
53}
54
55#[derive(thiserror::Error)]
56pub enum Error {
57 #[error("Expected an argument named `{0}`")]
58 ExpectedNamed(&'static str),
59 #[error("Expected an argument at position `{0}`")]
60 ExpectedPositional(usize),
61 #[error("Expected a value after argument `{0}`")]
62 ExpectedValue(&'static str),
63 #[error("Unknown flag `{0}`")]
64 UnknownFlag(String),
65 #[error("Unexpected positional argument `{0}`")]
66 ExtraArg(String),
67 #[error("Unknown subcommand `{0}`")]
68 UnknownSub(String),
69 #[error("Error parsing {0}:\n{1}")]
70 Parse(ArgRef, Box<dyn StdError>),
71}
72
73pub enum ArgRef {
75 Positional(usize),
76 Named(&'static str),
77}
78use std::fmt::{self, Display};
79impl Display for ArgRef {
80 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
81 match self {
82 &ArgRef::Positional(index) => {
83 write!(f, "positional argument `{}`", index)
84 }
85 &ArgRef::Named(name) => {
86 write!(f, "argument `{}`", name)
87 }
88 }
89 }
90}
91
92impl std::fmt::Debug for Error {
93 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
94 std::fmt::Display::fmt(self, f)
95 }
96}