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
use crate::cell::{Cell, CellAttributes};
/// A `CellCluster` is another representation of a Line.
/// A `Vec<CellCluster>` is produced by walking through the Cells in
/// a line and collecting succesive Cells with the same attributes
/// together into a `CellCluster` instance. Additional metadata to
/// aid in font rendering is also collected.
#[derive(Debug, Clone)]
pub struct CellCluster {
pub attrs: CellAttributes,
pub text: String,
pub byte_to_cell_idx: Vec<usize>,
}
impl CellCluster {
/// Compute the list of CellClusters from a set of visible cells.
/// The input is typically the result of calling `Line::visible_cells()`.
pub fn make_cluster<'a>(iter: impl Iterator<Item = (usize, &'a Cell)>) -> Vec<CellCluster> {
let mut last_cluster = None;
let mut clusters = Vec::new();
for (cell_idx, c) in iter {
let cell_str = c.str();
last_cluster = match last_cluster.take() {
None => {
// Start new cluster
Some(CellCluster::new(c.attrs().clone(), cell_str, cell_idx))
}
Some(mut last) => {
if last.attrs != *c.attrs() {
// Flush pending cluster and start a new one
clusters.push(last);
Some(CellCluster::new(c.attrs().clone(), cell_str, cell_idx))
} else {
// Add to current cluster
last.add(cell_str, cell_idx);
Some(last)
}
}
};
}
if let Some(cluster) = last_cluster {
// Don't forget to include any pending cluster on the final step!
clusters.push(cluster);
}
clusters
}
/// Start off a new cluster with some initial data
fn new(attrs: CellAttributes, text: &str, cell_idx: usize) -> CellCluster {
let mut idx = Vec::new();
for _ in 0..text.len() {
idx.push(cell_idx);
}
CellCluster {
attrs,
text: text.into(),
byte_to_cell_idx: idx,
}
}
/// Add to this cluster
fn add(&mut self, text: &str, cell_idx: usize) {
for _ in 0..text.len() {
self.byte_to_cell_idx.push(cell_idx);
}
self.text.push_str(text);
}
}