Skip to main content

oxide_update_engine_display/
line_display.rs

1// This Source Code Form is subject to the terms of the Mozilla Public
2// License, v. 2.0. If a copy of the MPL was not distributed with this
3// file, You can obtain one at https://mozilla.org/MPL/2.0/.
4
5use crate::line_display_shared::{
6    LineDisplayFormatter, LineDisplayOutput, LineDisplayShared,
7};
8use chrono::{DateTime, Utc};
9use debug_ignore::DebugIgnore;
10use derive_where::derive_where;
11use owo_colors::Style;
12use oxide_update_engine_types::{
13    buffer::{EventBuffer, ExecutionTerminalInfo},
14    spec::EngineSpec,
15};
16use std::time::Duration;
17
18/// A line-oriented display.
19///
20/// This display produces output to the provided writer.
21#[derive_where(Debug)]
22pub struct LineDisplay<W> {
23    writer: DebugIgnore<W>,
24    shared: LineDisplayShared,
25    formatter: LineDisplayFormatter,
26    prefix: String,
27}
28
29impl<W: std::io::Write> LineDisplay<W> {
30    /// Creates a new LineDisplay.
31    pub fn new(writer: W) -> Self {
32        Self {
33            writer: DebugIgnore(writer),
34            shared: LineDisplayShared::default(),
35            formatter: LineDisplayFormatter::new(),
36            prefix: String::new(),
37        }
38    }
39
40    /// Sets the prefix for all future lines.
41    #[inline]
42    pub fn set_prefix(&mut self, prefix: impl Into<String>) {
43        self.prefix = prefix.into();
44    }
45
46    /// Sets the styles for all future lines.
47    #[inline]
48    pub fn set_styles(&mut self, styles: LineDisplayStyles) {
49        self.formatter.set_styles(styles);
50    }
51
52    /// Sets the start time for all future lines.
53    ///
54    /// If the start time is set, then the progress display will be relative to
55    /// that time. Otherwise, only the offset from the start of the job will be
56    /// displayed.
57    #[inline]
58    pub fn set_start_time(&mut self, start_time: DateTime<Utc>) {
59        self.shared.set_start_time(start_time);
60    }
61
62    /// Sets the amount of time before the next progress event is shown.
63    #[inline]
64    pub fn set_progress_interval(&mut self, interval: Duration) {
65        self.formatter.set_progress_interval(interval);
66    }
67
68    /// Writes an event buffer to the writer, incrementally.
69    ///
70    /// This is a stateful method that will only display events that have not
71    /// been displayed before.
72    pub fn write_event_buffer<S: EngineSpec>(
73        &mut self,
74        buffer: &EventBuffer<S>,
75    ) -> std::io::Result<()> {
76        let mut out = LineDisplayOutput::new();
77        self.shared
78            .with_context(&self.prefix, &self.formatter)
79            .format_event_buffer(buffer, &mut out);
80        for line in out.iter() {
81            writeln!(self.writer, "{line}")?;
82        }
83
84        Ok(())
85    }
86
87    /// Writes terminal information to the writer.
88    pub fn write_terminal_info(
89        &mut self,
90        info: &ExecutionTerminalInfo,
91    ) -> std::io::Result<()> {
92        let line = self
93            .shared
94            .with_context(&self.prefix, &self.formatter)
95            .format_terminal_info(info);
96        writeln!(self.writer, "{line}")
97    }
98
99    /// Writes a generic line to the writer, with prefix attached if provided.
100    pub fn write_generic(&mut self, message: &str) -> std::io::Result<()> {
101        let line = self
102            .shared
103            .with_context(&self.prefix, &self.formatter)
104            .format_generic(message);
105        writeln!(self.writer, "{line}")
106    }
107}
108
109/// Styles for [`LineDisplay`].
110///
111/// By default this isn't colorized, but it can be if so chosen.
112#[derive(Debug, Default)]
113#[non_exhaustive]
114pub struct LineDisplayStyles {
115    pub prefix_style: Style,
116    pub meta_style: Style,
117    pub step_name_style: Style,
118    pub progress_style: Style,
119    pub progress_message_style: Style,
120    pub warning_style: Style,
121    pub warning_message_style: Style,
122    pub error_style: Style,
123    pub error_message_style: Style,
124    pub skipped_style: Style,
125    pub retry_style: Style,
126}
127
128impl LineDisplayStyles {
129    /// Returns a default set of colorized styles with ANSI colors.
130    pub fn colorized() -> Self {
131        Self {
132            prefix_style: Style::new().bold(),
133            meta_style: Style::new().bold(),
134            step_name_style: Style::new().cyan(),
135            progress_style: Style::new().bold().green(),
136            progress_message_style: Style::new().green(),
137            warning_style: Style::new().bold().yellow(),
138            warning_message_style: Style::new().yellow(),
139            error_style: Style::new().bold().red(),
140            error_message_style: Style::new().red(),
141            skipped_style: Style::new().bold().yellow(),
142            retry_style: Style::new().bold().yellow(),
143        }
144    }
145}