swears 0.1.0

Use swears, not curses
Documentation
use crate::{Color, ColorString, Key};
use pancurses::{
    curs_set, def_prog_mode, def_shell_mode, doupdate, echo, endwin, init_color, init_pair,
    initscr, noecho, noraw, raw, reset_prog_mode, reset_shell_mode, resize_term, start_color,
    Window, COLOR_BLACK, COLOR_BLUE, COLOR_CYAN, COLOR_GREEN, COLOR_MAGENTA, COLOR_PAIR, COLOR_RED,
    COLOR_WHITE, COLOR_YELLOW,
};

use std::{
    str::Chars,
    fmt::Display,
    i32::{MAX, MIN},
};


#[derive(Debug)]
pub struct Terminal {
    win: Window,
}

impl Terminal {
    pub fn new() -> Self {
        let result = Self { win: initscr() };
        raw();
        result.win.keypad(true);
        result.disable_echo();
        result.disable_scrolling();
        result.hide_cursor();
        result
    }

    pub fn with_color() -> Self {
        let result = Self::new();
        start_color();
        init_pair(COLOR_WHITE, COLOR_WHITE, COLOR_BLACK);
        init_pair(COLOR_RED, COLOR_RED, COLOR_BLACK);
        init_pair(COLOR_BLUE, COLOR_BLUE, COLOR_BLACK);
        init_pair(COLOR_GREEN, COLOR_GREEN, COLOR_BLACK);
        init_pair(COLOR_CYAN, COLOR_CYAN, COLOR_BLACK);
        init_pair(COLOR_YELLOW, COLOR_YELLOW, COLOR_BLACK);
        init_pair(COLOR_MAGENTA, COLOR_MAGENTA, COLOR_BLACK);
        init_pair(COLOR_BLACK, COLOR_BLACK, COLOR_BLACK);
        result
    }

    pub fn hide_cursor(&self) {
        curs_set(0);
    }
    pub fn show_cursor(&self) {
        curs_set(1);
    }

    pub fn enable_echo(&self) {
        echo();
    }
    pub fn disable_echo(&self) {
        noecho();
    }

    pub fn enable_scrolling(&self) {
        resize_term(MAX, MAX);
        self.win.setscrreg(MIN, MAX);
        self.win.scrollok(true);
    }

    pub fn disable_scrolling(&self) {
        self.win.scrollok(false);
    }

    pub fn get_key(&self) -> Option<Key> {
        if let Some(input) = self.win.getch() {
            Some(Key::from(input))
        } else {
            None
        }
    }

    pub fn set_input_timeout(&self, milliseconds: u32) {
        self.win.timeout(milliseconds as i32);
    }

    pub fn pause(&self) {
        def_prog_mode();
        noraw();
        reset_shell_mode();
        endwin();
    }

    pub fn resume(&self) {
        def_shell_mode();
        raw();
        reset_prog_mode();
        self.win.refresh();
        doupdate();
    }

    pub fn refresh(&self) {
        self.win.touch();
        self.win.refresh();
    }

    pub fn clear(&self) {
        self.win.clear();
    }

    pub fn move_print(&self, mut x: i32, mut y: i32, s: impl Into<ColorString>) {
        let x_initial = x;
        let cs = s.into();
        let color_num = match cs.to_color() {
            Color::Red => COLOR_RED,
            Color::Green => COLOR_GREEN,
            Color::Blue => COLOR_BLUE,
            Color::Cyan => COLOR_CYAN,
            Color::Magenta => COLOR_MAGENTA,
            Color::Yellow => COLOR_YELLOW,
            Color::White => COLOR_WHITE,
            Color::Black => COLOR_BLACK,
            Color::Default => COLOR_WHITE,
        };

        self.win.attrset(COLOR_PAIR(color_num as u64));

        for ch in cs.to_string().chars() {
            if ch == '\n' {
                y += 1;
                x = x_initial;
            } else {
                x += 1;
                self.win.mvaddch(y, x, ch);
            }
        }
    }

    pub fn println(&self, s: impl Into<ColorString>) {
        let cs = s.into();
        let color = cs.to_color();
        self.print(ColorString(color, cs.to_string() + "\n\r"));
    }

    pub fn print(&self, s: impl Into<ColorString>) {
        let cs = s.into();
        let color_num = match cs.to_color() {
            Color::Red => COLOR_RED,
            Color::Green => COLOR_GREEN,
            Color::Blue => COLOR_BLUE,
            Color::Cyan => COLOR_CYAN,
            Color::Magenta => COLOR_MAGENTA,
            Color::Yellow => COLOR_YELLOW,
            Color::White => COLOR_WHITE,
            Color::Black => COLOR_BLACK,
            Color::Default => COLOR_WHITE,
        };

        self.win.attrset(COLOR_PAIR(color_num as u64));
        self.win.printw(cs.to_string());
    }

    pub fn clear_current_line(&self) {
        self.print("\r");
        self.win.clrtoeol();
    }

    pub fn move_cursor(&self, x: i32, y: i32) {
        self.win.mv(y, x);
    }

    pub fn get_size(&self) -> (i32, i32) {
        (self.get_width(), self.get_height())
    }

    pub fn get_width(&self) -> i32 {
        self.win.get_max_x()
    }

    pub fn get_height(&self) -> i32 {
        self.win.get_max_y()
    }
}

impl Iterator for Terminal {
    type Item = Key;
    fn next(&mut self) -> Option<Key> {
        self.get_key()
    }
}

impl Iterator for &Terminal {
    type Item = Key;
    fn next(&mut self) -> Option<Key> {
        self.get_key()
    }
}

impl Drop for Terminal {
    fn drop(&mut self) {
        endwin();
    }
}

impl Clone for Terminal {
    fn clone(&self) -> Self {
        let win = self.win.dupwin();
        Self { win }
    }
}