aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJesse Luehrs <doy@tozt.net>2021-12-14 16:46:19 -0500
committerJesse Luehrs <doy@tozt.net>2021-12-14 16:46:19 -0500
commitbead64f9498f2787fb1d5aa247d79536f2424528 (patch)
tree6827737a841cc7e3c582e9b69e5b1dbe5fc91fa5
parent89206651ffb9815aca7f2b010722fe673a25b2ac (diff)
downloadtextmode-bead64f9498f2787fb1d5aa247d79536f2424528.tar.gz
textmode-bead64f9498f2787fb1d5aa247d79536f2424528.zip
clippy
-rw-r--r--src/blocking/input.rs56
-rw-r--r--src/blocking/output.rs38
-rw-r--r--src/input.rs58
-rw-r--r--src/key.rs48
-rw-r--r--src/lib.rs23
-rw-r--r--src/output.rs42
-rw-r--r--src/private.rs68
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<Self> {
+ ///
+ /// # Errors
+ /// * `Error::SetRaw`: failed to put the terminal into raw mode
+ pub fn new() -> crate::error::Result<Self> {
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<u8> {
@@ -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<Self> {
+ ///
+ /// # Errors
+ /// * `Error::SetRaw`: failed to put the terminal into raw mode
+ pub fn new() -> crate::error::Result<Self> {
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<Option<crate::Key>> {
+ ///
+ /// # Errors
+ /// * `Error::ReadStdin`: failed to read data from stdin
+ pub fn read_key(&mut self) -> crate::error::Result<Option<crate::Key>> {
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<usize> {
- std::io::stdin().read(buf).map_err(Error::ReadStdin)
+fn read_stdin(buf: &mut [u8]) -> crate::error::Result<usize> {
+ 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<Self> {
+ ///
+ /// # Errors
+ /// * `Error::WriteStdout`: failed to write initialization to stdout
+ pub fn new() -> crate::error::Result<Self> {
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<Self> {
+ ///
+ /// # Errors
+ /// * `Error::WriteStdout`: failed to write initialization to stdout
+ pub fn new() -> crate::error::Result<Self> {
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<Self> {
+ ///
+ /// # Errors
+ /// * `Error::SetRaw`: failed to put the terminal into raw mode
+ pub async fn new() -> crate::error::Result<Self> {
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<u8> {
@@ -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<Self> {
+ ///
+ /// # Errors
+ /// * `Error::SetRaw`: failed to put the terminal into raw mode
+ pub async fn new() -> crate::error::Result<Self> {
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<Option<crate::Key>> {
+ ///
+ /// # Errors
+ /// * `Error::ReadStdin`: failed to read data from stdin
+ pub async fn read_key(
+ &mut self,
+ ) -> crate::error::Result<Option<crate::Key>> {
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<std::io::Stdin>,
buf: &mut [u8],
-) -> Result<usize> {
- stdin.read(buf).await.map_err(Error::ReadStdin)
+) -> crate::error::Result<usize> {
+ 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<u8> {
- 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<Self> {
+ ///
+ /// # Errors
+ /// * `Error::WriteStdout`: failed to write initialization to stdout
+ pub async fn new() -> crate::error::Result<Self> {
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<Self> {
+ ///
+ /// # Errors
+ /// * `Error::WriteStdout`: failed to write initialization to stdout
+ pub async fn new() -> crate::error::Result<Self> {
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<std::io::Stdout>,
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<crate::Key> {
+ #[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<crate::Key> {
+ enum EscapeState {
+ Escape,
+ Csi(Vec<u8>),
+ 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<u8>),
- 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<u8> {
- 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,