fwatcher 0.4.2

Auto run command when some files changed.
Documentation
extern crate glob;
extern crate getopts;
extern crate fwatcher;

use fwatcher::Fwatcher;
use getopts::{HasArg, Occur, Options, ParsingStyle};
use glob::Pattern;
use std::{env, process};
use std::path::PathBuf;
use std::time::Duration;

fn main() {
    let mut opts = Options::new();
    opts.parsing_style(ParsingStyle::StopAtFirstFree);
    opts.optflag("h", "help", "Display this message");
    opts.optflag("v", "version", "Print version info");
    opts.optflag("r", "restart", "Auto restart command, default to false");
    opts.opt("d",
             "directory",
             "Watch directory, default to current directory",
             "<dir>",
             HasArg::Yes,
             Occur::Multi);
    opts.opt("p",
             "pattern",
             r#"Watch file glob pattern, default to "*""#,
             "<pattern>",
             HasArg::Yes,
             Occur::Multi);
    opts.opt("P",
             "exclude_pattern",
             "Watch file glob pattern exclusively, default null",
             "<exclude_pattern>",
             HasArg::Yes,
             Occur::Multi);
    opts.opt("",
             "delay",
             "Delay in seconds for watcher, default to 2",
             "<second>",
             HasArg::Yes,
             Occur::Optional);
    opts.opt("i",
             "interval",
             "Interval in seconds to scan filesystem, default to 1",
             "<second>",
             HasArg::Yes,
             Occur::Optional);

    let args: Vec<_> = env::args().collect();
    let matches = match opts.parse(&args[1..]) {
        Ok(m) => m,
        Err(why) => {
            eprintln!("{}", why);
            eprintln!("run `fwatcher -h` to get the usage.");
            process::exit(1);
        },
    };

    if matches.opt_present("h") {
        print_usage_and_exit(opts, 0);
    } else if matches.opt_present("v") {
        println!("fwatcher {}", env!("CARGO_PKG_VERSION"));
        process::exit(0);
    } else if matches.free.len() == 0 {
        print_usage_and_exit(opts, 1);
    }

    let dirs: Vec<_> = matches.opt_strs("directory")
                              .iter()
                              .map(|dir| PathBuf::from(dir))
                              .collect();
    let mut patterns: Vec<_> =
        matches.opt_strs("pattern")
               .iter()
               .map(|dir| Pattern::new(dir).expect("create pattern error"))
               .collect();
    if patterns.is_empty() {
        patterns.push(Pattern::new("*").unwrap());
    }
    let exclude_patterns: Vec<_> =
        matches.opt_strs("exclude_pattern")
               .iter()
               .map(|dir| Pattern::new(dir).expect("create pattern error"))
               .collect();
    let delay = matches.opt_str("delay")
                       .map(|i| i.parse().expect("parse delay option error"))
                       .or(Some(2))
                       .map(|i| Duration::new(i, 0))
                       .unwrap();
    let interval = matches.opt_str("interval")
                          .map(|i| i.parse().expect("parse interval option error"))
                          .or(Some(1))
                          .map(|i| Duration::new(i, 0))
                          .unwrap();
    let restart = matches.opt_present("restart");
    let mut fwatcher = Fwatcher::new(dirs, matches.free);
    fwatcher.patterns(&patterns)
            .exclude_patterns(&exclude_patterns)
            .delay(delay)
            .interval(interval)
            .restart(restart)
            .run();
}

fn print_usage_and_exit(opts: Options, exit_code: i32) -> ! {
    let brief = "\
Usage:
    fwatcher [options] CMD";
    if exit_code == 0 {
        print!("{}", opts.usage(brief));
    } else {
        eprint!("{}", opts.usage(brief));
    }
    process::exit(exit_code);
}