1use super::{linebreak, styled::Span};
2
3#[derive(Debug, Clone)]
4pub struct PageRow {
5 pub text: String,
6 pub spans: Vec<Span>, pub char_offset: usize, }
9
10#[derive(Debug, Clone)]
11pub struct Page {
12 pub rows: Vec<PageRow>,
13}
14
15pub fn paginate(spans: &[Span], width: u16, height: u16) -> Vec<Page> {
19 let height = height as usize;
20 if spans.is_empty() {
21 return vec![Page { rows: vec![] }];
22 }
23
24 let mut text = String::new();
26 for s in spans {
27 text.push_str(&s.text);
28 }
29 let lines = linebreak::wrap(&text, width);
30
31 let mut rows: Vec<PageRow> = Vec::with_capacity(lines.len());
33 let mut cursor = 0usize;
34 for l in &lines {
35 if l.is_empty() {
36 rows.push(PageRow {
37 text: String::new(),
38 spans: vec![],
39 char_offset: cursor,
40 });
41 continue;
42 }
43 let off = text[cursor..]
44 .find(l.as_str())
45 .map(|b| cursor + b)
46 .unwrap_or(cursor);
47 let char_off = text[..off].chars().count();
48 rows.push(PageRow {
49 text: l.clone(),
50 spans: vec![],
51 char_offset: char_off,
52 });
53 cursor = off + l.len();
54 }
55
56 rows.chunks(height)
58 .map(|c| Page { rows: c.to_vec() })
59 .collect()
60}