zte 0.1.5

A buffer/window-driven text editor that takes inspiration from Howl
// Reexports
pub use crate::display::{
    Color,
    Attr,
};

use vek::*;
use crate::display::{
    Cell,
    Display,
};

fn rect_to_points(canvas: &impl Canvas, pos: Vec2<usize>, size: Extent2<isize>) -> (Vec2<usize>, Vec2<usize>) {
    let this_size = canvas.size();
    let size = size.map2((Vec2::from(this_size) - pos).into(), |e, sz: usize| if e < 0 {
        sz as isize + e + 1
    } else {
        e
    } as usize);

    (pos, pos + size)
}

pub trait Canvas: Sized {
    fn set_cursor_raw(&mut self, pos: Option<Vec2<usize>>);
    fn set_raw(&mut self, pos: Vec2<usize>, cell: Cell);
    fn rect(&self) -> Rect<usize, usize>;
    fn size(&self) -> Extent2<usize>;

    fn fg(&self) -> Color;
    fn bg(&self) -> Color;
    fn attr(&self) -> Attr;

    fn set_cursor(&mut self, pos: Option<Vec2<usize>>) {
        self.set_cursor_raw(pos.map(|pos| self.rect().position() + pos));
    }

    fn set(&mut self, pos: Vec2<usize>, cell: Cell) {
        let pos = pos.map2(self.size().into(), |e, sz: usize| e.min(sz.saturating_sub(1)));
        self.set_raw(self.rect().position() + pos, cell);
    }

    fn write_char(&mut self, pos: Vec2<usize>, c: char) {
        self.set(pos, Cell(c, self.fg(), self.bg(), self.attr()));
    }

    fn write_str(&mut self, pos: Vec2<usize>, s: &str) {
        for (i, c) in s.chars().enumerate() {
            self.write_char(pos + Vec2::new(i, 0), c);
        }
    }

    fn with_fg<'a>(&'a mut self, fg: Color) -> Drawer<'a, Self> {
        Drawer { fg, bg: self.bg(), attr: self.attr(), rect: self.rect(), canvas: self }
    }

    fn with_bg<'a>(&'a mut self, bg: Color) -> Drawer<'a, Self> {
        Drawer { fg: self.fg(), bg, attr: self.attr(), rect: self.rect(), canvas: self }
    }

    fn with_attr<'a>(&'a mut self, attr: Attr) -> Drawer<'a, Self> {
        Drawer { fg: self.fg(), bg: self.bg(), attr, rect: self.rect(), canvas: self }
    }

    fn window<'a>(&'a mut self, rect: Rect<usize, usize>) -> Drawer<'a, Self> {
        let rect = Rect::new(
            self.rect().position().x + rect.x,
            self.rect().position().y + rect.y,
            rect.w.min(self.rect().w.saturating_sub(rect.x)),
            rect.h.min(self.rect().h.saturating_sub(rect.y)),
        );
        Drawer { fg: self.fg(), bg: self.bg(), attr: self.attr(), rect, canvas: self }
    }

    fn rectangle(&mut self, pos: impl Into<Vec2<usize>>, size: impl Into<Extent2<usize>>, c: char) {
        let from = pos.into();
        let to = from + Vec2::from(size.into());

        let cell = Cell(c, self.fg(), self.bg(), self.attr());
        for y in from.y..to.y {
            for x in from.x..to.x {
                self.set(Vec2::new(x, y), cell);
            }
        }
    }

    fn frame(&mut self) {
        let sz = self.size();
        for i in 1..sz.w.saturating_sub(1) {
            self.write_char(Vec2::new(i, 0), '');
            self.write_char(Vec2::new(i, sz.h.saturating_sub(1)), '');
        }
        for j in 1..sz.h.saturating_sub(1) {
            self.write_char(Vec2::new(0, j), ''.into());
            self.write_char(Vec2::new(sz.w.saturating_sub(1), j), '');
        }
        self.write_char(Vec2::new(0, 0), ''.into());
        self.write_char(Vec2::new(sz.w.saturating_sub(1), 0), '');
        self.write_char(Vec2::new(0, sz.h.saturating_sub(1)), '');
        self.write_char(Vec2::new(sz.w.saturating_sub(1), sz.h.saturating_sub(1)), '');
    }
}

pub struct Drawer<'a, D: Canvas> {
    fg: Color,
    bg: Color,
    attr: Attr,
    canvas: &'a mut D,
    rect: Rect<usize, usize>,
}

impl<'a, D: Canvas> Canvas for Drawer<'a, D> {
    fn set_cursor_raw(&mut self, pos: Option<Vec2<usize>>) {
        self.canvas.set_cursor_raw(pos);
    }

    fn set_raw(&mut self, pos: Vec2<usize>, cell: Cell) {
        self.canvas.set_raw(pos, cell);
    }

    fn rect(&self) -> Rect<usize, usize> {
        self.rect
    }

    fn size(&self) -> Extent2<usize> {
        self.rect.extent()
    }

    fn fg(&self) -> Color { self.fg }
    fn bg(&self) -> Color { self.bg }
    fn attr(&self) -> Attr { self.attr }
}

impl Canvas for Display {
    fn set_cursor_raw(&mut self, pos: Option<Vec2<usize>>) {
        self.set_cursor(pos);
    }

    fn set_raw(&mut self, pos: Vec2<usize>, cell: Cell) {
        self.grid_mut().set(pos, cell);
    }

    fn rect(&self) -> Rect<usize, usize> {
        Rect::new(0, 0, self.size().w, self.size().h)
    }

    fn size(&self) -> Extent2<usize> {
        self.size().into()
    }

    fn fg(&self) -> Color { Color::Reset }
    fn bg(&self) -> Color { Color::Reset }
    fn attr(&self) -> Attr { Attr::Reset }
}