summaryrefslogtreecommitdiff
path: root/src/lib.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib.rs')
-rw-r--r--src/lib.rs112
1 files changed, 18 insertions, 94 deletions
diff --git a/src/lib.rs b/src/lib.rs
index e25725d..d968cf2 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -1,5 +1,12 @@
mod query;
+mod switchboard;
+mod value;
+
pub use query::*;
+pub use switchboard::*;
+pub use value::*;
+
+use log::*;
pub enum SwitchName {
@@ -7,107 +14,24 @@ pub enum SwitchName {
Long(String),
}
-
-pub struct Switchboard {
- // First positional argument.
- pub program: String,
- // Positional arguments, stored in reverse order.
- pub positional: Vec<String>,
- // Named arguments, stored in forward order.
- pub switches: Vec<(SwitchName, Option<String>)>,
- // All arguments following a '--' token, stored in forward order.
- pub unprocessed: Option<Vec<String>>,
-}
-
-impl Switchboard {
- pub fn parse(mut args: Vec<String>) -> Self {
- let mut positional = Vec::new();
- let mut switches = Vec::new();
- let mut unprocessed = None;
- args.reverse();
-
- while let Some(arg) = args.pop() {
- if arg.is_empty() {
- continue;
- } else if arg == "--" {
- args.reverse();
- unprocessed = Some(args);
- break;
- } else if let Some(arg) = arg.strip_prefix("--") {
- let (name, value) = match arg.split_once("=") {
- Some((name, "")) => (name, None),
- Some((name, value)) => (name, Some(value.to_string())),
- None => (arg, None),
- };
- if name.is_empty() { continue }
- switches.push((SwitchName::Long(name.to_string()), value));
- } else if let Some(arg) = arg.strip_prefix("-") {
- let (name, value) = match arg.split_once("=") {
- Some((name, "")) => (name, None),
- Some((name, value)) => (name, Some(value.to_string())),
- None => (arg, None),
- };
- let chars: Vec<char> = name.chars().collect();
- if chars.len() != 1 { continue }
- switches.push((SwitchName::Short(chars[0]), value));
- } else {
- positional.push(arg)
- }
- }
- // Reverse order of positional arguments and move program name.
- positional.reverse();
- let program = positional.pop().unwrap();
- Self {
- program, positional, switches, unprocessed,
- }
- }
-
- pub fn from_env() -> Self {
- let mut args = Vec::new();
- for arg_os in std::env::args_os() {
- args.push(arg_os.to_string_lossy().to_string());
- }
- Self::parse(args)
- }
-
- pub fn named(&mut self, name: &str) -> NamedSwitchQuery {
- validate_name(name);
- NamedSwitchQuery {
- switchboard: self,
- name: name.to_string(),
- short: None,
- default: None,
- quick: None,
- }
- }
-
- pub fn positional(&mut self, name: &str) -> PositionalSwitchQuery {
- validate_name(name);
- PositionalSwitchQuery {
- switchboard: self,
- name: name.to_string(),
- default: None,
+impl std::fmt::Display for SwitchName {
+ fn fmt(&self, f: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> {
+ match self {
+ SwitchName::Short(c) => write!(f, "-{c}"),
+ SwitchName::Long(s) => write!(f, "--{s}"),
}
}
-
- /// Check the next positional argument without consuming it.
- pub fn peek(&self) -> Option<&str> {
- self.positional.last().map(|p| p.as_str())
- }
-
- /// Consume the next positional argument.
- pub fn pop(&mut self) {
- self.positional.pop();
- }
}
-
-pub enum SwitchboardError {
+pub enum QueryError {
+ MissingNamed(String),
+ MissingPositional(String),
+ // String is the debug name of the switch
+ Repeated(String),
}
-
fn validate_name(name: &str) {
if !name.chars().all(|c| c.is_ascii_lowercase() || c.is_digit(10) || c == '-') {
- panic!("Invalid name for argument: {name:?}");
+ log::fatal!("Invalid name for argument: {name:?}");
}
}