Return written bytes (#212)

* `write_cout!` returns number of written bytes
* `Terminal::write` returns number of written bytes (result of `write_cout!`)
* `execute!` macro is a bit simpler
* Remove unused `std::io::Write` imports
This commit is contained in:
Zrzka 2019-09-14 16:42:42 +02:00 committed by Timon
parent 6c320b1c16
commit be05974b70
13 changed files with 49 additions and 66 deletions

View File

@ -1,11 +1,17 @@
//! //!
//! Examples of actions that could be performed with the cursor. //! Examples of actions that could be performed with the cursor.
//! //!
#![allow(unused_must_use, dead_code)]
extern crate crossterm_cursor; extern crate crossterm_cursor;
use std::io::Write;
use std::time::Instant;
use crossterm_cursor::cursor; use crossterm_cursor::cursor;
use self::crossterm_cursor::{queue, Goto, Hide, Output, QueueableCommand};
/// Set the cursor to position X: 10, Y: 5 in the terminal. /// Set the cursor to position X: 10, Y: 5 in the terminal.
pub fn goto() { pub fn goto() {
// Get the cursor // Get the cursor
@ -86,20 +92,11 @@ pub fn blink_cursor() {
cursor.blink(false); cursor.blink(false);
} }
use self::crossterm_cursor::{
execute, queue, BlinkOff, BlinkOn, Command, Down, ExecutableCommand, Goto, Hide, Left, Output,
QueueableCommand, ResetPos, Right, SavePos, Show, Up,
};
use std::fmt::Display;
use std::io::{stdout, Write};
use std::thread;
use std::time::{Duration, Instant};
fn benchmark_cursor_goto() -> f32 { fn benchmark_cursor_goto() -> f32 {
let mut stdout = ::std::io::stdout(); let mut stdout = ::std::io::stdout();
let instant1 = Instant::now(); let instant1 = Instant::now();
for i in 0..10 { for _ in 0..10 {
for x in 0..200 { for x in 0..200 {
for y in 0..50 { for y in 0..50 {
queue!(stdout, Goto(x, y), Hide, Output(y.to_string())); queue!(stdout, Goto(x, y), Hide, Output(y.to_string()));
@ -110,7 +107,7 @@ fn benchmark_cursor_goto() -> f32 {
let new_api = instant1.elapsed(); let new_api = instant1.elapsed();
let cursor = cursor(); let cursor = cursor();
let instant2 = Instant::now(); let instant2 = Instant::now();
for i in 0..10 { for _ in 0..10 {
for x in 0..200 { for x in 0..200 {
for y in 0..50 { for y in 0..50 {
cursor.goto(x, y); cursor.goto(x, y);
@ -128,10 +125,8 @@ fn benchmark_cursor_goto() -> f32 {
} }
fn start_goto_benchmark() { fn start_goto_benchmark() {
let mut stdout = ::std::io::stdout();
let mut performance_metrics = Vec::new(); let mut performance_metrics = Vec::new();
for i in 1..=20 { for _ in 1..=20 {
performance_metrics.push(benchmark_cursor_goto()); performance_metrics.push(benchmark_cursor_goto());
} }
@ -142,7 +137,7 @@ fn start_goto_benchmark() {
} }
fn main() { fn main() {
let mut stdout = ::std::io::stdout(); let stdout = ::std::io::stdout();
stdout stdout
.queue(Goto(5, 5)) .queue(Goto(5, 5))

View File

@ -4,7 +4,6 @@
use super::ITerminalCursor; use super::ITerminalCursor;
use crate::sys::{get_cursor_position, show_cursor}; use crate::sys::{get_cursor_position, show_cursor};
use std::io::Write;
use crossterm_utils::{write_cout, Result}; use crossterm_utils::{write_cout, Result};

View File

@ -1,3 +1,4 @@
#![allow(unused_must_use)]
use super::AnsiCursor; use super::AnsiCursor;
use super::ITerminalCursor; use super::ITerminalCursor;

View File

@ -1,16 +1,16 @@
//! This is a UNIX specific implementation for input related action. //! This is a UNIX specific implementation for input related action.
use super::*;
use crate::sys::unix::{get_tty, read_char_raw};
use crossterm_utils::{csi, write_cout, ErrorKind, Result};
use std::char; use std::char;
use std::sync::atomic::{AtomicBool, Ordering}; use std::sync::atomic::{AtomicBool, Ordering};
use std::{ use std::{io::Read, str};
io::{Read, Write},
str,
};
use std::{sync::mpsc, thread}; use std::{sync::mpsc, thread};
use crossterm_utils::{csi, write_cout, ErrorKind, Result};
use crate::sys::unix::{get_tty, read_char_raw};
use super::*;
pub struct UnixInput; pub struct UnixInput;
impl UnixInput { impl UnixInput {

View File

@ -1,5 +1,3 @@
use std::io::Write;
use crossterm_utils::{csi, write_cout, Result}; use crossterm_utils::{csi, write_cout, Result};
#[cfg(unix)] #[cfg(unix)]

View File

@ -1,11 +1,10 @@
//! This is a ANSI specific implementation for styling related action. //! This is a ANSI specific implementation for styling related action.
//! This module is used for Windows 10 terminals and Unix terminals by default. //! This module is used for Windows 10 terminals and Unix terminals by default.
use std::io::Write;
use crossterm_utils::{csi, write_cout, Result}; use crossterm_utils::{csi, write_cout, Result};
use crate::{Attribute, Color, Colored, ITerminalColor}; use crate::Colored;
use crate::{Attribute, Color, ITerminalColor};
#[inline] #[inline]
pub fn get_set_fg_ansi(fg_color: Color) -> String { pub fn get_set_fg_ansi(fg_color: Color) -> String {

View File

@ -16,7 +16,7 @@ use serde::{Deserialize, Serialize};
/// # Example /// # Example
/// You can use an attribute in a write statement to apply the attribute to the terminal output. /// You can use an attribute in a write statement to apply the attribute to the terminal output.
/// ///
/// ```rust /// ```ignore
/// println!( /// println!(
/// "{} Underlined {} No Underline", /// "{} Underlined {} No Underline",
/// Attribute::Underlined, /// Attribute::Underlined,
@ -25,8 +25,8 @@ use serde::{Deserialize, Serialize};
/// ``` /// ```
/// ///
/// You can also call attribute functions on a `&'static str`: /// You can also call attribute functions on a `&'static str`:
/// ```rust /// ```ignore
/// use crossterm(_style)::Colorizer; /// use Colorizer;
/// ///
/// println!("{}", style("Bold text").bold()); /// println!("{}", style("Bold text").bold());
/// println!("{}", style("Underlined text").underlined()); /// println!("{}", style("Underlined text").underlined());

View File

@ -15,14 +15,13 @@ use crate::enums::Color;
/// ///
/// You can use `Colored` in a write statement to apply the attribute to the terminal output. /// You can use `Colored` in a write statement to apply the attribute to the terminal output.
/// ///
/// ```rust /// ```ignore
/// println!("{} Red foreground color", Colored::Fg(Color::Red)); /// println!("{} Red foreground color", Colored::Fg(Color::Red));
/// println!("{} Blue background color", Colored::Bg(Color::Blue)); /// println!("{} Blue background color", Colored::Bg(Color::Blue));
/// ``` /// ```
/// ///
/// You can also call coloring functions on a `&'static str`: /// You can also call coloring functions on a `&'static str`:
/// ```rust /// ```ignore
/// use crossterm(_style)::Colorizer;
/// 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);
/// ``` /// ```

View File

@ -46,7 +46,7 @@ trait ITerminalColor {
/// This could be used to style a type that implements `Display` with colors and attributes. /// This could be used to style a type that implements `Display` with colors and attributes.
/// ///
/// # Example /// # Example
/// ```rust /// ```ignore
/// // get a styled object which could be painted to the terminal. /// // get a styled object which could be painted to the terminal.
/// let styled_object = style("Some Blue colored text on black background") /// let styled_object = style("Some Blue colored text on black background")
/// .with(Color::Blue) /// .with(Color::Blue)

View File

@ -6,7 +6,7 @@ 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.
/// ///
/// ``` rust /// ```ignore
/// use Colorizer; /// use Colorizer;
/// ///
/// let styled_text = "Red forground color on blue background.".red().on_blue(); /// let styled_text = "Red forground color on blue background.".red().on_blue();
@ -53,7 +53,7 @@ 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
/// ``` rust /// ```ignore
/// use Colorizer; /// use Colorizer;
/// ///
/// println!("{}", "Bold text".bold(); /// println!("{}", "Bold text".bold();

View File

@ -1,8 +1,6 @@
//! This is an `ANSI escape code` specific implementation for terminal related action. //! This is an `ANSI escape code` specific implementation for terminal related action.
//! This module is used for windows 10 terminals and unix terminals by default. //! This module is used for windows 10 terminals and unix terminals by default.
use std::io::Write;
use crossterm_cursor::TerminalCursor; use crossterm_cursor::TerminalCursor;
use crossterm_utils::{csi, write_cout, Result}; use crossterm_utils::{csi, write_cout, Result};

View File

@ -2,7 +2,6 @@
//! Like clearing and scrolling in the terminal or getting the window size from the terminal. //! Like clearing and scrolling in the terminal or getting the window size from the terminal.
use std::fmt; use std::fmt;
use std::io::Write;
#[cfg(windows)] #[cfg(windows)]
use crossterm_utils::supports_ansi; use crossterm_utils::supports_ansi;
@ -131,8 +130,7 @@ impl Terminal {
/// ///
/// This will also flush the standard output. /// This will also flush the standard output.
pub fn write<D: fmt::Display>(&self, value: D) -> Result<usize> { pub fn write<D: fmt::Display>(&self, value: D) -> Result<usize> {
write_cout!(format!("{}", value))?; write_cout!(format!("{}", value))
Ok(0)
} }
} }

View File

@ -10,16 +10,19 @@ macro_rules! write_cout {
($write:expr, $string:expr) => {{ ($write:expr, $string:expr) => {{
use $crate::ErrorKind; use $crate::ErrorKind;
if let Err(e) = write!($write, "{}", $string) { let fmt = format!("{}", $string);
Err(ErrorKind::IoError(e)) let bytes = fmt.as_bytes();
} else {
match $write.flush() { $write
Ok(size) => Ok(size), .write_all(bytes)
Err(e) => Err(ErrorKind::IoError(e)), .and_then(|_| $write.flush().map(|_| bytes.len()))
} .map_err(ErrorKind::IoError)
}
}}; }};
($string:expr) => {{ ($string:expr) => {{
// Bring Write into the scope and ignore unused imports if it's
// already imported by the user
#[allow(unused_imports)]
use std::io::Write;
write_cout!(::std::io::stdout(), $string) write_cout!(::std::io::stdout(), $string)
}}; }};
} }
@ -151,32 +154,25 @@ macro_rules! execute {
#[cfg(windows)] #[cfg(windows)]
{ {
if $crate::supports_ansi() { if $crate::supports_ansi() {
match write_cout!($write, $command.get_ansi_code()) { if let Err(e) = write_cout!($write, $command.get_ansi_code()) {
Err(e) => { error = Some($crate::ErrorKind::from(e));
error = Some(Err($crate::ErrorKind::from(e)));
}
_ => {}
}; };
} else { } else {
match $command.execute_winapi() { if let Err(e) = $command.execute_winapi() {
Err(e) => { error = Some($crate::ErrorKind::from(e));
error = Some(Err($crate::ErrorKind::from(e)));
}
_ => {}
}; };
}; };
} }
#[cfg(unix)] #[cfg(unix)]
match write_cout!($write, $command.get_ansi_code()) { {
Err(e) => { if let Err(e) = write_cout!($write, $command.get_ansi_code()) {
error = Some(Err($crate::ErrorKind::from(e))); error = Some($crate::ErrorKind::from(e));
}
} }
_ => {}
};
)* )*
if let Some(error) = error { if let Some(error) = error {
error Err(error)
} else { } else {
Ok(()) Ok(())
} }