lalrpop/message/
mod.rs

1use ascii_canvas::{AsciiCanvas, AsciiView};
2
3use std::cmp;
4use std::fmt::Debug;
5
6pub mod builder;
7pub mod horiz;
8pub mod indent;
9#[allow(clippy::module_inception)] // A little silly but otherwise fine
10pub mod message;
11pub mod styled;
12#[cfg(test)]
13mod test;
14pub mod text;
15pub mod vert;
16pub mod wrap;
17
18/// Content which can be rendered.
19pub trait Content: Debug {
20    fn min_width(&self) -> usize;
21
22    fn emit(&self, view: &mut dyn AsciiView);
23
24    /// Creates a canvas at least `min_width` in width (it may be
25    /// larger if the content requires that) and fills it with the
26    /// current content. Returns the canvas. Typically `min_width`
27    /// would be 80 or the width of the current terminal.
28    fn emit_to_canvas(&self, min_width: usize) -> AsciiCanvas {
29        let computed_min = self.min_width();
30        let min_width = cmp::max(min_width, computed_min);
31        debug!(
32            "emit_to_canvas: min_width={} computed_min={} self={:#?}",
33            min_width, computed_min, self
34        );
35        let mut canvas = AsciiCanvas::new(0, min_width);
36        self.emit(&mut canvas);
37        canvas
38    }
39
40    /// Emit at a particular upper-left corner, returning the
41    /// lower-right corner that was emitted.
42    fn emit_at(&self, view: &mut dyn AsciiView, row: usize, column: usize) -> (usize, usize) {
43        debug!(
44            "emit_at({},{}) self={:?} min_width={:?}",
45            row,
46            column,
47            self,
48            self.min_width()
49        );
50        let mut shifted_view = view.shift(row, column);
51        self.emit(&mut shifted_view);
52        let (r, c) = shifted_view.close();
53        (r, c)
54    }
55
56    /// When items are enclosed into a wrap, this method deconstructs
57    /// them into their indivisible components.
58    fn into_wrap_items(self: Box<Self>, wrap_items: &mut Vec<Box<dyn Content>>);
59}
60
61/// Helper function: convert `content` into wrap items and then map
62/// those with `op`, appending the final result into `wrap_items`.
63/// Useful for "modifier" content items like `Styled` that do not
64/// affect wrapping.
65fn into_wrap_items_map<OP, C>(
66    content: Box<dyn Content>,
67    wrap_items: &mut Vec<Box<dyn Content>>,
68    op: OP,
69) where
70    OP: FnMut(Box<dyn Content>) -> C,
71    C: Content + 'static,
72{
73    let mut subvector = vec![];
74    content.into_wrap_items(&mut subvector);
75    wrap_items.extend(
76        subvector
77            .into_iter()
78            .map(op)
79            .map(|item| Box::new(item) as Box<dyn Content>),
80    );
81}
82
83pub use self::message::Message;