Skip to main content

truefix_log/
screen.rs

1//! Console log.
2
3use crate::{Log, is_heartbeat};
4
5/// Output switches for [`ScreenLog`] (FR-026): `ScreenLogShowEvents`/`ScreenLogShowHeartBeats`/
6/// `ScreenLogShowIncoming`/`ScreenLogShowOutgoing`/`ScreenIncludeMilliseconds`.
7#[derive(Debug, Clone, Copy)]
8pub struct ScreenLogOptions {
9    /// `ScreenLogShowEvents`: whether event lines are printed at all.
10    pub show_events: bool,
11    /// `ScreenLogShowHeartBeats`: whether Heartbeat (`35=0`) messages are printed.
12    pub show_heartbeats: bool,
13    /// `ScreenLogShowIncoming`: whether inbound messages are printed at all.
14    pub show_incoming: bool,
15    /// `ScreenLogShowOutgoing`: whether outbound messages are printed at all.
16    pub show_outgoing: bool,
17    /// `ScreenIncludeMilliseconds`: whether the timestamp prefix includes milliseconds.
18    pub include_milliseconds: bool,
19}
20
21impl Default for ScreenLogOptions {
22    fn default() -> Self {
23        Self {
24            show_events: true,
25            show_heartbeats: true,
26            show_incoming: true,
27            show_outgoing: true,
28            include_milliseconds: false,
29        }
30    }
31}
32
33/// Logs messages to stdout and events to stderr, with direction prefixes.
34pub struct ScreenLog {
35    options: ScreenLogOptions,
36}
37
38impl Default for ScreenLog {
39    fn default() -> Self {
40        Self::new()
41    }
42}
43
44impl ScreenLog {
45    /// Create a screen log with default (unfiltered) output switches.
46    pub fn new() -> Self {
47        Self::with_options(ScreenLogOptions::default())
48    }
49
50    /// Create a screen log honoring `options` (FR-026).
51    pub fn with_options(options: ScreenLogOptions) -> Self {
52        Self { options }
53    }
54
55    fn timestamp_prefix(&self) -> String {
56        crate::file::format_timestamp_prefix(self.options.include_milliseconds)
57    }
58}
59
60impl Log for ScreenLog {
61    fn on_incoming(&self, message: &str) {
62        if !self.options.show_incoming {
63            return;
64        }
65        if is_heartbeat(message) && !self.options.show_heartbeats {
66            return;
67        }
68        println!("{}<incoming> {message}", self.timestamp_prefix());
69    }
70    fn on_outgoing(&self, message: &str) {
71        if !self.options.show_outgoing {
72            return;
73        }
74        if is_heartbeat(message) && !self.options.show_heartbeats {
75            return;
76        }
77        println!("{}<outgoing> {message}", self.timestamp_prefix());
78    }
79    fn on_event(&self, text: &str) {
80        if !self.options.show_events {
81            return;
82        }
83        eprintln!("{}<event> {text}", self.timestamp_prefix());
84    }
85}