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
extern crate cargo_metadata;
extern crate cmake_config;
extern crate colored;
extern crate fel4_config;
#[macro_use]
extern crate log;
#[macro_use]
extern crate structopt;

use colored::Colorize;
use std::fmt;
use std::io;

mod build_cmd;
mod clean_cmd;
mod cmake_codegen;
mod command_ext;
mod config;
mod deploy_cmd;
mod generator;
mod new_cmd;
mod simulate_cmd;
mod test_cmd;

pub use build_cmd::handle_build_cmd;
pub use clean_cmd::handle_clean_cmd;
pub use config::{
    BuildCmd, CargoFel4Cli, CleanCmd, Fel4SubCmd, LoudnessOpts, NewCmd, ResolvedConfig,
    SimulateCmd, TestCmd, TestSubCmd,
};
pub use deploy_cmd::handle_deploy_cmd;
pub use new_cmd::handle_new_cmd;
pub use simulate_cmd::handle_simulate_cmd;
pub use test_cmd::handle_test_cmd;

#[derive(Clone, Debug, Eq, PartialEq, Hash)]
pub enum Error {
    ConfigError(String),
    IO(String),
    ExitStatusError(String),
}

impl From<io::Error> for Error {
    fn from(e: io::Error) -> Self {
        Error::IO(format!("{}", e))
    }
}

impl From<cargo_metadata::Error> for Error {
    fn from(e: cargo_metadata::Error) -> Self {
        Error::ConfigError(format!("{}", e))
    }
}

impl fmt::Display for Error {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self {
            Error::IO(msg) => write!(f, "[IO error] {}", msg),
            Error::ExitStatusError(msg) => write!(f, "[command error] {}", msg),
            Error::ConfigError(msg) => write!(
                f,
                "[config error] {}\n\nCheck your project's toml files for invalid syntax",
                msg
            ),
        }
    }
}

pub struct Logger;

impl log::Log for Logger {
    fn enabled(&self, metadata: &log::Metadata) -> bool {
        metadata.level() <= log::Level::Info
    }

    /// Error/Warn are colored red/brigh-yellow to match Cargo/rustc
    /// Info is colored bright-green
    fn log(&self, record: &log::Record) {
        if self.enabled(record.metadata()) {
            println!(
                "{}: {}",
                match record.level() {
                    log::Level::Error => "error".red(),
                    log::Level::Warn => "warn".bright_yellow(),
                    log::Level::Info => "info".bright_green(),
                    l => l.to_string().to_lowercase().normal(),
                },
                record.args()
            );
        }
    }

    fn flush(&self) {}
}