diff --git a/Cargo.toml b/Cargo.toml index e387e46..6374482 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -12,7 +12,7 @@ description = """ A terminal formatting library """ categories = ["command-line-interface"] -edition = "2018" +edition = "2021" rust-version = "1.63" [badges] diff --git a/rustfmt.toml b/rustfmt.toml deleted file mode 100644 index f86d8d1..0000000 --- a/rustfmt.toml +++ /dev/null @@ -1,3 +0,0 @@ -wrap_match_arms = true -struct_lit_multiline_style = "ForceMulti" -wrap_comments = false diff --git a/src/lib.rs b/src/lib.rs index d23d873..ce70bf3 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -27,16 +27,9 @@ //! term = "*" //! ``` //! -//! and this to your crate root: -//! -//! ```rust -//! extern crate term; -//! ``` -//! //! # Examples //! //! ```no_run -//! extern crate term; //! use std::io::prelude::*; //! //! fn main() { @@ -59,12 +52,12 @@ #![doc( html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png", html_favicon_url = "https://doc.rust-lang.org/favicon.ico", - html_root_url = "https://stebalien.github.io/doc/term/term/", + html_root_url = "https://docs.rs/term/latest", test(attr(deny(warnings))) )] #![deny(missing_docs)] +#![deny(rust_2018_idioms)] #![cfg_attr(test, deny(warnings))] -#![allow(clippy::redundant_field_names)] use std::io::prelude::*; @@ -180,6 +173,7 @@ pub enum Attr { /// An error arising from interacting with the terminal. #[derive(Debug)] +#[non_exhaustive] pub enum Error { /// Indicates an error from any underlying IO Io(io::Error), @@ -200,50 +194,21 @@ pub enum Error { /// /// This is like `NotSupported`, but more specific. ColorOutOfRange, - #[doc(hidden)] - /// Please don't match against this - if you do, we can't promise we won't break your crate - /// with a semver-compliant version bump. - __Nonexhaustive, } // manually implemented because std::io::Error does not implement Eq/PartialEq impl std::cmp::PartialEq for Error { fn eq(&self, other: &Error) -> bool { use crate::Error::*; - match *self { + match self { Io(_) => false, - TerminfoParsing(ref inner1) => match *other { - TerminfoParsing(ref inner2) => inner1 == inner2, - _ => false, - }, - ParameterizedExpansion(ref inner1) => match *other { - ParameterizedExpansion(ref inner2) => inner1 == inner2, - _ => false, - }, - NotSupported => match *other { - NotSupported => true, - _ => false, - }, - TermUnset => match *other { - TermUnset => true, - _ => false, - }, - TerminfoEntryNotFound => match *other { - TerminfoEntryNotFound => true, - _ => false, - }, - CursorDestinationInvalid => match *other { - CursorDestinationInvalid => true, - _ => false, - }, - ColorOutOfRange => match *other { - ColorOutOfRange => true, - _ => false, - }, - __Nonexhaustive => match *other { - __Nonexhaustive => true, - _ => false, - }, + TerminfoParsing(a) => matches!(other, TerminfoParsing(b) if a == b), + ParameterizedExpansion(a) => matches!(other, ParameterizedExpansion(b) if a == b), + NotSupported => matches!(other, NotSupported), + TermUnset => matches!(other, TermUnset), + TerminfoEntryNotFound => matches!(other, TerminfoEntryNotFound), + CursorDestinationInvalid => matches!(other, CursorDestinationInvalid), + ColorOutOfRange => matches!(other, ColorOutOfRange), } } } @@ -254,10 +219,10 @@ pub type Result = std::result::Result; impl std::fmt::Display for Error { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { use crate::Error::*; - match *self { - Io(ref io) => io.fmt(f), - TerminfoParsing(ref e) => e.fmt(f), - ParameterizedExpansion(ref e) => e.fmt(f), + match self { + Io(io) => io.fmt(f), + TerminfoParsing(e) => e.fmt(f), + ParameterizedExpansion(e) => e.fmt(f), NotSupported => f.write_str("operation not supported by the terminal"), TermUnset => { f.write_str("TERM environment variable unset, unable to detect a terminal") @@ -267,17 +232,16 @@ impl std::fmt::Display for Error { } CursorDestinationInvalid => f.write_str("could not move cursor to requested position"), ColorOutOfRange => f.write_str("color not supported by the terminal"), - __Nonexhaustive => f.write_str("placeholder variant that shouldn't be used"), } } } impl std::error::Error for Error { fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { - match *self { - Error::Io(ref io) => Some(io), - Error::TerminfoParsing(ref e) => Some(e), - Error::ParameterizedExpansion(ref e) => Some(e), + match self { + Error::Io(io) => Some(io), + Error::TerminfoParsing(e) => Some(e), + Error::ParameterizedExpansion(e) => Some(e), _ => None, } } @@ -285,8 +249,8 @@ impl std::error::Error for Error { impl From for io::Error { fn from(err: Error) -> io::Error { - let kind = match err { - Error::Io(ref e) => e.kind(), + let kind = match &err { + Error::Io(e) => e.kind(), _ => io::ErrorKind::Other, }; io::Error::new(kind, err) diff --git a/src/terminfo/mod.rs b/src/terminfo/mod.rs index 804c8dc..a8c414f 100644 --- a/src/terminfo/mod.rs +++ b/src/terminfo/mod.rs @@ -61,7 +61,7 @@ impl TermInfo { /// Create a `TermInfo` based on current environment. pub fn from_env() -> Result { let term_var = env::var("TERM").ok(); - let term_name = term_var.as_ref().map(|s| &**s).or_else(|| { + let term_name = term_var.as_deref().or_else(|| { env::var("MSYSCON").ok().and_then(|s| { if s == "mintty.exe" { Some("msyscon") @@ -91,7 +91,7 @@ impl TermInfo { /// Create a `TermInfo` for the named terminal. pub fn from_name(name: &str) -> Result { if let Some(path) = get_dbpath_for_term(name) { - match TermInfo::from_path(&path) { + match TermInfo::from_path(path) { Ok(term) => return Ok(term), // Skip IO Errors (e.g., permission denied). Err(crate::Error::Io(_)) => {} @@ -206,14 +206,14 @@ pub enum Error { impl ::std::fmt::Display for Error { fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { - match *self { + match self { BadMagic(v) => write!(f, "bad magic number {:x} in terminfo header", v), ShortNames => f.write_str("no names exposed, need at least one"), TooManyBools => f.write_str("more boolean properties than libterm knows about"), TooManyNumbers => f.write_str("more number properties than libterm knows about"), TooManyStrings => f.write_str("more string properties than libterm knows about"), InvalidLength => f.write_str("invalid length field value, must be >= -1"), - NotUtf8(ref e) => e.fmt(f), + NotUtf8(e) => e.fmt(f), NamesMissingNull => f.write_str("names table missing NUL terminator"), StringsMissingNull => f.write_str("string table missing NUL terminator"), } @@ -228,8 +228,8 @@ impl ::std::convert::From<::std::string::FromUtf8Error> for Error { impl ::std::error::Error for Error { fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { - match *self { - NotUtf8(ref e) => Some(e), + match self { + NotUtf8(e) => Some(e), _ => None, } } @@ -239,7 +239,7 @@ pub mod searcher; /// `TermInfo` format parsing. pub mod parser { - //! ncurses-compatible compiled terminfo format parsing (term(5)) + /// ncurses-compatible compiled terminfo format parsing (term(5)) pub mod compiled; mod names; } @@ -307,7 +307,7 @@ impl Terminal for TerminfoTerminal { Attr::ForegroundColor(_) | Attr::BackgroundColor(_) => self.num_colors > 0, _ => { let cap = cap_for_attr(attr); - self.ti.strings.get(cap).is_some() + self.ti.strings.contains_key(cap) } } } @@ -319,7 +319,7 @@ impl Terminal for TerminfoTerminal { fn supports_reset(&self) -> bool { ["sgr0", "sgr", "op"] .iter() - .any(|&cap| self.ti.strings.get(cap).is_some()) + .any(|&cap| self.ti.strings.contains_key(cap)) } fn supports_color(&self) -> bool { @@ -356,18 +356,17 @@ impl Terminal for TerminfoTerminal { impl TerminfoTerminal { /// Create a new TerminfoTerminal with the given TermInfo and Write. - pub fn new_with_terminfo(out: T, terminfo: TermInfo) -> TerminfoTerminal { - let nc = if terminfo.strings.contains_key("setaf") && terminfo.strings.contains_key("setab") - { - terminfo.numbers.get("colors").map_or(0, |&n| n) + pub fn new_with_terminfo(out: T, ti: TermInfo) -> TerminfoTerminal { + let num_colors = if ti.strings.contains_key("setaf") && ti.strings.contains_key("setab") { + ti.numbers.get("colors").map_or(0, |&n| n) } else { 0 }; TerminfoTerminal { - out: out, - ti: terminfo, - num_colors: nc as u32, + out, + ti, + num_colors, } } @@ -381,7 +380,7 @@ impl TerminfoTerminal { } fn dim_if_necessary(&self, color: color::Color) -> color::Color { - if color >= self.num_colors && color >= 8 && color < 16 { + if color >= self.num_colors && (8..16).contains(&color) { color - 8 } else { color diff --git a/src/terminfo/parm.rs b/src/terminfo/parm.rs index 8aa74af..cc23525 100644 --- a/src/terminfo/parm.rs +++ b/src/terminfo/parm.rs @@ -83,7 +83,7 @@ pub enum Error { impl ::std::fmt::Display for Error { fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { use self::Error::*; - match *self { + match self { StackUnderflow => f.write_str("not enough elements on the stack"), TypeMismatch => f.write_str("type mismatch"), UnrecognizedFormatOption(_) => f.write_str("unrecognized format option"), @@ -298,36 +298,40 @@ pub fn expand(cap: &[u8], params: &[Param], vars: &mut Variables) -> Result { - if cur >= 'A' && cur <= 'Z' { + SetVar => match cur { + 'A'..='Z' => { if let Some(arg) = stack.pop() { let idx = (cur as u8) - b'A'; vars.sta_vars[idx as usize] = arg; } else { return Err(Error::StackUnderflow); } - } else if cur >= 'a' && cur <= 'z' { + } + 'a'..='z' => { if let Some(arg) = stack.pop() { let idx = (cur as u8) - b'a'; vars.dyn_vars[idx as usize] = arg; } else { return Err(Error::StackUnderflow); } - } else { + } + _ => { return Err(Error::InvalidVariableName(cur)); } - } - GetVar => { - if cur >= 'A' && cur <= 'Z' { + }, + GetVar => match cur { + 'A'..='Z' => { let idx = (cur as u8) - b'A'; stack.push(vars.sta_vars[idx as usize].clone()); - } else if cur >= 'a' && cur <= 'z' { + } + 'a'..='z' => { let idx = (cur as u8) - b'a'; stack.push(vars.dyn_vars[idx as usize].clone()); - } else { + } + _ => { return Err(Error::InvalidVariableName(cur)); } - } + }, CharConstant => { stack.push(Number(i32::from(c))); state = CharClose; @@ -474,6 +478,7 @@ enum FormatOp { Digit, Octal, Hex, + #[allow(clippy::upper_case_acronyms)] HEX, String, } @@ -553,7 +558,7 @@ fn format(val: Param, op: FormatOp, flags: Flags) -> Result, Error> { } else { let mut s_ = Vec::with_capacity(flags.width); s_.extend(repeat(b' ').take(n)); - s_.extend(s.into_iter()); + s_.extend(s); s = s_; } } diff --git a/src/terminfo/searcher.rs b/src/terminfo/searcher.rs index 1763d2c..ab8909e 100644 --- a/src/terminfo/searcher.rs +++ b/src/terminfo/searcher.rs @@ -44,7 +44,7 @@ pub fn get_dbpath_for_term(term: &str) -> Option { if let Ok(dirs) = env::var("TERMINFO_DIRS") { for i in dirs.split(':') { - if i == "" { + if i.is_empty() { dirs_to_search.push(PathBuf::from("/usr/share/terminfo")); } else { dirs_to_search.push(PathBuf::from(i)); @@ -71,7 +71,7 @@ pub fn get_dbpath_for_term(term: &str) -> Option { for mut p in dirs_to_search { if fs::metadata(&p).is_ok() { p.push(&first_char.to_string()); - p.push(&term); + p.push(term); if fs::metadata(&p).is_ok() { return Some(p); }