diff options
author | Christian Duerr <contact@christianduerr.com> | 2018-11-06 18:29:34 +0100 |
---|---|---|
committer | Christian Duerr <contact@christianduerr.com> | 2018-11-10 18:07:42 +0100 |
commit | 5bd9b76b480a0c54f0e6d2a5312dd2b0d68fe5ad (patch) | |
tree | cf4c8db6b3a227d125e2911260f7966afe24167c | |
parent | 021b424858d0b2fcf50c4199e152e93596cc8d5d (diff) | |
download | alacritty-5bd9b76b480a0c54f0e6d2a5312dd2b0d68fe5ad.tar.gz alacritty-5bd9b76b480a0c54f0e6d2a5312dd2b0d68fe5ad.zip |
Replace sysout/err prints with logging
To make sure that all error and information reporting to the user is
unified, all instances of `print!`, `eprint!`, `println!` and
`eprintln!` have been removed and replaced by logging.
When `RUST_LOG` is not specified, the default Alacritty logger now also
prints to both the stdout and a log file. The log file is only created
when a message is written to it and its name is printed to stdout the
first time it is used.
-rw-r--r-- | Cargo.lock | 2 | ||||
-rw-r--r-- | Cargo.toml | 2 | ||||
-rw-r--r-- | build.rs | 4 | ||||
-rw-r--r-- | src/ansi.rs | 6 | ||||
-rw-r--r-- | src/cli.rs | 4 | ||||
-rw-r--r-- | src/config.rs | 77 | ||||
-rw-r--r-- | src/event.rs | 2 | ||||
-rw-r--r-- | src/grid/tests.rs | 12 | ||||
-rw-r--r-- | src/input.rs | 4 | ||||
-rw-r--r-- | src/lib.rs | 1 | ||||
-rw-r--r-- | src/logging.rs | 78 | ||||
-rw-r--r-- | src/macros.rs | 18 | ||||
-rw-r--r-- | src/main.rs | 12 |
13 files changed, 124 insertions, 98 deletions
@@ -54,7 +54,7 @@ dependencies = [ "serde_json 1.0.33 (registry+https://github.com/rust-lang/crates.io-index)", "serde_yaml 0.8.7 (registry+https://github.com/rust-lang/crates.io-index)", "static_assertions 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", - "tempdir 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", + "tempfile 3.0.4 (registry+https://github.com/rust-lang/crates.io-index)", "terminfo 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -49,6 +49,7 @@ image = "0.20.1" static_assertions = "0.2.5" terminfo = "0.6.1" url = "1.7.1" +tempfile = "3.0.4" [target.'cfg(any(target_os = "linux", target_os = "freebsd", target_os="dragonfly", target_os="openbsd"))'.dependencies] x11-dl = "2" @@ -76,7 +77,6 @@ gl_generator = "0.9" [target.'cfg(windows)'.build-dependencies] embed-resource = "1.1.4" reqwest = "0.8" -tempdir = "0.3" zip = "0.4" [profile.release] @@ -14,14 +14,14 @@ #[cfg(windows)] extern crate embed_resource; #[cfg(windows)] -extern crate tempdir; +extern crate tempfile; #[cfg(windows)] extern crate reqwest; #[cfg(windows)] extern crate zip; #[cfg(windows)] -use tempdir::TempDir; +use tempfile::TempDir; extern crate gl_generator; diff --git a/src/ansi.rs b/src/ansi.rs index f1ca759a..2171f868 100644 --- a/src/ansi.rs +++ b/src/ansi.rs @@ -60,7 +60,7 @@ fn parse_rgb_color(color: &[u8]) -> Option<Rgb> { let r = parse_hex!(); let val = next!(); - if val != Some('/') { println!("val={:?}", val); return None; } + if val != Some('/') { return None; } let g = parse_hex!(); if next!() != Some('/') { return None; } let b = parse_hex!(); @@ -901,7 +901,7 @@ impl<'a, H, W> vte::Perform for Performer<'a, H, W> macro_rules! unhandled { () => {{ - warn!("[Unhandled CSI] action={:?}, args={:?}, intermediates={:?}", + debug!("[Unhandled CSI] action={:?}, args={:?}, intermediates={:?}", action, args, intermediates); return; }} @@ -1137,7 +1137,7 @@ impl<'a, H, W> vte::Perform for Performer<'a, H, W> ) { macro_rules! unhandled { () => {{ - warn!("[unhandled] esc_dispatch params={:?}, ints={:?}, byte={:?} ({:02x})", + debug!("[unhandled] esc_dispatch params={:?}, ints={:?}, byte={:?} ({:02x})", params, intermediates, byte as char, byte); return; }} @@ -147,8 +147,8 @@ impl Options { } match matches.occurrences_of("v") { - 0 => {}, - 1 => options.log_level = log::LevelFilter::Info, + 0 if !options.print_events => {}, + 0 | 1 => options.log_level = log::LevelFilter::Info, 2 => options.log_level = log::LevelFilter::Debug, 3 | _ => options.log_level = log::LevelFilter::Trace } diff --git a/src/config.rs b/src/config.rs index b638ea43..1837cdf1 100644 --- a/src/config.rs +++ b/src/config.rs @@ -73,7 +73,7 @@ fn deserialize_duration_ms<'a, D>(deserializer: D) -> ::std::result::Result<Dura match u64::deserialize(deserializer) { Ok(threshold_ms) => Ok(Duration::from_millis(threshold_ms)), Err(err) => { - eprintln!("problem with config: {}; Using default value", err); + error!("problem with config: {}; Using default value", err); Ok(default_threshold_ms()) }, } @@ -172,7 +172,7 @@ fn deserialize_visual_bell_duration<'a, D>(deserializer: D) -> ::std::result::Re match u16::deserialize(deserializer) { Ok(duration) => Ok(duration), Err(err) => { - eprintln!("problem with config: {}; Using default value", err); + error!("problem with config: {}; Using default value", err); Ok(default_visual_bell_duration()) }, } @@ -310,19 +310,19 @@ impl<'de> Deserialize<'de> for Decorations { "none" => Ok(Decorations::None), "full" => Ok(Decorations::Full), "true" => { - eprintln!("deprecated decorations boolean value, \ + error!("deprecated decorations boolean value, \ use one of transparent|buttonless|none|full instead; \ Falling back to \"full\""); Ok(Decorations::Full) }, "false" => { - eprintln!("deprecated decorations boolean value, \ + error!("deprecated decorations boolean value, \ use one of transparent|buttonless|none|full instead; \ Falling back to \"none\""); Ok(Decorations::None) }, _ => { - eprintln!("invalid decorations value: {}; Using default value", value); + error!("invalid decorations value: {}; Using default value", value); Ok(Decorations::Full) } } @@ -336,23 +336,23 @@ impl<'de> Deserialize<'de> for Decorations { "none" => Ok(Decorations::None), "full" => Ok(Decorations::Full), "true" => { - eprintln!("deprecated decorations boolean value, \ + error!("deprecated decorations boolean value, \ use one of none|full instead; \ Falling back to \"full\""); Ok(Decorations::Full) }, "false" => { - eprintln!("deprecated decorations boolean value, \ + error!("deprecated decorations boolean value, \ use one of none|full instead; \ Falling back to \"none\""); Ok(Decorations::None) }, "transparent" | "buttonless" => { - eprintln!("macos-only decorations value: {}; Using default value", value); + error!("macos-only decorations value: {}; Using default value", value); Ok(Decorations::Full) }, _ => { - eprintln!("invalid decorations value: {}; Using default value", value); + error!("invalid decorations value: {}; Using default value", value); Ok(Decorations::Full) } } @@ -388,7 +388,7 @@ fn deserialize_padding<'a, D>(deserializer: D) -> ::std::result::Result<Delta<u8 match Delta::deserialize(deserializer) { Ok(delta) => Ok(delta), Err(err) => { - eprintln!("problem with config: {}; Using default value", err); + error!("problem with config: {}; Using default value", err); Ok(default_padding()) }, } @@ -519,7 +519,7 @@ fn failure_default_vec<'a, D, T>(deserializer: D) -> ::std::result::Result<Vec<T let vec = match Vec::<serde_yaml::Value>::deserialize(deserializer) { Ok(vec) => vec, Err(err) => { - eprintln!("problem with config: {}; Using empty vector", err); + error!("problem with config: {}; Using empty vector", err); return Ok(Vec::new()); }, }; @@ -530,7 +530,7 @@ fn failure_default_vec<'a, D, T>(deserializer: D) -> ::std::result::Result<Vec<T match T::deserialize(value) { Ok(binding) => bindings.push(binding), Err(err) => { - eprintln!("problem with config: {}; Skipping value", err); + error!("problem with config: {}; Skipping value", err); }, } } @@ -548,7 +548,7 @@ fn deserialize_tabspaces<'a, D>(deserializer: D) -> ::std::result::Result<usize, match usize::deserialize(deserializer) { Ok(value) => Ok(value), Err(err) => { - eprintln!("problem with config: {}; Using `8`", err); + error!("problem with config: {}; Using `8`", err); Ok(default_tabspaces()) }, } @@ -560,7 +560,7 @@ fn default_true_bool<'a, D>(deserializer: D) -> ::std::result::Result<bool, D::E match bool::deserialize(deserializer) { Ok(value) => Ok(value), Err(err) => { - eprintln!("problem with config: {}; Using `true`", err); + error!("problem with config: {}; Using `true`", err); Ok(true) }, } @@ -574,7 +574,7 @@ fn failure_default<'a, D, T>(deserializer: D) match T::deserialize(deserializer) { Ok(value) => Ok(value), Err(err) => { - eprintln!("problem with config: {}; Using default value", err); + error!("problem with config: {}; Using default value", err); Ok(T::default()) }, } @@ -636,7 +636,7 @@ fn deserialize_scrolling_history<'a, D>(deserializer: D) -> ::std::result::Resul match u32::deserialize(deserializer) { Ok(lines) => { if lines > MAX_SCROLLBACK_LINES { - eprintln!( + error!( "problem with config: scrollback size is {}, but expected a maximum of {}; \ Using {1} instead", lines, MAX_SCROLLBACK_LINES, @@ -647,7 +647,7 @@ fn deserialize_scrolling_history<'a, D>(deserializer: D) -> ::std::result::Resul } }, Err(err) => { - eprintln!("problem with config: {}; Using default value", err); + error!("problem with config: {}; Using default value", err); Ok(default_scrolling_history()) }, } @@ -659,7 +659,7 @@ fn deserialize_scrolling_multiplier<'a, D>(deserializer: D) -> ::std::result::Re match u8::deserialize(deserializer) { Ok(lines) => Ok(lines), Err(err) => { - eprintln!("problem with config: {}; Using default value", err); + error!("problem with config: {}; Using default value", err); Ok(default_scrolling_multiplier()) }, } @@ -701,7 +701,7 @@ impl<'a> de::Deserialize<'a> for ModsWrapper { "Shift" => res.shift = true, "Alt" | "Option" => res.alt = true, "Control" => res.ctrl = true, - _ => eprintln!("unknown modifier {:?}", modifier), + _ => error!("unknown modifier {:?}", modifier), } } @@ -822,7 +822,7 @@ impl<'a> de::Deserialize<'a> for ModeWrapper { "~AppCursor" => res.not_mode |= mode::TermMode::APP_CURSOR, "AppKeypad" => res.mode |= mode::TermMode::APP_KEYPAD, "~AppKeypad" => res.not_mode |= mode::TermMode::APP_KEYPAD, - _ => eprintln!("unknown mode {:?}", modifier), + _ => error!("unknown mode {:?}", modifier), } } @@ -1184,7 +1184,7 @@ fn deserialize_color_index<'a, D>(deserializer: D) -> ::std::result::Result<u8, match u8::deserialize(deserializer) { Ok(index) => { if index < 16 { - eprintln!( + error!( "problem with config: indexed_color's index is '{}', \ but a value bigger than 15 was expected; \ Ignoring setting", @@ -1198,7 +1198,7 @@ fn deserialize_color_index<'a, D>(deserializer: D) -> ::std::result::Result<u8, } }, Err(err) => { - eprintln!("problem with config: {}; Ignoring setting", err); + error!("problem with config: {}; Ignoring setting", err); // Return value out of range to ignore this color Ok(0) @@ -1253,7 +1253,7 @@ fn deserialize_optional_color<'a, D>(deserializer: D) -> ::std::result::Result<O }, Ok(None) => Ok(None), Err(err) => { - eprintln!("problem with config: {}; Using standard foreground color", err); + error!("problem with config: {}; Using standard foreground color", err); Ok(None) }, } @@ -1352,7 +1352,7 @@ fn rgb_from_hex<'a, D>(deserializer: D) -> ::std::result::Result<Rgb, D::Error> match rgb { Ok(rgb) => Ok(rgb), Err(err) => { - eprintln!("problem with config: {}; Using color #ff00ff", err); + error!("problem with config: {}; Using color #ff00ff", err); Ok(Rgb { r: 255, g: 0, b: 255 }) }, } @@ -1692,24 +1692,22 @@ impl Config { } fn print_deprecation_warnings(&mut self) { - use ::util::fmt; if self.dimensions.is_some() { - eprintln!("{}", fmt::Yellow("Config `dimensions` is deprecated. \ - Please use `window.dimensions` instead.")); + warn!("{}", "Config `dimensions` is deprecated. \ + Please use `window.dimensions` instead."); } if self.padding.is_some() { - eprintln!("{}", fmt::Yellow("Config `padding` is deprecated. \ - Please use `window.padding` instead.")); + warn!("{}", "Config `padding` is deprecated. Please use `window.padding` instead."); } if self.mouse.faux_scrollback_lines.is_some() { - println!("{}", fmt::Yellow("Config `mouse.faux_scrollback_lines` is deprecated. \ - Please use `mouse.faux_scrolling_lines` instead.")); + warn!("{}", "Config `mouse.faux_scrollback_lines` is deprecated. \ + Please use `mouse.faux_scrolling_lines` instead."); } if let Some(custom_cursor_colors) = self.custom_cursor_colors { - eprintln!("{}", fmt::Yellow("Config `custom_cursor_colors` is deprecated.")); + warn!("{}", "Config `custom_cursor_colors` is deprecated."); if !custom_cursor_colors { self.colors.cursor.cursor = None; @@ -1718,18 +1716,17 @@ impl Config { } if self.cursor_style.is_some() { - eprintln!("{}", fmt::Yellow("Config `cursor_style` is deprecated. \ - Please use `cursor.style` instead.")); + warn!("{}", "Config `cursor_style` is deprecated. Please use `cursor.style` instead."); } if self.hide_cursor_when_typing.is_some() { - eprintln!("{}", fmt::Yellow("Config `hide_cursor_when_typing` is deprecated. \ - Please use `mouse.hide_when_typing` instead.")); + warn!("{}", "Config `hide_cursor_when_typing` is deprecated. \ + Please use `mouse.hide_when_typing` instead."); } if self.unfocused_hollow_cursor.is_some() { - eprintln!("{}", fmt::Yellow("Config `unfocused_hollow_cursor` is deprecated. \ - Please use `cursor.unfocused_hollow` instead.")); + warn!("{}", "Config `unfocused_hollow_cursor` is deprecated. \ + Please use `cursor.unfocused_hollow` instead."); } } } @@ -1830,7 +1827,7 @@ impl DeserializeSize for Size { match size { Ok(size) => Ok(size), Err(err) => { - eprintln!("problem with config: {}; Using size 12", err); + error!("problem with config: {}; Using size 12", err); Ok(Size::new(12.)) }, } @@ -2053,7 +2050,7 @@ impl Monitor { let _ = config_tx.send(config); handler.on_config_reload(); }, - Err(err) => eprintln!("Ignoring invalid config: {}", err), + Err(err) => error!("Ignoring invalid config: {}", err), } } } diff --git a/src/event.rs b/src/event.rs index 7a1faa70..ece8ec6f 100644 --- a/src/event.rs +++ b/src/event.rs @@ -488,7 +488,7 @@ impl<N: Notify> Processor<N> { let hide_mouse = &mut self.hide_mouse; let mut process = |event| { if print_events { - println!("glutin event: {:?}", event); + info!("glutin event: {:?}", event); } Processor::handle_event( &mut processor, diff --git a/src/grid/tests.rs b/src/grid/tests.rs index e136e3b3..9cb30a7f 100644 --- a/src/grid/tests.rs +++ b/src/grid/tests.rs @@ -20,19 +20,13 @@ use index::{Point, Line, Column}; // Scroll up moves lines upwards #[test] fn scroll_up() { - println!(); - let mut grid = Grid::new(Line(10), Column(1), 0, 0); for i in 0..10 { grid[Line(i)][Column(0)] = i; } - println!("grid: {:?}", grid); - grid.scroll_up(&(Line(0)..Line(10)), Line(2), &0); - println!("grid: {:?}", grid); - assert_eq!(grid[Line(0)][Column(0)], 2); assert_eq!(grid[Line(0)].occ, 1); assert_eq!(grid[Line(1)][Column(0)], 3); @@ -58,19 +52,13 @@ fn scroll_up() { // Scroll down moves lines downwards #[test] fn scroll_down() { - println!(); - let mut grid = Grid::new(Line(10), Column(1), 0, 0); for i in 0..10 { grid[Line(i)][Column(0)] = i; } - println!("grid: {:?}", grid); - grid.scroll_down(&(Line(0)..Line(10)), Line(2), &0); - println!("grid: {:?}", grid); - assert_eq!(grid[Line(0)][Column(0)], 0); // was 8 assert_eq!(grid[Line(0)].occ, 0); assert_eq!(grid[Line(1)][Column(0)], 0); // was 9 diff --git a/src/input.rs b/src/input.rs index 600a1abe..d2f8f6b5 100644 --- a/src/input.rs +++ b/src/input.rs @@ -218,7 +218,7 @@ impl Action { .and_then(|clipboard| clipboard.load_primary() ) .map(|contents| { self.paste(ctx, &contents) }) .unwrap_or_else(|err| { - eprintln!("Error loading data from clipboard. {}", Red(err)); + error!("Error loading data from clipboard. {}", Red(err)); }); }, Action::PasteSelection => { @@ -228,7 +228,7 @@ impl Action { .and_then(|clipboard| clipboard.load_selection() ) .map(|contents| { self.paste(ctx, &contents) }) .unwrap_or_else(|err| { - warn!("Error loading data from clipboard. {}", Red(err)); + error!("Error loading data from clipboard. {}", Red(err)); }); } }, @@ -64,6 +64,7 @@ extern crate xdg; extern crate base64; extern crate terminfo; extern crate url; +extern crate tempfile; #[macro_use] pub mod macros; diff --git a/src/logging.rs b/src/logging.rs index 10929980..3fb768e9 100644 --- a/src/logging.rs +++ b/src/logging.rs @@ -17,37 +17,51 @@ //! The main executable is supposed to call `initialize()` exactly once during //! startup. All logging messages are written to stdout, given that their //! log-level is sufficient for the level configured in `cli::Options`. -use log; -use std::sync; -use std::io; use cli; +use log; +use tempfile; + +use std::fs::File; +use std::io::{self, LineWriter, Stdout, Write}; +use std::sync::Mutex; -pub struct Logger<T> { +pub struct Logger { level: log::LevelFilter, - output: sync::Mutex<T> + logfile: Mutex<OnDemandTempFile>, + stdout: Mutex<LineWriter<Stdout>>, } -impl<T: Send + io::Write> Logger<T> { +impl Logger { // False positive, see: https://github.com/rust-lang-nursery/rust-clippy/issues/734 #[cfg_attr(feature = "cargo-clippy", allow(new_ret_no_self))] - pub fn new(output: T, level: log::LevelFilter) -> Logger<io::LineWriter<T>> { + pub fn new(level: log::LevelFilter) -> Self { log::set_max_level(level); + + let logfile = Mutex::new(OnDemandTempFile::new("alacritty", String::from(".log"))); + + let stdout = Mutex::new(LineWriter::new(io::stdout())); + Logger { level, - output: sync::Mutex::new(io::LineWriter::new(output)) + logfile, + stdout, } } } -impl<T: Send + io::Write> log::Log for Logger<T> { +impl log::Log for Logger { fn enabled(&self, metadata: &log::Metadata) -> bool { metadata.level() <= self.level } fn log(&self, record: &log::Record) { if self.enabled(record.metadata()) && record.target().starts_with("alacritty") { - if let Ok(ref mut writer) = self.output.lock() { - let _ = writer.write_all(format!("{}\n", record.args()).as_ref()); + if let Ok(ref mut logfile) = self.logfile.lock() { + let _ = logfile.write_all(format!("{}\n", record.args()).as_ref()); + } + + if let Ok(ref mut stdout) = self.stdout.lock() { + let _ = stdout.write_all(format!("{}\n", record.args()).as_ref()); } } } @@ -55,12 +69,52 @@ impl<T: Send + io::Write> log::Log for Logger<T> { fn flush(&self) {} } +struct OnDemandTempFile { + file: Option<LineWriter<File>>, + prefix: String, + suffix: String, +} + +impl OnDemandTempFile { + fn new<T: Into<String>, J: Into<String>>(prefix: T, suffix: J) -> Self { + OnDemandTempFile { + file: None, + prefix: prefix.into(), + suffix: suffix.into(), + } + } + + fn file(&mut self) -> Result<&mut LineWriter<File>, io::Error> { + if self.file.is_none() { + let file = tempfile::Builder::new() + .prefix(&self.prefix) + .suffix(&self.suffix) + .tempfile()?; + let path = file.path().to_owned(); + self.file = Some(io::LineWriter::new(file.persist(&path)?)); + println!("Created log file at {:?}", path); + } + + Ok(self.file.as_mut().unwrap()) + } +} + +impl Write for OnDemandTempFile { + fn write(&mut self, buf: &[u8]) -> Result<usize, io::Error> { + self.file()?.write(buf) + } + + fn flush(&mut self) -> Result<(), io::Error> { + self.file()?.flush() + } +} + pub fn initialize(options: &cli::Options) -> Result<(), log::SetLoggerError> { // Use env_logger if RUST_LOG environment variable is defined. Otherwise, // use the alacritty-only logger. if ::std::env::var("RUST_LOG").is_ok() { ::env_logger::try_init() } else { - log::set_boxed_logger(Box::new(Logger::new(io::stdout(), options.log_level))) + log::set_boxed_logger(Box::new(Logger::new(options.log_level))) } } diff --git a/src/macros.rs b/src/macros.rs index 464110e6..f3327083 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -15,7 +15,7 @@ #[macro_export] macro_rules! die { ($($arg:tt)*) => {{ - eprintln!($($arg)*); + error!($($arg)*); ::std::process::exit(1); }} } @@ -29,19 +29,3 @@ macro_rules! maybe { } } } - -#[macro_export] -macro_rules! print { - ($($arg:tt)*) => {{ - use std::io::Write; - let _ = write!(::std::io::stdout(), $($arg)*); - }}; -} - -#[macro_export] -macro_rules! eprint { - ($($arg:tt)*) => {{ - use std::io::Write; - let _ = write!(::std::io::stderr(), $($arg)*); - }}; -} diff --git a/src/main.rs b/src/main.rs index e72df15d..bdb401fc 100644 --- a/src/main.rs +++ b/src/main.rs @@ -65,8 +65,13 @@ fn main() { #[cfg(windows)] unsafe { AttachConsole(ATTACH_PARENT_PROCESS); } - // Load command line options and config + // Load command line options let options = cli::Options::load(); + + // Initialize the logger as soon as possible as to capture output from other subsystems + logging::initialize(&options).expect("Unable to initialize logger"); + + // Load configuration file let config = load_config(&options).update_dynamic_title(&options); // Switch to home directory @@ -98,7 +103,7 @@ fn load_config(options: &cli::Options) -> Config { }); Config::load_from(&*config_path).unwrap_or_else(|err| { - eprintln!("Error: {}; Loading default config", err); + error!("Error: {}; Loading default config", err); Config::default() }) } @@ -108,9 +113,6 @@ fn load_config(options: &cli::Options) -> Config { /// Creates a window, the terminal state, pty, I/O event loop, input processor, /// config change monitor, and runs the main display loop. fn run(mut config: Config, options: &cli::Options) -> Result<(), Box<Error>> { - // Initialize the logger first as to capture output from other subsystems - logging::initialize(options)?; - info!("Welcome to Alacritty."); if let Some(config_path) = config.path() { info!("Configuration loaded from {}", config_path.display()); |