mirror of
https://github.com/soywod/himalaya.git
synced 2024-11-25 04:20:22 +00:00
refactor output system (#74)
This commit is contained in:
parent
ebf1b854be
commit
f26051685c
9 changed files with 325 additions and 92 deletions
|
@ -12,6 +12,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||||
- Wiki entry for Gmail users [#58]
|
- Wiki entry for Gmail users [#58]
|
||||||
- Info logs for copy/move/delete cmd + silent mode [#74]
|
- Info logs for copy/move/delete cmd + silent mode [#74]
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
- Refactor output system + log levels [#74]
|
||||||
|
|
||||||
## [0.2.3] - 2021-04-08
|
## [0.2.3] - 2021-04-08
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|
65
Cargo.lock
generated
65
Cargo.lock
generated
|
@ -30,6 +30,17 @@ version = "0.5.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "23b62fc65de8e4e7f52534fb52b0f3ed04746ae267519eef2a83941e8085068b"
|
checksum = "23b62fc65de8e4e7f52534fb52b0f3ed04746ae267519eef2a83941e8085068b"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "atty"
|
||||||
|
version = "0.2.14"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8"
|
||||||
|
dependencies = [
|
||||||
|
"hermit-abi",
|
||||||
|
"libc",
|
||||||
|
"winapi",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "autocfg"
|
name = "autocfg"
|
||||||
version = "1.0.1"
|
version = "1.0.1"
|
||||||
|
@ -194,6 +205,19 @@ dependencies = [
|
||||||
"cfg-if 1.0.0",
|
"cfg-if 1.0.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "env_logger"
|
||||||
|
version = "0.8.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "17392a012ea30ef05a610aa97dfb49496e71c9f676b27879922ea5bdf60d9d3f"
|
||||||
|
dependencies = [
|
||||||
|
"atty",
|
||||||
|
"humantime",
|
||||||
|
"log",
|
||||||
|
"regex",
|
||||||
|
"termcolor",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "error-chain"
|
name = "error-chain"
|
||||||
version = "0.12.4"
|
version = "0.12.4"
|
||||||
|
@ -271,14 +295,25 @@ version = "0.9.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "d7afe4a420e3fe79967a00898cc1f4db7c8a49a9333a29f8a4bd76a253d5cd04"
|
checksum = "d7afe4a420e3fe79967a00898cc1f4db7c8a49a9333a29f8a4bd76a253d5cd04"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "hermit-abi"
|
||||||
|
version = "0.1.18"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "322f4de77956e22ed0e5032c359a0f1273f1f7f0d79bfa3b8ffbc730d7fbcc5c"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "himalaya"
|
name = "himalaya"
|
||||||
version = "0.2.3"
|
version = "0.2.3"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"clap",
|
"clap",
|
||||||
|
"env_logger",
|
||||||
"error-chain",
|
"error-chain",
|
||||||
"imap",
|
"imap",
|
||||||
"lettre",
|
"lettre",
|
||||||
|
"log",
|
||||||
"mailparse",
|
"mailparse",
|
||||||
"native-tls",
|
"native-tls",
|
||||||
"rfc2047-decoder",
|
"rfc2047-decoder",
|
||||||
|
@ -325,6 +360,12 @@ version = "0.3.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "494b4d60369511e7dea41cf646832512a94e542f68bb9c49e54518e0f468eb47"
|
checksum = "494b4d60369511e7dea41cf646832512a94e542f68bb9c49e54518e0f468eb47"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "humantime"
|
||||||
|
version = "2.1.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "hyperx"
|
name = "hyperx"
|
||||||
version = "1.3.0"
|
version = "1.3.0"
|
||||||
|
@ -475,11 +516,11 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "log"
|
name = "log"
|
||||||
version = "0.4.11"
|
version = "0.4.14"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "4fabed175da42fed1fa0746b0ea71f412aa9d35e76e95e59b192c64b9dc2bf8b"
|
checksum = "51b9bbe6c47d51fc3e1a9b945965946b4c44142ab8792c50835a980d362c2710"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cfg-if 0.1.10",
|
"cfg-if 1.0.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -1033,6 +1074,15 @@ dependencies = [
|
||||||
"winapi",
|
"winapi",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "termcolor"
|
||||||
|
version = "1.1.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "2dfed899f0eb03f32ee8c6a0aabdb8a7949659e3466561fc0adf54e26d88c5f4"
|
||||||
|
dependencies = [
|
||||||
|
"winapi-util",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "terminal_size"
|
name = "terminal_size"
|
||||||
version = "0.1.15"
|
version = "0.1.15"
|
||||||
|
@ -1197,6 +1247,15 @@ version = "0.4.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
|
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "winapi-util"
|
||||||
|
version = "0.1.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178"
|
||||||
|
dependencies = [
|
||||||
|
"winapi",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "winapi-x86_64-pc-windows-gnu"
|
name = "winapi-x86_64-pc-windows-gnu"
|
||||||
version = "0.4.0"
|
version = "0.4.0"
|
||||||
|
|
|
@ -7,9 +7,11 @@ edition = "2018"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
clap = {version = "2.33.3", default-features = false, features = ["suggestions"]}
|
clap = {version = "2.33.3", default-features = false, features = ["suggestions"]}
|
||||||
|
env_logger = "0.8.3"
|
||||||
error-chain = "0.12.4"
|
error-chain = "0.12.4"
|
||||||
imap = "2.4.0"
|
imap = "2.4.0"
|
||||||
lettre = "0.10.0-beta.3"
|
lettre = "0.10.0-beta.3"
|
||||||
|
log = "0.4.14"
|
||||||
mailparse = "0.13.1"
|
mailparse = "0.13.1"
|
||||||
native-tls = "0.2"
|
native-tls = "0.2"
|
||||||
rfc2047-decoder = "0.1.2"
|
rfc2047-decoder = "0.1.2"
|
||||||
|
|
|
@ -87,17 +87,18 @@ soywod <clement.douin@posteo.net>
|
||||||
📫 Minimalist CLI email client
|
📫 Minimalist CLI email client
|
||||||
|
|
||||||
USAGE:
|
USAGE:
|
||||||
himalaya [FLAGS] [OPTIONS] [SUBCOMMAND]
|
himalaya [OPTIONS] [SUBCOMMAND]
|
||||||
|
|
||||||
FLAGS:
|
FLAGS:
|
||||||
-h, --help Prints help information
|
-h, --help Prints help information
|
||||||
-s, --silent Disables any output
|
|
||||||
-V, --version Prints version information
|
-V, --version Prints version information
|
||||||
|
|
||||||
OPTIONS:
|
OPTIONS:
|
||||||
-a, --account <STRING> Selects a specific account
|
-a, --account <STRING> Selects a specific account
|
||||||
|
-l, --log <LEVEL> Defines the logs level [default: info] [possible values: error, warn, info, debug,
|
||||||
|
trace]
|
||||||
-m, --mailbox <MAILBOX> Selects a specific mailbox [default: INBOX]
|
-m, --mailbox <MAILBOX> Selects a specific mailbox [default: INBOX]
|
||||||
-o, --output <STRING> Defines the output format [default: plain] [possible values: plain, json]
|
-o, --output <FMT> Defines the output format [default: plain] [possible values: plain, json]
|
||||||
|
|
||||||
SUBCOMMANDS:
|
SUBCOMMANDS:
|
||||||
attachments Downloads all message attachments
|
attachments Downloads all message attachments
|
||||||
|
|
22
src/main.rs
22
src/main.rs
|
@ -7,6 +7,8 @@ mod config {
|
||||||
}
|
}
|
||||||
mod output {
|
mod output {
|
||||||
pub(crate) mod cli;
|
pub(crate) mod cli;
|
||||||
|
pub(crate) mod fmt;
|
||||||
|
pub(crate) mod log;
|
||||||
pub(crate) mod utils;
|
pub(crate) mod utils;
|
||||||
}
|
}
|
||||||
mod imap {
|
mod imap {
|
||||||
|
@ -28,6 +30,7 @@ mod mbox {
|
||||||
|
|
||||||
use clap;
|
use clap;
|
||||||
use error_chain::error_chain;
|
use error_chain::error_chain;
|
||||||
|
use log::{debug, error};
|
||||||
use std::env;
|
use std::env;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
|
@ -36,7 +39,11 @@ use crate::{
|
||||||
imap::cli::{imap_matches, imap_subcmds},
|
imap::cli::{imap_matches, imap_subcmds},
|
||||||
mbox::cli::{mbox_matches, mbox_source_arg, mbox_subcmds},
|
mbox::cli::{mbox_matches, mbox_source_arg, mbox_subcmds},
|
||||||
msg::cli::{msg_matches, msg_subcmds},
|
msg::cli::{msg_matches, msg_subcmds},
|
||||||
output::cli::output_args,
|
output::{
|
||||||
|
cli::output_args,
|
||||||
|
fmt::OutputFmt,
|
||||||
|
log::{init as init_logger, LogLevel},
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
error_chain! {
|
error_chain! {
|
||||||
|
@ -45,6 +52,7 @@ error_chain! {
|
||||||
ImapCli(crate::imap::cli::Error, crate::imap::cli::ErrorKind);
|
ImapCli(crate::imap::cli::Error, crate::imap::cli::ErrorKind);
|
||||||
MboxCli(crate::mbox::cli::Error, crate::mbox::cli::ErrorKind);
|
MboxCli(crate::mbox::cli::Error, crate::mbox::cli::ErrorKind);
|
||||||
MsgCli(crate::msg::cli::Error, crate::msg::cli::ErrorKind);
|
MsgCli(crate::msg::cli::Error, crate::msg::cli::ErrorKind);
|
||||||
|
OutputLog(crate::output::log::Error, crate::output::log::ErrorKind);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -62,6 +70,14 @@ fn run() -> Result<()> {
|
||||||
.subcommands(msg_subcmds())
|
.subcommands(msg_subcmds())
|
||||||
.get_matches();
|
.get_matches();
|
||||||
|
|
||||||
|
let output_fmt: OutputFmt = matches.value_of("output").unwrap().into();
|
||||||
|
let log_level: LogLevel = matches.value_of("log").unwrap().into();
|
||||||
|
|
||||||
|
init_logger(&output_fmt, &log_level)?;
|
||||||
|
debug!("Logger initialized");
|
||||||
|
debug!("Output format: {}", &output_fmt);
|
||||||
|
debug!("Log level: {}", &log_level);
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
if mbox_matches(&matches)? {
|
if mbox_matches(&matches)? {
|
||||||
break;
|
break;
|
||||||
|
@ -88,8 +104,8 @@ fn main() {
|
||||||
match errs.next() {
|
match errs.next() {
|
||||||
None => (),
|
None => (),
|
||||||
Some(err) => {
|
Some(err) => {
|
||||||
eprintln!("{}", err);
|
error!("{}", err);
|
||||||
errs.for_each(|err| eprintln!(" ↳ {}", err));
|
errs.for_each(|err| error!(" ↳ {}", err));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
170
src/msg/cli.rs
170
src/msg/cli.rs
|
@ -1,5 +1,6 @@
|
||||||
use clap::{self, App, Arg, ArgMatches, SubCommand};
|
use clap::{self, App, Arg, ArgMatches, SubCommand};
|
||||||
use error_chain::error_chain;
|
use error_chain::error_chain;
|
||||||
|
use log::{debug, error, info};
|
||||||
use std::{fs, ops::Deref};
|
use std::{fs, ops::Deref};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
|
@ -9,7 +10,6 @@ use crate::{
|
||||||
input,
|
input,
|
||||||
mbox::cli::mbox_target_arg,
|
mbox::cli::mbox_target_arg,
|
||||||
msg::model::{Attachments, Msg, Msgs, ReadableMsg},
|
msg::model::{Attachments, Msg, Msgs, ReadableMsg},
|
||||||
output::utils::{print, Info},
|
|
||||||
smtp,
|
smtp,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -19,7 +19,6 @@ error_chain! {
|
||||||
Imap(crate::imap::model::Error, crate::imap::model::ErrorKind);
|
Imap(crate::imap::model::Error, crate::imap::model::ErrorKind);
|
||||||
Input(crate::input::Error, crate::input::ErrorKind);
|
Input(crate::input::Error, crate::input::ErrorKind);
|
||||||
MsgModel(crate::msg::model::Error, crate::msg::model::ErrorKind);
|
MsgModel(crate::msg::model::Error, crate::msg::model::ErrorKind);
|
||||||
OutputUtils(crate::output::utils::Error, crate::output::utils::ErrorKind);
|
|
||||||
Smtp(crate::smtp::Error, crate::smtp::ErrorKind);
|
Smtp(crate::smtp::Error, crate::smtp::ErrorKind);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -162,25 +161,33 @@ pub fn msg_subcmds<'a>() -> Vec<App<'a, 'a>> {
|
||||||
pub fn msg_matches(matches: &ArgMatches) -> Result<()> {
|
pub fn msg_matches(matches: &ArgMatches) -> Result<()> {
|
||||||
let config = Config::new_from_file()?;
|
let config = Config::new_from_file()?;
|
||||||
let account = config.find_account_by_name(matches.value_of("account"))?;
|
let account = config.find_account_by_name(matches.value_of("account"))?;
|
||||||
let output_fmt = matches.value_of("output").unwrap();
|
|
||||||
let silent = matches.is_present("silent");
|
|
||||||
let mbox = matches.value_of("mailbox").unwrap();
|
let mbox = matches.value_of("mailbox").unwrap();
|
||||||
|
|
||||||
if let Some(matches) = matches.subcommand_matches("list") {
|
if let Some(matches) = matches.subcommand_matches("list") {
|
||||||
|
debug!("Subcommand matched: list");
|
||||||
|
|
||||||
let mut imap_conn = ImapConnector::new(&account)?;
|
let mut imap_conn = ImapConnector::new(&account)?;
|
||||||
let page_size: usize = matches.value_of("page-size").unwrap().parse().unwrap();
|
let page_size: usize = matches.value_of("page-size").unwrap().parse().unwrap();
|
||||||
|
debug!("Page size: {}", &page_size);
|
||||||
let page: usize = matches.value_of("page").unwrap().parse().unwrap();
|
let page: usize = matches.value_of("page").unwrap().parse().unwrap();
|
||||||
|
debug!("Page: {}", &page);
|
||||||
|
|
||||||
let msgs = imap_conn.list_msgs(&mbox, &page_size, &page)?;
|
let msgs = imap_conn.list_msgs(&mbox, &page_size, &page)?;
|
||||||
let msgs = Msgs::from(&msgs);
|
let msgs = Msgs::from(&msgs);
|
||||||
print(&output_fmt, &silent, msgs)?;
|
info!("{}", msgs);
|
||||||
|
|
||||||
imap_conn.logout();
|
imap_conn.logout();
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(matches) = matches.subcommand_matches("search") {
|
if let Some(matches) = matches.subcommand_matches("search") {
|
||||||
|
debug!("Subcommand matched: search");
|
||||||
|
|
||||||
let mut imap_conn = ImapConnector::new(&account)?;
|
let mut imap_conn = ImapConnector::new(&account)?;
|
||||||
let page_size: usize = matches.value_of("page-size").unwrap().parse().unwrap();
|
let page_size: usize = matches.value_of("page-size").unwrap().parse().unwrap();
|
||||||
|
debug!("Page size: {}", &page_size);
|
||||||
let page: usize = matches.value_of("page").unwrap().parse().unwrap();
|
let page: usize = matches.value_of("page").unwrap().parse().unwrap();
|
||||||
|
debug!("Page: {}", &page);
|
||||||
let query = matches
|
let query = matches
|
||||||
.values_of("query")
|
.values_of("query")
|
||||||
.unwrap_or_default()
|
.unwrap_or_default()
|
||||||
|
@ -205,62 +212,61 @@ pub fn msg_matches(matches: &ArgMatches) -> Result<()> {
|
||||||
})
|
})
|
||||||
.1
|
.1
|
||||||
.join(" ");
|
.join(" ");
|
||||||
|
debug!("Query: {}", &query);
|
||||||
|
|
||||||
let msgs = imap_conn.search_msgs(&mbox, &query, &page_size, &page)?;
|
let msgs = imap_conn.search_msgs(&mbox, &query, &page_size, &page)?;
|
||||||
let msgs = Msgs::from(&msgs);
|
let msgs = Msgs::from(&msgs);
|
||||||
print(&output_fmt, &silent, msgs)?;
|
info!("{}", msgs);
|
||||||
|
|
||||||
imap_conn.logout();
|
imap_conn.logout();
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(matches) = matches.subcommand_matches("read") {
|
if let Some(matches) = matches.subcommand_matches("read") {
|
||||||
|
debug!("Subcommand matched: read");
|
||||||
|
|
||||||
let mut imap_conn = ImapConnector::new(&account)?;
|
let mut imap_conn = ImapConnector::new(&account)?;
|
||||||
let uid = matches.value_of("uid").unwrap();
|
let uid = matches.value_of("uid").unwrap();
|
||||||
|
debug!("UID: {}", &uid);
|
||||||
let mime = format!("text/{}", matches.value_of("mime-type").unwrap());
|
let mime = format!("text/{}", matches.value_of("mime-type").unwrap());
|
||||||
|
debug!("MIME: {}", &mime);
|
||||||
|
|
||||||
let msg = imap_conn.read_msg(&mbox, &uid)?;
|
let msg = imap_conn.read_msg(&mbox, &uid)?;
|
||||||
let msg = ReadableMsg::from_bytes(&mime, &msg)?;
|
let msg = ReadableMsg::from_bytes(&mime, &msg)?;
|
||||||
print(&output_fmt, &silent, msg)?;
|
info!("{}", msg);
|
||||||
|
|
||||||
imap_conn.logout();
|
imap_conn.logout();
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(matches) = matches.subcommand_matches("attachments") {
|
if let Some(matches) = matches.subcommand_matches("attachments") {
|
||||||
|
debug!("Subcommand matched: attachments");
|
||||||
|
|
||||||
let mut imap_conn = ImapConnector::new(&account)?;
|
let mut imap_conn = ImapConnector::new(&account)?;
|
||||||
let uid = matches.value_of("uid").unwrap();
|
let uid = matches.value_of("uid").unwrap();
|
||||||
|
debug!("UID: {}", &uid);
|
||||||
|
|
||||||
let msg = imap_conn.read_msg(&mbox, &uid)?;
|
let msg = imap_conn.read_msg(&mbox, &uid)?;
|
||||||
let attachments = Attachments::from_bytes(&msg)?;
|
let attachments = Attachments::from_bytes(&msg)?;
|
||||||
|
debug!(
|
||||||
match output_fmt {
|
|
||||||
"plain" => {
|
|
||||||
println!(
|
|
||||||
"{} attachment(s) found for message {}",
|
"{} attachment(s) found for message {}",
|
||||||
attachments.0.len(),
|
attachments.0.len(),
|
||||||
uid
|
uid
|
||||||
);
|
);
|
||||||
|
|
||||||
attachments.0.iter().for_each(|attachment| {
|
attachments.0.iter().for_each(|attachment| {
|
||||||
let filepath = config.downloads_filepath(&account, &attachment.filename);
|
let filepath = config.downloads_filepath(&account, &attachment.filename);
|
||||||
println!("Downloading {}…", &attachment.filename);
|
debug!("Downloading {}…", &attachment.filename);
|
||||||
fs::write(filepath, &attachment.raw).unwrap()
|
fs::write(filepath, &attachment.raw).unwrap()
|
||||||
});
|
});
|
||||||
|
info!("{} attachment(s) successfully downloaded", &uid);
|
||||||
|
|
||||||
println!("Done!");
|
|
||||||
}
|
|
||||||
"json" => {
|
|
||||||
attachments.0.iter().for_each(|attachment| {
|
|
||||||
let filepath = config.downloads_filepath(&account, &attachment.filename);
|
|
||||||
fs::write(filepath, &attachment.raw).unwrap()
|
|
||||||
});
|
|
||||||
|
|
||||||
print!("{{}}");
|
|
||||||
}
|
|
||||||
_ => (),
|
|
||||||
}
|
|
||||||
imap_conn.logout();
|
imap_conn.logout();
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(matches) = matches.subcommand_matches("write") {
|
if let Some(matches) = matches.subcommand_matches("write") {
|
||||||
|
debug!("Subcommand matched: write");
|
||||||
|
|
||||||
let mut imap_conn = ImapConnector::new(&account)?;
|
let mut imap_conn = ImapConnector::new(&account)?;
|
||||||
let attachments = matches
|
let attachments = matches
|
||||||
.values_of("attachments")
|
.values_of("attachments")
|
||||||
|
@ -276,17 +282,17 @@ pub fn msg_matches(matches: &ArgMatches) -> Result<()> {
|
||||||
match input::post_edit_choice() {
|
match input::post_edit_choice() {
|
||||||
Ok(choice) => match choice {
|
Ok(choice) => match choice {
|
||||||
input::Choice::Send => {
|
input::Choice::Send => {
|
||||||
println!("Sending…");
|
debug!("Sending message…");
|
||||||
let msg = msg.to_sendable_msg()?;
|
let msg = msg.to_sendable_msg()?;
|
||||||
smtp::send(&account, &msg)?;
|
smtp::send(&account, &msg)?;
|
||||||
imap_conn.append_msg("Sent", &msg.formatted(), &[Flag::Seen])?;
|
imap_conn.append_msg("Sent", &msg.formatted(), &[Flag::Seen])?;
|
||||||
println!("Done!");
|
info!("Message successfully sent");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
input::Choice::Draft => {
|
input::Choice::Draft => {
|
||||||
println!("Saving to draft…");
|
debug!("Saving to draft…");
|
||||||
imap_conn.append_msg("Drafts", &msg.to_vec()?, &[Flag::Seen])?;
|
imap_conn.append_msg("Drafts", &msg.to_vec()?, &[Flag::Seen])?;
|
||||||
println!("Done!");
|
info!("Message successfully saved to Drafts");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
input::Choice::Edit => {
|
input::Choice::Edit => {
|
||||||
|
@ -295,7 +301,7 @@ pub fn msg_matches(matches: &ArgMatches) -> Result<()> {
|
||||||
}
|
}
|
||||||
input::Choice::Quit => break,
|
input::Choice::Quit => break,
|
||||||
},
|
},
|
||||||
Err(err) => eprintln!("{}", err),
|
Err(err) => error!("{}", err),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
imap_conn.logout();
|
imap_conn.logout();
|
||||||
|
@ -303,30 +309,44 @@ pub fn msg_matches(matches: &ArgMatches) -> Result<()> {
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(matches) = matches.subcommand_matches("template") {
|
if let Some(matches) = matches.subcommand_matches("template") {
|
||||||
|
debug!("Subcommand matched: template");
|
||||||
|
|
||||||
if let Some(_) = matches.subcommand_matches("new") {
|
if let Some(_) = matches.subcommand_matches("new") {
|
||||||
|
debug!("Subcommand matched: new");
|
||||||
|
|
||||||
let tpl = Msg::build_new_tpl(&config, &account)?;
|
let tpl = Msg::build_new_tpl(&config, &account)?;
|
||||||
print(&output_fmt, &silent, &tpl)?;
|
info!("{}", tpl);
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(matches) = matches.subcommand_matches("reply") {
|
if let Some(matches) = matches.subcommand_matches("reply") {
|
||||||
|
debug!("Subcommand matched: reply");
|
||||||
|
|
||||||
let mut imap_conn = ImapConnector::new(&account)?;
|
let mut imap_conn = ImapConnector::new(&account)?;
|
||||||
let uid = matches.value_of("uid").unwrap();
|
let uid = matches.value_of("uid").unwrap();
|
||||||
|
debug!("UID: {}", &uid);
|
||||||
|
|
||||||
let msg = Msg::from(imap_conn.read_msg(&mbox, &uid)?);
|
let msg = Msg::from(imap_conn.read_msg(&mbox, &uid)?);
|
||||||
let tpl = if matches.is_present("reply-all") {
|
let tpl = if matches.is_present("reply-all") {
|
||||||
msg.build_reply_all_tpl(&config, &account)?
|
msg.build_reply_all_tpl(&config, &account)?
|
||||||
} else {
|
} else {
|
||||||
msg.build_reply_tpl(&config, &account)?
|
msg.build_reply_tpl(&config, &account)?
|
||||||
};
|
};
|
||||||
print(&output_fmt, &silent, &tpl)?;
|
info!("{}", tpl);
|
||||||
|
|
||||||
imap_conn.logout();
|
imap_conn.logout();
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(matches) = matches.subcommand_matches("forward") {
|
if let Some(matches) = matches.subcommand_matches("forward") {
|
||||||
|
debug!("Subcommand matched: forward");
|
||||||
|
|
||||||
let mut imap_conn = ImapConnector::new(&account)?;
|
let mut imap_conn = ImapConnector::new(&account)?;
|
||||||
let uid = matches.value_of("uid").unwrap();
|
let uid = matches.value_of("uid").unwrap();
|
||||||
|
debug!("UID: {}", &uid);
|
||||||
|
|
||||||
let msg = Msg::from(imap_conn.read_msg(&mbox, &uid)?);
|
let msg = Msg::from(imap_conn.read_msg(&mbox, &uid)?);
|
||||||
let tpl = msg.build_forward_tpl(&config, &account)?;
|
let tpl = msg.build_forward_tpl(&config, &account)?;
|
||||||
print(&output_fmt, &silent, &tpl)?;
|
info!("{}", tpl);
|
||||||
|
|
||||||
imap_conn.logout();
|
imap_conn.logout();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -334,6 +354,8 @@ pub fn msg_matches(matches: &ArgMatches) -> Result<()> {
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(matches) = matches.subcommand_matches("reply") {
|
if let Some(matches) = matches.subcommand_matches("reply") {
|
||||||
|
debug!("Subcommand matched: reply");
|
||||||
|
|
||||||
let mut imap_conn = ImapConnector::new(&account)?;
|
let mut imap_conn = ImapConnector::new(&account)?;
|
||||||
let attachments = matches
|
let attachments = matches
|
||||||
.values_of("attachments")
|
.values_of("attachments")
|
||||||
|
@ -341,6 +363,7 @@ pub fn msg_matches(matches: &ArgMatches) -> Result<()> {
|
||||||
.map(String::from)
|
.map(String::from)
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
let uid = matches.value_of("uid").unwrap();
|
let uid = matches.value_of("uid").unwrap();
|
||||||
|
debug!("UID: {}", &uid);
|
||||||
|
|
||||||
let msg = Msg::from(imap_conn.read_msg(&mbox, &uid)?);
|
let msg = Msg::from(imap_conn.read_msg(&mbox, &uid)?);
|
||||||
let tpl = if matches.is_present("reply-all") {
|
let tpl = if matches.is_present("reply-all") {
|
||||||
|
@ -357,17 +380,17 @@ pub fn msg_matches(matches: &ArgMatches) -> Result<()> {
|
||||||
match input::post_edit_choice() {
|
match input::post_edit_choice() {
|
||||||
Ok(choice) => match choice {
|
Ok(choice) => match choice {
|
||||||
input::Choice::Send => {
|
input::Choice::Send => {
|
||||||
println!("Sending…");
|
debug!("Sending message…");
|
||||||
smtp::send(&account, &msg.to_sendable_msg()?)?;
|
smtp::send(&account, &msg.to_sendable_msg()?)?;
|
||||||
imap_conn.append_msg("Sent", &msg.to_vec()?, &[Flag::Seen])?;
|
imap_conn.append_msg("Sent", &msg.to_vec()?, &[Flag::Seen])?;
|
||||||
imap_conn.add_flags(mbox, uid, "\\Answered")?;
|
imap_conn.add_flags(mbox, uid, "\\Answered")?;
|
||||||
println!("Done!");
|
info!("Message successfully sent");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
input::Choice::Draft => {
|
input::Choice::Draft => {
|
||||||
println!("Saving to draft…");
|
debug!("Saving draft message…");
|
||||||
imap_conn.append_msg("Drafts", &msg.to_vec()?, &[Flag::Seen])?;
|
imap_conn.append_msg("Drafts", &msg.to_vec()?, &[Flag::Seen])?;
|
||||||
println!("Done!");
|
info!("Message successfully saved to Drafts");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
input::Choice::Edit => {
|
input::Choice::Edit => {
|
||||||
|
@ -376,7 +399,7 @@ pub fn msg_matches(matches: &ArgMatches) -> Result<()> {
|
||||||
}
|
}
|
||||||
input::Choice::Quit => break,
|
input::Choice::Quit => break,
|
||||||
},
|
},
|
||||||
Err(err) => eprintln!("{}", err),
|
Err(err) => error!("{}", err),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -385,6 +408,8 @@ pub fn msg_matches(matches: &ArgMatches) -> Result<()> {
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(matches) = matches.subcommand_matches("forward") {
|
if let Some(matches) = matches.subcommand_matches("forward") {
|
||||||
|
debug!("Subcommand matched: forward");
|
||||||
|
|
||||||
let mut imap_conn = ImapConnector::new(&account)?;
|
let mut imap_conn = ImapConnector::new(&account)?;
|
||||||
let attachments = matches
|
let attachments = matches
|
||||||
.values_of("attachments")
|
.values_of("attachments")
|
||||||
|
@ -392,6 +417,7 @@ pub fn msg_matches(matches: &ArgMatches) -> Result<()> {
|
||||||
.map(String::from)
|
.map(String::from)
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
let uid = matches.value_of("uid").unwrap();
|
let uid = matches.value_of("uid").unwrap();
|
||||||
|
debug!("UID: {}", &uid);
|
||||||
|
|
||||||
let msg = Msg::from(imap_conn.read_msg(&mbox, &uid)?);
|
let msg = Msg::from(imap_conn.read_msg(&mbox, &uid)?);
|
||||||
let tpl = msg.build_forward_tpl(&config, &account)?;
|
let tpl = msg.build_forward_tpl(&config, &account)?;
|
||||||
|
@ -403,16 +429,16 @@ pub fn msg_matches(matches: &ArgMatches) -> Result<()> {
|
||||||
match input::post_edit_choice() {
|
match input::post_edit_choice() {
|
||||||
Ok(choice) => match choice {
|
Ok(choice) => match choice {
|
||||||
input::Choice::Send => {
|
input::Choice::Send => {
|
||||||
println!("Sending…");
|
debug!("Sending message…");
|
||||||
smtp::send(&account, &msg.to_sendable_msg()?)?;
|
smtp::send(&account, &msg.to_sendable_msg()?)?;
|
||||||
imap_conn.append_msg("Sent", &msg.to_vec()?, &[Flag::Seen])?;
|
imap_conn.append_msg("Sent", &msg.to_vec()?, &[Flag::Seen])?;
|
||||||
println!("Done!");
|
info!("Message successfully sent");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
input::Choice::Draft => {
|
input::Choice::Draft => {
|
||||||
println!("Saving to draft…");
|
debug!("Saving draft message…");
|
||||||
imap_conn.append_msg("Drafts", &msg.to_vec()?, &[Flag::Seen])?;
|
imap_conn.append_msg("Drafts", &msg.to_vec()?, &[Flag::Seen])?;
|
||||||
println!("Done!");
|
info!("Message successfully saved to Drafts");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
input::Choice::Edit => {
|
input::Choice::Edit => {
|
||||||
|
@ -421,7 +447,7 @@ pub fn msg_matches(matches: &ArgMatches) -> Result<()> {
|
||||||
}
|
}
|
||||||
input::Choice::Quit => break,
|
input::Choice::Quit => break,
|
||||||
},
|
},
|
||||||
Err(err) => eprintln!("{}", err),
|
Err(err) => error!("{}", err),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -430,63 +456,67 @@ pub fn msg_matches(matches: &ArgMatches) -> Result<()> {
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(matches) = matches.subcommand_matches("copy") {
|
if let Some(matches) = matches.subcommand_matches("copy") {
|
||||||
|
debug!("Subcommand matched: copy");
|
||||||
|
|
||||||
let mut imap_conn = ImapConnector::new(&account)?;
|
let mut imap_conn = ImapConnector::new(&account)?;
|
||||||
let uid = matches.value_of("uid").unwrap();
|
let uid = matches.value_of("uid").unwrap();
|
||||||
|
debug!("UID: {}", &uid);
|
||||||
let target = matches.value_of("target").unwrap();
|
let target = matches.value_of("target").unwrap();
|
||||||
|
debug!("Target: {}", &target);
|
||||||
|
|
||||||
let msg = Msg::from(imap_conn.read_msg(&mbox, &uid)?);
|
let msg = Msg::from(imap_conn.read_msg(&mbox, &uid)?);
|
||||||
let mut flags = msg.flags.deref().to_vec();
|
let mut flags = msg.flags.deref().to_vec();
|
||||||
flags.push(Flag::Seen);
|
flags.push(Flag::Seen);
|
||||||
imap_conn.append_msg(target, &msg.raw, &flags)?;
|
imap_conn.append_msg(target, &msg.raw, &flags)?;
|
||||||
imap_conn.logout();
|
info!(
|
||||||
|
|
||||||
print(
|
|
||||||
&output_fmt,
|
|
||||||
&silent,
|
|
||||||
Info(format!(
|
|
||||||
"Message {} successfully copied to folder `{}`",
|
"Message {} successfully copied to folder `{}`",
|
||||||
&uid, &target
|
&uid, &target
|
||||||
)),
|
);
|
||||||
)?;
|
|
||||||
|
imap_conn.logout();
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(matches) = matches.subcommand_matches("move") {
|
if let Some(matches) = matches.subcommand_matches("move") {
|
||||||
|
debug!("Subcommand matched: move");
|
||||||
|
|
||||||
let mut imap_conn = ImapConnector::new(&account)?;
|
let mut imap_conn = ImapConnector::new(&account)?;
|
||||||
let uid = matches.value_of("uid").unwrap();
|
let uid = matches.value_of("uid").unwrap();
|
||||||
|
debug!("UID: {}", &uid);
|
||||||
let target = matches.value_of("target").unwrap();
|
let target = matches.value_of("target").unwrap();
|
||||||
|
debug!("Target: {}", &target);
|
||||||
|
|
||||||
let msg = Msg::from(imap_conn.read_msg(&mbox, &uid)?);
|
let msg = Msg::from(imap_conn.read_msg(&mbox, &uid)?);
|
||||||
let mut flags = msg.flags.deref().to_vec();
|
let mut flags = msg.flags.deref().to_vec();
|
||||||
flags.push(Flag::Seen);
|
flags.push(Flag::Seen);
|
||||||
imap_conn.append_msg(target, &msg.raw, msg.flags.deref())?;
|
imap_conn.append_msg(target, &msg.raw, msg.flags.deref())?;
|
||||||
imap_conn.add_flags(mbox, uid, "\\Seen \\Deleted")?;
|
imap_conn.add_flags(mbox, uid, "\\Seen \\Deleted")?;
|
||||||
imap_conn.logout();
|
info!(
|
||||||
|
|
||||||
print(
|
|
||||||
&output_fmt,
|
|
||||||
&silent,
|
|
||||||
Info(format!(
|
|
||||||
"Message {} successfully moved to folder `{}`",
|
"Message {} successfully moved to folder `{}`",
|
||||||
&uid, &target
|
&uid, &target
|
||||||
)),
|
);
|
||||||
)?;
|
|
||||||
|
imap_conn.logout();
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(matches) = matches.subcommand_matches("delete") {
|
if let Some(matches) = matches.subcommand_matches("delete") {
|
||||||
|
debug!("Subcommand matched: delete");
|
||||||
|
|
||||||
let mut imap_conn = ImapConnector::new(&account)?;
|
let mut imap_conn = ImapConnector::new(&account)?;
|
||||||
let uid = matches.value_of("uid").unwrap();
|
let uid = matches.value_of("uid").unwrap();
|
||||||
imap_conn.add_flags(mbox, uid, "\\Seen \\Deleted")?;
|
debug!("UID: {}", &uid);
|
||||||
imap_conn.logout();
|
|
||||||
|
|
||||||
print(
|
imap_conn.add_flags(mbox, uid, "\\Seen \\Deleted")?;
|
||||||
&output_fmt,
|
info!("Message {} successfully deleted", &uid);
|
||||||
&silent,
|
|
||||||
Info(format!("Message {} successfully deleted", &uid)),
|
imap_conn.logout();
|
||||||
)?;
|
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(matches) = matches.subcommand_matches("send") {
|
if let Some(matches) = matches.subcommand_matches("send") {
|
||||||
|
debug!("Subcommand matched: send");
|
||||||
|
|
||||||
let mut imap_conn = ImapConnector::new(&account)?;
|
let mut imap_conn = ImapConnector::new(&account)?;
|
||||||
let msg = matches.value_of("message").unwrap();
|
let msg = matches.value_of("message").unwrap();
|
||||||
let msg = Msg::from(msg.to_string());
|
let msg = Msg::from(msg.to_string());
|
||||||
|
@ -498,6 +528,8 @@ pub fn msg_matches(matches: &ArgMatches) -> Result<()> {
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(matches) = matches.subcommand_matches("save") {
|
if let Some(matches) = matches.subcommand_matches("save") {
|
||||||
|
debug!("Subcommand matched: save");
|
||||||
|
|
||||||
let mut imap_conn = ImapConnector::new(&account)?;
|
let mut imap_conn = ImapConnector::new(&account)?;
|
||||||
let msg = matches.value_of("message").unwrap();
|
let msg = matches.value_of("message").unwrap();
|
||||||
let msg = Msg::from(msg.to_string());
|
let msg = Msg::from(msg.to_string());
|
||||||
|
@ -506,11 +538,13 @@ pub fn msg_matches(matches: &ArgMatches) -> Result<()> {
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Default case: list first page messages
|
debug!("Default subcommand matched: list");
|
||||||
|
|
||||||
let mut imap_conn = ImapConnector::new(&account)?;
|
let mut imap_conn = ImapConnector::new(&account)?;
|
||||||
let msgs = imap_conn.list_msgs(&mbox, &10, &0)?;
|
let msgs = imap_conn.list_msgs(&mbox, &10, &0)?;
|
||||||
let msgs = Msgs::from(&msgs);
|
let msgs = Msgs::from(&msgs);
|
||||||
print(&output_fmt, &silent, msgs)?;
|
info!("{}", &msgs);
|
||||||
|
|
||||||
imap_conn.logout();
|
imap_conn.logout();
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,12 +6,15 @@ pub fn output_args<'a>() -> Vec<Arg<'a, 'a>> {
|
||||||
.long("output")
|
.long("output")
|
||||||
.short("o")
|
.short("o")
|
||||||
.help("Defines the output format")
|
.help("Defines the output format")
|
||||||
.value_name("STRING")
|
.value_name("FMT")
|
||||||
.possible_values(&["plain", "json"])
|
.possible_values(&["plain", "json"])
|
||||||
.default_value("plain"),
|
.default_value("plain"),
|
||||||
Arg::with_name("silent")
|
Arg::with_name("log")
|
||||||
.long("silent")
|
.long("log")
|
||||||
.short("s")
|
.short("l")
|
||||||
.help("Disables any output"),
|
.help("Defines the logs level")
|
||||||
|
.value_name("LEVEL")
|
||||||
|
.possible_values(&["error", "warn", "info", "debug", "trace"])
|
||||||
|
.default_value("info"),
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
28
src/output/fmt.rs
Normal file
28
src/output/fmt.rs
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
use std::fmt;
|
||||||
|
|
||||||
|
pub enum OutputFmt {
|
||||||
|
Json,
|
||||||
|
Plain,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<&str> for OutputFmt {
|
||||||
|
fn from(s: &str) -> Self {
|
||||||
|
match s {
|
||||||
|
"json" => Self::Json,
|
||||||
|
"plain" | _ => Self::Plain,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Display for OutputFmt {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
write!(
|
||||||
|
f,
|
||||||
|
"{}",
|
||||||
|
match *self {
|
||||||
|
OutputFmt::Json => "JSON",
|
||||||
|
OutputFmt::Plain => "PLAIN",
|
||||||
|
},
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
86
src/output/log.rs
Normal file
86
src/output/log.rs
Normal file
|
@ -0,0 +1,86 @@
|
||||||
|
use error_chain::error_chain;
|
||||||
|
use log::{Level, LevelFilter, Metadata, Record};
|
||||||
|
use std::fmt;
|
||||||
|
|
||||||
|
use super::fmt::OutputFmt;
|
||||||
|
|
||||||
|
error_chain! {}
|
||||||
|
|
||||||
|
// Log level struct
|
||||||
|
|
||||||
|
pub struct LogLevel(pub LevelFilter);
|
||||||
|
|
||||||
|
impl From<&str> for LogLevel {
|
||||||
|
fn from(s: &str) -> Self {
|
||||||
|
match s {
|
||||||
|
"error" => Self(LevelFilter::Error),
|
||||||
|
"warn" => Self(LevelFilter::Warn),
|
||||||
|
"debug" => Self(LevelFilter::Debug),
|
||||||
|
"trace" => Self(LevelFilter::Trace),
|
||||||
|
"info" | _ => Self(LevelFilter::Info),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Display for LogLevel {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
write!(f, "{}", self.0.to_string())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Plain logger
|
||||||
|
|
||||||
|
struct PlainLogger;
|
||||||
|
|
||||||
|
impl log::Log for PlainLogger {
|
||||||
|
fn enabled(&self, metadata: &Metadata) -> bool {
|
||||||
|
metadata.level() <= Level::Trace
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
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 {
|
||||||
|
// Should be safe enough to `.unwrap()` since it's
|
||||||
|
// formatted by Himalaya itself
|
||||||
|
print!("{}", serde_json::to_string(record.args()).unwrap());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn flush(&self) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Init
|
||||||
|
|
||||||
|
pub fn init(fmt: &OutputFmt, level: &LogLevel) -> Result<()> {
|
||||||
|
log::set_boxed_logger(match fmt {
|
||||||
|
&OutputFmt::Json => Box::new(JsonLogger),
|
||||||
|
&OutputFmt::Plain => Box::new(PlainLogger),
|
||||||
|
})
|
||||||
|
.map(|()| log::set_max_level(level.0))
|
||||||
|
.chain_err(|| "Could not init logger")
|
||||||
|
}
|
Loading…
Reference in a new issue