rtlibs-tui 0.1.4

rtools library: ratatui widgets
Documentation
use clap::ArgMatches;
use clap::Command;
use ratatui::text::Line;

pub trait CommanderCommand
{
    fn is<S>(
        &self,
        prefix: S,
    ) -> bool
    where
        S: AsRef<str>;

    fn is_filtered_by<S>(
        &self,
        prefix: S,
    ) -> bool
    where
        S: AsRef<str>;

    fn wrapped_description(
        &self,
        width: usize,
    ) -> Vec<Line>;
}

impl CommanderCommand for Command
{
    fn is<S>(
        &self,
        prefix: S,
    ) -> bool
    where
        S: AsRef<str>,
    {
        let inner = move |prefix: &str| {
            let cond1 = self
                .get_name()
                .eq(prefix);
            let mut cond2 = false;
            for alias in self.get_all_aliases()
            {
                if alias.eq(prefix)
                {
                    cond2 = true;
                }
            }
            cond1 || cond2
        };

        inner(prefix.as_ref())
    }

    fn is_filtered_by<S>(
        &self,
        prefix: S,
    ) -> bool
    where
        S: AsRef<str>,
    {
        let inner = move |prefix: &str| {
            let cond1 = self
                .get_name()
                .starts_with(prefix);
            let mut cond2 = false;
            for alias in self.get_all_aliases()
            {
                if alias.starts_with(prefix)
                {
                    cond2 = true;
                }
            }
            cond1 || cond2
        };

        inner(prefix.as_ref())
    }

    fn wrapped_description(
        &self,
        width: usize,
    ) -> Vec<Line>
    {
        let about = self
            .get_long_about()
            .or(self.get_about())
            .unwrap_or_default();

        let description = if self
            .get_all_aliases()
            .count()
            == 0
        {
            about.to_string()
        }
        else
        {
            format!(
                "{about}\n\nAliases: {}",
                self.get_all_aliases()
                    .collect::<Vec<_>>()
                    .join(", ")
            )
        };

        let wrapped = textwrap::wrap(
            &description,
            width,
        )
        .iter()
        .map(|s| Line::raw(s.to_string()))
        .collect::<Vec<_>>();

        wrapped
    }
}

pub(crate) fn get_current_subcommands(
    filter: String,
    filtered: bool,
    command: &Command,
    matches: ArgMatches,
) -> Vec<&Command>
{
    let Some((name, submatches)) = matches.subcommand()
    else
    {
        let options = command
            .get_subcommands()
            .filter(
                |c| {
                    if filtered
                    {
                        c.is_filtered_by(&filter)
                    }
                    else
                    {
                        true
                    }
                },
            )
            .collect::<Vec<_>>();
        // if options.len() > 1
        // {
        return options;
        // }
        // else
        // {
        // return Vec::new();
        // }
    };

    let Some(subcommand) = command
        .get_subcommands()
        .find(|c| c.is(name))
    else
    {
        return command
            .get_subcommands()
            // .filter(|c| c.is_filtered_by(&filter))
            .collect::<Vec<_>>();
        // return Vec::new();
    };

    get_current_subcommands(
        filter,
        filtered,
        subcommand,
        submatches.to_owned(),
    )
}

pub(crate) fn get_current_command(
    filter: String,
    filtered: bool,
    command: &Command,
    matches: ArgMatches,
) -> Option<&Command>
{
    let Some((name, submatches)) = matches.subcommand()
    else
    {
        if filtered
        {
            let mut available = command
                .get_subcommands()
                .filter(|c| c.is_filtered_by(&filter))
                .collect::<Vec<_>>();
            if available.is_empty()
            {
                return None;
            }
            else if available.len() == 1
            {
                return available.pop();
            }
            else
            {
                return Some(command);
            }
            // return command
            //     .get_subcommands()
            //     .find(|c| c.is_filtered_by(&filter));
        }
        else
        {
            return Some(command);
        }
    };

    let Some(subcommand) = command
        .get_subcommands()
        .find(|c| c.is(name))
    else
    {
        return None;
        // return command
        //     .get_subcommands()
        //     .find(|c| c.is())
        //     // .filter(|c| c.is_filtered_by(&filter))
        //     .collect::<Vec<_>>();
        // return Vec::new();
    };

    get_current_command(
        filter,
        filtered,
        subcommand,
        submatches.to_owned(),
    )
}

pub(crate) fn get_arg_matches(
    command: &Command,
    items: &mut Vec<String>,
    filtered: bool,
) -> Option<(
    ArgMatches,
    bool,
)>
{
    let matches = match command
        .clone()
        .try_get_matches_from(items.iter())
    {
        Ok(value) => value,
        Err(_) =>
        {
            if items.len() == 1
            {
                return None;
            }
            else
            {
                items.pop();
                return get_arg_matches(
                    command, items, true,
                );
            }
        }
    };
    Some((
        matches, filtered,
    ))
}