par_term_terminal/
styled_content.rs1use par_term_emu_core_rust::grid::Grid;
2
3#[derive(Debug, Clone)]
5#[allow(dead_code)]
6pub struct StyledSegment {
7 pub text: String,
8 pub fg_color: (u8, u8, u8),
9 pub bg_color: (u8, u8, u8),
10 pub bold: bool,
11 pub italic: bool,
12 pub underline: bool,
13 pub line: usize,
14 pub start_col: usize,
15}
16
17#[allow(dead_code)]
19pub fn extract_styled_segments(grid: &Grid) -> Vec<StyledSegment> {
20 let mut segments = Vec::new();
21 let rows = grid.rows();
22 let cols = grid.cols();
23
24 for row in 0..rows {
25 let mut current_segment: Option<StyledSegment> = None;
26
27 for col in 0..cols {
28 if let Some(cell) = grid.get(col, row) {
29 let fg = cell.fg.to_rgb();
30 let bg = cell.bg.to_rgb();
31 let bold = cell.flags.bold();
32 let italic = cell.flags.italic();
33 let underline = cell.flags.underline();
34
35 if let Some(ref mut segment) = current_segment {
37 let same_style = segment.fg_color == fg
38 && segment.bg_color == bg
39 && segment.bold == bold
40 && segment.italic == italic
41 && segment.underline == underline;
42
43 if same_style {
44 if cell.has_combining_chars() {
47 segment.text.push_str(&cell.get_grapheme());
48 } else {
49 segment.text.push(cell.base_char());
50 }
51 } else {
52 segments.push(segment.clone());
54 let text = if cell.has_combining_chars() {
56 cell.get_grapheme()
57 } else {
58 cell.base_char().to_string()
59 };
60 current_segment = Some(StyledSegment {
61 text,
62 fg_color: fg,
63 bg_color: bg,
64 bold,
65 italic,
66 underline,
67 line: row,
68 start_col: col,
69 });
70 }
71 } else {
72 let text = if cell.has_combining_chars() {
75 cell.get_grapheme()
76 } else {
77 cell.base_char().to_string()
78 };
79 current_segment = Some(StyledSegment {
80 text,
81 fg_color: fg,
82 bg_color: bg,
83 bold,
84 italic,
85 underline,
86 line: row,
87 start_col: col,
88 });
89 }
90 }
91 }
92
93 if let Some(segment) = current_segment {
95 segments.push(segment);
96 }
97 }
98
99 segments
100}
101
102#[allow(dead_code)]
104pub fn segments_to_plain_text(segments: &[StyledSegment]) -> String {
105 let mut result = String::new();
106 let mut current_line = 0;
107
108 for segment in segments {
109 while current_line < segment.line {
111 result.push('\n');
112 current_line += 1;
113 }
114
115 result.push_str(&segment.text);
116 }
117
118 result
119}
120
121#[cfg(test)]
122mod tests {
123 use super::*;
124 use par_term_emu_core_rust::cell::Cell;
125 use par_term_emu_core_rust::color::{Color, NamedColor};
126 use par_term_emu_core_rust::grid::Grid;
127
128 #[test]
129 fn test_extract_single_segment() {
130 let mut grid = Grid::new(10, 1, 0);
131
132 for col in 0..5 {
134 let mut cell = Cell::new('A');
135 cell.fg = Color::Named(NamedColor::White);
136 cell.bg = Color::Named(NamedColor::Black);
137 grid.set(col, 0, cell);
138 }
139
140 let segments = extract_styled_segments(&grid);
141 assert_eq!(segments.len(), 1);
144 assert_eq!(segments[0].text.trim_end(), "AAAAA");
145 }
146
147 #[test]
148 fn test_extract_multiple_segments() {
149 let mut grid = Grid::new(10, 1, 0);
150
151 for col in 0..3 {
153 let mut cell = Cell::new('A');
154 cell.fg = Color::Named(NamedColor::White);
155 grid.set(col, 0, cell);
156 }
157
158 for col in 3..6 {
160 let mut cell = Cell::new('B');
161 cell.fg = Color::Named(NamedColor::Red);
162 grid.set(col, 0, cell);
163 }
164
165 let segments = extract_styled_segments(&grid);
166 assert!(segments.len() >= 2);
168 assert_eq!(segments[0].text, "AAA");
169 assert_eq!(segments[1].text.trim_start(), "BBB");
170 }
171}