yacll 0.7.1

Yet Another Curses-Like Library
Documentation
/*!
Enums and structs for getting input from the user.
```rust, no_run
use yacll::{
    input::{
        Event,
        KeyCode,
    },
    Result, Yogurt,
};
use std::{
    time::Duration,
    thread::sleep,
};

fn main() -> Result<()> {
    let mut y = Yogurt::new();
    y.enter_alt()?;

    y.cursor_on(yacll::stylize::CursorAttr::Hidden)?;

    y.mv_print((0, 0), "press the any key to advance.")?;
    y.flush()?;
    y.block_event()?;

    y.mv_print((0, 1), "now press the q key in the next 10 seconds!")?;
    y.flush()?;
    match y.read_event(Duration::from_secs(10))? {
        Some(some) => if let Event::Key(ke) = some {
            if let KeyCode::Char('q') = ke.code {
                y.mv_print((0, 2), "you did it!")?;
            } else {
                y.mv_print((0, 2), "that's not q!")?;
            }
        } else {
            y.mv_print((0, 2), "that event isn't a key event!")?;
        }
        None => y.mv_print((0, 2), "you failed...")?,
    }
    y.flush()?;

    sleep(Duration::from_secs(3));

    y.cursor_off(yacll::stylize::CursorAttr::Hidden)?;

    y.leave_alt()?;
    Ok(())
}
// try running `$ cargo run --example=input` if you have the repository cloned!
```
*/

use crate::{Result, Yarr, Yogurt};
use crossterm::event::read;
use crossterm::event::DisableMouseCapture;
use crossterm::event::EnableMouseCapture;
pub use crossterm::event::KeyEventKind;
/// Key modifiers such as control, alt, and shift.
///
pub use crossterm::event::KeyModifiers;
use crossterm::event::{self, poll};
use crossterm::execute;
pub use event::MouseEvent;
use std::time::Duration;
pub use crossterm::event::MouseEventKind;
pub use crossterm::event::MouseButton;

/// Functions for getting input from the user.
impl Yogurt {
    /// Read an event. Will error if not in alt-mode. Duration is how long to wait for an event
    /// before returning.
    pub fn read_event(&mut self, dur: Duration) -> Result<Option<Event>> {
        if self.size.is_none() {
            return Err(Yarr::NotInAltMode);
        }
        if poll(dur)? {
            let read = read()?;
            let event = read.try_into()?;
            Ok(Some(event))
        } else {
            Ok(None)
        }
    }
    /// Like [`read_event`](Yogurt::read_event), except instead of exiting with `None` after `dur`
    /// has passed, it blocks the thread.
    pub fn block_event(&mut self) -> Result<Event> {
        if self.size.is_none() {
            return Err(Yarr::NotInAltMode);
        }
        let read = read()?;
        let event = read.try_into()?;
        Ok(event)
    }
    /// Enable mouse event capture. Mouse events can be read with the
    /// [`read_event`](Yogurt::read_event) or [`block_event`](Yogurt::block_event) functions, like
    /// any other event.
    ///
    /// See also [`disable_mouse_capture`](Yogurt::disable_mouse_capture).
    pub fn enable_mouse_capture(&mut self) -> Result<()> {
        execute! {
            self.stdout,
            EnableMouseCapture,
        }?;
        Ok(())
    }
    /// Disable mouse capture.
    ///
    /// See also [`enable_mouse_capture`](Yogurt::enable_mouse_capture).
    pub fn disable_mouse_capture(&mut self) -> Result<()> {
        execute! {
            self.stdout,
            DisableMouseCapture,
        }?;
        Ok(())
    }
}

/// Possible events.
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
pub enum Event {
    /// The terminal gained focus.
    FocusGained,
    /// The terminal lost focus.
    FocusLost,
    /// A single key event with additional pressed modifiers.
    Key(KeyEvent),
    /// A single mouse event with additional pressed modifiers.
    Mouse(MouseEvent),
    /// A string that was pasted into the terminal. Only emitted if bracketed paste has been
    /// enabled.
    Paste(String),
    /// An resize event with new dimensions after resize (columns, rows).
    /// **Note** that resize events can be occur in batches.
    Resize(u16, u16),
}

