Skip to main content

vfa_tui/ui/widgets/
output.rs

1use ratatui::{
2    layout::Rect,
3    style::{Color, Style},
4    text::{Line, Span},
5    widgets::{Block, Borders, Paragraph, Wrap},
6    Frame,
7};
8
9use crate::subprocess::stream::OutputStream;
10
11use super::super::theme::Theme;
12
13/// A line of subprocess output with stream identification.
14#[derive(Debug, Clone)]
15pub struct OutputLine {
16    pub content: String,
17    pub stream: OutputStream,
18}
19
20/// Render subprocess output panel showing stdout/stderr lines with differentiation.
21/// Supports scrolling via the `scroll` parameter (vertical offset in lines).
22pub fn render_output(
23    lines: &[OutputLine],
24    title: &str,
25    area: Rect,
26    frame: &mut Frame,
27    theme: &Theme,
28) {
29    render_output_scrolled(lines, title, area, frame, 0, theme);
30}
31
32/// Render subprocess output panel with explicit scroll offset.
33/// `scroll` is the number of lines to skip from the top.
34pub fn render_output_scrolled(
35    lines: &[OutputLine],
36    title: &str,
37    area: Rect,
38    frame: &mut Frame,
39    scroll: u16,
40    theme: &Theme,
41) {
42    let display_lines: Vec<Line> = lines
43        .iter()
44        .map(|line| {
45            let style = if theme.no_color {
46                Style::default()
47            } else {
48                match line.stream {
49                    OutputStream::Stdout => Style::default().fg(Color::White),
50                    OutputStream::Stderr => Style::default().fg(Color::Red),
51                }
52            };
53            Line::from(vec![Span::styled(line.content.clone(), style)])
54        })
55        .collect();
56
57    let paragraph = Paragraph::new(display_lines)
58        .block(
59            Block::default()
60                .borders(Borders::ALL)
61                .title(title.to_string())
62                .border_style(theme.border_style()),
63        )
64        .wrap(Wrap { trim: false })
65        .scroll((scroll, 0));
66
67    frame.render_widget(paragraph, area);
68}