diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/event.rs | 20 | ||||
-rw-r--r-- | src/main.rs | 45 |
2 files changed, 59 insertions, 6 deletions
diff --git a/src/event.rs b/src/event.rs index 83bb876..f497359 100644 --- a/src/event.rs +++ b/src/event.rs @@ -150,6 +150,26 @@ pub enum Type<'a> { } } +impl<'a> Type<'a> { + pub fn involves(&self, needle: &str) -> bool { + use self::Type::*; + match self { + &Msg { ref from, .. } => from == needle, + &Action { ref from, .. } => from == needle, + &Join { ref nick, .. } => nick == needle, + &Part { ref nick, .. } => nick == needle, + &Quit { ref nick, .. } => nick == needle, + &Nick { ref old_nick, ref new_nick, .. } => old_nick == needle || new_nick == needle, + &Notice { ref from, .. } => from == needle, + &Kick { ref kicked_nick, ref kicking_nick, .. } => *kicked_nick == Cow::Borrowed(needle) + || kicking_nick.as_ref().map_or(false, |k| k.as_ref() == Cow::Borrowed(needle)), + &TopicChange { ref nick, .. } => nick.as_ref().map_or(false, |k| k.as_ref() == needle), + &Mode { ref nick, .. } => nick.as_ref().map_or(false, |k| k.as_ref() == Cow::Borrowed(needle)), + _ => false + } + } +} + #[derive(Clone, Debug, PartialEq, Eq, RustcEncodable, RustcDecodable)] pub struct NoTimeHash<'a>(pub Event<'a>); diff --git a/src/main.rs b/src/main.rs index d650158..4bbb9ff 100644 --- a/src/main.rs +++ b/src/main.rs @@ -24,10 +24,12 @@ extern crate blist; use std::process; use std::io::{ self, BufRead, BufReader, Write, BufWriter }; +use std::path::{ Path, PathBuf }; use std::fs::File; use std::error::Error; use std::str::FromStr; use std::collections::HashMap; +use std::ffi::OsStr; use docopt::Docopt; @@ -61,6 +63,7 @@ Usage: ilc parse [options] [-i FILE...] ilc convert [options] [-i FILE...] ilc freq [options] [-i FILE...] + ilc seen <nick> [options] [-i FILE...] ilc sort [options] [-i FILE...] ilc dedup [options] [-i FILE...] ilc (-h | --help | -v | --version) @@ -75,6 +78,7 @@ Options: --outf OUTF Set the output format. --in -i IN Give an input file, instead of stdin. --out -o OUT Give an output file, instead of stdout. + --infer-date Try to use the filename as date for the log. "#; #[derive(RustcDecodable, Debug)] @@ -82,9 +86,11 @@ struct Args { cmd_parse: bool, cmd_convert: bool, cmd_freq: bool, + cmd_seen: bool, cmd_sort: bool, cmd_dedup: bool, arg_file: Vec<String>, + arg_nick: String, flag_in: Vec<String>, flag_out: Option<String>, flag_inf: Option<String>, @@ -93,7 +99,8 @@ struct Args { flag_version: bool, flag_date: Option<String>, flag_tz: Option<String>, - flag_channel: Option<String> + flag_channel: Option<String>, + flag_infer_date: bool } fn error(e: Box<Error>) -> ! { @@ -143,21 +150,31 @@ fn main() { process::exit(1) } - let context = Context { + let mut context = Context { timezone: FixedOffset::west(args.flag_tz.and_then(|s| s.parse().ok()).unwrap_or(0)), override_date: args.flag_date.and_then(|d| NaiveDate::from_str(&d).ok()), channel: args.flag_channel.clone() }; let mut input: Box<BufRead> = if args.flag_in.len() > 0 { - let input_files = args.flag_in.iter() + let input_files: Vec<PathBuf> = args.flag_in.iter() .flat_map(|p| { match glob(p) { Ok(paths) => paths, Err(e) => die(&format!("{}", e.msg)) } - }).filter_map(Result::ok).map(|p| File::open(p).unwrap()).collect(); - Box::new(BufReader::new(chain::Chain::new(input_files))) + }).filter_map(Result::ok).collect();//.map(|p| File::open(p).unwrap()).collect(); + if args.flag_infer_date { + if input_files.len() > 1 { die("Too many input files, can't infer date") } + if let Some(date) = input_files.iter().next() + .map(PathBuf::as_path) + .and_then(Path::file_stem) + .and_then(OsStr::to_str) + .and_then(|s: &str| NaiveDate::from_str(s).ok()) { + context.override_date = Some(date); + } + } + Box::new(BufReader::new(chain::Chain::new(input_files.iter().map(|p| File::open(p).unwrap()).collect()))) } else { Box::new(BufReader::new(io::stdin())) }; @@ -178,7 +195,7 @@ fn main() { let e = e.unwrap(); let _ = encoder.encode(&context, &mut output, &e); } - }else if args.cmd_convert { + } else if args.cmd_convert { let mut decoder = force_decoder(args.flag_inf); let encoder = force_encoder(args.flag_outf); for e in decoder.decode(&context, &mut input) { @@ -253,6 +270,22 @@ fn main() { "{}:\n\tTotal lines: {}\n\tLines without alphabetic characters: {}\n\tTotal words: {}\n\tWords per line: {}\n", name, stat.lines, stat.lines - stat.alpha_lines, stat.words, stat.words as f32 / stat.lines as f32); } + } else if args.cmd_seen { + let mut decoder = force_decoder(args.flag_inf); + let mut last: Option<Event> = None; + for e in decoder.decode(&context, &mut input) { + let m = match e { + Ok(m) => m, + Err(err) => error(Box::new(err)) + }; + + if m.ty.involves(&args.arg_nick) + && last.as_ref().map_or(true, |last| m.time.as_timestamp() > last.time.as_timestamp()) { last = Some(m) } + } + let encoder = format::weechat3::Weechat3; + if let Some(ref m) = last { + let _ = encoder.encode(&context, &mut output, m); + } } else if args.cmd_sort { let mut decoder = force_decoder(args.flag_inf); let encoder = force_encoder(args.flag_outf); |