diff --git a/src/main.rs b/src/main.rs index 3a8623d..a021c1c 100644 --- a/src/main.rs +++ b/src/main.rs @@ -43,15 +43,15 @@ fn main() { let families = family::group_by_family_sort_by_name(&font_set); if families.is_empty() { - println!("No font support this character."); + eprintln!("No font support this character {}.", argument.char.description()); return; } if argument.tui { - let ui = UI::new(families).unwrap(); - ui.show().unwrap_or_else(|err| { + let ui = UI::new(families).expect("family length checked before, must not empty"); + if let Err(err) = ui.show() { eprintln!("{:?}", err); - }); + }; } else { let builder = if argument.preview { Some(PreviewServerBuilder::from_iter(families.iter())) @@ -72,10 +72,10 @@ fn show_preview_addr_and_wait(addr: SocketAddr) { println!("{}", "-".repeat(40)); println!("Please visit http://{}/ in your browser for preview", addr); print!("And press Enter after your finish..."); - std::io::stdout().flush().unwrap(); + std::io::stdout().flush().expect("flush stdout should not fail"); // Wait until user input any character before stop the server - let _ = std::io::stdin().read(&mut [0u8]).unwrap(); + let _ = std::io::stdin().read(&mut [0u8]).expect("read from stdout should not fail"); } fn show_font_list(families: Vec>, verbose: u8) { diff --git a/src/one_char.rs b/src/one_char.rs index a0f50b8..88db23d 100644 --- a/src/one_char.rs +++ b/src/one_char.rs @@ -97,10 +97,11 @@ impl OneChar { }) .take_while(|(c1, _)| c1.is_some()) .map(|(c1, c2)| -> Result { - let c1 = c1.unwrap(); // at least one char because of the `take_while` + let c1 = c1.expect("at least one char because of the take_while"); let c2 = c2.ok_or(ParseError::UTF8BytesStrCantAlignToBytes)?; if c1.is_ascii_hexdigit() && c2.is_ascii_hexdigit() { - Ok((c1.to_digit(16).unwrap() << 4 | c2.to_digit(16).unwrap()) as u8) + Ok((c1.to_digit(16).expect("hexdigit") << 4 + | c2.to_digit(16).expect("hexdigit")) as u8) } else { Err(ParseError::InvalidDigitInRadix(16)) } diff --git a/src/preview/browser/server.rs b/src/preview/browser/server.rs index 6dc460b..d9944cc 100644 --- a/src/preview/browser/server.rs +++ b/src/preview/browser/server.rs @@ -47,7 +47,7 @@ enum CheckRequestResult { } impl SingleThread { - pub const fn new(html: String) -> Self { + pub fn new(html: String) -> Self { Self { html } } @@ -183,13 +183,18 @@ impl SingleThread { addr_tx: Sender, exit_rx: Receiver<()>, content: String, ) -> Result<(), IOError> { let loopback = Ipv4Addr::new(127, 0, 0, 1); - let server = TcpListener::bind((loopback, 0)).unwrap_or_else(|err| { - eprintln!("Error when start http server: {:?}", err); - std::process::exit(-1) - }); + let server = match TcpListener::bind((loopback, 0)) { + Ok(server) => server, + Err(err) => { + eprintln!("Error when start http server: {:?}", err); + std::process::exit(-1) + } + }; - let addr = server.local_addr().unwrap(); - addr_tx.send(addr).unwrap(); + let addr = server.local_addr().expect("tcp listener must have a local addr"); + if addr_tx.send(addr).is_err() { + return Ok(()); + } // set non-blocking mode to give chance to receive exit message server.set_nonblocking(true)?; @@ -197,22 +202,23 @@ impl SingleThread { for stream in server.incoming() { match stream { Ok(stream) => match Self::handler(stream, &content, &exit_rx) { - Ok(false) => return Ok(()), + Ok(true) => {} + Ok(false) => break, Err(err) => { eprintln!("Error when process request: {:?}", err); } - Ok(..) => (), }, Err(err) if err.kind() == IOErrorKind::WouldBlock => { thread::sleep(Duration::from_millis(100)); - match exit_rx.try_recv() { - Ok(()) | Err(TryRecvError::Disconnected) => break, - _ => { - continue; - } - } } - Err(_) => break, + Err(err) => { + eprintln!("Error when listening: {:?}", err); + } + } + + match exit_rx.try_recv() { + Ok(_) | Err(TryRecvError::Disconnected) => break, + Err(TryRecvError::Empty) => {} } } diff --git a/src/preview/terminal/ui/event.rs b/src/preview/terminal/ui/event.rs index 435c78d..dae2fa3 100644 --- a/src/preview/terminal/ui/event.rs +++ b/src/preview/terminal/ui/event.rs @@ -53,7 +53,8 @@ fn keyboard_event_generator(tick_interval: Duration, tx: mpsc::Sender { - if let Event::Key(key) = event::read().unwrap() { + let ev = event::read().expect("read terminal event should not fail"); + if let Event::Key(key) = ev { #[allow(clippy::collapsible_if)] if key.kind != KeyEventKind::Release { if tx.send(Ok(TerminalEvent::Key(key))).is_err() { diff --git a/src/preview/terminal/ui/state.rs b/src/preview/terminal/ui/state.rs index 0029197..c30fdcb 100644 --- a/src/preview/terminal/ui/state.rs +++ b/src/preview/terminal/ui/state.rs @@ -81,9 +81,10 @@ impl<'a> State<'a> { self.cache.borrow_mut().entry(key).or_insert_with(|| Rc::new(self.real_render())).clone() } - fn real_render(&self) -> Result { + fn rasterize(&self) -> Result { let info = self.font_faces_info[self.index()]; - let glyph = DATABASE + + DATABASE .with_face_data(info.id, |data, index| -> Option { let mut face = FontFace::new(data, index).ok()?; face.set_size(self.height.get(), self.width.get()); @@ -92,35 +93,36 @@ impl<'a> State<'a> { _ => PixelFormat::Gray, }) }) - .unwrap(); - - match glyph { - Some(bitmap) => { - let cache = match self.rt { - RenderType::Mono => GlyphCache::Canvas(GlyphCanvasShape::new( - MONO_RENDER.render(&bitmap), - self.width.get() as f64, - self.height.get() as f64, - )), - rt => GlyphCache::Paragraph(GlyphParagraph::new( - CHAR_RENDERS.get(&rt).expect("all render must be exist").render(&bitmap), - )), - }; - Ok(cache) - } - None => Err("Can't get glyph from this font"), - } + .ok_or("Can't read this font file")? + .ok_or("Can't get glyph from this font") + } + + fn real_render(&self) -> Result { + let bitmap = self.rasterize()?; + + let cache = match self.rt { + RenderType::Mono => GlyphCache::Canvas(GlyphCanvasShape::new( + MONO_RENDER.render(&bitmap), + self.width.get() as f64, + self.height.get() as f64, + )), + rt => GlyphCache::Paragraph(GlyphParagraph::new( + CHAR_RENDERS.get(&rt).expect("all render must be exist").render(&bitmap), + )), + }; + + Ok(cache) } pub fn current_name(&self) -> &'a str { self.font_faces_name[self.index()] } - pub const fn name_width_max(&self) -> usize { + pub fn name_width_max(&self) -> usize { self.name_width_max } - pub const fn family_names(&self) -> &Vec<&'a str> { + pub fn family_names(&self) -> &Vec<&'a str> { &self.font_faces_name } @@ -129,7 +131,7 @@ impl<'a> State<'a> { } pub fn index(&self) -> usize { - self.list_state.borrow().selected().unwrap() + self.list_state.borrow().selected().expect("always has a selected item") } pub fn move_up(&mut self) { @@ -145,7 +147,7 @@ impl<'a> State<'a> { self.list_state.borrow_mut().select(changed); } - pub const fn get_render_type(&self) -> &RenderType { + pub fn get_render_type(&self) -> &RenderType { &self.rt }