1use crate::env;
4use chrono::Local;
5use std::io::Write;
6use termcolor::{Color, ColorChoice, ColorSpec, StandardStream, WriteColor};
7
8#[derive(Default)]
9pub struct MotdOptions<'a> {
10 pub mode: Option<&'a str>, pub timestamp: Option<&'a str>, pub environment: Option<&'a str>, pub copyright: Option<&'a [&'a str]>,
14}
15
16pub fn capitalize_first(s: &str) -> String {
18 let lower = s.to_lowercase();
19 let mut c = lower.chars();
20 match c.next() {
21 None => String::new(),
22 Some(f) => f.to_uppercase().collect::<String>() + c.as_str(),
23 }
24}
25
26pub fn print_motd(
27 pkg_name: &str,
28 pkg_version: &str,
29 build_info: &str,
30 opts: MotdOptions,
31) -> std::io::Result<()> {
32 let mut stdout = StandardStream::stdout(ColorChoice::Auto);
33
34 writeln!(&mut stdout)?;
35 stdout.set_color(ColorSpec::new().set_fg(Some(Color::Magenta)))?;
36 write!(&mut stdout, " ▲ {} {}", pkg_name, pkg_version)?;
37 stdout.reset()?;
38
39 if !build_info.is_empty() && build_info != "None" {
40 if build_info.starts_with("(") {
41 write!(&mut stdout, " {}", build_info)?;
42 } else {
43 write!(&mut stdout, " ({})", build_info)?;
44 }
45 }
46 writeln!(&mut stdout)?;
47
48 if opts.timestamp.unwrap_or("") != "None" {
50 let ts = Local::now().format("%Y-%m-%d %H:%M:%S");
51 writeln!(&mut stdout, " - Timestamp: {}", ts)?;
52 }
53
54 if let Some(lines) = opts.copyright {
56 if !lines.is_empty() {
57 writeln!(&mut stdout, " - Copyright:")?;
58 for l in lines {
59 writeln!(&mut stdout, " ✓ {}", l)?;
60 }
61 }
62 }
63
64 if opts.environment.unwrap_or("") != "None" {
66 writeln!(&mut stdout, " - Environment:")?;
67 env::print_environment(&mut stdout, opts.mode.unwrap_or(""))?;
68 }
69
70 writeln!(&mut stdout)?;
71 Ok(())
72}