thwack 0.10.7

Command line version of Go To File utility, similar to the one on GitHub
Documentation
use std::fs::{File, OpenOptions};
use std::io::{self, Write};
use std::path::Path;
use std::sync::Mutex;

use log::{LevelFilter, Log, Metadata, Record, set_boxed_logger, set_max_level};

pub(crate) fn init<P: AsRef<Path>>(path: P) -> io::Result<()> {
    let logger = Logger::new(path)?;
    set_boxed_logger(Box::new(logger)).expect("Unable to set logger");
    set_max_level(LevelFilter::Trace);
    Ok(())
}

#[derive(Debug)]
struct Logger {
    log_file: Mutex<File>,
}

impl Logger {
    fn new<P: AsRef<Path>>(path: P) -> io::Result<Self> {
        let log_file = OpenOptions::new().create(true).append(true).open(path)?;
        Ok(Self {
            log_file: Mutex::new(log_file),
        })
    }
}

impl Log for Logger {
    fn enabled(&self, _metadata: &Metadata) -> bool {
        true
    }

    fn log(&self, record: &Record) {
        if !self.enabled(record.metadata()) {
            return;
        }
        let mut log_file = self
            .log_file
            .lock()
            .expect("Log file writer mutex was poisoned!");
        writeln!(
            log_file,
            "[{}] [{}:{}] {}",
            record.level(),
            record.module_path().unwrap_or_default(),
            record.line().unwrap_or_default(),
            record.args()
        )
        .expect("Unable to write the log file");
    }

    fn flush(&self) {
        let mut log_file = self.log_file.lock().expect("Unable to flush the log file");
        let _ = log_file.flush();
    }
}

#[cfg(test)]
mod tests {
    use std::fs;

    use tempfile::tempdir;

    use super::*;

    #[test]
    fn info_and_debug() {
        let tmp = tempdir().unwrap();
        let path = tmp.path().join("log.txt");
        init(&path).unwrap();
        log::info!("test");
        log::debug!("d!");
        let contents = &fs::read_to_string(&path).unwrap();
        assert!(contents.contains("[INFO] [thwack::logger::tests:72] test"));
        assert!(contents.contains("[DEBUG] [thwack::logger::tests:73] d!"));
    }
}