API Cleanup - part 2 (#238)
This commit is contained in:
parent
06c791714a
commit
4952cb33d9
@ -8,23 +8,22 @@ use crate::sys::{get_cursor_position, show_cursor};
|
|||||||
|
|
||||||
use super::ITerminalCursor;
|
use super::ITerminalCursor;
|
||||||
|
|
||||||
#[inline]
|
|
||||||
pub fn get_goto_ansi(x: u16, y: u16) -> String {
|
pub fn get_goto_ansi(x: u16, y: u16) -> String {
|
||||||
format!(csi!("{};{}H"), y + 1, x + 1)
|
format!(csi!("{};{}H"), y + 1, x + 1)
|
||||||
}
|
}
|
||||||
#[inline]
|
|
||||||
pub fn get_move_up_ansi(count: u16) -> String {
|
pub fn get_move_up_ansi(count: u16) -> String {
|
||||||
format!(csi!("{}A"), count)
|
format!(csi!("{}A"), count)
|
||||||
}
|
}
|
||||||
#[inline]
|
|
||||||
pub fn get_move_right_ansi(count: u16) -> String {
|
pub fn get_move_right_ansi(count: u16) -> String {
|
||||||
format!(csi!("{}C"), count)
|
format!(csi!("{}C"), count)
|
||||||
}
|
}
|
||||||
#[inline]
|
|
||||||
pub fn get_move_down_ansi(count: u16) -> String {
|
pub fn get_move_down_ansi(count: u16) -> String {
|
||||||
format!(csi!("{}B"), count)
|
format!(csi!("{}B"), count)
|
||||||
}
|
}
|
||||||
#[inline]
|
|
||||||
pub fn get_move_left_ansi(count: u16) -> String {
|
pub fn get_move_left_ansi(count: u16) -> String {
|
||||||
format!(csi!("{}D"), count)
|
format!(csi!("{}D"), count)
|
||||||
}
|
}
|
||||||
|
@ -83,7 +83,7 @@ impl TerminalCursor {
|
|||||||
|
|
||||||
/// Move the current cursor position `n` times left.
|
/// Move the current cursor position `n` times left.
|
||||||
pub fn move_left(&mut self, count: u16) -> Result<&mut TerminalCursor> {
|
pub fn move_left(&mut self, count: u16) -> Result<&mut TerminalCursor> {
|
||||||
self.cursor.move_left(count).unwrap();
|
self.cursor.move_left(count)?;
|
||||||
Ok(self)
|
Ok(self)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -129,7 +129,7 @@ impl AsyncReader {
|
|||||||
/// # Remarks
|
/// # Remarks
|
||||||
/// - Background thread will be closed.
|
/// - 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.
|
/// - 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);
|
self.shutdown.store(true, Ordering::SeqCst);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -161,7 +161,7 @@ impl Iterator for AsyncReader {
|
|||||||
|
|
||||||
impl Drop for AsyncReader {
|
impl Drop for AsyncReader {
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
self.stop_reading();
|
self.stop();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -490,13 +490,17 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
#[test]
|
mod tests {
|
||||||
fn test_parse_utf8() {
|
use super::parse_utf8_char;
|
||||||
let st = "abcéŷ¤£€ù%323";
|
|
||||||
let ref mut bytes = st.bytes();
|
#[test]
|
||||||
let chars = st.chars();
|
fn test_parse_utf8() {
|
||||||
for c in chars {
|
let st = "abcéŷ¤£€ù%323";
|
||||||
let b = bytes.next().unwrap();
|
let ref mut bytes = st.bytes();
|
||||||
assert_eq!(c, parse_utf8_char(b, bytes).unwrap());
|
let chars = st.chars();
|
||||||
|
for c in chars {
|
||||||
|
let b = bytes.next().unwrap();
|
||||||
|
assert_eq!(c, parse_utf8_char(b, bytes).unwrap());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -180,14 +180,14 @@ impl AsyncReader {
|
|||||||
/// # Remarks
|
/// # Remarks
|
||||||
/// - Background thread will be closed.
|
/// - 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.
|
/// - 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);
|
self.shutdown.store(true, Ordering::SeqCst);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Drop for AsyncReader {
|
impl Drop for AsyncReader {
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
self.stop_reading();
|
self.stop();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -53,8 +53,8 @@ impl RawScreen {
|
|||||||
Ok(())
|
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.
|
/// Keeps the raw mode when the `RawMode` value is dropped.
|
||||||
pub fn disable_raw_mode_on_drop(&mut self) {
|
pub fn keep_raw_mode_on_drop(&mut self) {
|
||||||
self.disable_raw_mode_on_drop = false;
|
self.disable_raw_mode_on_drop = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -18,7 +18,7 @@ impl ToAlternateScreenCommand {
|
|||||||
impl IAlternateScreenCommand for ToAlternateScreenCommand {
|
impl IAlternateScreenCommand for ToAlternateScreenCommand {
|
||||||
/// enable alternate screen.
|
/// enable alternate screen.
|
||||||
fn enable(&self) -> Result<()> {
|
fn enable(&self) -> Result<()> {
|
||||||
write_cout!(csi!("?1049h")).unwrap();
|
write_cout!(csi!("?1049h"))?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5,17 +5,14 @@ use crossterm_utils::{csi, write_cout, Result};
|
|||||||
|
|
||||||
use crate::{Attribute, Color, Colored, ITerminalColor};
|
use crate::{Attribute, Color, Colored, ITerminalColor};
|
||||||
|
|
||||||
#[inline]
|
|
||||||
pub fn get_set_fg_ansi(fg_color: Color) -> String {
|
pub fn get_set_fg_ansi(fg_color: Color) -> String {
|
||||||
format!(csi!("{}m"), color_value(Colored::Fg(fg_color)),)
|
format!(csi!("{}m"), color_value(Colored::Fg(fg_color)),)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
|
||||||
pub fn get_set_bg_ansi(bg_color: Color) -> String {
|
pub fn get_set_bg_ansi(bg_color: Color) -> String {
|
||||||
format!(csi!("{}m"), color_value(Colored::Bg(bg_color)),)
|
format!(csi!("{}m"), color_value(Colored::Bg(bg_color)),)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
|
||||||
pub fn get_set_attr_ansi(attribute: Attribute) -> String {
|
pub fn get_set_attr_ansi(attribute: Attribute) -> String {
|
||||||
format!(csi!("{}m"), attribute as i16,)
|
format!(csi!("{}m"), attribute as i16,)
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
//! Like applying attributes to text and changing the foreground and background.
|
//! Like applying attributes to text and changing the foreground and background.
|
||||||
|
|
||||||
use std::clone::Clone;
|
use std::clone::Clone;
|
||||||
|
use std::env;
|
||||||
use std::fmt::Display;
|
use std::fmt::Display;
|
||||||
|
|
||||||
#[cfg(windows)]
|
#[cfg(windows)]
|
||||||
@ -65,19 +66,14 @@ impl TerminalColor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Get available color count.
|
/// Get available color count.
|
||||||
/// (This does not always provide a good result.)
|
///
|
||||||
pub fn get_available_color_count(&self) -> Result<u16> {
|
/// # Remarks
|
||||||
use std::env;
|
///
|
||||||
Ok(match env::var_os("TERM") {
|
/// This does not always provide a good result.
|
||||||
Some(val) => {
|
pub fn get_available_color_count(&self) -> u16 {
|
||||||
if val.to_str().unwrap_or("").contains("256color") {
|
env::var("TERM")
|
||||||
256
|
.map(|x| if x.contains("256color") { 256 } else { 8 })
|
||||||
} else {
|
.unwrap_or(8)
|
||||||
8
|
|
||||||
}
|
|
||||||
}
|
|
||||||
None => 8,
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -46,24 +46,15 @@ pub enum Color {
|
|||||||
AnsiValue(u8),
|
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 {
|
impl FromStr for Color {
|
||||||
type Err = ();
|
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> {
|
fn from_str(src: &str) -> ::std::result::Result<Self, Self::Err> {
|
||||||
let src = src.to_lowercase();
|
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));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -37,12 +37,12 @@ impl Display for Colored {
|
|||||||
let colored_terminal = color();
|
let colored_terminal = color();
|
||||||
|
|
||||||
match *self {
|
match *self {
|
||||||
Colored::Fg(color) => {
|
Colored::Fg(color) => colored_terminal
|
||||||
colored_terminal.set_fg(color).unwrap();
|
.set_fg(color)
|
||||||
}
|
.map_err(|_| std::fmt::Error)?,
|
||||||
Colored::Bg(color) => {
|
Colored::Bg(color) => colored_terminal
|
||||||
colored_terminal.set_bg(color).unwrap();
|
.set_bg(color)
|
||||||
}
|
.map_err(|_| std::fmt::Error)?,
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -1,34 +1,32 @@
|
|||||||
macro_rules! def_attr {
|
macro_rules! def_attr {
|
||||||
($name: ident => $attr: path) => {
|
($name:ident => $attr:path) => {
|
||||||
fn $name(self) -> StyledObject<D> {
|
fn $name(self) -> StyledObject<D> {
|
||||||
let so = self;
|
self.attr($attr)
|
||||||
|
|
||||||
so.attr($attr)
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
macro_rules! def_color {
|
macro_rules! def_color {
|
||||||
($side:ident: $name: ident => $color: path) => {
|
($side:ident: $name:ident => $color:path) => {
|
||||||
fn $name(self) -> StyledObject<D> {
|
fn $name(self) -> StyledObject<D> {
|
||||||
StyledObject {
|
StyledObject {
|
||||||
object_style: ObjectStyle {
|
object_style: ObjectStyle {
|
||||||
$side: Some($color),
|
$side: Some($color),
|
||||||
.. self.object_style
|
..self.object_style
|
||||||
},
|
},
|
||||||
.. self
|
..self
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
macro_rules! def_str_color {
|
macro_rules! def_str_color {
|
||||||
($side:ident: $name: ident => $color: path) => {
|
($side:ident: $name:ident => $color:path) => {
|
||||||
fn $name(self) -> StyledObject< &'static str> {
|
fn $name(self) -> StyledObject< &'static str> {
|
||||||
StyledObject {
|
StyledObject {
|
||||||
object_style: ObjectStyle {
|
object_style: ObjectStyle {
|
||||||
$side: Some($color),
|
$side: Some($color),
|
||||||
.. ObjectStyle::default()
|
..Default::default()
|
||||||
},
|
},
|
||||||
content: self
|
content: self
|
||||||
}
|
}
|
||||||
@ -37,12 +35,12 @@ macro_rules! def_str_color {
|
|||||||
}
|
}
|
||||||
|
|
||||||
macro_rules! def_str_attr {
|
macro_rules! def_str_attr {
|
||||||
($name: ident => $color: path) => {
|
($name:ident => $color:path) => {
|
||||||
fn $name(self) -> StyledObject<&'static str> {
|
fn $name(self) -> StyledObject<&'static str> {
|
||||||
StyledObject {
|
StyledObject {
|
||||||
object_style: ObjectStyle::default(),
|
object_style: Default::default(),
|
||||||
content: self
|
content: self,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,23 +5,13 @@ use std::fmt::Display;
|
|||||||
use super::{Attribute, Color, StyledObject};
|
use super::{Attribute, Color, StyledObject};
|
||||||
|
|
||||||
/// Struct that contains the style properties that can be applied to a displayable object.
|
/// 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 struct ObjectStyle {
|
||||||
pub fg_color: Option<Color>,
|
pub fg_color: Option<Color>,
|
||||||
pub bg_color: Option<Color>,
|
pub bg_color: Option<Color>,
|
||||||
pub attrs: Vec<Attribute>,
|
pub attrs: Vec<Attribute>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for ObjectStyle {
|
|
||||||
fn default() -> ObjectStyle {
|
|
||||||
ObjectStyle {
|
|
||||||
fg_color: None,
|
|
||||||
bg_color: None,
|
|
||||||
attrs: Vec::new(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ObjectStyle {
|
impl ObjectStyle {
|
||||||
/// Apply a `StyledObject` to the passed displayable object.
|
/// Apply a `StyledObject` to the passed displayable object.
|
||||||
pub fn apply_to<D: Display + Clone>(&self, val: D) -> StyledObject<D> {
|
pub fn apply_to<D: Display + Clone>(&self, val: D) -> StyledObject<D> {
|
||||||
@ -33,11 +23,7 @@ impl ObjectStyle {
|
|||||||
|
|
||||||
/// Get a new instance of `ObjectStyle`
|
/// Get a new instance of `ObjectStyle`
|
||||||
pub fn new() -> ObjectStyle {
|
pub fn new() -> ObjectStyle {
|
||||||
ObjectStyle {
|
ObjectStyle::default()
|
||||||
fg_color: None,
|
|
||||||
bg_color: None,
|
|
||||||
attrs: Vec::new(),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Set the background color of `ObjectStyle` to the passed color.
|
/// Set the background color of `ObjectStyle` to the passed color.
|
||||||
|
@ -55,11 +55,11 @@ impl<D: Display + Clone> Display for StyledObject<D> {
|
|||||||
let mut reset = false;
|
let mut reset = false;
|
||||||
|
|
||||||
if let Some(bg) = self.object_style.bg_color {
|
if let Some(bg) = self.object_style.bg_color {
|
||||||
queue!(f, SetBg(bg)).unwrap();
|
queue!(f, SetBg(bg)).map_err(|_| fmt::Error)?;
|
||||||
reset = true;
|
reset = true;
|
||||||
}
|
}
|
||||||
if let Some(fg) = self.object_style.fg_color {
|
if let Some(fg) = self.object_style.fg_color {
|
||||||
queue!(f, SetFg(fg)).unwrap();
|
queue!(f, SetFg(fg)).map_err(|_| fmt::Error)?;
|
||||||
reset = true;
|
reset = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -71,7 +71,7 @@ impl<D: Display + Clone> Display for StyledObject<D> {
|
|||||||
fmt::Display::fmt(&self.content, f)?;
|
fmt::Display::fmt(&self.content, f)?;
|
||||||
|
|
||||||
if reset {
|
if reset {
|
||||||
colored_terminal.reset().unwrap();
|
colored_terminal.reset().map_err(|_| fmt::Error)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -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.
|
/// This trait is implemented for `&static str` and `StyledObject` and thus the methods of this trait could be called on them.
|
||||||
///
|
///
|
||||||
/// ```ignore
|
/// ```rust
|
||||||
/// use Colorizer;
|
/// use crossterm_style::Colorize;
|
||||||
///
|
///
|
||||||
/// let styled_text = "Red forground color on blue background.".red().on_blue();
|
/// let styled_text = "Red forground color on blue background.".red().on_blue();
|
||||||
/// println!("{}", styled_text);
|
/// 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.
|
/// This trait is implemented for `&static str` and `StyledObject` and thus the methods of this trait could be called on them.
|
||||||
///
|
///
|
||||||
/// # Example
|
/// # Example
|
||||||
/// ```ignore
|
|
||||||
/// use Colorizer;
|
|
||||||
///
|
///
|
||||||
/// println!("{}", "Bold text".bold();
|
/// ```rust
|
||||||
/// println!("{}", "Underlined text".underlined();
|
/// use crossterm_style::Styler;
|
||||||
/// println!("{}", "Negative text".negative();
|
///
|
||||||
|
/// println!("{}", "Bold text".bold());
|
||||||
|
/// println!("{}", "Underlined text".underlined());
|
||||||
|
/// println!("{}", "Negative text".negative());
|
||||||
/// ```
|
/// ```
|
||||||
pub trait Styler<D: Display + Clone> {
|
pub trait Styler<D: Display + Clone> {
|
||||||
fn reset(self) -> StyledObject<D>;
|
fn reset(self) -> StyledObject<D>;
|
||||||
|
@ -44,7 +44,7 @@ impl ITerminalColor for WinApiColor {
|
|||||||
let mut color: u16;
|
let mut color: u16;
|
||||||
let attrs = csbi.attributes();
|
let attrs = csbi.attributes();
|
||||||
let bg_color = attrs & 0x0070;
|
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,
|
// background intensity is a separate value in attrs,
|
||||||
// wee need to check if this was applied to the current bg color.
|
// 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 mut color: u16;
|
||||||
let attrs = csbi.attributes();
|
let attrs = csbi.attributes();
|
||||||
let fg_color = attrs & 0x0007;
|
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,
|
// Foreground intensity is a separate value in attrs,
|
||||||
// So we need to check if this was applied to the current fg color.
|
// So we need to check if this was applied to the current fg color.
|
||||||
|
@ -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_FROM_CURRENT_LINE: &'static str = csi!("2K");
|
||||||
pub static CLEAR_UNTIL_NEW_LINE: &'static str = csi!("K");
|
pub static CLEAR_UNTIL_NEW_LINE: &'static str = csi!("K");
|
||||||
|
|
||||||
#[inline]
|
|
||||||
pub fn get_scroll_up_ansi(count: u16) -> String {
|
pub fn get_scroll_up_ansi(count: u16) -> String {
|
||||||
format!(csi!("{}S"), count)
|
format!(csi!("{}S"), count)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
|
||||||
pub fn get_scroll_down_ansi(count: u16) -> String {
|
pub fn get_scroll_down_ansi(count: u16) -> String {
|
||||||
format!(csi!("{}T"), count)
|
format!(csi!("{}T"), count)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
|
||||||
pub fn get_set_size_ansi(width: u16, height: u16) -> String {
|
pub fn get_set_size_ansi(width: u16, height: u16) -> String {
|
||||||
format!(csi!("8;{};{}t"), height, width)
|
format!(csi!("8;{};{}t"), height, width)
|
||||||
}
|
}
|
||||||
|
@ -5,6 +5,8 @@ use std::{
|
|||||||
io,
|
io,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
use crate::impl_from;
|
||||||
|
|
||||||
/// The `crossterm` result type.
|
/// The `crossterm` result type.
|
||||||
pub type Result<T> = std::result::Result<T, ErrorKind>;
|
pub type Result<T> = std::result::Result<T, ErrorKind>;
|
||||||
|
|
||||||
@ -23,8 +25,11 @@ pub enum ErrorKind {
|
|||||||
|
|
||||||
impl std::error::Error for ErrorKind {
|
impl std::error::Error for ErrorKind {
|
||||||
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
|
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
|
||||||
match *self {
|
match self {
|
||||||
ErrorKind::IoError(ref e) => Some(e),
|
ErrorKind::IoError(e) => Some(e),
|
||||||
|
ErrorKind::FmtError(e) => Some(e),
|
||||||
|
ErrorKind::Utf8Error(e) => Some(e),
|
||||||
|
ErrorKind::ParseIntError(e) => Some(e),
|
||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -40,26 +45,7 @@ impl Display for ErrorKind {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<io::Error> for ErrorKind {
|
impl_from!(io::Error, ErrorKind::IoError);
|
||||||
fn from(e: io::Error) -> ErrorKind {
|
impl_from!(fmt::Error, ErrorKind::FmtError);
|
||||||
ErrorKind::IoError(e)
|
impl_from!(std::string::FromUtf8Error, ErrorKind::Utf8Error);
|
||||||
}
|
impl_from!(std::num::ParseIntError, ErrorKind::ParseIntError);
|
||||||
}
|
|
||||||
|
|
||||||
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)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
@ -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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
@ -9,7 +9,7 @@ use crate::{ErrorKind, Result};
|
|||||||
static mut ORIGINAL_TERMINAL_MODE: Option<Termios> = None;
|
static mut ORIGINAL_TERMINAL_MODE: Option<Termios> = None;
|
||||||
pub static mut RAW_MODE_ENABLED: bool = false;
|
pub static mut RAW_MODE_ENABLED: bool = false;
|
||||||
|
|
||||||
fn unwrap(t: i32) -> Result<()> {
|
fn wrap_with_result(t: i32) -> Result<()> {
|
||||||
if t == -1 {
|
if t == -1 {
|
||||||
Err(ErrorKind::IoError(io::Error::last_os_error()))
|
Err(ErrorKind::IoError(io::Error::last_os_error()))
|
||||||
} else {
|
} else {
|
||||||
@ -31,7 +31,7 @@ pub fn get_terminal_attr() -> Result<Termios> {
|
|||||||
}
|
}
|
||||||
unsafe {
|
unsafe {
|
||||||
let mut termios = mem::zeroed();
|
let mut termios = mem::zeroed();
|
||||||
unwrap(tcgetattr(0, &mut termios))?;
|
wrap_with_result(tcgetattr(0, &mut termios))?;
|
||||||
Ok(termios)
|
Ok(termios)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -40,7 +40,7 @@ pub fn set_terminal_attr(termios: &Termios) -> Result<()> {
|
|||||||
extern "C" {
|
extern "C" {
|
||||||
pub fn tcsetattr(fd: c_int, opt: c_int, termptr: *const Termios) -> c_int;
|
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<()> {
|
pub fn into_raw_mode() -> Result<()> {
|
||||||
@ -61,9 +61,8 @@ pub fn into_raw_mode() -> Result<()> {
|
|||||||
|
|
||||||
pub fn disable_raw_mode() -> Result<()> {
|
pub fn disable_raw_mode() -> Result<()> {
|
||||||
unsafe {
|
unsafe {
|
||||||
if ORIGINAL_TERMINAL_MODE.is_some() {
|
if let Some(original_terminal_mode) = ORIGINAL_TERMINAL_MODE.as_ref() {
|
||||||
set_terminal_attr(&ORIGINAL_TERMINAL_MODE.unwrap())?;
|
set_terminal_attr(original_terminal_mode)?;
|
||||||
|
|
||||||
RAW_MODE_ENABLED = false;
|
RAW_MODE_ENABLED = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -24,11 +24,11 @@ pub mod ansi {
|
|||||||
} else {
|
} else {
|
||||||
old_mode & !mask
|
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(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -76,7 +76,7 @@ impl From<Handle> for ConsoleMode {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod test {
|
mod tests {
|
||||||
use super::ConsoleMode;
|
use super::ConsoleMode;
|
||||||
|
|
||||||
// TODO - Test is ignored, because it's failing on Travis CI
|
// TODO - Test is ignored, because it's failing on Travis CI
|
||||||
|
@ -175,7 +175,7 @@ impl From<HANDLE> for Handle {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod test {
|
mod tests {
|
||||||
use super::{Handle, HandleType};
|
use super::{Handle, HandleType};
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -122,7 +122,7 @@ impl From<HANDLE> for ScreenBuffer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod test {
|
mod tests {
|
||||||
use super::ScreenBuffer;
|
use super::ScreenBuffer;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -20,7 +20,7 @@ fn main() -> Result<()> {
|
|||||||
|
|
||||||
/// run the program
|
/// run the program
|
||||||
fn run() -> Result<()> {
|
fn run() -> Result<()> {
|
||||||
// let screen = RawScreen::into_raw_mode().expect("failed to enable raw modes");
|
// let screen = RawScreen::into_raw_mode()?;
|
||||||
print_welcome_screen()?;
|
print_welcome_screen()?;
|
||||||
start_algorithm()?;
|
start_algorithm()?;
|
||||||
exit()
|
exit()
|
||||||
@ -90,7 +90,7 @@ fn print_welcome_screen() -> Result<()> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn exit() -> Result<()> {
|
fn exit() -> Result<()> {
|
||||||
RawScreen::disable_raw_mode().expect("Failed to disable raw modes.");
|
RawScreen::disable_raw_mode()?;
|
||||||
cursor().show()?;
|
cursor().show()?;
|
||||||
color().reset()
|
color().reset()
|
||||||
}
|
}
|
||||||
|
@ -399,7 +399,7 @@ fn print_text_with_attributes() {
|
|||||||
|
|
||||||
/// Print all supported RGB colors, not supported for Windows systems < 10 | demonstration.
|
/// Print all supported RGB colors, not supported for Windows systems < 10 | demonstration.
|
||||||
fn print_supported_colors() {
|
fn print_supported_colors() {
|
||||||
let count = color().get_available_color_count().unwrap();
|
let count = color().get_available_color_count();
|
||||||
|
|
||||||
for i in 0..count {
|
for i in 0..count {
|
||||||
println!("Test {}", Colored::Bg(Color::AnsiValue(i as u8)));
|
println!("Test {}", Colored::Bg(Color::AnsiValue(i as u8)));
|
||||||
|
Loading…
Reference in New Issue
Block a user