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
use console::{pad_str, Alignment, Style};
use serde::{Serialize, Serializer};

use crate::Message;

/// Indication of starting or finishing of a significant process in the application.
///
/// The `status` part categorizes the process, and should always be a single verb, for example:
/// _Compiling_, _Running_.
/// In text mode, status messages are coloured and right-padded for better aesthetics.
/// Padding is hardcoded to **12** characters, therefore avoid using words longer than
/// **11** characters.
/// The `message` part is a free-form text describing the details of what's going on.
#[derive(Serialize)]
pub struct Status<'a> {
    status: &'a str,
    #[serde(skip)]
    color: &'a str,
    message: &'a str,
}

impl<'a> Status<'a> {
    /// Create a new [`Status`] with default color (green).
    pub fn new(status: &'a str, message: &'a str) -> Self {
        Self::with_color(status, "green", message)
    }

    /// Create a new [`Status`] with the given color.
    pub fn with_color(status: &'a str, color: &'a str, message: &'a str) -> Self {
        Self {
            status,
            color,
            message,
        }
    }
}

impl<'a> Message for Status<'a> {
    fn text(self) -> String {
        format!(
            "{} {}",
            Style::from_dotted_str(self.color).bold().apply_to(pad_str(
                self.status,
                12,
                Alignment::Right,
                None,
            )),
            self.message
        )
    }

    fn structured<S: Serializer>(self, ser: S) -> Result<S::Ok, S::Error> {
        let status = self.status.to_lowercase();
        Status {
            status: &status,
            color: self.color,
            message: self.message,
        }
        .serialize(ser)
    }
}