vaz_lib 0.2.8

vaz_lib is a small library made for those who just don't want to fuddle with complex stuff.
Documentation
/// Module containing terminal tools
pub mod terminal {
    /// Creates a `term` as seen in the `console` crate
    pub fn new_term() -> console::Term {
        console::Term::stdout()
    }

    /// Clears the screen using the standard library's `std::process::Command`
    pub fn clear() {
        let _ = std::process::Command::new("clear").status();
    }

    /// Writes a displayable object to the screen.
    ///
    /// # Arguments
    ///
    /// * `term` - a reference to a `console::Term`, can be generated by `vaz_lib::terminal::new_term()`
    /// * `item` - a reference to an object that has the `std::fmt::Display` trait
    /// # Examples
    /// ```rust
    /// use vaz_lib::terminal;
    /// let t = terminal::new_term();
    /// let output = "Hello, World!\n";
    /// termina::write(&t, &output);
    /// ```

    pub fn write(term: &console::Term, item: &dyn std::fmt::Display) {
        let _ = term.write_str(format!("{}", item).as_str());
    }

    /// Gets a character from the console input without echo
    ///
    /// # Arguments
    ///
    /// * `term` - a reference to a `console::Term`, can be generated by `vaz_lib::terminal::new_term()`
    ///
    pub fn getch(term: &console::Term) -> char {
        term.read_char().unwrap()
    }

    /// Gets a character from the console input with echo
    ///
    /// When `ch` is `None`, it echoes the character it read, when it is  `Some(c)` it echoes `c`
    /// # Arguments
    ///
    /// * `term` - a reference to a `console::Term`, can be generated by `vaz_lib::terminal::new_term()`
    /// * `ch` - a `Option<char>`
    ///
    pub fn getche(term: &console::Term, ch: Option<char>) -> char {
        let new_ch = term.read_char().unwrap();
        let _ = match ch {
            Some(c) => {
                if new_ch != '\n' {
                    term.write_str(c.to_string().as_str())
                } else {
                    term.write_str(" ".to_string().as_str())
                }
            }
            None => term.write_str(new_ch.to_string().as_str()),
        };

        return new_ch;
    }

    /// Gets a vector of characters from the console input with echo
    ///
    /// When `ch` is `None`, it echoes the character it read, when it is  `Some(c)` it echoes `c`
    /// The vector is of size `n`
    /// # Arguments
    ///
    /// * `term` - a reference to a `console::Term`, can be generated by `vaz_lib::terminal::new_term()`
    /// * `ch` - a `Option<char>`
    /// * `n` - a `u8` the determines how many characters are read
    ///
    pub fn bulk_getche(term: &console::Term, ch: Option<char>, n: u8) -> Vec<char> {
        let mut chars: Vec<char> = Vec::new();
        for _ in 0..n {
            let x = getche(term, ch);
            if x == '\n' {
                break;
            } else {
                chars.push(x);
            }
        }
        chars
    }

    /// Gets a key input from the user, halts the rest of the program
    ///
    ///
    /// # Arguments
    ///
    /// * `term` - a reference to a `console::Term`, can be generated by `vaz_lib::terminal::new_term()`
    ///
    pub fn getk(term: &console::Term) -> console::Key {
        term.read_key().unwrap()
    }

