pidcat 0.2.1

An adb logcat wrapper and filters
Documentation
use crate::log::Log;
use crate::sink::Sink;
use async_trait::async_trait;
use colored::*;
use lazy_static::lazy_static;

struct Color(u8, u8, u8);

lazy_static! {
    static ref ERROR: Color = Color(255, 38, 0);
    static ref VERBOSE: Color = Color(255, 255, 255);
    static ref INFO: Color = Color(5, 215, 2);
    static ref WARNING: Color = Color(215, 95, 2);
    static ref DEBUG: Color = Color(95, 175, 255);
}

macro_rules! error {
    ($s:expr) => {
        println!("{}", $s.truecolor(ERROR.0, ERROR.1, ERROR.2))
    };
}

macro_rules! warn {
    ($s:expr) => {
        println!("{}", $s.truecolor(WARNING.0, WARNING.1, WARNING.2))
    };
}

macro_rules! info {
    ($s:expr) => {
        println!("{}", $s.truecolor(INFO.0, INFO.1, INFO.2))
    };
}

macro_rules! debug {
    ($s:expr) => {
        println!("{}", $s.truecolor(DEBUG.0, DEBUG.1, DEBUG.2))
    };
}

macro_rules! verbose {
    ($s:expr) => {
        println!("{}", $s.truecolor(VERBOSE.0, VERBOSE.1, VERBOSE.2))
    };
}

pub(crate) struct TerminalSink {
    color: bool,
    tag_width: usize,
}

impl TerminalSink {
    #[allow(dead_code)]
    pub(crate) fn new(color: String, tag_width: usize) -> Self {
        Self {
            color: color == "always" || color == "auto",
            tag_width,
        }
    }

    fn terminal_print(&self, level: &str, s: String) {
        if self.color {
            match level {
                "V" => verbose!(s),
                "D" => debug!(s),
                "I" => info!(s),
                "W" => warn!(s),
                "E" => error!(s),
                "F" => error!(s),
                _ => verbose!(s),
            };
        }
    }
}

#[async_trait]
impl Sink for TerminalSink {
    async fn write(&self, log: Log) {
        let mut tag = log.tag;
        if tag.len() > self.tag_width {
            tag.truncate(self.tag_width);
        }
        let message = &log.message.split('\n').collect::<Vec<&str>>();
        for (i, s) in message.iter().enumerate() {
            let s = if i == 0 {
                format!(
                    "{:11} {:>5} {:<5} {:width$} {:^3} {}",
                    log.time,
                    log.pid,
                    log.tid,
                    tag,
                    log.level.on_truecolor(88, 88, 88),
                    s,
                    width = self.tag_width
                )
            } else {
                format!(
                    "{:12} {:>5} {:<5} {:width$} {:^3} {}",
                    "",
                    "",
                    "",
                    " ",
                    log.level.on_truecolor(88, 88, 88),
                    s,
                    width = self.tag_width
                )
            };
            if self.color {
                self.terminal_print(log.level.as_str(), s);
            } else {
                println!("{}", s);
            }
        }
    }
}