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}