From cb296a5d985de3233cafa762fada6444379c63f4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20DOUIN?= Date: Mon, 26 Apr 2021 11:32:19 +0200 Subject: [PATCH] fix stderr redirection (#130) --- CHANGELOG.md | 2 ++ src/main.rs | 9 +++--- src/output/log.rs | 81 ++++++++++++++++------------------------------- 3 files changed, 35 insertions(+), 57 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6bdbc3a..2d9e157 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -25,6 +25,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Improve config compatibility on Windows [#111](https://github.com/soywod/himalaya/pull/111) - Vim table containing emoji [#122] - IDLE mode after network interruption [#123] +- Output redirected to `stderr` [#130] ## [0.2.6] - 2021-04-17 @@ -207,3 +208,4 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 [#123]: https://github.com/soywod/himalaya/issues/123 [#125]: https://github.com/soywod/himalaya/issues/125 [#126]: https://github.com/soywod/himalaya/issues/126 +[#130]: https://github.com/soywod/himalaya/issues/130 diff --git a/src/main.rs b/src/main.rs index a020e21..c975029 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,7 +1,7 @@ use clap; use error_chain::error_chain; use log::{debug, error, trace}; -use std::{env, path::PathBuf}; +use std::{env, path::PathBuf, process::exit}; mod comp; mod config; @@ -61,9 +61,7 @@ fn run() -> Result<()> { let output_fmt: OutputFmt = matches.value_of("output").unwrap().into(); let log_level: LogLevel = matches.value_of("log-level").unwrap().into(); - init_logger(&output_fmt, &log_level)?; - debug!("output format: {}", output_fmt); - debug!("log level: {}", log_level); + init_logger(output_fmt, log_level)?; // Check completion matches before the config init if comp_matches(build_app(), &matches)? { @@ -104,5 +102,8 @@ fn main() { errs.for_each(|err| error!(" ↳ {}", err)); } } + exit(1); + } else { + exit(0); } } diff --git a/src/output/log.rs b/src/output/log.rs index 5baafe8..3dc6235 100644 --- a/src/output/log.rs +++ b/src/output/log.rs @@ -1,14 +1,14 @@ use chrono::Local; use env_logger; use error_chain::error_chain; -use log::{self, Level, LevelFilter, Metadata, Record}; -use std::{fmt, io::Write}; +use log::{self, debug, Level, LevelFilter}; +use std::{fmt, io, io::Write, ops::Deref}; use super::fmt::{set_output_fmt, OutputFmt}; error_chain! {} -// Log level struct +// Log level wrapper pub struct LogLevel(pub LevelFilter); @@ -26,83 +26,58 @@ impl From<&str> for LogLevel { impl fmt::Display for LogLevel { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "{}", self.0.to_string()) + write!(f, "{}", self.deref()) } } -// Plain logger +impl Deref for LogLevel { + type Target = LevelFilter; -pub struct PlainLogger; - -impl log::Log for PlainLogger { - fn enabled(&self, metadata: &Metadata) -> bool { - metadata.level() <= Level::Trace + fn deref(&self) -> &Self::Target { + &self.0 } - - fn log(&self, record: &Record) { - if self.enabled(record.metadata()) { - if let Level::Error = record.level() { - eprintln!("{}", record.args()); - } else { - println!("{}", record.args()); - } - } - } - - fn flush(&self) {} -} - -// JSON logger - -pub struct JsonLogger; - -impl log::Log for JsonLogger { - fn enabled(&self, metadata: &Metadata) -> bool { - [Level::Error, Level::Info].contains(&metadata.level()) - } - - fn log(&self, record: &Record) { - if self.enabled(record.metadata()) { - if let Level::Error = record.level() { - eprintln!("{}", record.args()); - } else { - print!("{}", record.args()); - } - } - } - - fn flush(&self) {} } // Init -pub fn init(fmt: &OutputFmt, level: &LogLevel) -> Result<()> { +pub fn init(fmt: OutputFmt, filter: LogLevel) -> Result<()> { + let level_filter = filter.deref(); + let level = level_filter.to_level(); + match fmt { - &OutputFmt::Plain => { + OutputFmt::Plain => { set_output_fmt(&OutputFmt::Plain); } - &OutputFmt::Json => { + OutputFmt::Json => { set_output_fmt(&OutputFmt::Json); } }; env_logger::Builder::new() - .format(|buf, record| { - if let log::Level::Info = record.metadata().level() { - write!(buf, "{}", record.args()) - } else { + .target(env_logger::Target::Stdout) + .format(move |buf, record| match level { + None => Ok(()), + Some(Level::Info) => match record.metadata().level() { + Level::Info => write!(buf, "{}", record.args()), + Level::Error => writeln!(&mut io::stderr(), "{}", record.args()), + _ => writeln!(buf, "{}", record.args()), + }, + _ => { writeln!( buf, "[{} {:5} {}] {}", Local::now().format("%Y-%m-%dT%H:%M:%S"), record.metadata().level(), record.module_path().unwrap_or_default(), - record.args() + record.args(), ) } }) - .filter_level(level.0) + .filter_level(*level_filter) .init(); + debug!("output format: {}", fmt); + debug!("log level: {}", filter); + Ok(()) }