impl TryFrom<event::Event> for Event {
    type Error = Yarr;
    fn try_from(value: event::Event) -> Result<Self> {
        match value {
            event::Event::FocusGained => Ok(Event::FocusGained),
            event::Event::FocusLost => Ok(Event::FocusLost),
            event::Event::Key(ke) => Ok(Event::Key(ke.try_into()?)),
            event::Event::Mouse(me) => Ok(Event::Mouse(me)),
            event::Event::Paste(ps) => Ok(Event::Paste(ps)),
            event::Event::Resize(x, y) => Ok(Event::Resize(x, y)),
        }
    }
}

/// A key event.
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
pub struct KeyEvent {
    /// Key itself.
    pub code: KeyCode,
    /// Kind of event, ie: release, press, or repeat
    pub kind: KeyEventKind,
    /// Key modifiers, ie: shift, control, alt
    pub mods: KeyModifiers,
}

impl From<KeyEvent> for event::KeyEvent {
    fn from(ke: KeyEvent) -> Self {
        event::KeyEvent {
            code: ke.code.into(),
            modifiers: ke.mods,
            kind: ke.kind,
            state: event::KeyEventState::NONE,
        }
    }
}

impl TryFrom<event::KeyEvent> for KeyEvent {
    type Error = Yarr;
    fn try_from(ke: event::KeyEvent) -> Result<Self> {
        let code = ke.code.try_into()?;
        Ok(KeyEvent {
            code,
            kind: ke.kind,
            mods: ke.modifiers,
        })
    }
}

/// Represents possible keys.
#[derive(Copy, Clone, Debug, PartialEq, Eq, Ord, PartialOrd, Hash)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub enum KeyCode {
    /// Backspace key.
    Backspace,
    /// Enter key.
    Enter,
    /// Left arrow key.
    Left,
    /// Right arrow key.
    Right,
    /// Up arrow key.
    Up,
    /// Down arrow key.
    Down,
    /// Home key.
    Home,
    /// End key.
    End,
    /// Page up key.
    PageUp,
    /// Page down key.
    PageDown,
    /// Tab key.
    Tab,
    /// Shift + Tab key.
    Backtab,
    /// Delete key.
    Delete,
    /// Insert key.
    Insert,
    /// F key.
    ///
    /// `KeyCode::F(1)` represents F1 key, etc.
    F(u8),
    /// A character.
    ///
    /// `KeyCode::Char('c')` represents `c` character, etc.
    Char(char),
    /// Null.
    Null,
    /// Escape key.
    Esc,
}

impl From<KeyCode> for event::KeyCode {
    fn from(kc: KeyCode) -> Self {
        use KeyCode::*;
        match kc {
            Backspace => event::KeyCode::Backspace,
            Enter => event::KeyCode::Enter,
            Left => event::KeyCode::Left,
            Right => event::KeyCode::Right,
            Up => event::KeyCode::Up,
            Down => event::KeyCode::Down,
            Home => event::KeyCode::Home,
            End => event::KeyCode::End,
            PageUp => event::KeyCode::PageUp,
            PageDown => event::KeyCode::PageDown,
            Tab => event::KeyCode::Tab,
            Backtab => event::KeyCode::BackTab,
            Delete => event::KeyCode::Delete,
            Insert => event::KeyCode::Insert,
            F(f) => event::KeyCode::F(f),
            Char(ch) => event::KeyCode::Char(ch),
            Null => event::KeyCode::Null,
            Esc => event::KeyCode::Esc,
        }
    }
}

impl TryFrom<event::KeyCode> for KeyCode {
    type Error = Yarr;
    fn try_from(kc: event::KeyCode) -> Result<KeyCode> {
        use KeyCode::*;
        match kc {
            event::KeyCode::Backspace => Ok(Backspace),
            event::KeyCode::Enter => Ok(Enter),
            event::KeyCode::Left => Ok(Left),
            event::KeyCode::Right => Ok(Right),
            event::KeyCode::Up => Ok(Up),
            event::KeyCode::Down => Ok(Down),
            event::KeyCode::Home => Ok(Home),
            event::KeyCode::End => Ok(End),
            event::KeyCode::PageUp => Ok(PageUp),
            event::KeyCode::PageDown => Ok(PageDown),
            event::KeyCode::Tab => Ok(Tab),
            event::KeyCode::BackTab => Ok(Backtab),
            event::KeyCode::Delete => Ok(Delete),
            event::KeyCode::Insert => Ok(Insert),
            event::KeyCode::F(f) => Ok(F(f)),
            event::KeyCode::Char(ch) => Ok(Char(ch)),
            event::KeyCode::Null => Ok(Null),
            event::KeyCode::Esc => Ok(Esc),
            _ => Err(Yarr::FromCrossKeyCodeError),
        }
    }
}