use crate::*;
pub struct NamedSwitchQuery<'a> {
/// The borrowed switchboard instance.
pub switchboard: &'a mut Switchboard,
/// Long switch name.
pub name: String,
/// Short switch name.
pub short: Option<char>,
/// The default value if the switch has been provided with no value.
pub quick: Option<String>,
/// Documentation string.
pub doc: Option<String>,
/// True if this query has already been committed.
pub committed: bool,
}
impl NamedSwitchQuery<'_> {
pub fn doc(mut self, doc: &str) -> Self {
self.doc = Some(doc.to_string());
self
}
pub fn short(mut self, short: char) -> Self {
if !short.is_ascii_alphanumeric() {
fatal!("Invalid short name for argument: {short:?}");
}
self.short = Some(short);
self
}
pub fn quick(mut self, value: &str) -> Self {
self.quick = Some(value.to_string());
self
}
pub fn optional(&mut self) {
let value = self.get_value();
self.insert(value);
}
pub fn default(&mut self, default: &str) {
match self.get_value() {
Some(value) => self.insert(Some(value)),
None => self.insert(Some(Some(default.to_string()))),
};
}
pub fn required(&mut self) {
match self.get_value() {
Some(value) => self.insert(Some(value)),
None => {
let error = SwitchboardError::MissingNamed(self.debug_name());
self.switchboard.errors.push(error);
}
}
}
fn insert(&mut self, value: Option<Option<String>>) {
let queried = QueriedValue {
doc: self.doc.clone(),
name: self.name.clone(),
variant: QueryVariant::Named(self.debug_name()),
value,
};
if let Some(_) = self.switchboard.values.insert(self.name.clone(), queried) {
error!("Duplicate query for name {:?}", self.name.clone());
}
self.committed = true;
}
fn get_value(&mut self) -> Option<Option<String>> {
// Find all matches first.
let mut matches = Vec::new();
for (i, switch) in self.switchboard.switches.iter().enumerate() {
match &switch.0 {
SwitchName::Short(other) => if let Some(short) = self.short {
if short == *other { matches.push(i) }
}
SwitchName::Long(other) => if self.name == *other {
matches.push(i);
},
};
}
// Return a value.
match matches.len() {
0 => None,
1 => {
let found = self.switchboard.switches.remove(matches[0]).1;
match found {
Some(string) => Some(Some(string)),
None => Some(self.quick.clone()),
}
}
_ => {
let error = SwitchboardError::Repeated(self.debug_name());
self.switchboard.errors.push(error);
None
}
}
}
fn debug_name(&self) -> String {
let mut debug_name = format!("--{}", self.name);
if let Some(short) = self.short {
debug_name.push_str(&format!(" (-{})", short));
}
debug_name
}
}
impl Drop for NamedSwitchQuery<'_> {
fn drop(&mut self) {
if !self.committed {
self.optional();
}
}
}
pub struct PositionalSwitchQuery<'a> {
/// The borrowed switchboard instance.
pub switchboard: &'a mut Switchboard,
/// The display name of this argument.
pub name: String,
/// Documentation string.
pub doc: Option<String>,
/// True if this query has already been committed.
pub committed: bool,
}
impl PositionalSwitchQuery<'_> {
pub fn doc(mut self, doc: &str) -> Self {
self.doc = Some(doc.to_string());
self
}
pub fn optional(&mut self) {
let value = self.switchboard.pop();
self.insert(value);
}
pub fn default(&mut self, default: &str) {
match self.switchboard.pop() {
Some(value) => self.insert(Some(value)),
None => self.insert(Some(default.to_string())),
};
}
pub fn required(&mut self) {
match self.switchboard.pop() {
Some(value) => self.insert(Some(value)),
None => {
let error = SwitchboardError::MissingPositional(self.name.clone());
self.switchboard.errors.push(error);
}
}
}
fn insert(&mut self, value: Option<String>) {
let queried = QueriedValue {
doc: self.doc.clone(),
name: self.name.clone(),
variant: QueryVariant::Positional(self.switchboard.i),
value: Some(value),
};
if let Some(_) = self.switchboard.values.insert(self.name.clone(), queried) {
error!("Duplicate query for name {:?}", self.name.clone());
}
self.committed = true;
}
}
impl Drop for PositionalSwitchQuery<'_> {
fn drop(&mut self) {
if !self.committed {
self.optional();
}
}
}