shell_compose/
display.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
use crate::{ProcInfo, ProcStatus};
use chrono::Local;
use comfy_table::{presets::UTF8_FULL, ContentArrangement, Table};
use env_logger::{
    fmt::style::{AnsiColor, Color, RgbColor, Style},
    Env,
};
use std::io::Write;

pub fn init_cli_logger() {
    const COLOR: Style = Style::new().fg_color(Some(Color::Ansi(AnsiColor::Magenta)));
    let mut builder = env_logger::Builder::from_env(Env::default().default_filter_or("info"));
    builder.format(|buf, record| {
        let target = record.target();
        let time = buf.timestamp();
        // let level = record.level();

        writeln!(buf, "{COLOR}{time} [{target}] {}{COLOR:#}", record.args(),)
    });

    builder.init();
}

pub fn init_daemon_logger() {
    let mut builder = env_logger::Builder::from_env(Env::default().default_filter_or("info"));
    builder.format(|buf, record| {
        let target = record.target();
        writeln!(buf, "[{target}] {}", record.args(),)
    });

    builder.init();
}

const PALETTE: [Style; 20] = [
    Style::new().fg_color(Some(Color::Rgb(RgbColor(0, 238, 110)))),
    Style::new().fg_color(Some(Color::Rgb(RgbColor(11, 123, 224)))),
    Style::new().fg_color(Some(Color::Rgb(RgbColor(2, 219, 129)))),
    Style::new().fg_color(Some(Color::Rgb(RgbColor(3, 206, 142)))),
    Style::new().fg_color(Some(Color::Rgb(RgbColor(9, 149, 198)))),
    Style::new().fg_color(Some(Color::Rgb(RgbColor(7, 168, 179)))),
    Style::new().fg_color(Some(Color::Rgb(RgbColor(4, 193, 154)))),
    Style::new().fg_color(Some(Color::Rgb(RgbColor(8, 155, 192)))),
    Style::new().fg_color(Some(Color::Rgb(RgbColor(5, 187, 161)))),
    Style::new().fg_color(Some(Color::Rgb(RgbColor(6, 181, 167)))),
    Style::new().fg_color(Some(Color::Rgb(RgbColor(12, 117, 230)))),
    Style::new().fg_color(Some(Color::Rgb(RgbColor(6, 174, 173)))),
    Style::new().fg_color(Some(Color::Rgb(RgbColor(1, 232, 116)))),
    Style::new().fg_color(Some(Color::Rgb(RgbColor(8, 162, 186)))),
    Style::new().fg_color(Some(Color::Rgb(RgbColor(4, 200, 148)))),
    Style::new().fg_color(Some(Color::Rgb(RgbColor(9, 142, 205)))),
    Style::new().fg_color(Some(Color::Rgb(RgbColor(10, 136, 211)))),
    Style::new().fg_color(Some(Color::Rgb(RgbColor(3, 213, 135)))),
    Style::new().fg_color(Some(Color::Rgb(RgbColor(1, 225, 123)))),
    Style::new().fg_color(Some(Color::Rgb(RgbColor(11, 130, 217)))),
];

const ERR_PALETTE: [Style; 20] = [
    Style::new().fg_color(Some(Color::Rgb(RgbColor(237, 227, 66)))),
    Style::new().fg_color(Some(Color::Rgb(RgbColor(251, 112, 199)))),
    Style::new().fg_color(Some(Color::Rgb(RgbColor(249, 127, 182)))),
    Style::new().fg_color(Some(Color::Rgb(RgbColor(253, 96, 217)))),
    Style::new().fg_color(Some(Color::Rgb(RgbColor(250, 119, 191)))),
    Style::new().fg_color(Some(Color::Rgb(RgbColor(240, 204, 93)))),
    Style::new().fg_color(Some(Color::Rgb(RgbColor(241, 196, 102)))),
    Style::new().fg_color(Some(Color::Rgb(RgbColor(242, 189, 110)))),
    Style::new().fg_color(Some(Color::Rgb(RgbColor(239, 212, 84)))),
    Style::new().fg_color(Some(Color::Rgb(RgbColor(243, 181, 119)))),
    Style::new().fg_color(Some(Color::Rgb(RgbColor(244, 173, 128)))),
    Style::new().fg_color(Some(Color::Rgb(RgbColor(245, 166, 137)))),
    Style::new().fg_color(Some(Color::Rgb(RgbColor(238, 219, 75)))),
    Style::new().fg_color(Some(Color::Rgb(RgbColor(246, 150, 155)))),
    Style::new().fg_color(Some(Color::Rgb(RgbColor(254, 89, 226)))),
    Style::new().fg_color(Some(Color::Rgb(RgbColor(247, 142, 164)))),
    Style::new().fg_color(Some(Color::Rgb(RgbColor(248, 135, 173)))),
    Style::new().fg_color(Some(Color::Rgb(RgbColor(246, 158, 146)))),
    Style::new().fg_color(Some(Color::Rgb(RgbColor(252, 104, 208)))),
    Style::new().fg_color(Some(Color::Rgb(RgbColor(255, 81, 235)))),
];

pub fn log_color(idx: usize, err: bool) -> &'static Style {
    if err {
        &ERR_PALETTE[idx % 20]
    } else {
        &PALETTE[idx % 20]
    }
}

pub fn log_info(text: &str) {
    const COLOR: Style = Style::new().fg_color(Some(Color::Ansi(AnsiColor::Magenta)));

    let time = Local::now().format("%F %T%.3f");
    println!("{COLOR}{time} [dispatcher] {text}{COLOR:#}")
}

pub fn proc_info_table(proc_infos: &[ProcInfo]) {
    const EMPTY: String = String::new();

    fn clip_str(text: &str, max_len: usize) -> String {
        if text.len() > max_len {
            format!("{}...", &text[..max_len.max(3) - 3])
        } else {
            text.to_string()
        }
    }

    let mut table = Table::new();
    table
        .load_preset(UTF8_FULL)
        .set_header(vec!["PID", "Status", "Command", "Start", "End"])
        .set_content_arrangement(ContentArrangement::DynamicFullWidth)
        .add_rows(proc_infos.iter().map(|info| {
            let status = match &info.state {
                ProcStatus::ExitOk => "Success".to_string(),
                ProcStatus::ExitErr(code) => format!("Error {code}"),
                ProcStatus::Unknown(err) => clip_str(err, 20),
                st => format!("{st:?}"),
            };
            let end = if let Some(ts) = info.end {
                format!("{}", ts.format("%F %T"))
            } else {
                EMPTY
            };
            vec![
                format!("{}", info.pid),
                status,
                clip_str(&info.command, 30),
                format!("{}", info.start.format("%F %T")),
                end,
            ]
        }));

    println!("{table}");
}