roped 0.8.2

a libary for simple cli
Documentation
pub mod base_types;
pub mod command;
pub mod console;
pub mod error;
pub mod strand;

#[allow(unused)]
pub use base_types::EmptyState;
#[allow(unused)]
pub use base_types::Trigger;
#[allow(unused)]
pub use parsr::parser_matcher::Matcher;
#[allow(unused)]
pub use strand::Strand;
#[allow(unused)]
pub use strand_derive::Strand;

#[allow(unused)]
pub use error::Error;

#[allow(clippy::single_component_path_imports)]
pub use parsr;

pub extern crate self as roped;

#[cfg(test)]
mod tests {
    use self::command::Command;

    use super::*;

    use base_types::EmptyState;
    use console::run_console;
    use parsr::{
        parser::trimmed::Trimmed,
        parser_matcher::{Matcher, MatcherSingle},
    };
    use strand::Strand;

    use strand_derive::Strand;

    #[allow(unused)]
    use crate as roped;

    struct ManualImplStrand;
    impl Strand for ManualImplStrand {
        type State = EmptyState;
        type Err = String;

        fn run(
            _state: &mut Self::State,
            input: Option<Trimmed<str>>,
            _index: usize,
        ) -> Result<(), error::Error<Self::Err>> {
            let input = match input {
                Some(v) => v,
                None => return Err(error::Error::Err("Recieved no input".to_string())),
            };

            let pair = input.parse_once();

            match pair.trail {
                Some(v) => println!("{} + {}", pair.arg.get_internal(), v.get_internal()),
                None => println!("{}", pair.arg.get_internal()),
            }

            Ok(())
        }
    }

    #[test]
    fn manual_strand_instance() {
        run_console::<ManualImplStrand>(
            &mut EmptyState,
            "> ".into(),
            ". ".into(),
            "!".into(),
            Matcher::Single(MatcherSingle::Item(' ')),
            Matcher::List(&[MatcherSingle::Item('\n'), MatcherSingle::Item(';')]),
        )
        .unwrap();
    }

    #[derive(Strand)]
    struct TrailStrand {
        num: usize,
        #[strand(trail)]
        trail: String,
    }

    impl Command for TrailStrand {
        type State = EmptyState;

        type Err = String;

        fn action(self, _state: &mut Self::State) -> Result<(), Self::Err> {
            let matcher: Matcher<str, char> = Matcher::Single(MatcherSingle::Item(' '));

            let trail = Trimmed::<str>::new(&self.trail, &matcher);

            print!("number: {}", self.num);
            if let Some(trail) = trail {
                let pair = trail.parse_once();
                print!(" + trail args: {}", pair.arg.get_internal());

                if let Some(trail) = pair.trail {
                    for arg in trail.parse_all() {
                        print!(", {}", arg.get_internal());
                    }
                }
            }

            println!();

            Ok(())
        }
    }

    #[derive(Strand)]
    struct FlagStrand {
        num: usize,
        #[strand(flag = "f1")]
        f1: Option<Trigger>,
        #[strand(flag = "f2")]
        f2: Option<String>,
    }

    impl Command for FlagStrand {
        type State = EmptyState;

        type Err = String;

        fn action(self, _state: &mut Self::State) -> Result<(), Self::Err> {
            println!("num: {}, f1: {:?}, f2: {:?}", self.num, self.f1, self.f2);

            Ok(())
        }
    }

    #[derive(Strand)]
    struct DefaultStrand {
        num: usize,
        #[strand(default = "abc".into())]
        d1: String,
        #[strand(default = 2)]
        d2: usize,
    }

    impl Command for DefaultStrand {
        type State = EmptyState;

        type Err = String;

        fn action(self, _state: &mut Self::State) -> Result<(), Self::Err> {
            println!("{}, {}, {}", self.num, self.d1, self.d2);

            Ok(())
        }
    }

    #[allow(unused)]
    #[derive(Strand)]
    enum ScopeStrand {
        #[strand(prefix = "$")]
        A(DefaultStrand),
        #[strand(name = "flag")]
        B(FlagStrand),
        #[strand(other)]
        C(TrailStrand),
    }

    #[test]
    fn strand_instance() {
        run_console::<ScopeStrand>(
            &mut EmptyState,
            "> ".into(),
            ". ".into(),
            "!".into(),
            Matcher::Single(MatcherSingle::Item(' ')),
            Matcher::List(&[MatcherSingle::Item('\n'), MatcherSingle::Item(';')]),
        )
        .unwrap();
    }
}