1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
//! Renderable containers.
//!
//! Port of upstream `rich/containers.py` (the `Renderables` class). `Lines` is
//! internal to upstream's `Text` wrapping, which this port does at the segment
//! level, so it is not ported.
use std::sync::Arc;
use crate::console::{Console, ConsoleOptions};
use crate::measure::Measurement;
use crate::protocol::Renderable;
use crate::segment::Segment;
/// A list of renderables rendered one after another. Mirrors
/// `rich.containers.Renderables`, which `LogRender` puts in its message column.
#[derive(Clone, Default)]
pub struct Renderables {
renderables: Vec<Arc<dyn Renderable + Send + Sync>>,
}
impl Renderables {
/// A container of `renderables`, rendered in order.
pub fn new(renderables: Vec<Arc<dyn Renderable + Send + Sync>>) -> Self {
Renderables { renderables }
}
/// Add a renderable to the end. Port of `Renderables.append`.
pub fn append(&mut self, renderable: Arc<dyn Renderable + Send + Sync>) {
self.renderables.push(renderable);
}
/// The contained renderables.
pub fn renderables(&self) -> &[Arc<dyn Renderable + Send + Sync>] {
&self.renderables
}
}
impl Renderable for Renderables {
/// `yield from self._renderables`, each through `Console.render`.
///
/// Upstream's renderables each end their output with a newline; this
/// port's separate lines instead, so each child's output is joined to the
/// previous one with a newline. A child that renders nothing adds no line.
fn rich_render(&self, console: &Console, options: &ConsoleOptions) -> Vec<Segment> {
let options = options.reset_height();
let mut segments: Vec<Segment> = Vec::new();
let mut first = true;
for renderable in &self.renderables {
let rendered = console.render(renderable.as_ref(), Some(&options));
if rendered.is_empty() {
continue;
}
if !first {
segments.push(Segment::line());
}
first = false;
segments.extend(rendered);
}
segments
}
/// Port of `Renderables.__rich_measure__`: the widest minimum and maximum
/// of the children, or `(1, 1)` when there are none.
fn measure(&self, console: &Console, options: &ConsoleOptions) -> Measurement {
let dimensions: Vec<Measurement> = self
.renderables
.iter()
.map(|renderable| Measurement::get(console, options, renderable.as_ref()))
.collect();
if dimensions.is_empty() {
return Measurement::new(1, 1);
}
Measurement::new(
dimensions.iter().map(|d| d.minimum).max().unwrap_or(0),
dimensions.iter().map(|d| d.maximum).max().unwrap_or(0),
)
}
}