    /// Gets a string of characters from the console input with echo
    ///
    /// When `ch` is `None`, it echoes the character it read, when it is  `Some(c)` it echoes `c`
    /// The string is of size `n`
    /// # Arguments
    ///
    /// * `term` - a reference to a `console::Term`, can be generated by `vaz_lib::terminal::new_term()`
    /// * `ch` - a `Option<char>`
    /// * `n` - a `u8` the determines how many characters are read
    ///
    pub fn get_string(term: &console::Term, ch: Option<char>, n: u8) -> String {
        use console::Key;
        let mut charlist: Vec<char> = Vec::new();

        let mut index: u8 = 0;
        while index < n + 1 {
            let x = getk(term);
            match x {
                Key::Enter => break,
                Key::Char(s) => {
                    if index == n {
                    } else if index == charlist.len() as u8 {
                        charlist.push(s);
                        let _ = term.write_str(
                            format!(
                                "{}",
                                match ch {
                                    Some(c) => c,
                                    None => s,
                                }
                            )
                            .as_str(),
                        );
                        index += 1;
                    } else {
                        charlist[index as usize] = s;
                        let _ = term.write_str(
                            format!(
                                "{}",
                                match ch {
                                    Some(c) => c,
                                    None => s,
                                }
                            )
                            .as_str(),
                        );
                        index += 1;
                    }
                }
                Key::ArrowLeft => {
                    if index != 0 {
                        let _ = term.write_str("\x1b[D");
                        index -= 1;
                    }
                }
                Key::ArrowRight => {
                    if index != charlist.len() as u8 {
                        let _ = term.write_str("\x1b[C");
                        index += 1;
                    }
                }
                Key::Backspace => {
                    if index == charlist.len() as u8 && index != 0 {
                        charlist.pop();
                        let _ = term.write_str("\x1b[D \x1b[D");
                        index -= 1;
                    }
                }

                _ => (),
            }
        }

        charlist.iter().fold(String::new(), |x, y| {
            let mut z = x;
            z.push(*y);
            z
        })
    }
    ///Creates a terminal menu that the user can scroll through using the arrow keys.
    /// It outputs the index of the element the user chose
    ///
    /// # Arguments
    ///
    /// * `term` - a reference
    /// * `items` - a vector of items that have the `std::fmt::Display` trait
    pub fn menu(term: &console::Term, items: Vec<&dyn core::fmt::Display>) -> u32 {
        use console::Key;
        let mut i = 0;
        let mut new_i = 0;
        for item in &items {
            let _ = term.write_str(format!("{}\n", item).as_str());
        }
        for _ in &items {
            let _ = term.write_str("\x1b[A\r");
        }

        loop {
            let _ = term.write_str(
                format!(
                    "\r\x1b[2K\x1b[38;2;0;0;0m\x1b[48;2;255;255;255m\
                    {}\
                    \x1b[m\x1b[?25l\
                    ",
                    items[i]
                )
                .as_str(),
            );
            let key = getk(term);

            match key {
                Key::Enter => {
                    break;
                }
                Key::ArrowUp => {
                    if i != 0 {
                        new_i -= 1;
                    }
                }
                Key::ArrowDown => {
                    if i < items.len() - 1 {
                        new_i += 1;
                    }
                }
                _ => (),
            }
            if new_i != i {
                let _ = term.write_str("\x1b[2K\r");
                let _ = term.write_str(format!("{}", items[i]).as_str());
                for _ in i..items.len() {
                    let _ = term.write_str("\x1b[B");
                }
                for _ in new_i..items.len() {
                    let _ = term.write_str("\x1b[A");
                }
            }
            i = new_i;
        }

        for _ in 0..(items.len() - i) {
            let _ = term.write_str("\x1b[B\x1b[2K\r");
        }
        for _ in &items {
            let _ = term.write_str("\x1b[A\x1b[2K\r");
        }

        let _ = term.write_str("\x1b[?25h");

        i as u32
    }
}

/// A Linear algebra module, dealing with vectors/matrices
/// Only square matrices allowed currently
/// A Linear algebra module, dealing with vectors/matrices
pub mod linear_algebra {

    #[repr(transparent)]
    #[derive(Debug, Copy, Clone)]
    pub struct Matrix<const H: usize, const W: usize> {
        data: [[f32; W]; H],
    }
    impl<const H: usize, const W: usize> Matrix<H,W> {
        pub fn new(input: [[f32;W];H])->Matrix<H,W> {
            Matrix {
                data: input
            }
        }
    }

    impl<const H: usize, const W: usize> std::ops::Index<(usize, usize)> for Matrix<H, W> {
        type Output = f32;
        fn index(&self, (x,y): (usize, usize)) -> &Self::Output {
   return &self.data[y][x];
}
    }

    impl<const H: usize, const W: usize> std::ops::Add for Matrix<H, W> {
        type Output = Matrix<H, W>;

        fn add(self, rhs: Self) -> Self::Output {
            let mut result = [[0.0; W]; H];
            for h in 0..H {
                for w in 0..W {
                    result[h][w] = self[(w,h)] + rhs[(w,h)];
                }
            }
            Matrix { data: result }
        }
        
    }
}