#![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();
}