monospace-core 0.1.0

Core library for Monospace: parsing, layout and ASCII rendering of diagrams
Documentation
//! The end fragment: the cell where a stroke stops. See _What a terminal writes_ in
//! [`docs/model.md`](../../../../../docs/model.md).

use crate::cell::Side;
use crate::{Arm, Cell, Pos, Shape, Stroke, StrokeCell, Surface};

/// An end: one cell carrying the single arm the stroke runs on, `Unset` on the other three.
///
/// A fragment in the sense of _Complete and fragment_ in
/// [`docs/model.md`](../../../../../docs/model.md). It renders through the glyph set like any
/// other stroke cell, so two ends meeting at a shared position compose into the
/// corner the two make rather than into a chosen glyph that refuses every junction.
#[derive(Debug)]
pub(crate) struct End {
    pub(crate) at: Pos,
    pub(crate) side: Side,
    pub(crate) stroke: Stroke,
}

impl Shape for End {
    fn draw(&self, surface: &mut dyn Surface) {
        let arm_toward = |side: Side| {
            if side == self.side {
                Arm::Set(self.stroke.clone())
            } else {
                Arm::Unset
            }
        };
        let cell: Cell = StrokeCell {
            base: self.stroke.clone(),
            top: arm_toward(Side::Top),
            right: arm_toward(Side::Right),
            bottom: arm_toward(Side::Bottom),
            left: arm_toward(Side::Left),
        }
        .into();

        surface.stamp(self.at, cell);
    }
}

#[cfg(test)]
mod tests {
    use super::End;
    use crate::cell::Side;
    use crate::{
        Arm, Buffer, Cell, CellReader, FigureLayer, Pos, Shape, Size, StampMode, Stroke,
        StrokeCell, Window,
    };

    /// An end toward `Right` carries `Set` there and `Unset` on the
    /// other three sides — decided nothing about what lies beyond it.
    #[test]
    fn an_end_carries_one_arm_and_leaves_the_other_three_unset() {
        let mut buffer = Buffer::new(Window {
            origin: Pos { x: 0, y: 0 },
            size: Size {
                width: 1,
                height: 1,
            },
        });
        let mut layer = FigureLayer::new(&mut buffer, StampMode::Above);

        End {
            at: Pos { x: 0, y: 0 },
            side: Side::Right,
            stroke: Stroke::from("light"),
        }
        .draw(&mut layer);

        assert_eq!(
            buffer.cell(Pos { x: 0, y: 0 }),
            Some(&Cell::from(StrokeCell {
                base: Stroke::from("light"),
                top: Arm::Unset,
                right: Arm::Set(Stroke::from("light")),
                bottom: Arm::Unset,
                left: Arm::Unset,
            }))
        );
    }
}