diff --git a/src/display.rs b/src/display.rs index 8e2134ab..2ddf1bdd 100644 --- a/src/display.rs +++ b/src/display.rs @@ -30,6 +30,52 @@ use term::{Term, SizeInfo}; use window::{self, Size, Pixels, Window, SetInnerSize}; +#[derive(Debug)] +pub enum Error { + /// Error with window management + Window(window::Error), + + /// Error dealing with fonts + Font(font::Error), +} + +impl ::std::error::Error for Error { + fn cause(&self) -> Option<&::std::error::Error> { + match *self { + Error::Window(ref err) => Some(err), + Error::Font(ref err) => Some(err), + } + } + + fn description(&self) -> &str { + match *self { + Error::Window(ref err) => err.description(), + Error::Font(ref err) => err.description(), + } + } +} + +impl ::std::fmt::Display for Error { + fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { + match *self { + Error::Window(ref err) => err.fmt(f), + Error::Font(ref err) => err.fmt(f), + } + } +} + +impl From for Error { + fn from(val: window::Error) -> Error { + Error::Window(val) + } +} + +impl From for Error { + fn from(val: font::Error) -> Error { + Error::Font(val) + } +} + /// The display wraps a window, font rasterizer, and GPU renderer pub struct Display { window: Window, @@ -74,26 +120,23 @@ impl Display { pub fn new( config: &Config, options: &cli::Options, - ) -> Result { + ) -> Result { // Extract some properties from config let font = config.font(); let dpi = config.dpi(); let render_timer = config.render_timer(); // Create the window where Alacritty will be displayed - let mut window = match Window::new() { - Ok(window) => window, - Err(err) => die!("{}", err) - }; + let mut window = Window::new()?; // get window properties for initializing the other subsytems - let size = window.inner_size_pixels().unwrap(); + let size = window.inner_size_pixels() + .expect("glutin returns window size"); let dpr = window.hidpi_factor(); println!("device_pixel_ratio: {}", dpr); - // TODO ERROR HANDLING - let rasterizer = font::Rasterizer::new(dpi.x(), dpi.y(), dpr).unwrap(); + let rasterizer = font::Rasterizer::new(dpi.x(), dpi.y(), dpr)?; // Create renderer let mut renderer = QuadRenderer::new(config, size); @@ -105,7 +148,7 @@ impl Display { let cache = renderer.with_loader(|mut api| { GlyphCache::new(rasterizer, config, &mut api) - }); + })?; let stop = init_start.elapsed(); let stop_f = stop.as_secs() as f64 + stop.subsec_nanos() as f64 / 1_000_000_000f64; @@ -247,8 +290,10 @@ impl Display { } } - // Unlock the terminal mutex + // Unlock the terminal mutex; following call to swap_buffers() may block drop(terminal); - self.window.swap_buffers().unwrap(); + self.window + .swap_buffers() + .expect("swap buffers"); } } diff --git a/src/main.rs b/src/main.rs index cce55354..a1c8e77c 100644 --- a/src/main.rs +++ b/src/main.rs @@ -52,12 +52,20 @@ fn main() { // Run alacritty if let Err(err) = run(config, options) { - die!("{}", err); + die!("Alacritty encountered an unrecoverable error:\n\n\t{}\n", Red(err)); } println!("Goodbye"); } +use std::fmt; +struct Red(T); +impl fmt::Display for Red { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "\x1b[31m{}\x1b[0m", self.0) + } +} + /// Run Alacritty /// /// Creates a window, the terminal state, pty, I/O event loop, input processor, diff --git a/src/renderer/mod.rs b/src/renderer/mod.rs index 838555b8..cb8db636 100644 --- a/src/renderer/mod.rs +++ b/src/renderer/mod.rs @@ -119,7 +119,11 @@ pub struct GlyphCache { } impl GlyphCache { - pub fn new(mut rasterizer: Rasterizer, config: &Config, loader: &mut L) -> GlyphCache + pub fn new( + mut rasterizer: Rasterizer, + config: &Config, + loader: &mut L + ) -> Result where L: LoadGlyph { let font = config.font(); @@ -128,8 +132,7 @@ impl GlyphCache { // Load regular font let regular_desc = FontDesc::new(font.family(), font.style()); let regular = rasterizer - .load_font(®ular_desc, size) - .expect("regular font load ok"); + .load_font(®ular_desc, size)?; // Load bold font let bold_style = font.bold_style().unwrap_or("Bold"); @@ -177,21 +180,22 @@ impl GlyphCache { load_glyphs_for_font!(bold); load_glyphs_for_font!(italic); - cache + Ok(cache) } pub fn font_metrics(&self) -> font::Metrics { - // TODO ERROR HANDLING - self.rasterizer.metrics(self.font_key, self.font_size).unwrap() + self.rasterizer + .metrics(self.font_key, self.font_size) + .expect("metrics load since font is loaded at glyph cache creation") } fn load_and_cache_glyph(&mut self, glyph_key: GlyphKey, loader: &mut L) where L: LoadGlyph { - // TODO ERROR HANDLING - let rasterized = self.rasterizer.get_glyph(&glyph_key).unwrap(); - let glyph = loader.load_glyph(&rasterized); - self.cache.insert(glyph_key, glyph); + if let Ok(rasterized) = self.rasterizer.get_glyph(&glyph_key) { + let glyph = loader.load_glyph(&rasterized); + self.cache.insert(glyph_key, glyph); + } } pub fn get(&mut self, glyph_key: &GlyphKey, loader: &mut L) -> Option<&Glyph> @@ -783,7 +787,8 @@ impl<'a> LoadGlyph for LoaderApi<'a> { /// /// If the current atlas is full, a new one will be created. fn load_glyph(&mut self, rasterized: &RasterizedGlyph) -> Glyph { - // At least one atlas is guaranteed to be in the `self.atlas` list; thus the unwrap. + // At least one atlas is guaranteed to be in the `self.atlas` list; thus + // the unwrap should always be ok. match self.atlas.last_mut().unwrap().insert(rasterized, &mut self.active_tex) { Ok(glyph) => glyph, Err(_) => { @@ -801,7 +806,8 @@ impl<'a> LoadGlyph for RenderApi<'a> { /// /// If the current atlas is full, a new one will be created. fn load_glyph(&mut self, rasterized: &RasterizedGlyph) -> Glyph { - // At least one atlas is guaranteed to be in the `self.atlas` list; thus the unwrap. + // At least one atlas is guaranteed to be in the `self.atlas` list; thus + // the unwrap. match self.atlas.last_mut().unwrap().insert(rasterized, &mut self.active_tex) { Ok(glyph) => glyph, Err(_) => {