use std::str::FromStr;
use anyhow::{anyhow, Error};
use regex::Regex;
use structopt::StructOpt;
use topfew::{top_few_from_stream, KeyFinder};
fn main() -> Result<(), Error> {
let options = Options::from_args();
if options.num < 1 {
return Err(anyhow!(
"--num needs to be 1 or larger, got {}",
options.num
));
}
let sep = Regex::new(&options.regex)?;
let kf = KeyFinder::new(Some(options.fields.indices), sep)?;
let top_list = top_few_from_stream(options.file.into(), &kf, options.num)?;
for kc in top_list {
println!("{} {}", kc.count, kc.key);
}
Ok(())
}
#[derive(Debug, StructOpt)]
#[structopt(name = "topfew")]
struct Options {
#[structopt(long, short)]
fields: FieldSpec,
#[structopt(long, short = "n", default_value = "10")]
num: usize,
#[structopt(long, short = "e", default_value = "[ \\t]")]
regex: String,
file: String,
}
#[derive(Debug)]
struct FieldSpec {
indices: Vec<usize>,
}
impl FromStr for FieldSpec {
type Err = Error;
fn from_str(s: &str) -> Result<Self, Self::Err> {
let mut indices = Vec::new();
for f in s.split(',') {
indices.push(usize::from_str(f)?);
}
Ok(FieldSpec { indices })
}
}