API Cleanup - part 2 (#238)

This commit is contained in:
Zrzka 2019-09-19 17:39:14 +02:00 committed by Timon
parent 06c791714a
commit 4952cb33d9
25 changed files with 138 additions and 143 deletions

View File

@ -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)
}

View File

@ -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)
}

View File

@ -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,6 +490,9 @@ where
}
#[cfg(test)]
mod tests {
use super::parse_utf8_char;
#[test]
fn test_parse_utf8() {
let st = "abcéŷ¤£€ù%323";
@ -500,3 +503,4 @@ fn test_parse_utf8() {
assert_eq!(c, parse_utf8_char(b, bytes).unwrap());
}
}
}

View File

@ -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();
}
}

View File

@ -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;
}
}

View File

@ -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(())
}

View File

@ -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,)
}

View File

@ -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<u16> {
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)
}
}

View File

@ -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<String> 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<Self, Self::Err> {
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));
}
}

View File

@ -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(())

View File

@ -1,9 +1,7 @@
macro_rules! def_attr {
($name:ident => $attr:path) => {
fn $name(self) -> StyledObject<D> {
let so = self;
so.attr($attr)
self.attr($attr)
}
};
}
@ -28,7 +26,7 @@ macro_rules! def_str_color {
StyledObject {
object_style: ObjectStyle {
$side: Some($color),
.. ObjectStyle::default()
..Default::default()
},
content: self
}
@ -40,8 +38,8 @@ macro_rules! def_str_attr {
($name:ident => $color:path) => {
fn $name(self) -> StyledObject<&'static str> {
StyledObject {
object_style: ObjectStyle::default(),
content: self
object_style: Default::default(),
content: self,
}
}
}

View File

@ -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<Color>,
pub bg_color: Option<Color>,
pub attrs: Vec<Attribute>,
}
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<D: Display + Clone>(&self, val: D) -> StyledObject<D> {
@ -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.

View File

@ -55,11 +55,11 @@ impl<D: Display + Clone> Display for StyledObject<D> {
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<D: Display + Clone> Display for StyledObject<D> {
fmt::Display::fmt(&self.content, f)?;
if reset {
colored_terminal.reset().unwrap();
colored_terminal.reset().map_err(|_| fmt::Error)?;
}
Ok(())

View File

@ -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<D: Display + Clone> {
/// 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<D: Display + Clone> {
fn reset(self) -> StyledObject<D>;

View File

@ -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::<u16>().unwrap() | bg_color;
color = color_value.parse::<u16>()? | 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::<u16>().unwrap();
color = fg_color | color_value.parse::<u16>()?;
// Foreground intensity is a separate value in attrs,
// So we need to check if this was applied to the current fg color.

View File

@ -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)
}

View File

@ -5,6 +5,8 @@ use std::{
io,
};
use crate::impl_from;
/// The `crossterm` result type.
pub type Result<T> = std::result::Result<T, ErrorKind>;
@ -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<io::Error> for ErrorKind {
fn from(e: io::Error) -> ErrorKind {
ErrorKind::IoError(e)
}
}
impl From<fmt::Error> for ErrorKind {
fn from(e: fmt::Error) -> ErrorKind {
ErrorKind::FmtError(e)
}
}
impl From<std::string::FromUtf8Error> for ErrorKind {
fn from(e: std::string::FromUtf8Error) -> Self {
ErrorKind::Utf8Error(e)
}
}
impl From<std::num::ParseIntError> 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);

View File

@ -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)
}
}
};
}

View File

@ -9,7 +9,7 @@ use crate::{ErrorKind, Result};
static mut ORIGINAL_TERMINAL_MODE: Option<Termios> = 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<Termios> {
}
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;
}
}

View File

@ -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(())
}
}

View File

@ -76,7 +76,7 @@ impl From<Handle> for ConsoleMode {
}
#[cfg(test)]
mod test {
mod tests {
use super::ConsoleMode;
// TODO - Test is ignored, because it's failing on Travis CI

View File

@ -175,7 +175,7 @@ impl From<HANDLE> for Handle {
}
#[cfg(test)]
mod test {
mod tests {
use super::{Handle, HandleType};
#[test]

View File

@ -122,7 +122,7 @@ impl From<HANDLE> for ScreenBuffer {
}
#[cfg(test)]
mod test {
mod tests {
use super::ScreenBuffer;
#[test]

View File

@ -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()
}

View File

@ -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)));