use crate::errors::Result;
use crate::measure::{MeasureOptions, Measurement};
use crate::segment::Segments;
#[derive(Debug, Clone)]
pub struct RenderOptions {
pub max_width: usize,
pub highlight: bool,
pub markup: bool,
}
impl Default for RenderOptions {
fn default() -> Self {
Self {
max_width: 80,
highlight: false,
markup: true,
}
}
}
impl RenderOptions {
#[inline]
#[must_use]
pub const fn new(max_width: usize) -> Self {
Self {
max_width,
highlight: false,
markup: true,
}
}
}
pub trait Renderable {
fn render(&self, options: &RenderOptions) -> Result<Segments>;
fn measure(&self, options: &MeasureOptions) -> Result<Measurement> {
let render_opts = RenderOptions::new(options.max_width);
let segments = self.render(&render_opts)?;
let width = segments.cell_length();
Ok(Measurement::fixed(width).clamp_max(options.max_width))
}
}
pub trait RichRepr {
type Output: Renderable;
fn rich_repr(&self) -> Self::Output;
}
#[cfg(test)]
mod tests {
#![allow(clippy::unwrap_used)]
use super::*;
use crate::segment::Segment;
#[test]
fn test_render_options_default() {
let opts = RenderOptions::default();
assert_eq!(opts.max_width, 80);
assert!(!opts.highlight);
assert!(opts.markup);
}
#[test]
fn test_render_options_new() {
let opts = RenderOptions::new(120);
assert_eq!(opts.max_width, 120);
assert!(!opts.highlight);
assert!(opts.markup);
}
#[test]
fn test_render_options_fields() {
let mut opts = RenderOptions::new(100);
opts.highlight = true;
opts.markup = false;
assert_eq!(opts.max_width, 100);
assert!(opts.highlight);
assert!(!opts.markup);
}
struct SimpleRenderable {
text: String,
}
impl Renderable for SimpleRenderable {
fn render(&self, _options: &RenderOptions) -> Result<Segments> {
let mut segments = Segments::new();
segments.push(Segment::new(&self.text));
Ok(segments)
}
}
#[test]
fn test_renderable_render() {
let r = SimpleRenderable {
text: "Hello".to_string(),
};
let opts = RenderOptions::new(80);
let result = r.render(&opts);
assert!(result.is_ok());
let segments = result.unwrap();
assert!(!segments.is_empty());
}
#[test]
fn test_renderable_measure_default() {
let r = SimpleRenderable {
text: "Hello".to_string(),
};
let opts = MeasureOptions::new(80);
let result = r.measure(&opts);
assert!(result.is_ok());
let measurement = result.unwrap();
assert!(measurement.minimum > 0);
}
}