From a88ed21e17c14085d52df5a7c5e092a54f0c1be7 Mon Sep 17 00:00:00 2001 From: Avril Date: Tue, 10 Nov 2020 17:51:50 +0000 Subject: [PATCH] arg parsing untested --- Cargo.lock | 7 +++ Cargo.toml | 1 + src/args/flags.rs | 69 +++++++++++++++++++---- src/iterators.rs | 139 ---------------------------------------------- src/main.rs | 2 +- 5 files changed, 67 insertions(+), 151 deletions(-) delete mode 100644 src/iterators.rs diff --git a/Cargo.lock b/Cargo.lock index 644e6dd..44f4954 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,5 +1,11 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. +[[package]] +name = "ad-hoc-iter" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5068a429476033d1940f21e21d317afae2fc3a82f412d5d8fe08c13f100a00e8" + [[package]] name = "addr2line" version = "0.13.0" @@ -890,6 +896,7 @@ checksum = "b5a972e5669d67ba988ce3dc826706fb0a8b01471c088cb0b6110b805cc36aed" name = "videl" version = "0.1.0" dependencies = [ + "ad-hoc-iter", "base64", "cfg-if", "chrono", diff --git a/Cargo.toml b/Cargo.toml index c18e71d..f7e2091 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -32,6 +32,7 @@ termprogress = "0.3.4" uuid = {version = "0.8.1", features=["v4"]} lazy_format = "1.8.3" recolored = "1.9.3" +ad-hoc-iter = {version = "^0.2.2", features = ["maybe-many"]} [build-dependencies] rustc_version = "0.2" diff --git a/src/args/flags.rs b/src/args/flags.rs index e0fcd36..53fd3b0 100644 --- a/src/args/flags.rs +++ b/src/args/flags.rs @@ -10,9 +10,11 @@ use super::error::{ Error, ContextualError, }; -use iterators::*; +use ad_hoc_iter::{ + maybe::*, +}; -type ShortFlag= (char,); +pub type ShortFlag= (char,); #[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] pub enum Kind<'a> @@ -212,9 +214,13 @@ pub enum ValueKind { /// No values, this is a boolean flag None, - /// A value in the form of `--option=value` + /// A value in the form of `--option=value`. + /// + /// If user provides without an `=value` part, the `held` state will be empty. Equals, /// The next `n` arguments are the values + /// + /// If user provides less than `n` arguments after this one, arg parsing will fail with an error. Next(usize), /// The whole rest of the iterator is the values Rest, @@ -263,7 +269,7 @@ impl ArgState /// A handle to mutate the arg state. pub struct StateHandle<'a, T> { - held: Either>, + held: MaybeMany>, state: &'a mut T, args: &'a mut (dyn Iterator + 'a), @@ -322,7 +328,7 @@ impl<'a, T> StateHandle<'a,T> /// # Note /// This moves the values, if you want to call this more than once, use `clone_held`. /// If called more than once will yield no values - pub fn extract_held(&mut self) -> EitherIter> + pub fn extract_held(&mut self) -> MaybeManyIter> { self.held.take().into_iter() } @@ -332,7 +338,7 @@ impl<'a, T> StateHandle<'a,T> /// # Note /// This clones all the values, instead of moving like `extract_held`, so multiple calls to this will yield the same clones. /// However, if `extract_held` has been called, this will yield no values. - pub fn clone_held(&self) -> EitherIter> + pub fn clone_held(&self) -> MaybeManyIter> { self.held.clone().into_iter() } @@ -360,17 +366,57 @@ impl ArgState if *single { *chk = false; } - //TODO: When value is `Equals`, split at `=` and pass only the first part to `is_match`. + + let (arg, held) = { + let arg = &arg[..]; + if let ValueKind::Equals = &value { + match arg.split_once("=") { + Some((a,v)) => (a, MaybeMany::one(v.to_owned())), + _ => (arg, MaybeMany::None), + } + } else { + (arg, MaybeMany::None) + } + }; + if let Some(kind_match) = kind.is_match(&arg[..]) { - //TODO: Check `value` matches `input` or `kind_match` + let held = { + match value { + ValueKind::Next(n) => { + let n = *n; + let mut held = held.map_single_into_many(|x| vec![x]); + let taken = held.on_many(|vec| { + let l = vec.len(); + vec.extend((&mut input).take(n)); + vec.len() - l + }).unwrap(); + if taken != n { + return Err(Error{flag: kind.clone(), + from: Err::(eyre!("Not enough args")) + .with_note(|| format!("Expected {} items, only got {}", n, taken)) + .with_suggestion(|| format!("See `-help` for {}", arg)).unwrap_err(), + desc: Some(desc.clone().into_owned()), + arg: (i, arg.to_owned())})?; + } + held + }, + ValueKind::Rest => { + let mut held = held.map_single_into_many(|x| vec![x]); + held.on_many(|vec| vec.extend(&mut input)); + held + }, + _ => held.map_none(), + } + }; + output.push(callback(&mut StateHandle{ state: &mut self.user, args: &mut input, chk, idx: i, - held: Either::None, //TODO: This will be for either one `=` or many `` from args as according to `value`. + held, //This will be for either one `=` or many `` from args as according to `value`. }, i, kind_match) - .map_err(|err| Error{flag: kind.clone(), from: err, desc: Some(desc.clone().into_owned()), arg: (i, arg.clone())})?); + .map_err(|err| Error{flag: kind.clone(), from: err, desc: Some(desc.clone().into_owned()), arg: (i, arg.to_owned())})?); } } i+=1; @@ -391,6 +437,7 @@ impl ArgState mod tests { use super::*; + use ad_hoc_iter::iter; #[test] fn errors() -> Result<(), eyre::Report> { @@ -415,7 +462,7 @@ mod tests { let kd = Kind::Abrev(&["logging:high", "verbose", "verbose-mode"], &[('V',)], true, true); - let args = over!["--logging:high", "--verbose", "-abcVdfg"]; + let args = iter!["--logging:high", "--verbose", "-abcVdfg"]; for arg in args { diff --git a/src/iterators.rs b/src/iterators.rs deleted file mode 100644 index 48191c7..0000000 --- a/src/iterators.rs +++ /dev/null @@ -1,139 +0,0 @@ -//! Useful iterators -use super::*; - - -/// An iterator that can yield `0,1,2+` items -#[derive(Debug, Clone)] -pub enum Either -{ - None, - One(T), - Many(U), -} - -impl Either -{ - pub fn take(&mut self) -> Self - { - std::mem::replace(self, Self::None) - } -} - -#[derive(Debug, Clone)] -pub enum EitherIter -{ - None, - One(std::iter::Once), - Many(std::iter::Fuse), -} - -impl Iterator for EitherIter -where U: Iterator -{ - type Item = T; - fn next(&mut self) -> Option - { - match self { - Self::None => None, - Self::One(one) => one.next(), - Self::Many(many) => many.next(), - } - } - - fn size_hint(&self) -> (usize, Option) { - match self { - Self::None => (0, Some(0)), - Self::One(_) => (1, Some(1)), - Self::Many(many) => many.size_hint(), - } - } -} -impl> std::iter::FusedIterator for EitherIter{} -impl> std::iter::ExactSizeIterator for EitherIter -where U: ExactSizeIterator{} - -impl> IntoIterator for Either -{ - type Item= T; - type IntoIter = EitherIter::IntoIter>; - - fn into_iter(self) -> Self::IntoIter - { - match self { - Self::None => EitherIter::None, - Self::One(one) => EitherIter::One(std::iter::once(one)), - Self::Many(many) => EitherIter::Many(many.into_iter().fuse()) - } - } -} - -/// A bespoke iterator type with an exact size -#[macro_export] macro_rules! over { - (@) => (0usize); - (@ $x:tt $($xs:tt)* ) => (1usize + $crate::over!(@ $($xs)*)); - - ($($value:expr),*) => { - { - use ::std::mem::MaybeUninit; - use ::std::ops::Drop; - struct Arr([MaybeUninit; $crate::over!(@ $($value)*)], usize); - impl Arr - { - const LEN: usize = $crate::over!(@ $($value)*); - } - impl Iterator for Arr - { - type Item = T; - fn next(&mut self) -> Option - { - if self.1 >= self.0.len() { - None - } else { - //take one - let one = unsafe { - ::std::mem::replace(&mut self.0[self.1], MaybeUninit::uninit()).assume_init() - }; - self.1+=1; - Some(one) - } - } - - #[inline] fn size_hint(&self) -> (usize, Option) - { - (Self::LEN, Some(Self::LEN)) - } - } - impl ::std::iter::FusedIterator for Arr{} - impl ::std::iter::ExactSizeIterator for Arr{} - - impl Drop for Arr - { - fn drop(&mut self) { - if ::std::mem::needs_drop::() { - for idx in self.1..self.0.len() { - unsafe { - ::std::mem::replace(&mut self.0[idx], MaybeUninit::uninit()).assume_init(); - } - } - } - } - } - - Arr([$(MaybeUninit::new($value)),*], 0) - } - } -} - -#[cfg(test)] -mod tests -{ - #[test] - fn iter_over() - { - const EXPECT: usize = 10 + 9 + 8 + 7 + 6 + 5 + 4 + 3 + 2 + 1; - let iter = over![10,9,8,7,6,5,4,3,2,1]; - - assert_eq!(iter.len(), 10); - assert_eq!(iter.sum::(), EXPECT); - } -} diff --git a/src/main.rs b/src/main.rs index 192c53e..2448735 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,5 +1,6 @@ #![cfg_attr(nightly, feature(never_type))] #![cfg_attr(nightly, feature(drain_filter))] +#![cfg_attr(nightly, feature(str_split_once))] #![allow(dead_code)] @@ -30,7 +31,6 @@ mod ext; use ext::*; mod util; mod dedup; -mod iterators; mod resolve; mod database;