use notify::{Event, RecursiveMode, Result, Watcher}; use std::{fs::File, io::{Read as _, Seek as _, SeekFrom, pipe}, path::{Path, PathBuf}, sync::mpsc}; pub fn default_log_file () -> PathBuf { let base = xdg::BaseDirectories::new () .data_home .expect ("could not find default log file."); base.join ("Steam/steamapps/common/Team Fortress 2/tf/console.log") .to_path_buf () } pub struct Console { prev_size : usize, } fn file_size (file : &Path) -> u64 { if let Ok (mut f) = File::open (file) { let x = f.seek (SeekFrom::End (0)); x.unwrap_or (0) } else { 0 } } impl Console { pub fn watch (log_file : &Path, cb : F) -> Result< // mpsc::Receiver> () > where F : Fn (&str) -> () { let mut prev_size = file_size (log_file); let (tx, rx) = mpsc::channel::> (); let mut watcher = notify::recommended_watcher (tx)?; watcher.watch (log_file, RecursiveMode::NonRecursive)?; for res in rx { if let Err (err) = res { log::error! ("{:?}", err); continue }; let new_size = file_size (log_file); if prev_size < new_size { let mut f = File::open (log_file) .expect ("failed to read log file"); f.seek (SeekFrom::Start (prev_size)).unwrap (); let mut buf = String::new (); f.read_to_string (&mut buf).unwrap (); cb (&buf) } if new_size < prev_size { log::warn! ("log file shrank!??"); } prev_size = new_size; } Ok (()) } }