aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristian Duerr <contact@christianduerr.com>2018-11-07 23:41:42 +0100
committerChristian Duerr <contact@christianduerr.com>2018-11-10 18:18:59 +0100
commit1e80a2e757134e602400c8d925558c986e3555d1 (patch)
treecdd1f6166fcd8d0d51184d031d02add8fca7fbf8
parent26746b4421bee93ebbed9d63d468e8105ede3f06 (diff)
downloadalacritty-1e80a2e757134e602400c8d925558c986e3555d1.tar.gz
alacritty-1e80a2e757134e602400c8d925558c986e3555d1.zip
Display log path
When an error or warning is shown, it now correctly points to the log file where the error has been written to.
-rw-r--r--Cargo.toml2
-rw-r--r--src/display.rs18
-rw-r--r--src/lib.rs1
-rw-r--r--src/logging.rs123
-rw-r--r--src/main.rs16
-rw-r--r--src/term/mod.rs13
6 files changed, 112 insertions, 61 deletions
diff --git a/Cargo.toml b/Cargo.toml
index 7d28341c..2ef7f7d1 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -49,12 +49,12 @@ 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"
[target.'cfg(windows)'.dependencies]
+tempfile = "3.0.4"
winpty = { path = "./winpty" }
mio-named-pipes = "0.1"
winapi = { version = "0.3.5", features = ["winuser", "synchapi", "roerrorapi", "winerror"]}
diff --git a/src/display.rs b/src/display.rs
index b185b6be..eb37dc54 100644
--- a/src/display.rs
+++ b/src/display.rs
@@ -28,7 +28,7 @@ use renderer::{self, GlyphCache, QuadRenderer};
use term::{Term, SizeInfo, RenderableCell};
use sync::FairMutex;
use window::{self, Window};
-use logging;
+use logging::LoggerProxy;
use Rgb;
#[derive(Debug)]
@@ -100,6 +100,7 @@ pub struct Display {
meter: Meter,
font_size: font::Size,
size_info: SizeInfo,
+ logger_proxy: LoggerProxy,
}
/// Can wakeup the render loop from other threads
@@ -130,7 +131,11 @@ impl Display {
&self.size_info
}
- pub fn new(config: &Config, options: &cli::Options) -> Result<Display, Error> {
+ pub fn new(
+ config: &Config,
+ options: &cli::Options,
+ logger_proxy: LoggerProxy
+ ) -> Result<Display, Error> {
// Extract some properties from config
let render_timer = config.render_timer();
@@ -210,6 +215,7 @@ impl Display {
meter: Meter::new(),
font_size: font::Size::new(0.),
size_info,
+ logger_proxy,
})
}
@@ -403,8 +409,8 @@ impl Display {
}
// Display errors and warnings
- if logging::errors() {
- let msg = " ERROR: Full log at /tmp/alacritty-todo.log ";
+ if self.logger_proxy.errors() {
+ let msg = format!(" ERROR: Full log at {} ", self.logger_proxy.log_path());
let color = Rgb {
r: 0xff,
g: 0x00,
@@ -413,8 +419,8 @@ impl Display {
self.renderer.with_api(config, &size_info, visual_bell_intensity, |mut api| {
api.render_string(&msg, size_info.lines() - 1, glyph_cache, color);
});
- } else if logging::warnings() {
- let msg = " WARNING: Full log at /tmp/alacritty-todo.log ";
+ } else if self.logger_proxy.warnings() {
+ let msg = format!(" WARNING: Full log at {} ", self.logger_proxy.log_path());
let color = Rgb {
r: 0xff,
g: 0xff,
diff --git a/src/lib.rs b/src/lib.rs
index 4f295f53..1d393d1a 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -64,7 +64,6 @@ 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 6b43c2a7..d10c9579 100644
--- a/src/logging.rs
+++ b/src/logging.rs
@@ -19,55 +19,82 @@
//! log-level is sufficient for the level configured in `cli::Options`.
use cli;
use log::{self, Level};
-use tempfile;
-use std::fs::File;
+use std::borrow::Cow;
+use std::env;
+use std::fs::{File, OpenOptions};
use std::io::{self, LineWriter, Stdout, Write};
+use std::path::PathBuf;
use std::sync::atomic::{AtomicBool, Ordering};
-use std::sync::Mutex;
+use std::sync::{Arc, Mutex};
-static ERRORS: AtomicBool = AtomicBool::new(false);
-static WARNINGS: AtomicBool = AtomicBool::new(false);
+const LOG_FILE_NAME: &'static str = "Alacritty.log";
-pub fn initialize(options: &cli::Options) -> Result<(), log::SetLoggerError> {
+pub fn initialize(options: &cli::Options) -> Result<LoggerProxy, 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()
+ ::env_logger::try_init()?;
+ Ok(LoggerProxy::default())
} else {
- log::set_boxed_logger(Box::new(Logger::new(options.log_level)))
+ let logger = Logger::new(options.log_level);
+ let proxy = logger.proxy();
+
+ log::set_boxed_logger(Box::new(logger))?;
+
+ Ok(proxy)
}
}
-pub fn warnings() -> bool {
- WARNINGS.load(Ordering::Relaxed)
+/// Proxy object for bidirectional communicating with the global logger.
+#[derive(Clone, Default)]
+pub struct LoggerProxy {
+ errors: Arc<AtomicBool>,
+ warnings: Arc<AtomicBool>,
+ log_path: String,
}
-pub fn errors() -> bool {
- ERRORS.load(Ordering::Relaxed)
-}
+impl LoggerProxy {
+ /// Check for new logged errors.
+ pub fn errors(&self) -> bool {
+ self.errors.load(Ordering::Relaxed)
+ }
-pub fn clear_errors() {
- ERRORS.store(false, Ordering::Relaxed);
-}
+ /// Check for new logged warnings.
+ pub fn warnings(&self) -> bool {
+ self.warnings.load(Ordering::Relaxed)
+ }
+
+ /// Get the path of the log file.
+ pub fn log_path(&self) -> &str {
+ &self.log_path
+ }
-pub fn clear_warnings() {
- WARNINGS.store(false, Ordering::Relaxed);
+ /// Clear log warnings/errors from the Alacritty UI.
+ pub fn clear(&mut self) {
+ self.errors.store(false, Ordering::Relaxed);
+ self.warnings.store(false, Ordering::Relaxed);
+ }
}
-pub struct Logger {
+struct Logger {
level: log::LevelFilter,
- logfile: Mutex<OnDemandTempFile>,
+ logfile: Mutex<OnDemandLogFile>,
stdout: Mutex<LineWriter<Stdout>>,
+ errors: Arc<AtomicBool>,
+ warnings: Arc<AtomicBool>,
+ log_path: String,
}
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(level: log::LevelFilter) -> Self {
+ fn new(level: log::LevelFilter) -> Self {
log::set_max_level(level);
- let logfile = Mutex::new(OnDemandTempFile::new("alacritty", String::from(".log")));
+ let logfile = OnDemandLogFile::new();
+ let log_path = logfile.path().to_string();
+ let logfile = Mutex::new(logfile);
let stdout = Mutex::new(LineWriter::new(io::stdout()));
@@ -75,6 +102,17 @@ impl Logger {
level,
logfile,
stdout,
+ log_path,
+ errors: Arc::new(AtomicBool::new(false)),
+ warnings: Arc::new(AtomicBool::new(false)),
+ }
+ }
+
+ fn proxy(&self) -> LoggerProxy {
+ LoggerProxy {
+ errors: self.errors.clone(),
+ warnings: self.warnings.clone(),
+ log_path: self.log_path.clone(),
}
}
}
@@ -95,8 +133,8 @@ impl log::Log for Logger {
}
match record.level() {
- Level::Error => ERRORS.store(true, Ordering::Relaxed),
- Level::Warn => WARNINGS.store(true, Ordering::Relaxed),
+ Level::Error => self.errors.store(true, Ordering::Relaxed),
+ Level::Warn => self.warnings.store(true, Ordering::Relaxed),
_ => (),
}
}
@@ -105,37 +143,38 @@ impl log::Log for Logger {
fn flush(&self) {}
}
-struct OnDemandTempFile {
+struct OnDemandLogFile {
file: Option<LineWriter<File>>,
- prefix: String,
- suffix: String,
+ path: PathBuf,
}
-impl OnDemandTempFile {
- fn new<T: Into<String>, J: Into<String>>(prefix: T, suffix: J) -> Self {
- OnDemandTempFile {
- file: None,
- prefix: prefix.into(),
- suffix: suffix.into(),
- }
+impl OnDemandLogFile {
+ fn new() -> Self {
+ let mut path = env::temp_dir();
+ path.push(LOG_FILE_NAME);
+
+ OnDemandLogFile { file: None, path }
}
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);
+ let file = OpenOptions::new()
+ .append(true)
+ .create(true)
+ .open(&self.path)?;
+ self.file = Some(io::LineWriter::new(file));
+ println!("Created log file at {:?}", self.path);
}
Ok(self.file.as_mut().unwrap())
}
+
+ fn path(&self) -> Cow<str> {
+ self.path.to_string_lossy()
+ }
}
-impl Write for OnDemandTempFile {
+impl Write for OnDemandLogFile {
fn write(&mut self, buf: &[u8]) -> Result<usize, io::Error> {
self.file()?.write(buf)
}
diff --git a/src/main.rs b/src/main.rs
index bdb401fc..1498c14a 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -52,7 +52,7 @@ use alacritty::event;
use alacritty::event_loop::{self, EventLoop, Msg};
#[cfg(target_os = "macos")]
use alacritty::locale;
-use alacritty::logging;
+use alacritty::logging::{self, LoggerProxy};
use alacritty::sync::FairMutex;
use alacritty::term::Term;
use alacritty::tty::{self, process_should_exit};
@@ -69,7 +69,7 @@ fn main() {
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");
+ let logger_proxy = logging::initialize(&options).expect("Unable to initialize logger");
// Load configuration file
let config = load_config(&options).update_dynamic_title(&options);
@@ -82,7 +82,7 @@ fn main() {
locale::set_locale_environment();
// Run alacritty
- if let Err(err) = run(config, &options) {
+ if let Err(err) = run(config, &options, logger_proxy) {
die!("Alacritty encountered an unrecoverable error:\n\n\t{}\n", Red(err));
}
@@ -112,7 +112,11 @@ 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>> {
+fn run(
+ mut config: Config,
+ options: &cli::Options,
+ logger_proxy: LoggerProxy,
+) -> Result<(), Box<Error>> {
info!("Welcome to Alacritty.");
if let Some(config_path) = config.path() {
info!("Configuration loaded from {}", config_path.display());
@@ -121,7 +125,7 @@ fn run(mut config: Config, options: &cli::Options) -> Result<(), Box<Error>> {
// Create a display.
//
// The display manages a window and can draw the terminal
- let mut display = Display::new(&config, options)?;
+ let mut display = Display::new(&config, options, logger_proxy.clone())?;
info!(
"PTY Dimensions: {:?} x {:?}",
@@ -134,7 +138,7 @@ fn run(mut config: Config, options: &cli::Options) -> Result<(), Box<Error>> {
// This object contains all of the state about what's being displayed. It's
// wrapped in a clonable mutex since both the I/O loop and display need to
// access it.
- let terminal = Term::new(&config, display.size().to_owned());
+ let terminal = Term::new(&config, display.size().to_owned(), logger_proxy);
let terminal = Arc::new(FairMutex::new(terminal));
// Find the window ID for setting $WINDOWID
diff --git a/src/term/mod.rs b/src/term/mod.rs
index 8663a073..b47e6dcb 100644
--- a/src/term/mod.rs
+++ b/src/term/mod.rs
@@ -31,7 +31,7 @@ use config::{Config, VisualBellAnimation};
use {MouseCursor, Rgb};
use copypasta::{Clipboard, Load, Store};
use input::FONT_SIZE_STEP;
-use logging;
+use logging::LoggerProxy;
pub mod cell;
pub mod color;
@@ -811,6 +811,9 @@ pub struct Term {
/// Automatically scroll to bottom when new lines are added
auto_scroll: bool,
+
+ /// Proxy object for clearing displayed errors and warnings
+ logger_proxy: LoggerProxy,
}
/// Terminal size info
@@ -893,7 +896,7 @@ impl Term {
self.next_mouse_cursor.take()
}
- pub fn new(config: &Config, size: SizeInfo) -> Term {
+ pub fn new(config: &Config, size: SizeInfo, logger_proxy: LoggerProxy) -> Term {
let num_cols = size.cols();
let num_lines = size.lines();
@@ -937,6 +940,7 @@ impl Term {
dynamic_title: config.dynamic_title(),
tabspaces,
auto_scroll: config.scrolling().auto_scroll,
+ logger_proxy,
}
}
@@ -1823,9 +1827,8 @@ impl ansi::Handler for Term {
}
},
ansi::ClearMode::All => {
- // Clear errors and warnings
- logging::clear_errors();
- logging::clear_warnings();
+ // Clear displayed errors and warnings
+ self.logger_proxy.clear();
self.grid.region_mut(..).each(|c| c.reset(&template));
},