From bead64f9498f2787fb1d5aa247d79536f2424528 Mon Sep 17 00:00:00 2001 From: Jesse Luehrs Date: Tue, 14 Dec 2021 16:46:19 -0500 Subject: clippy --- src/blocking/input.rs | 56 +++++++++++++++++++++++++---------------- src/blocking/output.rs | 38 ++++++++++++++++++++-------- src/input.rs | 58 +++++++++++++++++++++++++++++------------- src/key.rs | 48 +++++++++++++++++------------------ src/lib.rs | 23 ++++++++++++----- src/output.rs | 42 +++++++++++++++++++++++-------- src/private.rs | 68 ++++++++++++++++++++++++-------------------------- 7 files changed, 209 insertions(+), 124 deletions(-) diff --git a/src/blocking/input.rs b/src/blocking/input.rs index dcfb3ba..6d6e5a0 100644 --- a/src/blocking/input.rs +++ b/src/blocking/input.rs @@ -1,5 +1,3 @@ -use crate::error::*; - use std::io::Read as _; use std::os::unix::io::AsRawFd as _; @@ -15,10 +13,13 @@ impl RawGuard { /// Switches the terminal on `stdin` to raw mode and returns a guard /// object. This is typically called as part of /// [`Input::new`](Input::new). - pub fn new() -> Result { + /// + /// # Errors + /// * `Error::SetRaw`: failed to put the terminal into raw mode + pub fn new() -> crate::error::Result { let stdin = std::io::stdin().as_raw_fd(); - let termios = - nix::sys::termios::tcgetattr(stdin).map_err(Error::SetRaw)?; + let termios = nix::sys::termios::tcgetattr(stdin) + .map_err(crate::error::Error::SetRaw)?; let mut termios_raw = termios.clone(); nix::sys::termios::cfmakeraw(&mut termios_raw); nix::sys::termios::tcsetattr( @@ -26,31 +27,34 @@ impl RawGuard { nix::sys::termios::SetArg::TCSANOW, &termios_raw, ) - .map_err(Error::SetRaw)?; + .map_err(crate::error::Error::SetRaw)?; Ok(Self { termios: Some(termios), }) } /// Switch back from raw mode early. - pub fn cleanup(&mut self) -> Result<()> { - if let Some(termios) = self.termios.take() { + /// + /// # Errors + /// * `Error::UnsetRaw`: failed to return the terminal from raw mode + pub fn cleanup(&mut self) -> crate::error::Result<()> { + self.termios.take().map_or(Ok(()), |termios| { let stdin = std::io::stdin().as_raw_fd(); nix::sys::termios::tcsetattr( stdin, nix::sys::termios::SetArg::TCSANOW, &termios, ) - .map_err(Error::UnsetRaw) - } else { - Ok(()) - } + .map_err(crate::error::Error::UnsetRaw) + }) } } impl Drop for RawGuard { /// Calls `cleanup`. fn drop(&mut self) { + // https://github.com/rust-lang/rust-clippy/issues/8003 + #[allow(clippy::let_underscore_drop)] let _ = self.cleanup(); } } @@ -76,11 +80,11 @@ pub struct Input { impl crate::private::Input for Input { fn buf(&self) -> &[u8] { - &self.buf[self.pos..] + self.buf.get(self.pos..).unwrap() } fn buf_mut(&mut self) -> &mut [u8] { - &mut self.buf[self.pos..] + self.buf.get_mut(self.pos..).unwrap() } fn buf_mut_vec(&mut self) -> &mut Vec { @@ -127,7 +131,10 @@ impl crate::private::Input for Input { impl Input { /// Creates a new `Input` instance containing a [`RawGuard`](RawGuard) /// instance. - pub fn new() -> Result { + /// + /// # Errors + /// * `Error::SetRaw`: failed to put the terminal into raw mode + pub fn new() -> crate::error::Result { let mut self_ = Self::new_without_raw(); self_.raw = Some(RawGuard::new()?); Ok(self_) @@ -135,6 +142,7 @@ impl Input { /// Creates a new `Input` instance without creating a /// [`RawGuard`](RawGuard) instance. + #[must_use] pub fn new_without_raw() -> Self { Self { raw: None, @@ -203,7 +211,10 @@ impl Input { /// Reads a keypress from the terminal on `stdin`. Returns `Ok(None)` on /// EOF. - pub fn read_key(&mut self) -> Result> { + /// + /// # Errors + /// * `Error::ReadStdin`: failed to read data from stdin + pub fn read_key(&mut self) -> crate::error::Result> { self.fill_buf()?; if self.parse_single { @@ -225,7 +236,7 @@ impl Input { } } - fn fill_buf(&mut self) -> Result<()> { + fn fill_buf(&mut self) -> crate::error::Result<()> { if self.buf_is_empty() { self.buf.resize(4096, 0); self.pos = 0; @@ -237,12 +248,13 @@ impl Input { } if self.parse_utf8 { - let expected_bytes = self.expected_leading_utf8_bytes(); + let expected_bytes = + self.expected_leading_utf8_bytes(*self.buf().get(0).unwrap()); if self.buf.len() < self.pos + expected_bytes { let mut cur = self.buf.len(); self.buf.resize(4096 + expected_bytes, 0); while cur < self.pos + expected_bytes { - let bytes = read_stdin(&mut self.buf[cur..])?; + let bytes = read_stdin(self.buf.get_mut(cur..).unwrap())?; if bytes == 0 { return Ok(()); } @@ -256,6 +268,8 @@ impl Input { } } -fn read_stdin(buf: &mut [u8]) -> Result { - std::io::stdin().read(buf).map_err(Error::ReadStdin) +fn read_stdin(buf: &mut [u8]) -> crate::error::Result { + std::io::stdin() + .read(buf) + .map_err(crate::error::Error::ReadStdin) } diff --git a/src/blocking/output.rs b/src/blocking/output.rs index cf24e3d..74c0590 100644 --- a/src/blocking/output.rs +++ b/src/blocking/output.rs @@ -1,5 +1,3 @@ -use crate::error::*; - use std::io::Write as _; use crate::private::Output as _; @@ -14,13 +12,19 @@ impl ScreenGuard { /// Switches the terminal on `stdout` to alternate screen mode and returns /// a guard object. This is typically called as part of /// [`Output::new`](Output::new). - pub fn new() -> Result { + /// + /// # Errors + /// * `Error::WriteStdout`: failed to write initialization to stdout + pub fn new() -> crate::error::Result { write_stdout(crate::INIT)?; Ok(Self { cleaned_up: false }) } /// Switch back from alternate screen mode early. - pub fn cleanup(&mut self) -> Result<()> { + /// + /// # Errors + /// * `Error::WriteStdout`: failed to write deinitialization to stdout + pub fn cleanup(&mut self) -> crate::error::Result<()> { if self.cleaned_up { return Ok(()); } @@ -32,6 +36,8 @@ impl ScreenGuard { impl Drop for ScreenGuard { /// Calls `cleanup`. fn drop(&mut self) { + // https://github.com/rust-lang/rust-clippy/issues/8003 + #[allow(clippy::let_underscore_drop)] let _ = self.cleanup(); } } @@ -72,7 +78,10 @@ impl crate::Textmode for Output {} impl Output { /// Creates a new `Output` instance containing a /// [`ScreenGuard`](ScreenGuard) instance. - pub fn new() -> Result { + /// + /// # Errors + /// * `Error::WriteStdout`: failed to write initialization to stdout + pub fn new() -> crate::error::Result { let mut self_ = Self::new_without_screen(); self_.screen = Some(ScreenGuard::new()?); Ok(self_) @@ -80,6 +89,7 @@ impl Output { /// Creates a new `Output` instance without creating a /// [`ScreenGuard`](ScreenGuard) instance. + #[must_use] pub fn new_without_screen() -> Self { let (rows, cols) = match terminal_size::terminal_size() { Some((terminal_size::Width(w), terminal_size::Height(h))) => { @@ -108,7 +118,10 @@ impl Output { /// Draws the in-memory screen to the terminal on `stdout`. This is done /// using a diff mechanism to only update the parts of the terminal which /// are different from the in-memory screen. - pub fn refresh(&mut self) -> Result<()> { + /// + /// # Errors + /// * `Error::WriteStdout`: failed to write screen state to stdout + pub fn refresh(&mut self) -> crate::error::Result<()> { let diff = self.next().screen().state_diff(self.cur().screen()); write_stdout(&diff)?; self.cur_mut().process(&diff); @@ -120,7 +133,10 @@ impl Output { /// mechanism like `refresh`. This can be useful when the current state of /// the terminal screen is unknown, such as after the terminal has been /// resized. - pub async fn hard_refresh(&mut self) -> Result<()> { + /// + /// # Errors + /// * `Error::WriteStdout`: failed to write screen state to stdout + pub async fn hard_refresh(&mut self) -> crate::error::Result<()> { let contents = self.next().screen().state_formatted(); write_stdout(&contents)?; self.cur_mut().process(&contents); @@ -128,9 +144,11 @@ impl Output { } } -fn write_stdout(buf: &[u8]) -> Result<()> { +fn write_stdout(buf: &[u8]) -> crate::error::Result<()> { let mut stdout = std::io::stdout(); - stdout.write_all(buf).map_err(Error::WriteStdout)?; - stdout.flush().map_err(Error::WriteStdout)?; + stdout + .write_all(buf) + .map_err(crate::error::Error::WriteStdout)?; + stdout.flush().map_err(crate::error::Error::WriteStdout)?; Ok(()) } diff --git a/src/input.rs b/src/input.rs index 5710f68..f24f9c3 100644 --- a/src/input.rs +++ b/src/input.rs @@ -1,5 +1,3 @@ -use crate::error::*; - use futures_lite::io::AsyncReadExt as _; use std::os::unix::io::AsRawFd as _; @@ -15,10 +13,14 @@ impl RawGuard { /// Switches the terminal on `stdin` to raw mode and returns a guard /// object. This is typically called as part of /// [`Input::new`](Input::new). - pub async fn new() -> Result { + /// + /// # Errors + /// * `Error::SetRaw`: failed to put the terminal into raw mode + pub async fn new() -> crate::error::Result { let stdin = std::io::stdin().as_raw_fd(); let termios = blocking::unblock(move || { - nix::sys::termios::tcgetattr(stdin).map_err(Error::SetRaw) + nix::sys::termios::tcgetattr(stdin) + .map_err(crate::error::Error::SetRaw) }) .await?; let mut termios_raw = termios.clone(); @@ -29,7 +31,7 @@ impl RawGuard { nix::sys::termios::SetArg::TCSANOW, &termios_raw, ) - .map_err(Error::SetRaw) + .map_err(crate::error::Error::SetRaw) }) .await?; Ok(Self { @@ -38,7 +40,10 @@ impl RawGuard { } /// Switch back from raw mode early. - pub async fn cleanup(&mut self) -> Result<()> { + /// + /// # Errors + /// * `Error::UnsetRaw`: failed to return the terminal from raw mode + pub async fn cleanup(&mut self) -> crate::error::Result<()> { if let Some(termios) = self.termios.take() { let stdin = std::io::stdin().as_raw_fd(); blocking::unblock(move || { @@ -47,7 +52,7 @@ impl RawGuard { nix::sys::termios::SetArg::TCSANOW, &termios, ) - .map_err(Error::UnsetRaw) + .map_err(crate::error::Error::UnsetRaw) }) .await } else { @@ -62,6 +67,8 @@ impl Drop for RawGuard { /// call `cleanup` manually instead. fn drop(&mut self) { futures_lite::future::block_on(async { + // https://github.com/rust-lang/rust-clippy/issues/8003 + #[allow(clippy::let_underscore_drop)] let _ = self.cleanup().await; }); } @@ -89,11 +96,11 @@ pub struct Input { impl crate::private::Input for Input { fn buf(&self) -> &[u8] { - &self.buf[self.pos..] + self.buf.get(self.pos..).unwrap() } fn buf_mut(&mut self) -> &mut [u8] { - &mut self.buf[self.pos..] + self.buf.get_mut(self.pos..).unwrap() } fn buf_mut_vec(&mut self) -> &mut Vec { @@ -140,7 +147,10 @@ impl crate::private::Input for Input { impl Input { /// Creates a new `Input` instance containing a [`RawGuard`](RawGuard) /// instance. - pub async fn new() -> Result { + /// + /// # Errors + /// * `Error::SetRaw`: failed to put the terminal into raw mode + pub async fn new() -> crate::error::Result { let mut self_ = Self::new_without_raw(); self_.raw = Some(RawGuard::new().await?); Ok(self_) @@ -148,6 +158,7 @@ impl Input { /// Creates a new `Input` instance without creating a /// [`RawGuard`](RawGuard) instance. + #[must_use] pub fn new_without_raw() -> Self { Self { stdin: blocking::Unblock::new(std::io::stdin()), @@ -217,7 +228,12 @@ impl Input { /// Reads a keypress from the terminal on `stdin`. Returns `Ok(None)` on /// EOF. - pub async fn read_key(&mut self) -> Result> { + /// + /// # Errors + /// * `Error::ReadStdin`: failed to read data from stdin + pub async fn read_key( + &mut self, + ) -> crate::error::Result> { self.fill_buf().await?; if self.parse_single { @@ -239,7 +255,7 @@ impl Input { } } - async fn fill_buf(&mut self) -> Result<()> { + async fn fill_buf(&mut self) -> crate::error::Result<()> { if self.buf_is_empty() { self.buf.resize(4096, 0); self.pos = 0; @@ -251,14 +267,17 @@ impl Input { } if self.parse_utf8 { - let expected_bytes = self.expected_leading_utf8_bytes(); + let expected_bytes = + self.expected_leading_utf8_bytes(*self.buf().get(0).unwrap()); if self.buf.len() < self.pos + expected_bytes { let mut cur = self.buf.len(); self.buf.resize(4096 + expected_bytes, 0); while cur < self.pos + expected_bytes { - let bytes = - read_stdin(&mut self.stdin, &mut self.buf[cur..]) - .await?; + let bytes = read_stdin( + &mut self.stdin, + self.buf.get_mut(cur..).unwrap(), + ) + .await?; if bytes == 0 { return Ok(()); } @@ -275,6 +294,9 @@ impl Input { async fn read_stdin( stdin: &mut blocking::Unblock, buf: &mut [u8], -) -> Result { - stdin.read(buf).await.map_err(Error::ReadStdin) +) -> crate::error::Result { + stdin + .read(buf) + .await + .map_err(crate::error::Error::ReadStdin) } diff --git a/src/key.rs b/src/key.rs index 505817f..15c0303 100644 --- a/src/key.rs +++ b/src/key.rs @@ -32,32 +32,32 @@ pub enum Key { impl Key { /// Returns bytes generated by the given key press. + #[must_use] pub fn into_bytes(self) -> Vec { - use Key::*; match self { - String(s) => s.into_bytes(), - Char(c) => c.to_string().into_bytes(), - Bytes(s) => s, - Byte(c) => vec![c], - Ctrl(c) => vec![c - b'a' + 1], - Meta(c) => vec![b'\x1b', c], - Backspace => b"\x7f".to_vec(), - Escape => b"\x1b".to_vec(), - Up => b"\x1b[A".to_vec(), - Down => b"\x1b[B".to_vec(), - Right => b"\x1b[C".to_vec(), - Left => b"\x1b[D".to_vec(), - KeypadUp => b"\x1bOA".to_vec(), - KeypadDown => b"\x1bOB".to_vec(), - KeypadRight => b"\x1bOC".to_vec(), - KeypadLeft => b"\x1bOD".to_vec(), - Home => b"\x1b[H".to_vec(), - End => b"\x1b[F".to_vec(), - Insert => b"\x1b[2~".to_vec(), - Delete => b"\x1b[3~".to_vec(), - PageUp => b"\x1b[5~".to_vec(), - PageDown => b"\x1b[6~".to_vec(), - F(c) => match c { + Key::String(s) => s.into_bytes(), + Key::Char(c) => c.to_string().into_bytes(), + Key::Bytes(s) => s, + Key::Byte(c) => vec![c], + Key::Ctrl(c) => vec![c - b'a' + 1], + Key::Meta(c) => vec![b'\x1b', c], + Key::Backspace => b"\x7f".to_vec(), + Key::Escape => b"\x1b".to_vec(), + Key::Up => b"\x1b[A".to_vec(), + Key::Down => b"\x1b[B".to_vec(), + Key::Right => b"\x1b[C".to_vec(), + Key::Left => b"\x1b[D".to_vec(), + Key::KeypadUp => b"\x1bOA".to_vec(), + Key::KeypadDown => b"\x1bOB".to_vec(), + Key::KeypadRight => b"\x1bOC".to_vec(), + Key::KeypadLeft => b"\x1bOD".to_vec(), + Key::Home => b"\x1b[H".to_vec(), + Key::End => b"\x1b[F".to_vec(), + Key::Insert => b"\x1b[2~".to_vec(), + Key::Delete => b"\x1b[3~".to_vec(), + Key::PageUp => b"\x1b[5~".to_vec(), + Key::PageDown => b"\x1b[6~".to_vec(), + Key::F(c) => match c { 1 => b"\x1bOP".to_vec(), 2 => b"\x1bOQ".to_vec(), 3 => b"\x1bOR".to_vec(), diff --git a/src/lib.rs b/src/lib.rs index 6c515c6..6a48a02 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,5 +1,3 @@ -#![allow(clippy::collapsible_if)] - //! `textmode` is a library for terminal interaction built on top of a real //! terminal parsing library. It allows you to do arbitrary drawing operations //! on an in-memory screen, and then update the visible terminal output to @@ -65,6 +63,19 @@ //! Additionally, the [`blocking`] module provides an equivalent interface //! with blocking calls instead of async. +#![warn(clippy::cargo)] +#![warn(clippy::pedantic)] +#![warn(clippy::nursery)] +#![warn(clippy::unwrap_used)] +#![warn(clippy::expect_used)] +#![warn(clippy::indexing_slicing)] +#![warn(clippy::as_conversions)] +#![allow(clippy::cognitive_complexity)] +#![allow(clippy::missing_const_for_fn)] +#![allow(clippy::struct_excessive_bools)] +#![allow(clippy::too_many_arguments)] +#![allow(clippy::too_many_lines)] + /// Blocking interface. pub mod blocking; @@ -128,22 +139,22 @@ pub trait Textmode: private::Output { if row_offset > 0 { self.write(b"\x1b["); self.write_u16(abs_row_offset); - self.write(b"B") + self.write(b"B"); } if row_offset < 0 { self.write(b"\x1b["); self.write_u16(abs_row_offset); - self.write(b"A") + self.write(b"A"); } if col_offset > 0 { self.write(b"\x1b["); self.write_u16(abs_col_offset); - self.write(b"C") + self.write(b"C"); } if col_offset < 0 { self.write(b"\x1b["); self.write_u16(abs_col_offset); - self.write(b"D") + self.write(b"D"); } } diff --git a/src/output.rs b/src/output.rs index 7669f4c..9b72438 100644 --- a/src/output.rs +++ b/src/output.rs @@ -1,5 +1,3 @@ -use crate::error::*; - use futures_lite::io::AsyncWriteExt as _; use crate::private::Output as _; @@ -14,7 +12,10 @@ impl ScreenGuard { /// Switches the terminal on `stdout` to alternate screen mode and returns /// a guard object. This is typically called as part of /// [`Output::new`](Output::new). - pub async fn new() -> Result { + /// + /// # Errors + /// * `Error::WriteStdout`: failed to write initialization to stdout + pub async fn new() -> crate::error::Result { write_stdout( &mut blocking::Unblock::new(std::io::stdout()), crate::INIT, @@ -24,7 +25,10 @@ impl ScreenGuard { } /// Switch back from alternate screen mode early. - pub async fn cleanup(&mut self) -> Result<()> { + /// + /// # Errors + /// * `Error::WriteStdout`: failed to write deinitialization to stdout + pub async fn cleanup(&mut self) -> crate::error::Result<()> { if self.cleaned_up { return Ok(()); } @@ -43,6 +47,8 @@ impl Drop for ScreenGuard { /// call `cleanup` manually instead. fn drop(&mut self) { futures_lite::future::block_on(async { + // https://github.com/rust-lang/rust-clippy/issues/8003 + #[allow(clippy::let_underscore_drop)] let _ = self.cleanup().await; }); } @@ -85,7 +91,10 @@ impl crate::Textmode for Output {} impl Output { /// Creates a new `Output` instance containing a /// [`ScreenGuard`](ScreenGuard) instance. - pub async fn new() -> Result { + /// + /// # Errors + /// * `Error::WriteStdout`: failed to write initialization to stdout + pub async fn new() -> crate::error::Result { let mut self_ = Self::new_without_screen(); self_.screen = Some(ScreenGuard::new().await?); Ok(self_) @@ -93,6 +102,7 @@ impl Output { /// Creates a new `Output` instance without creating a /// [`ScreenGuard`](ScreenGuard) instance. + #[must_use] pub fn new_without_screen() -> Self { let (rows, cols) = match terminal_size::terminal_size() { Some((terminal_size::Width(w), terminal_size::Height(h))) => { @@ -121,7 +131,10 @@ impl Output { /// Draws the in-memory screen to the terminal on `stdout`. This is done /// using a diff mechanism to only update the parts of the terminal which /// are different from the in-memory screen. - pub async fn refresh(&mut self) -> Result<()> { + /// + /// # Errors + /// * `Error::WriteStdout`: failed to write screen state to stdout + pub async fn refresh(&mut self) -> crate::error::Result<()> { let diff = self.next().screen().state_diff(self.cur().screen()); write_stdout(&mut self.stdout, &diff).await?; self.cur_mut().process(&diff); @@ -133,7 +146,10 @@ impl Output { /// mechanism like `refresh`. This can be useful when the current state of /// the terminal screen is unknown, such as after the terminal has been /// resized. - pub async fn hard_refresh(&mut self) -> Result<()> { + /// + /// # Errors + /// * `Error::WriteStdout`: failed to write screen state to stdout + pub async fn hard_refresh(&mut self) -> crate::error::Result<()> { let contents = self.next().screen().state_formatted(); write_stdout(&mut self.stdout, &contents).await?; self.cur_mut().process(&contents); @@ -144,8 +160,14 @@ impl Output { async fn write_stdout( stdout: &mut blocking::Unblock, buf: &[u8], -) -> Result<()> { - stdout.write_all(buf).await.map_err(Error::WriteStdout)?; - stdout.flush().await.map_err(Error::WriteStdout)?; +) -> crate::error::Result<()> { + stdout + .write_all(buf) + .await + .map_err(crate::error::Error::WriteStdout)?; + stdout + .flush() + .await + .map_err(crate::error::Error::WriteStdout)?; Ok(()) } diff --git a/src/private.rs b/src/private.rs index 6f23eed..ed69aa5 100644 --- a/src/private.rs +++ b/src/private.rs @@ -5,13 +5,13 @@ pub trait Output { fn next_mut(&mut self) -> &mut vt100::Parser; fn write_u16(&mut self, i: u16) { - // unwrap is fine because vt100::Parser::write can never fail - itoa::write(self.next_mut(), i).unwrap(); + // vt100::Parser::write can never fail + itoa::write(self.next_mut(), i).unwrap_or_else(|_| unreachable!()); } fn write_u8(&mut self, i: u8) { - // unwrap is fine because vt100::Parser::write can never fail - itoa::write(self.next_mut(), i).unwrap(); + // vt100::Parser::write can never fail + itoa::write(self.next_mut(), i).unwrap_or_else(|_| unreachable!()); } } @@ -54,13 +54,12 @@ pub trait Input { self.consume(i); s.truncate(i); return Some(crate::Key::String(s)); - } else { - // not quite correct, but figuring out how to - // take only the invalid utf8 seems hard (and - // this should come up very rarely) - self.consume(prefix.len()); - return Some(crate::Key::Bytes(prefix)); } + // not quite correct, but figuring out how to + // take only the invalid utf8 seems hard (and + // this should come up very rarely) + self.consume(prefix.len()); + return Some(crate::Key::Bytes(prefix)); } } self.consume(s.len()); @@ -73,6 +72,7 @@ pub trait Input { } fn try_read_bytes(&mut self) -> Option { + #[allow(clippy::match_same_arms)] let prefix: Vec<_> = self .buf() .iter() @@ -129,7 +129,7 @@ pub trait Input { Some(c @ 28..=31) => Some(crate::Key::Byte(c)), Some(c @ 32..=126) => { if self.should_parse_utf8() { - Some(crate::Key::Char(c as char)) + Some(crate::Key::Char(char::from(c))) } else { Some(crate::Key::Byte(c)) } @@ -153,6 +153,12 @@ pub trait Input { } fn read_escape_sequence(&mut self) -> Option { + enum EscapeState { + Escape, + Csi(Vec), + Ckm, + } + let mut seen = vec![b'\x1b']; macro_rules! fail { @@ -162,9 +168,8 @@ pub trait Input { } if self.should_parse_special_keys() { return Some(crate::Key::Escape); - } else { - return Some(crate::Key::Byte(27)); } + return Some(crate::Key::Byte(27)); }}; } macro_rules! next_byte { @@ -178,12 +183,6 @@ pub trait Input { }; } - enum EscapeState { - Escape, - Csi(Vec), - Ckm, - } - let mut state = EscapeState::Escape; loop { let c = next_byte!(); @@ -207,9 +206,8 @@ pub trait Input { b' '..=b'N' | b'P'..=b'Z' | b'\\'..=b'~' => { if self.should_parse_meta() { return Some(crate::Key::Meta(c)); - } else { - fail!() } + fail!() } _ => fail!(), }, @@ -306,11 +304,12 @@ pub trait Input { } match std::string::String::from_utf8(buf) { - // unwrap is fine because buf always contains at least the - // initial character, and we have already done the parsing to - // ensure that it contains a valid utf8 character before - // getting here - Ok(s) => Some(crate::Key::Char(s.chars().next().unwrap())), + Ok(s) => Some(crate::Key::Char( + // buf always contains at least the initial character, and we + // have already done the parsing to ensure that it contains a + // valid utf8 character before getting here + s.chars().next().unwrap_or_else(|| unreachable!()), + )), Err(e) => { buf = e.into_bytes(); fail!() @@ -319,12 +318,10 @@ pub trait Input { } fn getc(&mut self) -> Option { - if self.buf_is_empty() { - return None; - } - let c = self.buf()[0]; - self.consume(1); - Some(c) + self.buf().get(0).copied().map(|c| { + self.consume(1); + c + }) } fn ungetc(&mut self, c: u8) { @@ -332,12 +329,13 @@ pub trait Input { self.buf_mut_vec().insert(0, c); } else { self.unconsume(1); - self.buf_mut()[0] = c; + *self.buf_mut().get_mut(0).unwrap() = c; } } - fn expected_leading_utf8_bytes(&self) -> usize { - match self.buf()[0] { + #[allow(clippy::match_same_arms)] + fn expected_leading_utf8_bytes(&self, c: u8) -> usize { + match c { 0b0000_0000..=0b0111_1111 => 1, 0b1100_0000..=0b1101_1111 => 2, 0b1110_0000..=0b1110_1111 => 3, -- cgit v1.2.3-54-g00ecf