1use std::{
2 assert_eq, env, io,
3 process::{Command, Stdio},
4};
5
6use ratatui::{
7 backend::CrosstermBackend,
8 crossterm::{
9 execute,
10 terminal::{
11 disable_raw_mode, enable_raw_mode, EnterAlternateScreen, LeaveAlternateScreen, SetSize,
12 },
13 },
14 layout::Rect,
15 widgets::{Block, Borders, Paragraph},
16 Frame, Terminal,
17};
18use ratatui_image::{picker::Picker, protocol::Protocol, Image, Resize};
19struct App {
20 image: Protocol,
21}
22
23const ASSERT_FONT_SIZE: (u16, u16) = (9, 18);
24const SCREEN_SIZE: (u16, u16) = (46, 12);
25
26fn main() -> Result<(), Box<dyn std::error::Error>> {
27 enable_raw_mode()?;
29 let mut stdout = io::stdout();
30 execute!(
31 stdout,
32 EnterAlternateScreen,
33 SetSize(SCREEN_SIZE.0, SCREEN_SIZE.1)
34 )?;
35 let backend = CrosstermBackend::new(stdout);
36 let mut terminal = Terminal::new(backend)?;
37
38 let mut picker = Picker::from_query_stdio()?;
39 picker.set_background_color([255, 0, 255, 255]);
40 if false {
41 assert_eq!(
42 ASSERT_FONT_SIZE,
43 picker.font_size(),
44 "Font size must be fixed to a specific size: {ASSERT_FONT_SIZE:?}",
45 );
46 }
47 let dyn_img = image::io::Reader::open("./assets/Ada.png")?.decode()?;
48 let image = picker.new_protocol(
49 dyn_img,
50 Rect::new(0, 0, SCREEN_SIZE.0 - 10, SCREEN_SIZE.1 - 4),
51 Resize::Fit(None),
52 )?;
53 let mut app = App { image };
54
55 terminal.draw(|f| ui(f, &mut app))?;
56 std::thread::sleep(std::time::Duration::from_secs(1)); let xwd = Command::new("xwd")
58 .args(["-root", "-silent"])
59 .stdout(Stdio::piped())
60 .spawn()
61 .expect("Failed to start xwd command");
62 let screenshot_term = env::var("SCREENSHOT_TERM_NAME").unwrap_or("unknown".to_string());
63 std::process::Command::new("convert")
64 .args([
65 "xwd:-",
66 &format!("png:./target/screenshot_{screenshot_term}.png"),
67 ])
68 .stdin(xwd.stdout.expect("failed to get stdout"))
69 .stdout(std::process::Stdio::null())
70 .stderr(std::process::Stdio::null())
71 .spawn()
72 .and_then(|mut child| child.wait())?;
73
74 disable_raw_mode()?;
76 execute!(terminal.backend_mut(), LeaveAlternateScreen,)?;
77 terminal.show_cursor()?;
78
79 Ok(())
80}
81
82fn ui(f: &mut Frame<'_>, app: &mut App) {
83 let area = Rect::new(0, 0, SCREEN_SIZE.0, SCREEN_SIZE.1);
84 let block = Block::default()
85 .borders(Borders::ALL)
86 .title("Screenshot test");
87
88 f.render_widget(
89 Paragraph::new("PartiallyHiddenScreenshotParagraphBackground\n".repeat(10)),
90 block.inner(area),
91 );
92
93 let image = Image::new(&mut app.image);
94 f.render_widget(image, block.inner(area));
95 f.render_widget(block, area);
96}