diff --git a/crossterm_cursor/src/cursor/ansi_cursor.rs b/crossterm_cursor/src/cursor/ansi_cursor.rs index 6770592..80251ad 100644 --- a/crossterm_cursor/src/cursor/ansi_cursor.rs +++ b/crossterm_cursor/src/cursor/ansi_cursor.rs @@ -8,23 +8,22 @@ use crate::sys::{get_cursor_position, show_cursor}; use super::ITerminalCursor; -#[inline] pub fn get_goto_ansi(x: u16, y: u16) -> String { format!(csi!("{};{}H"), y + 1, x + 1) } -#[inline] + pub fn get_move_up_ansi(count: u16) -> String { format!(csi!("{}A"), count) } -#[inline] + pub fn get_move_right_ansi(count: u16) -> String { format!(csi!("{}C"), count) } -#[inline] + pub fn get_move_down_ansi(count: u16) -> String { format!(csi!("{}B"), count) } -#[inline] + pub fn get_move_left_ansi(count: u16) -> String { format!(csi!("{}D"), count) } diff --git a/crossterm_cursor/src/cursor/cursor.rs b/crossterm_cursor/src/cursor/cursor.rs index e21b6e7..b7c0367 100644 --- a/crossterm_cursor/src/cursor/cursor.rs +++ b/crossterm_cursor/src/cursor/cursor.rs @@ -83,7 +83,7 @@ impl TerminalCursor { /// Move the current cursor position `n` times left. pub fn move_left(&mut self, count: u16) -> Result<&mut TerminalCursor> { - self.cursor.move_left(count).unwrap(); + self.cursor.move_left(count)?; Ok(self) } diff --git a/crossterm_input/src/input/unix_input.rs b/crossterm_input/src/input/unix_input.rs index 798559c..384cf55 100644 --- a/crossterm_input/src/input/unix_input.rs +++ b/crossterm_input/src/input/unix_input.rs @@ -129,7 +129,7 @@ impl AsyncReader { /// # Remarks /// - Background thread will be closed. /// - This will consume the handle you won't be able to restart the reading with this handle, create a new `AsyncReader` instead. - pub fn stop_reading(&mut self) { + pub fn stop(&mut self) { self.shutdown.store(true, Ordering::SeqCst); } } @@ -161,7 +161,7 @@ impl Iterator for AsyncReader { impl Drop for AsyncReader { fn drop(&mut self) { - self.stop_reading(); + self.stop(); } } @@ -490,13 +490,17 @@ where } #[cfg(test)] -#[test] -fn test_parse_utf8() { - let st = "abcéŷ¤£€ù%323"; - let ref mut bytes = st.bytes(); - let chars = st.chars(); - for c in chars { - let b = bytes.next().unwrap(); - assert_eq!(c, parse_utf8_char(b, bytes).unwrap()); +mod tests { + use super::parse_utf8_char; + + #[test] + fn test_parse_utf8() { + let st = "abcéŷ¤£€ù%323"; + let ref mut bytes = st.bytes(); + let chars = st.chars(); + for c in chars { + let b = bytes.next().unwrap(); + assert_eq!(c, parse_utf8_char(b, bytes).unwrap()); + } } } diff --git a/crossterm_input/src/input/windows_input.rs b/crossterm_input/src/input/windows_input.rs index 1b781fb..5a83b46 100644 --- a/crossterm_input/src/input/windows_input.rs +++ b/crossterm_input/src/input/windows_input.rs @@ -180,14 +180,14 @@ impl AsyncReader { /// # Remarks /// - Background thread will be closed. /// - This will consume the handle you won't be able to restart the reading with this handle, create a new `AsyncReader` instead. - pub fn stop_reading(&mut self) { + pub fn stop(&mut self) { self.shutdown.store(true, Ordering::SeqCst); } } impl Drop for AsyncReader { fn drop(&mut self) { - self.stop_reading(); + self.stop(); } } diff --git a/crossterm_screen/src/screen/raw.rs b/crossterm_screen/src/screen/raw.rs index 782d034..3e7d5c2 100644 --- a/crossterm_screen/src/screen/raw.rs +++ b/crossterm_screen/src/screen/raw.rs @@ -53,8 +53,8 @@ impl RawScreen { Ok(()) } - /// This will disable the drop logic of this type, which means that the rawscreen will not be disabled when this instance goes out of scope. - pub fn disable_raw_mode_on_drop(&mut self) { + /// Keeps the raw mode when the `RawMode` value is dropped. + pub fn keep_raw_mode_on_drop(&mut self) { self.disable_raw_mode_on_drop = false; } } diff --git a/crossterm_screen/src/sys.rs b/crossterm_screen/src/sys.rs index b84af95..f4d7ec1 100644 --- a/crossterm_screen/src/sys.rs +++ b/crossterm_screen/src/sys.rs @@ -18,7 +18,7 @@ impl ToAlternateScreenCommand { impl IAlternateScreenCommand for ToAlternateScreenCommand { /// enable alternate screen. fn enable(&self) -> Result<()> { - write_cout!(csi!("?1049h")).unwrap(); + write_cout!(csi!("?1049h"))?; Ok(()) } diff --git a/crossterm_style/src/ansi_color.rs b/crossterm_style/src/ansi_color.rs index 94a56ca..65bda2a 100644 --- a/crossterm_style/src/ansi_color.rs +++ b/crossterm_style/src/ansi_color.rs @@ -5,17 +5,14 @@ use crossterm_utils::{csi, write_cout, Result}; use crate::{Attribute, Color, Colored, ITerminalColor}; -#[inline] pub fn get_set_fg_ansi(fg_color: Color) -> String { format!(csi!("{}m"), color_value(Colored::Fg(fg_color)),) } -#[inline] pub fn get_set_bg_ansi(bg_color: Color) -> String { format!(csi!("{}m"), color_value(Colored::Bg(bg_color)),) } -#[inline] pub fn get_set_attr_ansi(attribute: Attribute) -> String { format!(csi!("{}m"), attribute as i16,) } diff --git a/crossterm_style/src/color.rs b/crossterm_style/src/color.rs index 5dfff03..74190fc 100644 --- a/crossterm_style/src/color.rs +++ b/crossterm_style/src/color.rs @@ -2,6 +2,7 @@ //! Like applying attributes to text and changing the foreground and background. use std::clone::Clone; +use std::env; use std::fmt::Display; #[cfg(windows)] @@ -65,19 +66,14 @@ impl TerminalColor { } /// Get available color count. - /// (This does not always provide a good result.) - pub fn get_available_color_count(&self) -> Result { - use std::env; - Ok(match env::var_os("TERM") { - Some(val) => { - if val.to_str().unwrap_or("").contains("256color") { - 256 - } else { - 8 - } - } - None => 8, - }) + /// + /// # Remarks + /// + /// This does not always provide a good result. + pub fn get_available_color_count(&self) -> u16 { + env::var("TERM") + .map(|x| if x.contains("256color") { 256 } else { 8 }) + .unwrap_or(8) } } diff --git a/crossterm_style/src/enums/color.rs b/crossterm_style/src/enums/color.rs index f6ad372..d17303d 100644 --- a/crossterm_style/src/enums/color.rs +++ b/crossterm_style/src/enums/color.rs @@ -46,24 +46,15 @@ pub enum Color { AnsiValue(u8), } -impl<'a> From<&'a str> for Color { - /// Get a `Color` from a `&str` like `Color::from("blue")`. - fn from(src: &str) -> Self { - src.parse().unwrap_or(Color::White) - } -} - -impl From for Color { - /// Get a `Color` from a `&str` like `Color::from(String::from(blue))`. - fn from(src: String) -> Self { - src.parse().unwrap_or(Color::White) - } -} - impl FromStr for Color { type Err = (); - /// Convert a `&str` to a `Color` value + /// Creates a `Color` from the string representation. + /// + /// # Remarks + /// + /// * `Color::White` is returned in case of an unknown color. + /// * This function does not return `Err` and you can safely unwrap. fn from_str(src: &str) -> ::std::result::Result { let src = src.to_lowercase(); @@ -88,3 +79,33 @@ impl FromStr for Color { } } } + +#[cfg(test)] +mod tests { + use super::Color; + + #[test] + fn test_known_color_conversion() { + assert_eq!("black".parse(), Ok(Color::Black)); + assert_eq!("dark_grey".parse(), Ok(Color::DarkGrey)); + assert_eq!("red".parse(), Ok(Color::Red)); + assert_eq!("dark_red".parse(), Ok(Color::DarkRed)); + assert_eq!("green".parse(), Ok(Color::Green)); + assert_eq!("dark_green".parse(), Ok(Color::DarkGreen)); + assert_eq!("yellow".parse(), Ok(Color::Yellow)); + assert_eq!("dark_yellow".parse(), Ok(Color::DarkYellow)); + assert_eq!("blue".parse(), Ok(Color::Blue)); + assert_eq!("dark_blue".parse(), Ok(Color::DarkBlue)); + assert_eq!("magenta".parse(), Ok(Color::Magenta)); + assert_eq!("dark_magenta".parse(), Ok(Color::DarkMagenta)); + assert_eq!("cyan".parse(), Ok(Color::Cyan)); + assert_eq!("dark_cyan".parse(), Ok(Color::DarkCyan)); + assert_eq!("white".parse(), Ok(Color::White)); + assert_eq!("grey".parse(), Ok(Color::Grey)); + } + + #[test] + fn test_unknown_color_conversion_yields_white() { + assert_eq!("foo".parse(), Ok(Color::White)); + } +} diff --git a/crossterm_style/src/enums/colored.rs b/crossterm_style/src/enums/colored.rs index d2a0453..1073225 100644 --- a/crossterm_style/src/enums/colored.rs +++ b/crossterm_style/src/enums/colored.rs @@ -37,12 +37,12 @@ impl Display for Colored { let colored_terminal = color(); match *self { - Colored::Fg(color) => { - colored_terminal.set_fg(color).unwrap(); - } - Colored::Bg(color) => { - colored_terminal.set_bg(color).unwrap(); - } + Colored::Fg(color) => colored_terminal + .set_fg(color) + .map_err(|_| std::fmt::Error)?, + Colored::Bg(color) => colored_terminal + .set_bg(color) + .map_err(|_| std::fmt::Error)?, } Ok(()) diff --git a/crossterm_style/src/macros.rs b/crossterm_style/src/macros.rs index e2de61e..2138534 100644 --- a/crossterm_style/src/macros.rs +++ b/crossterm_style/src/macros.rs @@ -1,34 +1,32 @@ macro_rules! def_attr { - ($name: ident => $attr: path) => { + ($name:ident => $attr:path) => { fn $name(self) -> StyledObject { - let so = self; - - so.attr($attr) + self.attr($attr) } }; } macro_rules! def_color { - ($side:ident: $name: ident => $color: path) => { + ($side:ident: $name:ident => $color:path) => { fn $name(self) -> StyledObject { StyledObject { object_style: ObjectStyle { $side: Some($color), - .. self.object_style + ..self.object_style }, - .. self + ..self } } }; } macro_rules! def_str_color { - ($side:ident: $name: ident => $color: path) => { + ($side:ident: $name:ident => $color:path) => { fn $name(self) -> StyledObject< &'static str> { StyledObject { object_style: ObjectStyle { $side: Some($color), - .. ObjectStyle::default() + ..Default::default() }, content: self } @@ -37,12 +35,12 @@ macro_rules! def_str_color { } macro_rules! def_str_attr { - ($name: ident => $color: path) => { + ($name:ident => $color:path) => { fn $name(self) -> StyledObject<&'static str> { - StyledObject { - object_style: ObjectStyle::default(), - content: self - } + StyledObject { + object_style: Default::default(), + content: self, + } } } } diff --git a/crossterm_style/src/objectstyle.rs b/crossterm_style/src/objectstyle.rs index 2ff0851..4fb8608 100644 --- a/crossterm_style/src/objectstyle.rs +++ b/crossterm_style/src/objectstyle.rs @@ -5,23 +5,13 @@ use std::fmt::Display; use super::{Attribute, Color, StyledObject}; /// Struct that contains the style properties that can be applied to a displayable object. -#[derive(Debug, Clone)] +#[derive(Debug, Clone, Default)] pub struct ObjectStyle { pub fg_color: Option, pub bg_color: Option, pub attrs: Vec, } -impl Default for ObjectStyle { - fn default() -> ObjectStyle { - ObjectStyle { - fg_color: None, - bg_color: None, - attrs: Vec::new(), - } - } -} - impl ObjectStyle { /// Apply a `StyledObject` to the passed displayable object. pub fn apply_to(&self, val: D) -> StyledObject { @@ -33,11 +23,7 @@ impl ObjectStyle { /// Get a new instance of `ObjectStyle` pub fn new() -> ObjectStyle { - ObjectStyle { - fg_color: None, - bg_color: None, - attrs: Vec::new(), - } + ObjectStyle::default() } /// Set the background color of `ObjectStyle` to the passed color. diff --git a/crossterm_style/src/styledobject.rs b/crossterm_style/src/styledobject.rs index 56e4e82..f0b3ec7 100644 --- a/crossterm_style/src/styledobject.rs +++ b/crossterm_style/src/styledobject.rs @@ -55,11 +55,11 @@ impl Display for StyledObject { let mut reset = false; if let Some(bg) = self.object_style.bg_color { - queue!(f, SetBg(bg)).unwrap(); + queue!(f, SetBg(bg)).map_err(|_| fmt::Error)?; reset = true; } if let Some(fg) = self.object_style.fg_color { - queue!(f, SetFg(fg)).unwrap(); + queue!(f, SetFg(fg)).map_err(|_| fmt::Error)?; reset = true; } @@ -71,7 +71,7 @@ impl Display for StyledObject { fmt::Display::fmt(&self.content, f)?; if reset { - colored_terminal.reset().unwrap(); + colored_terminal.reset().map_err(|_| fmt::Error)?; } Ok(()) diff --git a/crossterm_style/src/traits.rs b/crossterm_style/src/traits.rs index cc6e08b..6867463 100644 --- a/crossterm_style/src/traits.rs +++ b/crossterm_style/src/traits.rs @@ -6,8 +6,8 @@ use crate::StyledObject; /// /// This trait is implemented for `&static str` and `StyledObject` and thus the methods of this trait could be called on them. /// -/// ```ignore -/// use Colorizer; +/// ```rust +/// use crossterm_style::Colorize; /// /// let styled_text = "Red forground color on blue background.".red().on_blue(); /// println!("{}", styled_text); @@ -53,12 +53,13 @@ pub trait Colorize { /// This trait is implemented for `&static str` and `StyledObject` and thus the methods of this trait could be called on them. /// /// # Example -/// ```ignore -/// use Colorizer; /// -/// println!("{}", "Bold text".bold(); -/// println!("{}", "Underlined text".underlined(); -/// println!("{}", "Negative text".negative(); +/// ```rust +/// use crossterm_style::Styler; +/// +/// println!("{}", "Bold text".bold()); +/// println!("{}", "Underlined text".underlined()); +/// println!("{}", "Negative text".negative()); /// ``` pub trait Styler { fn reset(self) -> StyledObject; diff --git a/crossterm_style/src/winapi_color.rs b/crossterm_style/src/winapi_color.rs index 0a581b3..0c14b17 100644 --- a/crossterm_style/src/winapi_color.rs +++ b/crossterm_style/src/winapi_color.rs @@ -44,7 +44,7 @@ impl ITerminalColor for WinApiColor { let mut color: u16; let attrs = csbi.attributes(); let bg_color = attrs & 0x0070; - color = color_value.parse::().unwrap() | bg_color; + color = color_value.parse::()? | bg_color; // background intensity is a separate value in attrs, // wee need to check if this was applied to the current bg color. @@ -71,7 +71,7 @@ impl ITerminalColor for WinApiColor { let mut color: u16; let attrs = csbi.attributes(); let fg_color = attrs & 0x0007; - color = fg_color | color_value.parse::().unwrap(); + color = fg_color | color_value.parse::()?; // Foreground intensity is a separate value in attrs, // So we need to check if this was applied to the current fg color. diff --git a/crossterm_terminal/src/terminal/ansi_terminal.rs b/crossterm_terminal/src/terminal/ansi_terminal.rs index 9e9630d..c432a48 100644 --- a/crossterm_terminal/src/terminal/ansi_terminal.rs +++ b/crossterm_terminal/src/terminal/ansi_terminal.rs @@ -14,17 +14,14 @@ pub static CLEAR_FROM_CURSOR_UP: &'static str = csi!("1J"); pub static CLEAR_FROM_CURRENT_LINE: &'static str = csi!("2K"); pub static CLEAR_UNTIL_NEW_LINE: &'static str = csi!("K"); -#[inline] pub fn get_scroll_up_ansi(count: u16) -> String { format!(csi!("{}S"), count) } -#[inline] pub fn get_scroll_down_ansi(count: u16) -> String { format!(csi!("{}T"), count) } -#[inline] pub fn get_set_size_ansi(width: u16, height: u16) -> String { format!(csi!("8;{};{}t"), height, width) } diff --git a/crossterm_utils/src/error.rs b/crossterm_utils/src/error.rs index 52f9d26..6ce4289 100644 --- a/crossterm_utils/src/error.rs +++ b/crossterm_utils/src/error.rs @@ -5,6 +5,8 @@ use std::{ io, }; +use crate::impl_from; + /// The `crossterm` result type. pub type Result = std::result::Result; @@ -23,8 +25,11 @@ pub enum ErrorKind { impl std::error::Error for ErrorKind { fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { - match *self { - ErrorKind::IoError(ref e) => Some(e), + match self { + ErrorKind::IoError(e) => Some(e), + ErrorKind::FmtError(e) => Some(e), + ErrorKind::Utf8Error(e) => Some(e), + ErrorKind::ParseIntError(e) => Some(e), _ => None, } } @@ -40,26 +45,7 @@ impl Display for ErrorKind { } } -impl From for ErrorKind { - fn from(e: io::Error) -> ErrorKind { - ErrorKind::IoError(e) - } -} - -impl From for ErrorKind { - fn from(e: fmt::Error) -> ErrorKind { - ErrorKind::FmtError(e) - } -} - -impl From for ErrorKind { - fn from(e: std::string::FromUtf8Error) -> Self { - ErrorKind::Utf8Error(e) - } -} - -impl From for ErrorKind { - fn from(e: std::num::ParseIntError) -> Self { - ErrorKind::ParseIntError(e) - } -} +impl_from!(io::Error, ErrorKind::IoError); +impl_from!(fmt::Error, ErrorKind::FmtError); +impl_from!(std::string::FromUtf8Error, ErrorKind::Utf8Error); +impl_from!(std::num::ParseIntError, ErrorKind::ParseIntError); diff --git a/crossterm_utils/src/macros.rs b/crossterm_utils/src/macros.rs index a047926..98332dd 100644 --- a/crossterm_utils/src/macros.rs +++ b/crossterm_utils/src/macros.rs @@ -190,3 +190,14 @@ macro_rules! impl_display { })* } } + +#[macro_export] +macro_rules! impl_from { + ($from:path, $to:expr) => { + impl From<$from> for ErrorKind { + fn from(e: $from) -> Self { + $to(e) + } + } + }; +} diff --git a/crossterm_utils/src/sys/unix.rs b/crossterm_utils/src/sys/unix.rs index 5f3f01e..9e62ba1 100644 --- a/crossterm_utils/src/sys/unix.rs +++ b/crossterm_utils/src/sys/unix.rs @@ -9,7 +9,7 @@ use crate::{ErrorKind, Result}; static mut ORIGINAL_TERMINAL_MODE: Option = None; pub static mut RAW_MODE_ENABLED: bool = false; -fn unwrap(t: i32) -> Result<()> { +fn wrap_with_result(t: i32) -> Result<()> { if t == -1 { Err(ErrorKind::IoError(io::Error::last_os_error())) } else { @@ -31,7 +31,7 @@ pub fn get_terminal_attr() -> Result { } unsafe { let mut termios = mem::zeroed(); - unwrap(tcgetattr(0, &mut termios))?; + wrap_with_result(tcgetattr(0, &mut termios))?; Ok(termios) } } @@ -40,7 +40,7 @@ pub fn set_terminal_attr(termios: &Termios) -> Result<()> { extern "C" { pub fn tcsetattr(fd: c_int, opt: c_int, termptr: *const Termios) -> c_int; } - unwrap(unsafe { tcsetattr(0, 0, termios) }).and(Ok(())) + wrap_with_result(unsafe { tcsetattr(0, 0, termios) }) } pub fn into_raw_mode() -> Result<()> { @@ -61,9 +61,8 @@ pub fn into_raw_mode() -> Result<()> { pub fn disable_raw_mode() -> Result<()> { unsafe { - if ORIGINAL_TERMINAL_MODE.is_some() { - set_terminal_attr(&ORIGINAL_TERMINAL_MODE.unwrap())?; - + if let Some(original_terminal_mode) = ORIGINAL_TERMINAL_MODE.as_ref() { + set_terminal_attr(original_terminal_mode)?; RAW_MODE_ENABLED = false; } } diff --git a/crossterm_utils/src/sys/winapi.rs b/crossterm_utils/src/sys/winapi.rs index c6ed7a1..9a2e618 100644 --- a/crossterm_utils/src/sys/winapi.rs +++ b/crossterm_utils/src/sys/winapi.rs @@ -24,11 +24,11 @@ pub mod ansi { } else { old_mode & !mask }; - if old_mode == new_mode { - return Ok(()); + + if old_mode != new_mode { + console_mode.set_mode(new_mode)?; } - console_mode.set_mode(new_mode)?; Ok(()) } } diff --git a/crossterm_winapi/src/console_mode.rs b/crossterm_winapi/src/console_mode.rs index 458a3ff..076a9bd 100644 --- a/crossterm_winapi/src/console_mode.rs +++ b/crossterm_winapi/src/console_mode.rs @@ -76,7 +76,7 @@ impl From for ConsoleMode { } #[cfg(test)] -mod test { +mod tests { use super::ConsoleMode; // TODO - Test is ignored, because it's failing on Travis CI diff --git a/crossterm_winapi/src/handle.rs b/crossterm_winapi/src/handle.rs index 7867422..e3beccb 100644 --- a/crossterm_winapi/src/handle.rs +++ b/crossterm_winapi/src/handle.rs @@ -175,7 +175,7 @@ impl From for Handle { } #[cfg(test)] -mod test { +mod tests { use super::{Handle, HandleType}; #[test] diff --git a/crossterm_winapi/src/screen_buffer.rs b/crossterm_winapi/src/screen_buffer.rs index 641d38b..a84b21e 100644 --- a/crossterm_winapi/src/screen_buffer.rs +++ b/crossterm_winapi/src/screen_buffer.rs @@ -122,7 +122,7 @@ impl From for ScreenBuffer { } #[cfg(test)] -mod test { +mod tests { use super::ScreenBuffer; #[test] diff --git a/examples/program_examples/first_depth_search/src/main.rs b/examples/program_examples/first_depth_search/src/main.rs index e5e6cb3..673cfa0 100644 --- a/examples/program_examples/first_depth_search/src/main.rs +++ b/examples/program_examples/first_depth_search/src/main.rs @@ -20,7 +20,7 @@ fn main() -> Result<()> { /// run the program fn run() -> Result<()> { - // let screen = RawScreen::into_raw_mode().expect("failed to enable raw modes"); + // let screen = RawScreen::into_raw_mode()?; print_welcome_screen()?; start_algorithm()?; exit() @@ -90,7 +90,7 @@ fn print_welcome_screen() -> Result<()> { } fn exit() -> Result<()> { - RawScreen::disable_raw_mode().expect("Failed to disable raw modes."); + RawScreen::disable_raw_mode()?; cursor().show()?; color().reset() } diff --git a/examples/style.rs b/examples/style.rs index 6450d20..2c9ef43 100644 --- a/examples/style.rs +++ b/examples/style.rs @@ -399,7 +399,7 @@ fn print_text_with_attributes() { /// Print all supported RGB colors, not supported for Windows systems < 10 | demonstration. fn print_supported_colors() { - let count = color().get_available_color_count().unwrap(); + let count = color().get_available_color_count(); for i in 0..count { println!("Test {}", Colored::Bg(Color::AnsiValue(i as u8)));