rmux_core/screen/
capture.rs1use crate::grid::{Grid, GridCapture, GridRenderOptions, GridStringState};
2use crate::hyperlinks::Hyperlinks;
3use crate::transcript::{resolve_screen_capture_range, ScreenCaptureRange};
4
5use super::Screen;
6
7impl Screen {
8 #[cfg_attr(not(test), allow(dead_code))]
9 #[must_use]
10 pub(crate) fn capture_grid(&self, join_wrapped: bool) -> GridCapture {
11 self.grid.capture(join_wrapped)
12 }
13
14 #[must_use]
16 pub fn capture_transcript(
17 &self,
18 range: ScreenCaptureRange,
19 options: GridRenderOptions,
20 ) -> Vec<u8> {
21 capture_grid_bytes(&self.grid, &self.hyperlinks, range, options)
22 }
23
24 #[must_use]
26 pub fn capture_saved_transcript(
27 &self,
28 range: ScreenCaptureRange,
29 options: GridRenderOptions,
30 ) -> Option<Vec<u8>> {
31 self.saved_grid
32 .as_ref()
33 .map(|saved| capture_grid_bytes(&saved.grid, &self.hyperlinks, range, options))
34 }
35}
36
37fn capture_grid_bytes(
38 grid: &Grid,
39 hyperlinks: &Hyperlinks,
40 range: ScreenCaptureRange,
41 options: GridRenderOptions,
42) -> Vec<u8> {
43 let total_lines = grid.hsize() + usize::try_from(grid.sy()).unwrap_or(usize::MAX);
44 let Some(range) = resolve_screen_capture_range(range, grid.hsize(), total_lines) else {
45 return Vec::new();
46 };
47
48 let mut output = Vec::new();
49 let mut state = GridStringState::default();
50 for absolute_y in range {
51 let Some(line) =
52 grid.render_absolute_line(absolute_y, options, &mut state, Some(hyperlinks))
53 else {
54 continue;
55 };
56 output.extend_from_slice(line.as_bytes());
57 let wrapped = grid.absolute_line_wrapped(absolute_y).unwrap_or(false);
58 if !options.join_wrapped || !wrapped {
59 output.push(b'\n');
60 }
61 }
62 output
63}