use crate::core::geometry::{Align, Edges};
use crate::core::render::Rendered;
use crate::core::style::Style;
use crate::core::text::{Line, Span};
use crate::output::layout::{blank_line, pad_line};
pub fn align(block: &Rendered, width: u16, how: Align) -> Rendered {
let width = width as usize;
let lines = block
.lines
.iter()
.cloned()
.map(|line| pad_line(line, width, how, Style::new()))
.collect();
Rendered::new(lines)
}
pub fn pad(block: &Rendered, edges: Edges) -> Rendered {
let content_width = block.width();
let inner_width = content_width + edges.horizontal() as usize;
let mut lines = Vec::new();
for _ in 0..edges.top {
lines.push(blank_line(inner_width, Style::new()));
}
for line in &block.lines {
lines.push(pad_content_line(line, edges, content_width));
}
for _ in 0..edges.bottom {
lines.push(blank_line(inner_width, Style::new()));
}
Rendered::new(lines)
}
fn pad_content_line(line: &Line, edges: Edges, content_width: usize) -> Line {
let mut spans = Vec::with_capacity(line.spans.len() + 2);
if edges.left > 0 {
spans.push(Span::raw(" ".repeat(edges.left as usize)));
}
if edges.right > 0 {
let padded =
pad_line(line.clone(), content_width, Align::Left, Style::new());
spans.extend(padded.spans);
spans.push(Span::raw(" ".repeat(edges.right as usize)));
} else {
spans.extend(line.spans.iter().cloned());
}
Line::new(spans)
}
pub fn vstack(parts: &[Rendered], gap: u16) -> Rendered {
let mut lines = Vec::new();
for (index, part) in parts.iter().enumerate() {
if index > 0 {
for _ in 0..gap {
lines.push(Line::default());
}
}
lines.extend(part.lines.iter().cloned());
}
Rendered::new(lines)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn align_pads_lines_to_width() {
let block = Rendered::new(vec![Line::raw("hi")]);
let aligned = align(&block, 5, Align::Right);
assert_eq!(aligned.lines[0].plain(), " hi");
}
#[test]
fn pad_adds_rows_and_columns() {
let block = Rendered::new(vec![Line::raw("ab")]);
let padded = pad(&block, Edges::all(1));
assert_eq!(padded.height(), 3);
assert_eq!(padded.lines[1].plain(), " ab ");
}
#[test]
fn vstack_inserts_gap_lines() {
let a = Rendered::new(vec![Line::raw("a")]);
let b = Rendered::new(vec![Line::raw("b")]);
let stacked = vstack(&[a, b], 1);
assert_eq!(stacked.height(), 3);
assert_eq!(stacked.lines[1].plain(), "");
}
}