brix_cli/
config.rs

1// Copyright (c) 2021 Ethan Lerner, Caleb Cushing, and the Brix contributors
2//
3// This software is released under the MIT License.
4// https://opensource.org/licenses/MIT
5
6//! Contains the `Config` struct and helper functions.
7
8use crate::error;
9use clap::ArgMatches;
10use colored::*;
11use log::LevelFilter;
12use std::borrow::Cow;
13use std::fmt::{self, Display, Formatter};
14use std::path::PathBuf;
15
16use crate::app;
17
18/// The core config struct used within Brix's lifecycle.
19/// Mostly the direct output of the CLI args and flags,
20/// but includes some additional properties as well.
21pub struct Config {
22    pub language: String,
23    pub config_name: String,
24    pub project: String,
25    pub module: String,
26
27    pub config_dir: Option<PathBuf>,
28    pub workdir: PathBuf,
29    pub home_dir: Option<PathBuf>,
30    pub log_level: log::LevelFilter,
31
32    pub raw_matches: ArgMatches<'static>,
33}
34
35impl Config {
36    /// Creates the config given the home directory and argument matches from `clap`.
37    pub fn new(home_dir: Option<PathBuf>, matches: ArgMatches<'static>) -> Self {
38        let current_dir: Result<PathBuf, ()> = std::env::current_dir().or_else(|_| {
39            error!(
40                "
41    Something went wrong. Your current working directory is invalid.
42    This is either due to the directory being deleted or insufficient permissions.",
43            );
44            std::process::exit(2);
45        });
46
47        let language = matches.value_of_lossy(app::LANGUAGE).unwrap().to_string();
48        let config_name = matches
49            .value_of_lossy(app::CONFIG_NAME)
50            .unwrap()
51            .to_string();
52        let project = matches.value_of_lossy(app::PROJECT).unwrap().to_string();
53        let module = matches.value_of_lossy(app::MODULE).unwrap().to_string();
54
55        let config_dir = matches
56            .value_of_lossy(app::CONFIG_DIR)
57            .and_then(|s| Some(PathBuf::from(s.to_string())));
58
59        let workdir = PathBuf::from(
60            matches
61                .value_of_lossy(app::WORKDIR)
62                .unwrap_or(Cow::from(current_dir.unwrap().to_str().unwrap()))
63                .to_string(),
64        );
65        let log_level = matches
66            .value_of_lossy(app::LOG_LEVEL)
67            .unwrap_or(Cow::from("off"))
68            .to_string();
69
70        Self {
71            raw_matches: matches,
72            language,
73            config_name,
74            project,
75            config_dir,
76            workdir,
77            home_dir,
78            log_level: log_level_to_struct(&log_level),
79            module,
80        }
81    }
82}
83
84/// Returns a `log::LevelFilter` given a string.
85fn log_level_to_struct(level: &str) -> LevelFilter {
86    match level {
87        "off" => LevelFilter::Off,
88        "error" => LevelFilter::Error,
89        "warn" => LevelFilter::Warn,
90        "info" => LevelFilter::Info,
91        "debug" => LevelFilter::Debug,
92        "trace" => LevelFilter::Trace,
93        _ => unimplemented!(),
94    }
95}
96
97#[doc(hidden)]
98macro_rules! s {
99    () => {
100        String::new()
101    };
102}
103
104impl std::default::Default for Config {
105    fn default() -> Self {
106        Self {
107            language: s!(),
108            config_name: s!(),
109            project: s!(),
110            module: s!(),
111            config_dir: None,
112            workdir: std::env::current_dir().unwrap(),
113            home_dir: None,
114            log_level: LevelFilter::Off,
115            raw_matches: ArgMatches::default(),
116        }
117    }
118}
119
120impl Display for Config {
121    fn fmt(&self, formatter: &mut Formatter) -> fmt::Result {
122        write!(
123            formatter,
124            "[LANGUAGE: {}, CONFIG_NAME: {}, PROJECT: {}, MODULE: {}, CONFIG_DIR: {:?}]",
125            self.language, self.config_name, self.project, self.module, self.config_dir
126        )
127    }
128}