uvm_cli/
lib.rs

1#[macro_use]
2extern crate log;
3#[macro_use]
4extern crate serde_derive;
5
6mod utils;
7use flexi_logger::{DeferredNow, Level, LevelFilter, LogSpecification, Logger, Record};
8
9pub use self::utils::find_sub_commands;
10pub use self::utils::print_error_and_exit;
11pub use self::utils::sub_command_path;
12use console::Style;
13
14use std::ffi::OsStr;
15use std::io;
16use std::process::Command;
17
18pub mod options;
19
20#[cfg(unix)]
21use std::os::unix::process::CommandExt;
22
23#[cfg(unix)]
24pub fn exec_command<C, I, S>(command: C, args: I) -> io::Result<i32>
25where
26    C: AsRef<OsStr>,
27    I: IntoIterator<Item = S>,
28    S: AsRef<OsStr>,
29{
30    Err(Command::new(command).args(args).exec())
31}
32
33#[cfg(windows)]
34pub fn exec_command<C, I, S>(command: C, args: I) -> io::Result<i32>
35where
36    C: AsRef<OsStr>,
37    I: IntoIterator<Item = S>,
38    S: AsRef<OsStr>,
39{
40    Command::new(command)
41        .args(args)
42        .spawn()?
43        .wait()
44        .and_then(|s| {
45            s.code().ok_or_else(|| {
46                io::Error::new(io::ErrorKind::Interrupted, "Process terminated by signal")
47            })
48        })
49}
50
51pub fn set_colors_enabled(color: &options::ColorOption) {
52    use options::ColorOption::*;
53    match color {
54        Never => console::set_colors_enabled(false),
55        Always => console::set_colors_enabled(true),
56        Auto => (),
57    };
58}
59
60pub fn set_loglevel(verbose: i32) {
61    let log_spec_builder = match verbose {
62        0 => LogSpecification::default(LevelFilter::Warn),
63        1 => LogSpecification::default(LevelFilter::Info),
64        2 => LogSpecification::default(LevelFilter::Debug),
65        _ => LogSpecification::default(LevelFilter::max()),
66    };
67
68    let log_spec = log_spec_builder.build();
69    Logger::with(log_spec).format(format_logs).start().unwrap();
70}
71
72pub fn format_logs(
73    write: &mut dyn std::io::Write,
74    _now: &mut DeferredNow,
75    record: &Record,
76) -> Result<(), std::io::Error> {
77    let style = match record.level() {
78        Level::Trace => Style::new().white().dim().italic(),
79        Level::Debug => Style::new().white().dim(),
80        Level::Info => Style::new().white(),
81        Level::Warn => Style::new().yellow(),
82        Level::Error => Style::new().red(),
83    };
84
85    write
86        .write(&format!("{}", style.apply_to(record.args())).into_bytes())
87        .map(|_| ())
88}