summaryrefslogtreecommitdiffstats
path: root/src/bin/main.rs
blob: 9b3652698c32477bb8e770550a5fd36c0a4fe1b8 (plain)
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
extern crate exa;
use exa::Exa;

use std::ffi::OsString;
use std::env::{args_os, var_os};
use std::io::{stdout, stderr, Write, ErrorKind};
use std::process::exit;


fn main() {
    configure_logger();

    let args: Vec<OsString> = args_os().skip(1).collect();
    match Exa::from_args(args.iter(), &mut stdout()) {
        Ok(mut exa) => {
            match exa.run() {
                Ok(exit_status) => exit(exit_status),
                Err(e) => {
                    match e.kind() {
                        ErrorKind::BrokenPipe => exit(exits::SUCCESS),
                        _ => {
                            eprintln!("{}", e);
                            exit(exits::RUNTIME_ERROR);
                        },
                    };
                }
            };
        },

        Err(ref e) if e.is_error() => {
            let mut stderr = stderr();
            writeln!(stderr, "{}", e).unwrap();

            if let Some(s) = e.suggestion() {
                let _ = writeln!(stderr, "{}", s);
            }

            exit(exits::OPTIONS_ERROR);
        },

        Err(ref e) => {
            println!("{}", e);
            exit(exits::SUCCESS);
        },
    };
}


/// Sets up a global logger if one is asked for.
/// The ‘EXA_DEBUG’ environment variable controls whether log messages are
/// displayed or not. Currently there are just two settings (on and off).
///
/// This can’t be done in exa’s own option parsing because that part of it
/// logs as well, so by the time execution gets there, the logger needs to
/// have already been set up.
pub fn configure_logger() {
    extern crate env_logger;
    extern crate log;

    let present = match var_os(exa::vars::EXA_DEBUG) {
        Some(debug)  => debug.len() > 0,
        None         => false,
    };

    let mut logs = env_logger::Builder::new();
    if present {
        logs.filter(None, log::LevelFilter::Debug);
    }
    else {
        logs.filter(None, log::LevelFilter::Off);
    }

    logs.init()
}


mod exits {

    /// Exit code for when exa runs OK.
    pub const SUCCESS: i32 = 0;

    /// Exit code for when there was at least one I/O error during execution.
    pub const RUNTIME_ERROR: i32 = 1;

    /// Exit code for when the command-line options are invalid.
    pub const OPTIONS_ERROR: i32 = 3;
}