1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
#![forbid(unsafe_code)]
#![warn(missing_docs)]

/*!
A library designed to provide a curses alternative.

Explaining things is hard, so here's an example:
```
use yacll::Yogurt;

fn main() -> yacll::Result<()> {
    let mut y = Yogurt::new();
    // does not add newline
    y.print("Hello, world!\n")?;
    // flush the buffer (print just queues things for execution)
    y.flush()?;
    Ok(())
}
// try running `$ cargo run --example=quickstart` if you have the repository cloned!
```
For serializing/deserializing of some structs, the `serde` feature can be enabled.
*/

pub use crossterm::terminal::ClearType as ClrT;
use std::io::{stdout, Stdout};
use thiserror::Error;
mod output;
pub mod stylize;
pub use output::*;
pub mod input;

/// **Y**et An**o**ther Data Stora**g**e **U** St**r**uc**t**. Main struct for methods.
///
/// Unless a method specifies it flushes the buffer, calling the [`flush`](Yogurt::flush) method will be required for the changes to take effect.
#[derive(Debug)]
pub struct Yogurt {
    stdout: Stdout,
    /// Terminal size before entering alternate mode
    size: Option<Point>,
}

impl Yogurt {
    /// Create a new yogurt.
    pub fn new() -> Self {
        Yogurt {
            stdout: stdout(),
            size: None,
        }
    }
}

impl Default for Yogurt {
    fn default() -> Self {
        Yogurt::new()
    }
}

/// A point on the screen.
#[derive(Debug, Copy, Clone)]
pub struct Point {
    /// Which column this point is on.
    pub x: u16,
    /// Which row this point is on.
    pub y: u16,
}

impl From<(u16, u16)> for Point {
    /// Convert a tuple to a point. The first tuple value is interpreted as `x`, while the second is interpreted as `y`.
    fn from(t: (u16, u16)) -> Self {
        Point { x: t.0, y: t.1 }
    }
}

impl From<Point> for (u16, u16) {
    fn from(point: Point) -> Self {
        (point.x, point.y)
    }
}

/// **Y**et **A**nother E**rr**or enum.
#[non_exhaustive]
#[derive(Error, Debug)]
pub enum Yarr {
    /// An IO error.
    #[error(transparent)]
    IO(#[from] std::io::Error),
    /// Tried to use something that depended on alternate mode, but wasn't in it already.
    #[error("tried to use something that depended on alternate mode, but wasn't in it already")]
    NotInAltMode,
    /// An error converting crossterm's KeyCode type to yacll's KeyCode type. This error will never
    /// appear in public interfaces (because it should be impossible), so you do not have to worry about it.
    #[error("tried to convert a crossterm keycode to a yacll keycode but failed")]
    FromCrossKeyCodeError,
}

/// Result with the given type and an instance of `Yarr`.
pub type Result<T> = core::result::Result<T, Yarr>;