zui-core 0.0.3

A Terminal UI Library, Written in Rust
Documentation
use std::{io::Error, sync::mpsc::Receiver, thread, time::Duration};

// Key Enum definitions
// A key (Shamefully Copied from Termion (How do I give credit!?))
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub enum Key {
    /// Backspace.
    Backspace,
    /// Enter.
    Enter,
    /// Tab.
    Tab,
    /// Left arrow.
    Left,
    /// Right arrow.
    Right,
    /// Up arrow.
    Up,
    /// Down arrow.
    Down,
    /// Home key.
    Home,
    /// End key.
    End,
    /// Page Up key.
    PageUp,
    /// Page Down key.
    PageDown,
    /// Backward Tab key.
    BackTab,
    /// Delete key.
    Delete,
    /// Insert key.
    Insert,
    /// Function keys.
    ///
    /// Only function keys 1 through 12 are supported.
    F(u8),
    /// Normal character.
    Char(char),
    // Number
    Num(u8),
    /// Ctrl modified character.
    /// Note that certain keys may not be modifiable with `ctrl`, due to limitations of terminals.
    Ctrl(char),
    // Alt modified character
    Alt(char),
    /// Null byte.
    Null,
    /// Esc key.
    Esc,
}

pub struct KeyIterator {
    bytes: Receiver<Result<u8, Error>>,
}

impl KeyIterator {
    pub fn from(rx: Receiver<Result<u8, Error>>) -> KeyIterator {
        KeyIterator { bytes: rx }
    }
}

impl Iterator for KeyIterator {
    type Item = Key;

    fn next(&mut self) -> Option<Key> {
        from_byte(&mut self.bytes)
    }
}

fn from_byte(i: &mut Receiver<Result<u8, Error>>) -> Option<Key> {
    let c = i.recv();
    match c {
        Ok(c) => {
            let c = c.unwrap();
            if c.is_ascii() {
                match c {
                    // Ctrl-Characters
                    1..=8 | 10..=12 | 14..=26 => Some(Key::Ctrl((c + 96) as char)),

                    13 => Some(Key::Enter),
                    9 => Some(Key::Tab),
                    // Escape Sequences... AKA Hard Part
                    27 => {
                        //TODO: Fix this delay of the main thread (maybe relegate basic processing to spawn)
                        thread::sleep(Duration::from_micros(100));
                        match i.try_recv() {
                            Ok(x) => {
                                match x {
                                    // F1-F4
                                    Ok(79) => match i.try_recv().unwrap() {
                                        Ok(r) => match r as char {
                                            'P' => Some(Key::F(1)),
                                            'Q' => Some(Key::F(2)),
                                            'R' => Some(Key::F(3)),
                                            'S' => Some(Key::F(4)),
                                            _ => Some(Key::Char(r as char)),
                                        },
                                        Err(_e) => Some(Key::Null),
                                    },
                                    Ok(91) => match i.try_recv().unwrap() {
                                        Ok(r) => match r {
                                            65 => Some(Key::Up),
                                            66 => Some(Key::Down),
                                            67 => Some(Key::Right),
                                            68 => Some(Key::Left),
                                            _ => Some(Key::Char(r as char)),
                                        },
                                        Err(_e) => Some(Key::Null),
                                    },
                                    Ok(97..=122) => Some(Key::Alt(x.unwrap() as char)),
                                    _ => Some(Key::Null),
                                }
                            }
                            Err(_e) => Some(Key::Esc),
                        }
                    }

                    // Numbers
                    48..=57 => Some(Key::Num(c - 48)),

                    // Alphabet
                    127 => Some(Key::Backspace),

                    97..=122 => Some(Key::Char(c as char)),
                    // Key not recognized, but user can parse it
                    _ => Some(Key::Char(c as char)),
                }
            } else {
                println!("{}", c);
                None
            }
        }
        Err(_e) => Some(Key::Null),
    }
}