file-expert 1.1.0

Expert system for recognizing source code files, similar to GitHub/lingust.
Documentation
//
// $COPYRIGHT$: 794d8002d1b6d954e2302879cb69c215d893c60c
#![recursion_limit = "512"]

mod data_structures;
mod expert;
mod heuristic;
mod linguist_aliases;
mod linguist_extensions;
mod linguist_filenames;
mod linguist_heuristics;
mod linguist_interpreters;
mod modeline;
mod shebang;

use clap::{Arg, ArgMatches};
use expert::Guess;
use std::io;
use std::io::prelude::*;
use std::path::Path;
use std::process::exit;
use update_informer::{registry, Check};

fn app() -> clap::Command<'static> {
    clap::command!()
        .override_help("Expert system for recognizing file types")
        .help_expected(true)
        .dont_collapse_args_in_usage(true)
        .arg(
            Arg::new("file")
                .help("Files to identify")
                .required(false)
                .multiple_values(true),
        )
}

fn main() {
    let matches: ArgMatches = app().get_matches();
    {
        let informer = update_informer::new(
            registry::Crates,
            env!("CARGO_PKG_NAME"),
            env!("CARGO_PKG_VERSION"),
        );
        if let Ok(Some(version)) = informer.check_version() {
            eprintln!("New version {} is available", version);
            eprintln!("Update with: cargo install file-expert");
        }
    }
    let mut exit_code = 0;
    if matches.is_present("file") {
        for file in matches.values_of("file").unwrap() {
            let result = expert::guess(Path::new(file));
            match result {
                Ok(lang) => {
                    if let Guess::Unknown = lang {
                        exit_code = 1;
                    }
                    println!("{}\t{}", file, lang);
                }
                Err(e) => {
                    exit_code = 1;
                    eprintln!("{}\t{}", file, e);
                }
            }
        }
    } else {
        let stdin = io::stdin();
        for line in stdin.lock().lines() {
            match line {
                Ok(l) => {
                    let result = expert::guess(Path::new(&l));
                    match result {
                        Ok(lang) => {
                            if let Guess::Unknown = lang {
                                exit_code = 1;
                            }
                            println!("{}\t{}", l, lang);
                        }
                        Err(e) => {
                            exit_code = 1;
                            eprintln!("{}\t{}", l, e);
                        }
                    }
                }
                Err(_) => break,
            }
        }
    }
    exit(exit_code);
}

#[test]
fn verify_app() {
    app().debug_assert();
}