cli_printer 0.2.0

A library for create a cli apps
Documentation
use crossterm::execute;
use crossterm::style::{Print, Stylize};

use crate::core::interfaces::Widget;

pub struct ListItem<'b>(pub &'b str);

#[derive(Default)]
pub struct ListState {
    pub offset: usize,
}

pub struct List<'b> {
    items: Vec<ListItem<'b>>,
    pub length: usize,
    pub state: ListState,
    icon_selected: &'b str,
    icon_space: String,
}

impl<'b> Widget for List<'b> {
    fn render(&mut self, stdout: &mut std::io::Stdout) -> std::io::Result<()> {
        let mut count = 0;
        for option in &self.items {
            if count == self.state.offset {
                execute!(
                    stdout,
                    Print(self.icon_selected.cyan()),
                    Print(option.0.cyan()),
                    Print("\n")
                )?;
            } else {
                execute!(
                    stdout,
                    Print(&self.icon_space),
                    Print(option.0),
                    Print("\n")
                )?;
            }
            count += 1;
        }
        Ok(())
    }
}

impl<'b> List<'b> {
    pub fn new(options: Vec<&'b str>) -> Self {
        let options_list: Vec<ListItem<'b>> = options.iter().map(|s| ListItem(s)).collect();
        let length = options_list.len();
        Self {
            items: options_list,
            state: ListState::default(),
            icon_selected: "> ",
            icon_space: "  ".to_string(),
            length,
        }
    }
    pub fn add_icon_selected(&mut self, icon: &'b str) {
        let chars: Vec<&str> = icon.chars().map(|_| " ").collect();
        self.icon_selected = icon;
        self.icon_space = chars.join("");
    }
    pub fn next(&mut self) {
        let offset = &self.state.offset;
        if offset + 1 >= self.items.len() {
            self.state.offset = 0;
        } else {
            self.state.offset += 1;
        }
    }
    pub fn prev(&mut self) {
        let offset = &self.state.offset;
        if *offset == 0 {
            self.state.offset = self.items.len() - 1;
        } else {
            self.state.offset -= 1;
        }
    }
    pub fn get_current_index(&self) -> (usize, Option<&ListItem<'b>>) {
        (self.state.offset.clone(), self.items.get(self.state.offset))
    }
}