Unwrap crossterm::Result<T, ErrorKind>  to std::io::Result. (#765)
				
					
				
			This commit is contained in:
		
							parent
							
								
									41901c6382
								
							
						
					
					
						commit
						a2c9350ff2
					
				@ -109,7 +109,7 @@ use crossterm::{
 | 
			
		||||
    event,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
fn main() -> Result<()> {
 | 
			
		||||
fn main() -> std::io::Result<()> {
 | 
			
		||||
    // using the macro
 | 
			
		||||
    execute!(
 | 
			
		||||
        stdout(),
 | 
			
		||||
 | 
			
		||||
@ -2,14 +2,13 @@
 | 
			
		||||
//!
 | 
			
		||||
//! cargo run --example event-poll-read
 | 
			
		||||
 | 
			
		||||
use std::{io::stdout, time::Duration};
 | 
			
		||||
use std::{io, time::Duration};
 | 
			
		||||
 | 
			
		||||
use crossterm::{
 | 
			
		||||
    cursor::position,
 | 
			
		||||
    event::{poll, read, DisableMouseCapture, EnableMouseCapture, Event, KeyCode},
 | 
			
		||||
    execute,
 | 
			
		||||
    terminal::{disable_raw_mode, enable_raw_mode},
 | 
			
		||||
    Result,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const HELP: &str = r#"Blocking poll() & non-blocking read()
 | 
			
		||||
@ -19,7 +18,7 @@ const HELP: &str = r#"Blocking poll() & non-blocking read()
 | 
			
		||||
 - Use Esc to quit
 | 
			
		||||
"#;
 | 
			
		||||
 | 
			
		||||
fn print_events() -> Result<()> {
 | 
			
		||||
fn print_events() -> io::Result<()> {
 | 
			
		||||
    loop {
 | 
			
		||||
        // Wait up to 1s for another event
 | 
			
		||||
        if poll(Duration::from_millis(1_000))? {
 | 
			
		||||
@ -44,12 +43,12 @@ fn print_events() -> Result<()> {
 | 
			
		||||
    Ok(())
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fn main() -> Result<()> {
 | 
			
		||||
fn main() -> io::Result<()> {
 | 
			
		||||
    println!("{}", HELP);
 | 
			
		||||
 | 
			
		||||
    enable_raw_mode()?;
 | 
			
		||||
 | 
			
		||||
    let mut stdout = stdout();
 | 
			
		||||
    let mut stdout = io::stdout();
 | 
			
		||||
    execute!(stdout, EnableMouseCapture)?;
 | 
			
		||||
 | 
			
		||||
    if let Err(e) = print_events() {
 | 
			
		||||
 | 
			
		||||
@ -3,12 +3,11 @@
 | 
			
		||||
//!
 | 
			
		||||
//! cargo run --example event-read-char-line
 | 
			
		||||
 | 
			
		||||
use crossterm::{
 | 
			
		||||
    event::{self, Event, KeyCode, KeyEvent},
 | 
			
		||||
    Result,
 | 
			
		||||
};
 | 
			
		||||
use std::io;
 | 
			
		||||
 | 
			
		||||
pub fn read_char() -> Result<char> {
 | 
			
		||||
use crossterm::event::{self, Event, KeyCode, KeyEvent};
 | 
			
		||||
 | 
			
		||||
pub fn read_char() -> io::Result<char> {
 | 
			
		||||
    loop {
 | 
			
		||||
        if let Event::Key(KeyEvent {
 | 
			
		||||
            code: KeyCode::Char(c),
 | 
			
		||||
@ -20,7 +19,7 @@ pub fn read_char() -> Result<char> {
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub fn read_line() -> Result<String> {
 | 
			
		||||
pub fn read_line() -> io::Result<String> {
 | 
			
		||||
    let mut line = String::new();
 | 
			
		||||
    while let Event::Key(KeyEvent { code, .. }) = event::read()? {
 | 
			
		||||
        match code {
 | 
			
		||||
 | 
			
		||||
@ -2,7 +2,7 @@
 | 
			
		||||
//!
 | 
			
		||||
//! cargo run --example event-read
 | 
			
		||||
 | 
			
		||||
use std::io::stdout;
 | 
			
		||||
use std::io;
 | 
			
		||||
 | 
			
		||||
use crossterm::event::{
 | 
			
		||||
    poll, KeyboardEnhancementFlags, PopKeyboardEnhancementFlags, PushKeyboardEnhancementFlags,
 | 
			
		||||
@ -15,7 +15,6 @@ use crossterm::{
 | 
			
		||||
    },
 | 
			
		||||
    execute, queue,
 | 
			
		||||
    terminal::{disable_raw_mode, enable_raw_mode},
 | 
			
		||||
    Result,
 | 
			
		||||
};
 | 
			
		||||
use std::time::Duration;
 | 
			
		||||
 | 
			
		||||
@ -25,7 +24,7 @@ const HELP: &str = r#"Blocking read()
 | 
			
		||||
 - Use Esc to quit
 | 
			
		||||
"#;
 | 
			
		||||
 | 
			
		||||
fn print_events() -> Result<()> {
 | 
			
		||||
fn print_events() -> io::Result<()> {
 | 
			
		||||
    loop {
 | 
			
		||||
        // Blocking read
 | 
			
		||||
        let event = read()?;
 | 
			
		||||
@ -63,12 +62,12 @@ fn flush_resize_events(first_resize: (u16, u16)) -> ((u16, u16), (u16, u16)) {
 | 
			
		||||
    (first_resize, last_resize)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fn main() -> Result<()> {
 | 
			
		||||
fn main() -> io::Result<()> {
 | 
			
		||||
    println!("{}", HELP);
 | 
			
		||||
 | 
			
		||||
    enable_raw_mode()?;
 | 
			
		||||
 | 
			
		||||
    let mut stdout = stdout();
 | 
			
		||||
    let mut stdout = io::stdout();
 | 
			
		||||
 | 
			
		||||
    let supports_keyboard_enhancement = matches!(
 | 
			
		||||
        crossterm::terminal::supports_keyboard_enhancement(),
 | 
			
		||||
 | 
			
		||||
@ -12,7 +12,6 @@ use crossterm::{
 | 
			
		||||
    event::{DisableMouseCapture, EnableMouseCapture, Event, EventStream, KeyCode},
 | 
			
		||||
    execute,
 | 
			
		||||
    terminal::{disable_raw_mode, enable_raw_mode},
 | 
			
		||||
    Result,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const HELP: &str = r#"EventStream based on futures_util::stream::Stream with async-std
 | 
			
		||||
@ -52,7 +51,7 @@ async fn print_events() {
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fn main() -> Result<()> {
 | 
			
		||||
fn main() -> std::io::Result<()> {
 | 
			
		||||
    println!("{}", HELP);
 | 
			
		||||
 | 
			
		||||
    enable_raw_mode()?;
 | 
			
		||||
 | 
			
		||||
@ -12,7 +12,6 @@ use crossterm::{
 | 
			
		||||
    event::{DisableMouseCapture, EnableMouseCapture, Event, EventStream, KeyCode},
 | 
			
		||||
    execute,
 | 
			
		||||
    terminal::{disable_raw_mode, enable_raw_mode},
 | 
			
		||||
    Result,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const HELP: &str = r#"EventStream based on futures_util::Stream with tokio
 | 
			
		||||
@ -53,7 +52,7 @@ async fn print_events() {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[tokio::main]
 | 
			
		||||
async fn main() -> Result<()> {
 | 
			
		||||
async fn main() -> std::io::Result<()> {
 | 
			
		||||
    println!("{}", HELP);
 | 
			
		||||
 | 
			
		||||
    enable_raw_mode()?;
 | 
			
		||||
 | 
			
		||||
@ -1,6 +1,6 @@
 | 
			
		||||
#![allow(clippy::cognitive_complexity)]
 | 
			
		||||
 | 
			
		||||
use std::io::{self, Write};
 | 
			
		||||
use std::io;
 | 
			
		||||
 | 
			
		||||
use crossterm::event::KeyEventKind;
 | 
			
		||||
pub use crossterm::{
 | 
			
		||||
@ -8,7 +8,7 @@ pub use crossterm::{
 | 
			
		||||
    event::{self, Event, KeyCode, KeyEvent},
 | 
			
		||||
    execute, queue, style,
 | 
			
		||||
    terminal::{self, ClearType},
 | 
			
		||||
    Command, Result,
 | 
			
		||||
    Command,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#[macro_use]
 | 
			
		||||
@ -33,9 +33,9 @@ Available tests:
 | 
			
		||||
Select test to run ('1', '2', ...) or hit 'q' to quit.
 | 
			
		||||
"#;
 | 
			
		||||
 | 
			
		||||
fn run<W>(w: &mut W) -> Result<()>
 | 
			
		||||
fn run<W>(w: &mut W) -> io::Result<()>
 | 
			
		||||
where
 | 
			
		||||
    W: Write,
 | 
			
		||||
    W: io::Write,
 | 
			
		||||
{
 | 
			
		||||
    execute!(w, terminal::EnterAlternateScreen)?;
 | 
			
		||||
 | 
			
		||||
@ -80,7 +80,7 @@ where
 | 
			
		||||
    terminal::disable_raw_mode()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub fn read_char() -> Result<char> {
 | 
			
		||||
pub fn read_char() -> std::io::Result<char> {
 | 
			
		||||
    loop {
 | 
			
		||||
        if let Ok(Event::Key(KeyEvent {
 | 
			
		||||
            code: KeyCode::Char(c),
 | 
			
		||||
@ -94,11 +94,11 @@ pub fn read_char() -> Result<char> {
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub fn buffer_size() -> Result<(u16, u16)> {
 | 
			
		||||
pub fn buffer_size() -> io::Result<(u16> {
 | 
			
		||||
    terminal::size()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fn main() -> Result<()> {
 | 
			
		||||
fn main() -> std::io::Result<()> {
 | 
			
		||||
    let mut stdout = io::stdout();
 | 
			
		||||
    run(&mut stdout)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -21,7 +21,7 @@ const ATTRIBUTES: [(style::Attribute, style::Attribute); 10] = [
 | 
			
		||||
    (style::Attribute::SlowBlink, style::Attribute::NoBlink),
 | 
			
		||||
];
 | 
			
		||||
 | 
			
		||||
fn test_set_display_attributes<W>(w: &mut W) -> Result<()>
 | 
			
		||||
fn test_set_display_attributes<W>(w: &mut W) -> std::io::Result<()>
 | 
			
		||||
where
 | 
			
		||||
    W: Write,
 | 
			
		||||
{
 | 
			
		||||
@ -48,7 +48,7 @@ where
 | 
			
		||||
    Ok(())
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub fn run<W>(w: &mut W) -> Result<()>
 | 
			
		||||
pub fn run<W>(w: &mut W) -> std::io::Result<()>
 | 
			
		||||
where
 | 
			
		||||
    W: Write,
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
@ -28,7 +28,7 @@ const COLORS: [Color; 21] = [
 | 
			
		||||
    Color::Rgb { r: 0, g: 0, b: 255 },
 | 
			
		||||
];
 | 
			
		||||
 | 
			
		||||
fn test_set_foreground_color<W>(w: &mut W) -> Result<()>
 | 
			
		||||
fn test_set_foreground_color<W>(w: &mut W) -> std::io::Result<()>
 | 
			
		||||
where
 | 
			
		||||
    W: Write,
 | 
			
		||||
{
 | 
			
		||||
@ -63,7 +63,7 @@ where
 | 
			
		||||
    Ok(())
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fn test_set_background_color<W>(w: &mut W) -> Result<()>
 | 
			
		||||
fn test_set_background_color<W>(w: &mut W) -> std::io::Result<()>
 | 
			
		||||
where
 | 
			
		||||
    W: Write,
 | 
			
		||||
{
 | 
			
		||||
@ -98,7 +98,7 @@ where
 | 
			
		||||
    Ok(())
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fn test_color_values_matrix_16x16<W, F>(w: &mut W, title: &str, color: F) -> Result<()>
 | 
			
		||||
fn test_color_values_matrix_16x16<W, F>(w: &mut W, title: &str, color: F) -> std::io::Result<()>
 | 
			
		||||
where
 | 
			
		||||
    W: Write,
 | 
			
		||||
    F: Fn(u16, u16) -> Color,
 | 
			
		||||
@ -140,7 +140,7 @@ where
 | 
			
		||||
    Ok(())
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fn test_color_ansi_values<W>(w: &mut W) -> Result<()>
 | 
			
		||||
fn test_color_ansi_values<W>(w: &mut W) -> std::io::Result<()>
 | 
			
		||||
where
 | 
			
		||||
    W: Write,
 | 
			
		||||
{
 | 
			
		||||
@ -149,7 +149,7 @@ where
 | 
			
		||||
    })
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fn test_rgb_red_values<W>(w: &mut W) -> Result<()>
 | 
			
		||||
fn test_rgb_red_values<W>(w: &mut W) -> std::io::Result<()>
 | 
			
		||||
where
 | 
			
		||||
    W: Write,
 | 
			
		||||
{
 | 
			
		||||
@ -160,7 +160,7 @@ where
 | 
			
		||||
    })
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fn test_rgb_green_values<W>(w: &mut W) -> Result<()>
 | 
			
		||||
fn test_rgb_green_values<W>(w: &mut W) -> std::io::Result<()>
 | 
			
		||||
where
 | 
			
		||||
    W: Write,
 | 
			
		||||
{
 | 
			
		||||
@ -171,7 +171,7 @@ where
 | 
			
		||||
    })
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fn test_rgb_blue_values<W>(w: &mut W) -> Result<()>
 | 
			
		||||
fn test_rgb_blue_values<W>(w: &mut W) -> std::io::Result<()>
 | 
			
		||||
where
 | 
			
		||||
    W: Write,
 | 
			
		||||
{
 | 
			
		||||
@ -182,7 +182,7 @@ where
 | 
			
		||||
    })
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub fn run<W>(w: &mut W) -> Result<()>
 | 
			
		||||
pub fn run<W>(w: &mut W) -> std::io::Result<()>
 | 
			
		||||
where
 | 
			
		||||
    W: Write,
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
@ -2,40 +2,39 @@
 | 
			
		||||
 | 
			
		||||
use std::io::Write;
 | 
			
		||||
 | 
			
		||||
use crate::Result;
 | 
			
		||||
use crossterm::{cursor, execute, queue, style, Command, style::Stylize};
 | 
			
		||||
use std::thread;
 | 
			
		||||
use std::time::Duration;
 | 
			
		||||
 | 
			
		||||
fn test_move_cursor_up<W>(w: &mut W) -> Result<()>
 | 
			
		||||
fn test_move_cursor_up<W>(w: &mut W) -> std::io::Result<()>
 | 
			
		||||
where
 | 
			
		||||
    W: Write,
 | 
			
		||||
{
 | 
			
		||||
    draw_cursor_box(w, "Move Up (2)", |_, _| cursor::MoveUp(2))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fn test_move_cursor_down<W>(w: &mut W) -> Result<()>
 | 
			
		||||
fn test_move_cursor_down<W>(w: &mut W) -> std::io::Result<()>
 | 
			
		||||
where
 | 
			
		||||
    W: Write,
 | 
			
		||||
{
 | 
			
		||||
    draw_cursor_box(w, "Move Down (2)", |_, _| cursor::MoveDown(2))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fn test_move_cursor_left<W>(w: &mut W) -> Result<()>
 | 
			
		||||
fn test_move_cursor_left<W>(w: &mut W) -> std::io::Result<()>
 | 
			
		||||
where
 | 
			
		||||
    W: Write,
 | 
			
		||||
{
 | 
			
		||||
    draw_cursor_box(w, "Move Left (2)", |_, _| cursor::MoveLeft(2))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fn test_move_cursor_right<W>(w: &mut W) -> Result<()>
 | 
			
		||||
fn test_move_cursor_right<W>(w: &mut W) -> std::io::Result<()>
 | 
			
		||||
where
 | 
			
		||||
    W: Write,
 | 
			
		||||
{
 | 
			
		||||
    draw_cursor_box(w, "Move Right (2)", |_, _| cursor::MoveRight(2))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fn test_move_cursor_to_previous_line<W>(w: &mut W) -> Result<()>
 | 
			
		||||
fn test_move_cursor_to_previous_line<W>(w: &mut W) -> std::io::Result<()>
 | 
			
		||||
where
 | 
			
		||||
    W: Write,
 | 
			
		||||
{
 | 
			
		||||
@ -44,14 +43,14 @@ where
 | 
			
		||||
    })
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fn test_move_cursor_to_next_line<W>(w: &mut W) -> Result<()>
 | 
			
		||||
fn test_move_cursor_to_next_line<W>(w: &mut W) -> std::io::Result<()>
 | 
			
		||||
where
 | 
			
		||||
    W: Write,
 | 
			
		||||
{
 | 
			
		||||
    draw_cursor_box(w, "MoveToNextLine (1)", |_, _| cursor::MoveToNextLine(1))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fn test_move_cursor_to_column<W>(w: &mut W) -> Result<()>
 | 
			
		||||
fn test_move_cursor_to_column<W>(w: &mut W) -> std::io::Result<()>
 | 
			
		||||
where
 | 
			
		||||
    W: Write,
 | 
			
		||||
{
 | 
			
		||||
@ -60,21 +59,21 @@ where
 | 
			
		||||
    })
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fn test_hide_cursor<W>(w: &mut W) -> Result<()>
 | 
			
		||||
fn test_hide_cursor<W>(w: &mut W) -> std::io::Result<()>
 | 
			
		||||
where
 | 
			
		||||
    W: Write,
 | 
			
		||||
{
 | 
			
		||||
    execute!(w, style::Print("HideCursor"), cursor::Hide)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fn test_show_cursor<W>(w: &mut W) -> Result<()>
 | 
			
		||||
fn test_show_cursor<W>(w: &mut W) -> std::io::Result<()>
 | 
			
		||||
where
 | 
			
		||||
    W: Write,
 | 
			
		||||
{
 | 
			
		||||
    execute!(w, style::Print("ShowCursor"), cursor::Show)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fn test_cursor_blinking_block<W>(w: &mut W) -> Result<()>
 | 
			
		||||
fn test_cursor_blinking_block<W>(w: &mut W) -> std::io::Result<()>
 | 
			
		||||
where
 | 
			
		||||
    W: Write,
 | 
			
		||||
{
 | 
			
		||||
@ -86,7 +85,7 @@ where
 | 
			
		||||
    )
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fn test_cursor_blinking_underscore<W>(w: &mut W) -> Result<()>
 | 
			
		||||
fn test_cursor_blinking_underscore<W>(w: &mut W) -> std::io::Result<()>
 | 
			
		||||
where
 | 
			
		||||
    W: Write,
 | 
			
		||||
{
 | 
			
		||||
@ -98,7 +97,7 @@ where
 | 
			
		||||
    )
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fn test_cursor_blinking_bar<W>(w: &mut W) -> Result<()>
 | 
			
		||||
fn test_cursor_blinking_bar<W>(w: &mut W) -> std::io::Result<()>
 | 
			
		||||
where
 | 
			
		||||
    W: Write,
 | 
			
		||||
{
 | 
			
		||||
@ -111,7 +110,7 @@ where
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
fn test_move_cursor_to<W>(w: &mut W) -> Result<()>
 | 
			
		||||
fn test_move_cursor_to<W>(w: &mut W) -> std::io::Result<()>
 | 
			
		||||
where
 | 
			
		||||
    W: Write,
 | 
			
		||||
{
 | 
			
		||||
@ -122,7 +121,7 @@ where
 | 
			
		||||
    )
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fn test_save_restore_cursor_position<W>(w: &mut W) -> Result<()>
 | 
			
		||||
fn test_save_restore_cursor_position<W>(w: &mut W) -> std::io::Result<()>
 | 
			
		||||
where
 | 
			
		||||
    W: Write,
 | 
			
		||||
{
 | 
			
		||||
@ -143,7 +142,7 @@ where
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// Draws  a box with an colored center, this center can be taken as a reference point after running the given cursor command.
 | 
			
		||||
fn draw_cursor_box<W, F, T>(w: &mut W, description: &str, cursor_command: F) -> Result<()>
 | 
			
		||||
fn draw_cursor_box<W, F, T>(w: &mut W, description: &str, cursor_command: F) -> std::io::Result<()>
 | 
			
		||||
where
 | 
			
		||||
    W: Write,
 | 
			
		||||
    F: Fn(u16, u16) -> T,
 | 
			
		||||
@ -199,7 +198,7 @@ where
 | 
			
		||||
    Ok(())
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub fn run<W>(w: &mut W) -> Result<()>
 | 
			
		||||
pub fn run<W>(w: &mut W) -> std::io::Result<()>
 | 
			
		||||
where
 | 
			
		||||
    W: Write,
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
@ -3,13 +3,13 @@
 | 
			
		||||
use crossterm::{
 | 
			
		||||
    cursor::position,
 | 
			
		||||
    event::{read, DisableMouseCapture, EnableMouseCapture, Event, KeyCode},
 | 
			
		||||
    execute, Result,
 | 
			
		||||
    execute,
 | 
			
		||||
};
 | 
			
		||||
use std::io::Write;
 | 
			
		||||
use std::io;
 | 
			
		||||
 | 
			
		||||
fn test_event<W>(w: &mut W) -> Result<()>
 | 
			
		||||
fn test_event<W>(w: &mut W) -> io::Result<()>
 | 
			
		||||
where
 | 
			
		||||
    W: Write,
 | 
			
		||||
    W: io::Write,
 | 
			
		||||
{
 | 
			
		||||
    execute!(w, EnableMouseCapture)?;
 | 
			
		||||
 | 
			
		||||
@ -33,7 +33,7 @@ where
 | 
			
		||||
    Ok(())
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub fn run<W>(w: &mut W) -> Result<()>
 | 
			
		||||
pub fn run<W>(w: &mut W) -> std::io::Result<()>
 | 
			
		||||
where
 | 
			
		||||
    W: Write,
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
@ -2,9 +2,7 @@ use std::io::Write;
 | 
			
		||||
 | 
			
		||||
use crossterm::{cursor, execute, style::Print, SynchronizedUpdate};
 | 
			
		||||
 | 
			
		||||
use crate::Result;
 | 
			
		||||
 | 
			
		||||
fn render_slowly<W>(w: &mut W) -> Result<()>
 | 
			
		||||
fn render_slowly<W>(w: &mut W) -> std::io::Result<()>
 | 
			
		||||
where
 | 
			
		||||
    W: Write,
 | 
			
		||||
{
 | 
			
		||||
@ -15,7 +13,7 @@ where
 | 
			
		||||
    Ok(())
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fn test_slow_rendering<W>(w: &mut W) -> Result<()>
 | 
			
		||||
fn test_slow_rendering<W>(w: &mut W) -> std::io::Result<()>
 | 
			
		||||
where
 | 
			
		||||
    W: Write,
 | 
			
		||||
{
 | 
			
		||||
@ -34,7 +32,7 @@ where
 | 
			
		||||
    Ok(())
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub fn run<W>(w: &mut W) -> Result<()>
 | 
			
		||||
pub fn run<W>(w: &mut W) -> std::io::Result<()>
 | 
			
		||||
where
 | 
			
		||||
    W: Write,
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
@ -8,7 +8,7 @@
 | 
			
		||||
//!
 | 
			
		||||
//! cargo run --example stderr
 | 
			
		||||
 | 
			
		||||
use std::io::{stderr, Write};
 | 
			
		||||
use std::io;
 | 
			
		||||
 | 
			
		||||
use crossterm::{
 | 
			
		||||
    cursor::{Hide, MoveTo, Show},
 | 
			
		||||
@ -17,7 +17,6 @@ use crossterm::{
 | 
			
		||||
    execute, queue,
 | 
			
		||||
    style::Print,
 | 
			
		||||
    terminal::{self, EnterAlternateScreen, LeaveAlternateScreen},
 | 
			
		||||
    Result,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const TEXT: &str = r#"
 | 
			
		||||
@ -46,9 +45,9 @@ Hit any key to quit this screen:
 | 
			
		||||
Any other key will print this text (so that you may copy-paste)
 | 
			
		||||
"#;
 | 
			
		||||
 | 
			
		||||
fn run_app<W>(write: &mut W) -> Result<char>
 | 
			
		||||
fn run_app<W>(write: &mut W) -> io::Result<char>
 | 
			
		||||
where
 | 
			
		||||
    W: Write,
 | 
			
		||||
    W: io::Write,
 | 
			
		||||
{
 | 
			
		||||
    queue!(
 | 
			
		||||
        write,
 | 
			
		||||
@ -73,7 +72,7 @@ where
 | 
			
		||||
    Ok(user_char)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub fn read_char() -> Result<char> {
 | 
			
		||||
pub fn read_char() -> io::Result<char> {
 | 
			
		||||
    loop {
 | 
			
		||||
        if let Event::Key(KeyEvent {
 | 
			
		||||
            code: KeyCode::Char(c),
 | 
			
		||||
@ -87,7 +86,7 @@ pub fn read_char() -> Result<char> {
 | 
			
		||||
 | 
			
		||||
// cargo run --example stderr
 | 
			
		||||
fn main() {
 | 
			
		||||
    match run_app(&mut stderr()).unwrap() {
 | 
			
		||||
    match run_app(&mut io::stderr()).unwrap() {
 | 
			
		||||
        '1' => print!(".."),
 | 
			
		||||
        '2' => print!("/"),
 | 
			
		||||
        '3' => print!("~"),
 | 
			
		||||
 | 
			
		||||
@ -4,8 +4,6 @@ use crossterm_winapi::{ConsoleMode, Handle};
 | 
			
		||||
use parking_lot::Once;
 | 
			
		||||
use winapi::um::wincon::ENABLE_VIRTUAL_TERMINAL_PROCESSING;
 | 
			
		||||
 | 
			
		||||
use crate::Result;
 | 
			
		||||
 | 
			
		||||
/// Enable virtual terminal processing.
 | 
			
		||||
///
 | 
			
		||||
/// This method attempts to enable virtual terminal processing for this
 | 
			
		||||
@ -15,7 +13,7 @@ use crate::Result;
 | 
			
		||||
/// When virtual terminal processing is enabled, characters emitted to the
 | 
			
		||||
/// console are parsed for VT100 and similar control character sequences
 | 
			
		||||
/// that control color and other similar operations.
 | 
			
		||||
fn enable_vt_processing() -> Result<()> {
 | 
			
		||||
fn enable_vt_processing() -> std::io::Result<()> {
 | 
			
		||||
    let mask = ENABLE_VIRTUAL_TERMINAL_PROCESSING;
 | 
			
		||||
 | 
			
		||||
    let console_mode = ConsoleMode::from(Handle::current_out_handle()?);
 | 
			
		||||
 | 
			
		||||
@ -3,8 +3,6 @@ use std::io::{self, Write};
 | 
			
		||||
 | 
			
		||||
use crate::terminal::{BeginSynchronizedUpdate, EndSynchronizedUpdate};
 | 
			
		||||
 | 
			
		||||
use super::error::Result;
 | 
			
		||||
 | 
			
		||||
/// An interface for a command that performs an action on the terminal.
 | 
			
		||||
///
 | 
			
		||||
/// Crossterm provides a set of commands,
 | 
			
		||||
@ -26,7 +24,7 @@ pub trait Command {
 | 
			
		||||
    ///
 | 
			
		||||
    /// This method does not need to be accessed manually, as it is used by the crossterm's [Command API](./index.html#command-api)
 | 
			
		||||
    #[cfg(windows)]
 | 
			
		||||
    fn execute_winapi(&self) -> Result<()>;
 | 
			
		||||
    fn execute_winapi(&self) -> io::Result<()>;
 | 
			
		||||
 | 
			
		||||
    /// Returns whether the ANSI code representation of this command is supported by windows.
 | 
			
		||||
    ///
 | 
			
		||||
@ -45,7 +43,7 @@ impl<T: Command + ?Sized> Command for &T {
 | 
			
		||||
 | 
			
		||||
    #[inline]
 | 
			
		||||
    #[cfg(windows)]
 | 
			
		||||
    fn execute_winapi(&self) -> Result<()> {
 | 
			
		||||
    fn execute_winapi(&self) -> io::Result<()> {
 | 
			
		||||
        T::execute_winapi(self)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -59,13 +57,13 @@ impl<T: Command + ?Sized> Command for &T {
 | 
			
		||||
/// An interface for types that can queue commands for further execution.
 | 
			
		||||
pub trait QueueableCommand {
 | 
			
		||||
    /// Queues the given command for further execution.
 | 
			
		||||
    fn queue(&mut self, command: impl Command) -> Result<&mut Self>;
 | 
			
		||||
    fn queue(&mut self, command: impl Command) -> io::Result<&mut Self>;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// An interface for types that can directly execute commands.
 | 
			
		||||
pub trait ExecutableCommand {
 | 
			
		||||
    /// Executes the given command directly.
 | 
			
		||||
    fn execute(&mut self, command: impl Command) -> Result<&mut Self>;
 | 
			
		||||
    fn execute(&mut self, command: impl Command) -> io::Result<&mut Self>;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl<T: Write + ?Sized> QueueableCommand for T {
 | 
			
		||||
@ -86,12 +84,11 @@ impl<T: Write + ?Sized> QueueableCommand for T {
 | 
			
		||||
    /// # Examples
 | 
			
		||||
    ///
 | 
			
		||||
    /// ```rust
 | 
			
		||||
    /// use std::io::{Write, stdout};
 | 
			
		||||
    /// use std::io::{self, Write};
 | 
			
		||||
    /// use crossterm::{QueueableCommand, style::Print};
 | 
			
		||||
    ///
 | 
			
		||||
    /// use crossterm::{Result, QueueableCommand, style::Print};
 | 
			
		||||
    ///
 | 
			
		||||
    ///  fn main() -> Result<()> {
 | 
			
		||||
    ///     let mut stdout = stdout();
 | 
			
		||||
    ///  fn main() -> io::Result<()> {
 | 
			
		||||
    ///     let mut stdout = io::stdout();
 | 
			
		||||
    ///
 | 
			
		||||
    ///     // `Print` will executed executed when `flush` is called.
 | 
			
		||||
    ///     stdout
 | 
			
		||||
@ -121,7 +118,7 @@ impl<T: Write + ?Sized> QueueableCommand for T {
 | 
			
		||||
    ///     and can therefore not be written to the given `writer`.
 | 
			
		||||
    ///     Therefore, there is no difference between [execute](./trait.ExecutableCommand.html)
 | 
			
		||||
    ///     and [queue](./trait.QueueableCommand.html) for those old Windows versions.
 | 
			
		||||
    fn queue(&mut self, command: impl Command) -> Result<&mut Self> {
 | 
			
		||||
    fn queue(&mut self, command: impl Command) -> io::Result<&mut Self> {
 | 
			
		||||
        #[cfg(windows)]
 | 
			
		||||
        if !command.is_ansi_code_supported() {
 | 
			
		||||
            // There may be queued commands in this writer, but `execute_winapi` will execute the
 | 
			
		||||
@ -151,13 +148,12 @@ impl<T: Write + ?Sized> ExecutableCommand for T {
 | 
			
		||||
    /// # Example
 | 
			
		||||
    ///
 | 
			
		||||
    /// ```rust
 | 
			
		||||
    /// use std::io::{Write, stdout};
 | 
			
		||||
    /// use std::io;
 | 
			
		||||
    /// use crossterm::{ExecutableCommand, style::Print};
 | 
			
		||||
    ///
 | 
			
		||||
    /// use crossterm::{Result, ExecutableCommand, style::Print};
 | 
			
		||||
    ///
 | 
			
		||||
    ///  fn main() -> Result<()> {
 | 
			
		||||
    /// fn main() -> io::Result<()> {
 | 
			
		||||
    ///      // will be executed directly
 | 
			
		||||
    ///       stdout()
 | 
			
		||||
    ///       io::stdout()
 | 
			
		||||
    ///         .execute(Print("sum:\n".to_string()))?
 | 
			
		||||
    ///         .execute(Print(format!("1 + 1= {} ", 1 + 1)))?;
 | 
			
		||||
    ///
 | 
			
		||||
@ -166,7 +162,7 @@ impl<T: Write + ?Sized> ExecutableCommand for T {
 | 
			
		||||
    ///      // ==== Output ====
 | 
			
		||||
    ///      // sum:
 | 
			
		||||
    ///      // 1 + 1 = 2
 | 
			
		||||
    ///  }
 | 
			
		||||
    /// }
 | 
			
		||||
    /// ```
 | 
			
		||||
    ///
 | 
			
		||||
    /// Have a look over at the [Command API](./index.html#command-api) for more details.
 | 
			
		||||
@ -179,7 +175,7 @@ impl<T: Write + ?Sized> ExecutableCommand for T {
 | 
			
		||||
    ///     and can therefore not be written to the given `writer`.
 | 
			
		||||
    ///     Therefore, there is no difference between [execute](./trait.ExecutableCommand.html)
 | 
			
		||||
    ///     and [queue](./trait.QueueableCommand.html) for those old Windows versions.
 | 
			
		||||
    fn execute(&mut self, command: impl Command) -> Result<&mut Self> {
 | 
			
		||||
    fn execute(&mut self, command: impl Command) -> io::Result<&mut Self> {
 | 
			
		||||
        self.queue(command)?;
 | 
			
		||||
        self.flush()?;
 | 
			
		||||
        Ok(self)
 | 
			
		||||
@ -189,7 +185,7 @@ impl<T: Write + ?Sized> ExecutableCommand for T {
 | 
			
		||||
/// An interface for types that support synchronized updates.
 | 
			
		||||
pub trait SynchronizedUpdate {
 | 
			
		||||
    /// Performs a set of actions against the given type.
 | 
			
		||||
    fn sync_update<T>(&mut self, operations: impl FnOnce(&mut Self) -> T) -> Result<T>;
 | 
			
		||||
    fn sync_update<T>(&mut self, operations: impl FnOnce(&mut Self) -> T) -> io::Result<T>;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl<W: std::io::Write + ?Sized> SynchronizedUpdate for W {
 | 
			
		||||
@ -207,19 +203,18 @@ impl<W: std::io::Write + ?Sized> SynchronizedUpdate for W {
 | 
			
		||||
    /// # Examples
 | 
			
		||||
    ///
 | 
			
		||||
    /// ```rust
 | 
			
		||||
    /// use std::io::{Write, stdout};
 | 
			
		||||
    /// use std::io;
 | 
			
		||||
    /// use crossterm::{ExecutableCommand, SynchronizedUpdate, style::Print};
 | 
			
		||||
    ///
 | 
			
		||||
    /// use crossterm::{Result, ExecutableCommand, SynchronizedUpdate, style::Print};
 | 
			
		||||
    ///
 | 
			
		||||
    ///  fn main() -> Result<()> {
 | 
			
		||||
    ///     let mut stdout = stdout();
 | 
			
		||||
    /// fn main() -> io::Result<()> {
 | 
			
		||||
    ///     let mut stdout = io::stdout();
 | 
			
		||||
    ///
 | 
			
		||||
    ///     stdout.sync_update(|stdout| {
 | 
			
		||||
    ///         stdout.execute(Print("foo 1\n".to_string()))?;
 | 
			
		||||
    ///         stdout.execute(Print("foo 2".to_string()))?;
 | 
			
		||||
    ///         // The effects of the print command will not be present in the terminal
 | 
			
		||||
    ///         // buffer, but not visible in the terminal.
 | 
			
		||||
    ///         crossterm::Result::Ok(())
 | 
			
		||||
    ///         std::io::Result::Ok(())
 | 
			
		||||
    ///     })?;
 | 
			
		||||
    ///
 | 
			
		||||
    ///     // The effects of the commands will be visible.
 | 
			
		||||
@ -247,7 +242,7 @@ impl<W: std::io::Write + ?Sized> SynchronizedUpdate for W {
 | 
			
		||||
    /// again the renderer may fetch the latest screen buffer state again, effectively avoiding the tearing effect
 | 
			
		||||
    /// by unintentionally rendering in the middle a of an application screen update.
 | 
			
		||||
    ///
 | 
			
		||||
    fn sync_update<T>(&mut self, operations: impl FnOnce(&mut Self) -> T) -> Result<T> {
 | 
			
		||||
    fn sync_update<T>(&mut self, operations: impl FnOnce(&mut Self) -> T) -> io::Result<T> {
 | 
			
		||||
        self.queue(BeginSynchronizedUpdate)?;
 | 
			
		||||
        let result = operations(self);
 | 
			
		||||
        self.execute(EndSynchronizedUpdate)?;
 | 
			
		||||
 | 
			
		||||
@ -13,17 +13,17 @@
 | 
			
		||||
//! Please have a look at [command documentation](../index.html#command-api) for a more detailed documentation.
 | 
			
		||||
//!
 | 
			
		||||
//! ```no_run
 | 
			
		||||
//! use std::io::{stdout, Write};
 | 
			
		||||
//! use std::io::{self, Write};
 | 
			
		||||
//!
 | 
			
		||||
//! use crossterm::{
 | 
			
		||||
//!     ExecutableCommand, execute, Result,
 | 
			
		||||
//!     ExecutableCommand, execute,
 | 
			
		||||
//!     cursor::{DisableBlinking, EnableBlinking, MoveTo, RestorePosition, SavePosition}
 | 
			
		||||
//! };
 | 
			
		||||
//!
 | 
			
		||||
//! fn main() -> Result<()> {
 | 
			
		||||
//! fn main() -> io::Result<()> {
 | 
			
		||||
//!     // with macro
 | 
			
		||||
//!     execute!(
 | 
			
		||||
//!         stdout(),
 | 
			
		||||
//!         io::stdout(),
 | 
			
		||||
//!         SavePosition,
 | 
			
		||||
//!         MoveTo(10, 10),
 | 
			
		||||
//!         EnableBlinking,
 | 
			
		||||
@ -32,7 +32,7 @@
 | 
			
		||||
//!     );
 | 
			
		||||
//!
 | 
			
		||||
//!   // with function
 | 
			
		||||
//!   stdout()
 | 
			
		||||
//!   io::stdout()
 | 
			
		||||
//!     .execute(MoveTo(11,11))?
 | 
			
		||||
//!     .execute(RestorePosition);
 | 
			
		||||
//!
 | 
			
		||||
@ -44,8 +44,6 @@
 | 
			
		||||
 | 
			
		||||
use std::fmt;
 | 
			
		||||
 | 
			
		||||
#[cfg(windows)]
 | 
			
		||||
use crate::Result;
 | 
			
		||||
use crate::{csi, impl_display, Command};
 | 
			
		||||
 | 
			
		||||
pub(crate) mod sys;
 | 
			
		||||
@ -67,7 +65,7 @@ impl Command for MoveTo {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    #[cfg(windows)]
 | 
			
		||||
    fn execute_winapi(&self) -> Result<()> {
 | 
			
		||||
    fn execute_winapi(&self) -> std::io::Result<()> {
 | 
			
		||||
        sys::move_to(self.0, self.1)
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@ -89,7 +87,7 @@ impl Command for MoveToNextLine {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    #[cfg(windows)]
 | 
			
		||||
    fn execute_winapi(&self) -> Result<()> {
 | 
			
		||||
    fn execute_winapi(&self) -> std::io::Result<()> {
 | 
			
		||||
        if self.0 != 0 {
 | 
			
		||||
            sys::move_to_next_line(self.0)?;
 | 
			
		||||
        }
 | 
			
		||||
@ -114,7 +112,7 @@ impl Command for MoveToPreviousLine {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    #[cfg(windows)]
 | 
			
		||||
    fn execute_winapi(&self) -> Result<()> {
 | 
			
		||||
    fn execute_winapi(&self) -> std::io::Result<()> {
 | 
			
		||||
        if self.0 != 0 {
 | 
			
		||||
            sys::move_to_previous_line(self.0)?;
 | 
			
		||||
        }
 | 
			
		||||
@ -137,7 +135,7 @@ impl Command for MoveToColumn {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    #[cfg(windows)]
 | 
			
		||||
    fn execute_winapi(&self) -> Result<()> {
 | 
			
		||||
    fn execute_winapi(&self) -> std::io::Result<()> {
 | 
			
		||||
        sys::move_to_column(self.0)
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@ -157,7 +155,7 @@ impl Command for MoveToRow {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    #[cfg(windows)]
 | 
			
		||||
    fn execute_winapi(&self) -> Result<()> {
 | 
			
		||||
    fn execute_winapi(&self) -> std::io::Result<()> {
 | 
			
		||||
        sys::move_to_row(self.0)
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@ -178,7 +176,7 @@ impl Command for MoveUp {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    #[cfg(windows)]
 | 
			
		||||
    fn execute_winapi(&self) -> Result<()> {
 | 
			
		||||
    fn execute_winapi(&self) -> std::io::Result<()> {
 | 
			
		||||
        sys::move_up(self.0)
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@ -199,7 +197,7 @@ impl Command for MoveRight {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    #[cfg(windows)]
 | 
			
		||||
    fn execute_winapi(&self) -> Result<()> {
 | 
			
		||||
    fn execute_winapi(&self) -> std::io::Result<()> {
 | 
			
		||||
        sys::move_right(self.0)
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@ -220,7 +218,7 @@ impl Command for MoveDown {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    #[cfg(windows)]
 | 
			
		||||
    fn execute_winapi(&self) -> Result<()> {
 | 
			
		||||
    fn execute_winapi(&self) -> std::io::Result<()> {
 | 
			
		||||
        sys::move_down(self.0)
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@ -241,7 +239,7 @@ impl Command for MoveLeft {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    #[cfg(windows)]
 | 
			
		||||
    fn execute_winapi(&self) -> Result<()> {
 | 
			
		||||
    fn execute_winapi(&self) -> std::io::Result<()> {
 | 
			
		||||
        sys::move_left(self.0)
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@ -263,7 +261,7 @@ impl Command for SavePosition {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    #[cfg(windows)]
 | 
			
		||||
    fn execute_winapi(&self) -> Result<()> {
 | 
			
		||||
    fn execute_winapi(&self) -> std::io::Result<()> {
 | 
			
		||||
        sys::save_position()
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@ -285,7 +283,7 @@ impl Command for RestorePosition {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    #[cfg(windows)]
 | 
			
		||||
    fn execute_winapi(&self) -> Result<()> {
 | 
			
		||||
    fn execute_winapi(&self) -> std::io::Result<()> {
 | 
			
		||||
        sys::restore_position()
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@ -304,7 +302,7 @@ impl Command for Hide {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    #[cfg(windows)]
 | 
			
		||||
    fn execute_winapi(&self) -> Result<()> {
 | 
			
		||||
    fn execute_winapi(&self) -> std::io::Result<()> {
 | 
			
		||||
        sys::show_cursor(false)
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@ -323,7 +321,7 @@ impl Command for Show {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    #[cfg(windows)]
 | 
			
		||||
    fn execute_winapi(&self) -> Result<()> {
 | 
			
		||||
    fn execute_winapi(&self) -> std::io::Result<()> {
 | 
			
		||||
        sys::show_cursor(true)
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@ -342,7 +340,7 @@ impl Command for EnableBlinking {
 | 
			
		||||
        f.write_str(csi!("?12h"))
 | 
			
		||||
    }
 | 
			
		||||
    #[cfg(windows)]
 | 
			
		||||
    fn execute_winapi(&self) -> Result<()> {
 | 
			
		||||
    fn execute_winapi(&self) -> std::io::Result<()> {
 | 
			
		||||
        Ok(())
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@ -361,7 +359,7 @@ impl Command for DisableBlinking {
 | 
			
		||||
        f.write_str(csi!("?12l"))
 | 
			
		||||
    }
 | 
			
		||||
    #[cfg(windows)]
 | 
			
		||||
    fn execute_winapi(&self) -> Result<()> {
 | 
			
		||||
    fn execute_winapi(&self) -> std::io::Result<()> {
 | 
			
		||||
        Ok(())
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@ -404,7 +402,7 @@ impl Command for SetCursorStyle {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    #[cfg(windows)]
 | 
			
		||||
    fn execute_winapi(&self) -> Result<()> {
 | 
			
		||||
    fn execute_winapi(&self) -> std::io::Result<()> {
 | 
			
		||||
        Ok(())
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -6,7 +6,6 @@ use std::{
 | 
			
		||||
use crate::{
 | 
			
		||||
    event::{filter::CursorPositionFilter, poll_internal, read_internal, InternalEvent},
 | 
			
		||||
    terminal::{disable_raw_mode, enable_raw_mode, sys::is_raw_mode_enabled},
 | 
			
		||||
    Result,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/// Returns the cursor position (column, row).
 | 
			
		||||
@ -15,7 +14,7 @@ use crate::{
 | 
			
		||||
///
 | 
			
		||||
/// On unix systems, this function will block and possibly time out while
 | 
			
		||||
/// [`crossterm::event::read`](crate::event::read) or [`crossterm::event::poll`](crate::event::poll) are being called.
 | 
			
		||||
pub fn position() -> Result<(u16, u16)> {
 | 
			
		||||
pub fn position() -> io::Result<(u16, u16)> {
 | 
			
		||||
    if is_raw_mode_enabled() {
 | 
			
		||||
        read_position_raw()
 | 
			
		||||
    } else {
 | 
			
		||||
@ -23,14 +22,14 @@ pub fn position() -> Result<(u16, u16)> {
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fn read_position() -> Result<(u16, u16)> {
 | 
			
		||||
fn read_position() -> io::Result<(u16, u16)> {
 | 
			
		||||
    enable_raw_mode()?;
 | 
			
		||||
    let pos = read_position_raw();
 | 
			
		||||
    disable_raw_mode()?;
 | 
			
		||||
    pos
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fn read_position_raw() -> Result<(u16, u16)> {
 | 
			
		||||
fn read_position_raw() -> io::Result<(u16, u16)> {
 | 
			
		||||
    // Use `ESC [ 6 n` to and retrieve the cursor position.
 | 
			
		||||
    let mut stdout = io::stdout();
 | 
			
		||||
    stdout.write_all(b"\x1B[6n")?;
 | 
			
		||||
 | 
			
		||||
@ -10,8 +10,6 @@ use winapi::{
 | 
			
		||||
    um::wincon::{SetConsoleCursorInfo, SetConsoleCursorPosition, CONSOLE_CURSOR_INFO, COORD},
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
use crate::Result;
 | 
			
		||||
 | 
			
		||||
/// The position of the cursor, written when you save the cursor's position.
 | 
			
		||||
///
 | 
			
		||||
/// This is `u64::MAX` initially. Otherwise, it stores the cursor's x position bit-shifted left 16
 | 
			
		||||
@ -21,7 +19,7 @@ static SAVED_CURSOR_POS: AtomicU64 = AtomicU64::new(u64::MAX);
 | 
			
		||||
// The 'y' position of the cursor is not relative to the window but absolute to screen buffer.
 | 
			
		||||
// We can calculate the relative cursor position by subtracting the top position of the terminal window from the y position.
 | 
			
		||||
// This results in an 1-based coord zo subtract 1 to make cursor position 0-based.
 | 
			
		||||
pub fn parse_relative_y(y: i16) -> Result<i16> {
 | 
			
		||||
pub fn parse_relative_y(y: i16) -> std::io::Result<i16> {
 | 
			
		||||
    let window = ScreenBuffer::current()?.info()?;
 | 
			
		||||
 | 
			
		||||
    let window_size = window.terminal_window();
 | 
			
		||||
@ -37,7 +35,7 @@ pub fn parse_relative_y(y: i16) -> Result<i16> {
 | 
			
		||||
/// Returns the cursor position (column, row).
 | 
			
		||||
///
 | 
			
		||||
/// The top left cell is represented `0,0`.
 | 
			
		||||
pub fn position() -> Result<(u16, u16)> {
 | 
			
		||||
pub fn position() -> io::Result<(u16, u16)> {
 | 
			
		||||
    let cursor = ScreenBufferCursor::output()?;
 | 
			
		||||
    let mut position = cursor.position()?;
 | 
			
		||||
    //    if position.y != 0 {
 | 
			
		||||
@ -46,70 +44,70 @@ pub fn position() -> Result<(u16, u16)> {
 | 
			
		||||
    Ok(position.into())
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub(crate) fn show_cursor(show_cursor: bool) -> Result<()> {
 | 
			
		||||
pub(crate) fn show_cursor(show_cursor: bool) -> std::io::Result<()> {
 | 
			
		||||
    ScreenBufferCursor::from(Handle::current_out_handle()?).set_visibility(show_cursor)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub(crate) fn move_to(column: u16, row: u16) -> Result<()> {
 | 
			
		||||
pub(crate) fn move_to(column: u16, row: u16) -> std::io::Result<()> {
 | 
			
		||||
    let cursor = ScreenBufferCursor::output()?;
 | 
			
		||||
    cursor.move_to(column as i16, row as i16)?;
 | 
			
		||||
    Ok(())
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub(crate) fn move_up(count: u16) -> Result<()> {
 | 
			
		||||
pub(crate) fn move_up(count: u16) -> std::io::Result<()> {
 | 
			
		||||
    let (column, row) = position()?;
 | 
			
		||||
    move_to(column, row - count)?;
 | 
			
		||||
    Ok(())
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub(crate) fn move_right(count: u16) -> Result<()> {
 | 
			
		||||
pub(crate) fn move_right(count: u16) -> std::io::Result<()> {
 | 
			
		||||
    let (column, row) = position()?;
 | 
			
		||||
    move_to(column + count, row)?;
 | 
			
		||||
    Ok(())
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub(crate) fn move_down(count: u16) -> Result<()> {
 | 
			
		||||
pub(crate) fn move_down(count: u16) -> std::io::Result<()> {
 | 
			
		||||
    let (column, row) = position()?;
 | 
			
		||||
    move_to(column, row + count)?;
 | 
			
		||||
    Ok(())
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub(crate) fn move_left(count: u16) -> Result<()> {
 | 
			
		||||
pub(crate) fn move_left(count: u16) -> std::io::Result<()> {
 | 
			
		||||
    let (column, row) = position()?;
 | 
			
		||||
    move_to(column - count, row)?;
 | 
			
		||||
    Ok(())
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub(crate) fn move_to_column(new_column: u16) -> Result<()> {
 | 
			
		||||
pub(crate) fn move_to_column(new_column: u16) -> std::io::Result<()> {
 | 
			
		||||
    let (_, row) = position()?;
 | 
			
		||||
    move_to(new_column, row)?;
 | 
			
		||||
    Ok(())
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub(crate) fn move_to_row(new_row: u16) -> Result<()> {
 | 
			
		||||
pub(crate) fn move_to_row(new_row: u16) -> std::io::Result<()> {
 | 
			
		||||
    let (col, _) = position()?;
 | 
			
		||||
    move_to(col, new_row)?;
 | 
			
		||||
    Ok(())
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub(crate) fn move_to_next_line(count: u16) -> Result<()> {
 | 
			
		||||
pub(crate) fn move_to_next_line(count: u16) -> std::io::Result<()> {
 | 
			
		||||
    let (_, row) = position()?;
 | 
			
		||||
    move_to(0, row + count)?;
 | 
			
		||||
    Ok(())
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub(crate) fn move_to_previous_line(count: u16) -> Result<()> {
 | 
			
		||||
pub(crate) fn move_to_previous_line(count: u16) -> std::io::Result<()> {
 | 
			
		||||
    let (_, row) = position()?;
 | 
			
		||||
    move_to(0, row - count)?;
 | 
			
		||||
    Ok(())
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub(crate) fn save_position() -> Result<()> {
 | 
			
		||||
pub(crate) fn save_position() -> std::io::Result<()> {
 | 
			
		||||
    ScreenBufferCursor::output()?.save_position()?;
 | 
			
		||||
    Ok(())
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub(crate) fn restore_position() -> Result<()> {
 | 
			
		||||
pub(crate) fn restore_position() -> std::io::Result<()> {
 | 
			
		||||
    ScreenBufferCursor::output()?.restore_position()?;
 | 
			
		||||
    Ok(())
 | 
			
		||||
}
 | 
			
		||||
@ -120,17 +118,17 @@ struct ScreenBufferCursor {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl ScreenBufferCursor {
 | 
			
		||||
    fn output() -> Result<ScreenBufferCursor> {
 | 
			
		||||
    fn output() -> std::io::Result<ScreenBufferCursor> {
 | 
			
		||||
        Ok(ScreenBufferCursor {
 | 
			
		||||
            screen_buffer: ScreenBuffer::from(Handle::new(HandleType::CurrentOutputHandle)?),
 | 
			
		||||
        })
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fn position(&self) -> Result<Coord> {
 | 
			
		||||
    fn position(&self) -> std::io::Result<Coord> {
 | 
			
		||||
        Ok(self.screen_buffer.info()?.cursor_pos())
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fn move_to(&self, x: i16, y: i16) -> Result<()> {
 | 
			
		||||
    fn move_to(&self, x: i16, y: i16) -> std::io::Result<()> {
 | 
			
		||||
        if x < 0 {
 | 
			
		||||
            return Err(io::Error::new(
 | 
			
		||||
                io::ErrorKind::Other,
 | 
			
		||||
@ -160,7 +158,7 @@ impl ScreenBufferCursor {
 | 
			
		||||
        Ok(())
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fn set_visibility(&self, visible: bool) -> Result<()> {
 | 
			
		||||
    fn set_visibility(&self, visible: bool) -> std::io::Result<()> {
 | 
			
		||||
        let cursor_info = CONSOLE_CURSOR_INFO {
 | 
			
		||||
            dwSize: 100,
 | 
			
		||||
            bVisible: if visible { TRUE } else { FALSE },
 | 
			
		||||
@ -179,7 +177,7 @@ impl ScreenBufferCursor {
 | 
			
		||||
        Ok(())
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fn restore_position(&self) -> Result<()> {
 | 
			
		||||
    fn restore_position(&self) -> std::io::Result<()> {
 | 
			
		||||
        if let Ok(val) = u32::try_from(SAVED_CURSOR_POS.load(Ordering::Relaxed)) {
 | 
			
		||||
            let x = (val >> 16) as i16;
 | 
			
		||||
            let y = val as i16;
 | 
			
		||||
@ -189,7 +187,7 @@ impl ScreenBufferCursor {
 | 
			
		||||
        Ok(())
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fn save_position(&self) -> Result<()> {
 | 
			
		||||
    fn save_position(&self) -> std::io::Result<()> {
 | 
			
		||||
        let position = self.position()?;
 | 
			
		||||
 | 
			
		||||
        let bits = u64::from(u32::from(position.x as u16) << 16 | u32::from(position.y as u16));
 | 
			
		||||
 | 
			
		||||
@ -1,8 +0,0 @@
 | 
			
		||||
//! Module containing error handling logic.
 | 
			
		||||
 | 
			
		||||
use std::io;
 | 
			
		||||
 | 
			
		||||
/// The `crossterm` result type.
 | 
			
		||||
pub type Result<T> = std::result::Result<T, ErrorKind>;
 | 
			
		||||
 | 
			
		||||
pub type ErrorKind = io::Error;
 | 
			
		||||
							
								
								
									
										53
									
								
								src/event.rs
									
									
									
									
									
								
							
							
						
						
									
										53
									
								
								src/event.rs
									
									
									
									
									
								
							@ -30,7 +30,7 @@
 | 
			
		||||
//! ```no_run
 | 
			
		||||
//! use crossterm::event::{read, Event};
 | 
			
		||||
//!
 | 
			
		||||
//! fn print_events() -> crossterm::Result<()> {
 | 
			
		||||
//! fn print_events() -> std::io::Result<()> {
 | 
			
		||||
//!     loop {
 | 
			
		||||
//!         // `read()` blocks until an `Event` is available
 | 
			
		||||
//!         match read()? {
 | 
			
		||||
@ -50,11 +50,11 @@
 | 
			
		||||
//! Non-blocking read:
 | 
			
		||||
//!
 | 
			
		||||
//! ```no_run
 | 
			
		||||
//! use std::time::Duration;
 | 
			
		||||
//! use std::{time::Duration, io};
 | 
			
		||||
//!
 | 
			
		||||
//! use crossterm::event::{poll, read, Event};
 | 
			
		||||
//!
 | 
			
		||||
//! fn print_events() -> crossterm::Result<()> {
 | 
			
		||||
//! fn print_events() -> io::Result<()> {
 | 
			
		||||
//!     loop {
 | 
			
		||||
//!         // `poll()` waits for an `Event` for a given time period
 | 
			
		||||
//!         if poll(Duration::from_millis(500))? {
 | 
			
		||||
@ -141,11 +141,10 @@ fn try_lock_internal_event_reader_for(
 | 
			
		||||
/// Return immediately:
 | 
			
		||||
///
 | 
			
		||||
/// ```no_run
 | 
			
		||||
/// use std::time::Duration;
 | 
			
		||||
/// use std::{time::Duration, io};
 | 
			
		||||
/// use crossterm::{event::poll};
 | 
			
		||||
///
 | 
			
		||||
/// use crossterm::{event::poll, Result};
 | 
			
		||||
///
 | 
			
		||||
/// fn is_event_available() -> Result<bool> {
 | 
			
		||||
/// fn is_event_available() -> io::Result<bool> {
 | 
			
		||||
///     // Zero duration says that the `poll` function must return immediately
 | 
			
		||||
///     // with an `Event` availability information
 | 
			
		||||
///     poll(Duration::from_secs(0))
 | 
			
		||||
@ -155,17 +154,17 @@ fn try_lock_internal_event_reader_for(
 | 
			
		||||
/// Wait up to 100ms:
 | 
			
		||||
///
 | 
			
		||||
/// ```no_run
 | 
			
		||||
/// use std::time::Duration;
 | 
			
		||||
/// use std::{time::Duration, io};
 | 
			
		||||
///
 | 
			
		||||
/// use crossterm::{event::poll, Result};
 | 
			
		||||
/// use crossterm::event::poll;
 | 
			
		||||
///
 | 
			
		||||
/// fn is_event_available() -> Result<bool> {
 | 
			
		||||
/// fn is_event_available() -> io::Result<bool> {
 | 
			
		||||
///     // Wait for an `Event` availability for 100ms. It returns immediately
 | 
			
		||||
///     // if an `Event` is/becomes available.
 | 
			
		||||
///     poll(Duration::from_millis(100))
 | 
			
		||||
/// }
 | 
			
		||||
/// ```
 | 
			
		||||
pub fn poll(timeout: Duration) -> crate::Result<bool> {
 | 
			
		||||
pub fn poll(timeout: Duration) -> std::io::Result<bool> {
 | 
			
		||||
    poll_internal(Some(timeout), &EventFilter)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -179,9 +178,10 @@ pub fn poll(timeout: Duration) -> crate::Result<bool> {
 | 
			
		||||
/// Blocking read:
 | 
			
		||||
///
 | 
			
		||||
/// ```no_run
 | 
			
		||||
/// use crossterm::{event::read, Result};
 | 
			
		||||
/// use crossterm::event::read;
 | 
			
		||||
/// use std::io;
 | 
			
		||||
///
 | 
			
		||||
/// fn print_events() -> Result<bool> {
 | 
			
		||||
/// fn print_events() -> io::Result<bool> {
 | 
			
		||||
///     loop {
 | 
			
		||||
///         // Blocks until an `Event` is available
 | 
			
		||||
///         println!("{:?}", read()?);
 | 
			
		||||
@ -193,10 +193,11 @@ pub fn poll(timeout: Duration) -> crate::Result<bool> {
 | 
			
		||||
///
 | 
			
		||||
/// ```no_run
 | 
			
		||||
/// use std::time::Duration;
 | 
			
		||||
/// use std::io;
 | 
			
		||||
///
 | 
			
		||||
/// use crossterm::{event::{read, poll}, Result};
 | 
			
		||||
/// use crossterm::event::{read, poll};
 | 
			
		||||
///
 | 
			
		||||
/// fn print_events() -> Result<bool> {
 | 
			
		||||
/// fn print_events() -> io::Result<bool> {
 | 
			
		||||
///     loop {
 | 
			
		||||
///         if poll(Duration::from_millis(100))? {
 | 
			
		||||
///             // It's guaranteed that `read` won't block, because `poll` returned
 | 
			
		||||
@ -208,7 +209,7 @@ pub fn poll(timeout: Duration) -> crate::Result<bool> {
 | 
			
		||||
///     }
 | 
			
		||||
/// }
 | 
			
		||||
/// ```
 | 
			
		||||
pub fn read() -> crate::Result<Event> {
 | 
			
		||||
pub fn read() -> std::io::Result<Event> {
 | 
			
		||||
    match read_internal(&EventFilter)? {
 | 
			
		||||
        InternalEvent::Event(event) => Ok(event),
 | 
			
		||||
        #[cfg(unix)]
 | 
			
		||||
@ -217,7 +218,7 @@ pub fn read() -> crate::Result<Event> {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// Polls to check if there are any `InternalEvent`s that can be read within the given duration.
 | 
			
		||||
pub(crate) fn poll_internal<F>(timeout: Option<Duration>, filter: &F) -> crate::Result<bool>
 | 
			
		||||
pub(crate) fn poll_internal<F>(timeout: Option<Duration>, filter: &F) -> std::io::Result<bool>
 | 
			
		||||
where
 | 
			
		||||
    F: Filter,
 | 
			
		||||
{
 | 
			
		||||
@ -235,7 +236,7 @@ where
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// Reads a single `InternalEvent`.
 | 
			
		||||
pub(crate) fn read_internal<F>(filter: &F) -> crate::Result<InternalEvent>
 | 
			
		||||
pub(crate) fn read_internal<F>(filter: &F) -> std::io::Result<InternalEvent>
 | 
			
		||||
where
 | 
			
		||||
    F: Filter,
 | 
			
		||||
{
 | 
			
		||||
@ -296,7 +297,7 @@ impl Command for EnableMouseCapture {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    #[cfg(windows)]
 | 
			
		||||
    fn execute_winapi(&self) -> crate::Result<()> {
 | 
			
		||||
    fn execute_winapi(&self) -> std::io::Result<()> {
 | 
			
		||||
        sys::windows::enable_mouse_capture()
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -325,7 +326,7 @@ impl Command for DisableMouseCapture {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    #[cfg(windows)]
 | 
			
		||||
    fn execute_winapi(&self) -> crate::Result<()> {
 | 
			
		||||
    fn execute_winapi(&self) -> std::io::Result<()> {
 | 
			
		||||
        sys::windows::disable_mouse_capture()
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -349,7 +350,7 @@ impl Command for EnableFocusChange {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    #[cfg(windows)]
 | 
			
		||||
    fn execute_winapi(&self) -> crate::Result<()> {
 | 
			
		||||
    fn execute_winapi(&self) -> std::io::Result<()> {
 | 
			
		||||
        // Focus events are always enabled on Windows
 | 
			
		||||
        Ok(())
 | 
			
		||||
    }
 | 
			
		||||
@ -365,7 +366,7 @@ impl Command for DisableFocusChange {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    #[cfg(windows)]
 | 
			
		||||
    fn execute_winapi(&self) -> crate::Result<()> {
 | 
			
		||||
    fn execute_winapi(&self) -> std::io::Result<()> {
 | 
			
		||||
        // Focus events can't be disabled on Windows
 | 
			
		||||
        Ok(())
 | 
			
		||||
    }
 | 
			
		||||
@ -388,7 +389,7 @@ impl Command for EnableBracketedPaste {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    #[cfg(windows)]
 | 
			
		||||
    fn execute_winapi(&self) -> crate::Result<()> {
 | 
			
		||||
    fn execute_winapi(&self) -> std::io::Result<()> {
 | 
			
		||||
        Err(std::io::Error::new(
 | 
			
		||||
            std::io::ErrorKind::Unsupported,
 | 
			
		||||
            "Bracketed paste not implemented in the legacy Windows API.",
 | 
			
		||||
@ -408,7 +409,7 @@ impl Command for DisableBracketedPaste {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    #[cfg(windows)]
 | 
			
		||||
    fn execute_winapi(&self) -> crate::Result<()> {
 | 
			
		||||
    fn execute_winapi(&self) -> std::io::Result<()> {
 | 
			
		||||
        Ok(())
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@ -458,7 +459,7 @@ impl Command for PushKeyboardEnhancementFlags {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    #[cfg(windows)]
 | 
			
		||||
    fn execute_winapi(&self) -> crate::Result<()> {
 | 
			
		||||
    fn execute_winapi(&self) -> std::io::Result<()> {
 | 
			
		||||
        use std::io;
 | 
			
		||||
 | 
			
		||||
        Err(io::Error::new(
 | 
			
		||||
@ -487,7 +488,7 @@ impl Command for PopKeyboardEnhancementFlags {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    #[cfg(windows)]
 | 
			
		||||
    fn execute_winapi(&self) -> crate::Result<()> {
 | 
			
		||||
    fn execute_winapi(&self) -> std::io::Result<()> {
 | 
			
		||||
        use std::io;
 | 
			
		||||
 | 
			
		||||
        Err(io::Error::new(
 | 
			
		||||
 | 
			
		||||
@ -7,7 +7,6 @@ use crate::event::source::windows::WindowsEventSource;
 | 
			
		||||
#[cfg(feature = "event-stream")]
 | 
			
		||||
use crate::event::sys::Waker;
 | 
			
		||||
use crate::event::{filter::Filter, source::EventSource, timeout::PollTimeout, InternalEvent};
 | 
			
		||||
use crate::Result;
 | 
			
		||||
 | 
			
		||||
/// Can be used to read `InternalEvent`s.
 | 
			
		||||
pub(crate) struct InternalEventReader {
 | 
			
		||||
@ -40,7 +39,7 @@ impl InternalEventReader {
 | 
			
		||||
        self.source.as_ref().expect("reader source not set").waker()
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    pub(crate) fn poll<F>(&mut self, timeout: Option<Duration>, filter: &F) -> Result<bool>
 | 
			
		||||
    pub(crate) fn poll<F>(&mut self, timeout: Option<Duration>, filter: &F) -> io::Result<bool>
 | 
			
		||||
    where
 | 
			
		||||
        F: Filter,
 | 
			
		||||
    {
 | 
			
		||||
@ -95,7 +94,7 @@ impl InternalEventReader {
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    pub(crate) fn read<F>(&mut self, filter: &F) -> Result<InternalEvent>
 | 
			
		||||
    pub(crate) fn read<F>(&mut self, filter: &F) -> io::Result<InternalEvent>
 | 
			
		||||
    where
 | 
			
		||||
        F: Filter,
 | 
			
		||||
    {
 | 
			
		||||
@ -131,8 +130,6 @@ mod tests {
 | 
			
		||||
    use std::io;
 | 
			
		||||
    use std::{collections::VecDeque, time::Duration};
 | 
			
		||||
 | 
			
		||||
    use crate::ErrorKind;
 | 
			
		||||
 | 
			
		||||
    #[cfg(unix)]
 | 
			
		||||
    use super::super::filter::CursorPositionFilter;
 | 
			
		||||
    use super::{
 | 
			
		||||
@ -312,11 +309,9 @@ mod tests {
 | 
			
		||||
 | 
			
		||||
    #[test]
 | 
			
		||||
    fn test_poll_propagates_error() {
 | 
			
		||||
        let source = FakeSource::with_error(ErrorKind::from(io::ErrorKind::Other));
 | 
			
		||||
 | 
			
		||||
        let mut reader = InternalEventReader {
 | 
			
		||||
            events: VecDeque::new(),
 | 
			
		||||
            source: Some(Box::new(source)),
 | 
			
		||||
            source: Some(Box::new(FakeSource::new(&[]))),
 | 
			
		||||
            skipped_events: Vec::with_capacity(32),
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
@ -324,18 +319,16 @@ mod tests {
 | 
			
		||||
            reader
 | 
			
		||||
                .poll(Some(Duration::from_secs(0)), &InternalEventFilter)
 | 
			
		||||
                .err()
 | 
			
		||||
                .map(|e| format!("{:?}", &e)),
 | 
			
		||||
            Some(format!("{:?}", ErrorKind::from(io::ErrorKind::Other)))
 | 
			
		||||
                .map(|e| format!("{:?}", &e.kind())),
 | 
			
		||||
            Some(format!("{:?}", io::ErrorKind::Other))
 | 
			
		||||
        );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    #[test]
 | 
			
		||||
    fn test_read_propagates_error() {
 | 
			
		||||
        let source = FakeSource::with_error(ErrorKind::from(io::ErrorKind::Other));
 | 
			
		||||
 | 
			
		||||
        let mut reader = InternalEventReader {
 | 
			
		||||
            events: VecDeque::new(),
 | 
			
		||||
            source: Some(Box::new(source)),
 | 
			
		||||
            source: Some(Box::new(FakeSource::new(&[]))),
 | 
			
		||||
            skipped_events: Vec::with_capacity(32),
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
@ -343,8 +336,8 @@ mod tests {
 | 
			
		||||
            reader
 | 
			
		||||
                .read(&InternalEventFilter)
 | 
			
		||||
                .err()
 | 
			
		||||
                .map(|e| format!("{:?}", &e)),
 | 
			
		||||
            Some(format!("{:?}", ErrorKind::from(io::ErrorKind::Other)))
 | 
			
		||||
                .map(|e| format!("{:?}", &e.kind())),
 | 
			
		||||
            Some(format!("{:?}", io::ErrorKind::Other))
 | 
			
		||||
        );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -352,7 +345,7 @@ mod tests {
 | 
			
		||||
    fn test_poll_continues_after_error() {
 | 
			
		||||
        const EVENT: InternalEvent = InternalEvent::Event(Event::Resize(10, 10));
 | 
			
		||||
 | 
			
		||||
        let source = FakeSource::new(&[EVENT, EVENT], ErrorKind::from(io::ErrorKind::Other));
 | 
			
		||||
        let source = FakeSource::new(&[EVENT, EVENT]);
 | 
			
		||||
 | 
			
		||||
        let mut reader = InternalEventReader {
 | 
			
		||||
            events: VecDeque::new(),
 | 
			
		||||
@ -371,7 +364,7 @@ mod tests {
 | 
			
		||||
    fn test_read_continues_after_error() {
 | 
			
		||||
        const EVENT: InternalEvent = InternalEvent::Event(Event::Resize(10, 10));
 | 
			
		||||
 | 
			
		||||
        let source = FakeSource::new(&[EVENT, EVENT], ErrorKind::from(io::ErrorKind::Other));
 | 
			
		||||
        let source = FakeSource::new(&[EVENT, EVENT]);
 | 
			
		||||
 | 
			
		||||
        let mut reader = InternalEventReader {
 | 
			
		||||
            events: VecDeque::new(),
 | 
			
		||||
@ -387,14 +380,14 @@ mod tests {
 | 
			
		||||
    #[derive(Default)]
 | 
			
		||||
    struct FakeSource {
 | 
			
		||||
        events: VecDeque<InternalEvent>,
 | 
			
		||||
        error: Option<ErrorKind>,
 | 
			
		||||
        error: Option<io::Error>,
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    impl FakeSource {
 | 
			
		||||
        fn new(events: &[InternalEvent], error: ErrorKind) -> FakeSource {
 | 
			
		||||
        fn new(events: &[InternalEvent]) -> FakeSource {
 | 
			
		||||
            FakeSource {
 | 
			
		||||
                events: events.to_vec().into(),
 | 
			
		||||
                error: Some(error),
 | 
			
		||||
                error: Some(io::Error::new(io::ErrorKind::Other, "")),
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@ -404,20 +397,10 @@ mod tests {
 | 
			
		||||
                error: None,
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        fn with_error(error: ErrorKind) -> FakeSource {
 | 
			
		||||
            FakeSource {
 | 
			
		||||
                events: VecDeque::new(),
 | 
			
		||||
                error: Some(error),
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    impl EventSource for FakeSource {
 | 
			
		||||
        fn try_read(
 | 
			
		||||
            &mut self,
 | 
			
		||||
            _timeout: Option<Duration>,
 | 
			
		||||
        ) -> Result<Option<InternalEvent>, ErrorKind> {
 | 
			
		||||
        fn try_read(&mut self, _timeout: Option<Duration>) -> io::Result<Option<InternalEvent>> {
 | 
			
		||||
            // Return error if set in case there's just one remaining event
 | 
			
		||||
            if self.events.len() == 1 {
 | 
			
		||||
                if let Some(error) = self.error.take() {
 | 
			
		||||
 | 
			
		||||
@ -1,4 +1,4 @@
 | 
			
		||||
use std::time::Duration;
 | 
			
		||||
use std::{io, time::Duration};
 | 
			
		||||
 | 
			
		||||
#[cfg(feature = "event-stream")]
 | 
			
		||||
use super::sys::Waker;
 | 
			
		||||
@ -19,7 +19,7 @@ pub(crate) trait EventSource: Sync + Send {
 | 
			
		||||
    ///               for the given timeout
 | 
			
		||||
    ///
 | 
			
		||||
    /// Returns `Ok(None)` if there's no event available and timeout expires.
 | 
			
		||||
    fn try_read(&mut self, timeout: Option<Duration>) -> crate::Result<Option<InternalEvent>>;
 | 
			
		||||
    fn try_read(&mut self, timeout: Option<Duration>) -> io::Result<Option<InternalEvent>>;
 | 
			
		||||
 | 
			
		||||
    /// Returns a `Waker` allowing to wake/force the `try_read` method to return `Ok(None)`.
 | 
			
		||||
    #[cfg(feature = "event-stream")]
 | 
			
		||||
 | 
			
		||||
@ -3,8 +3,6 @@ use std::{collections::VecDeque, io, time::Duration};
 | 
			
		||||
use mio::{unix::SourceFd, Events, Interest, Poll, Token};
 | 
			
		||||
use signal_hook_mio::v0_8::Signals;
 | 
			
		||||
 | 
			
		||||
use crate::Result;
 | 
			
		||||
 | 
			
		||||
#[cfg(feature = "event-stream")]
 | 
			
		||||
use crate::event::sys::Waker;
 | 
			
		||||
use crate::event::{
 | 
			
		||||
@ -35,11 +33,11 @@ pub(crate) struct UnixInternalEventSource {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl UnixInternalEventSource {
 | 
			
		||||
    pub fn new() -> Result<Self> {
 | 
			
		||||
    pub fn new() -> io::Result<Self> {
 | 
			
		||||
        UnixInternalEventSource::from_file_descriptor(tty_fd()?)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    pub(crate) fn from_file_descriptor(input_fd: FileDesc) -> Result<Self> {
 | 
			
		||||
    pub(crate) fn from_file_descriptor(input_fd: FileDesc) -> io::Result<Self> {
 | 
			
		||||
        let poll = Poll::new()?;
 | 
			
		||||
        let registry = poll.registry();
 | 
			
		||||
 | 
			
		||||
@ -67,7 +65,7 @@ impl UnixInternalEventSource {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl EventSource for UnixInternalEventSource {
 | 
			
		||||
    fn try_read(&mut self, timeout: Option<Duration>) -> Result<Option<InternalEvent>> {
 | 
			
		||||
    fn try_read(&mut self, timeout: Option<Duration>) -> io::Result<Option<InternalEvent>> {
 | 
			
		||||
        if let Some(event) = self.parser.next() {
 | 
			
		||||
            return Ok(Some(event));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@ -5,8 +5,6 @@ use signal_hook::low_level::pipe;
 | 
			
		||||
 | 
			
		||||
use crate::event::timeout::PollTimeout;
 | 
			
		||||
use crate::event::Event;
 | 
			
		||||
use crate::Result;
 | 
			
		||||
 | 
			
		||||
use filedescriptor::{poll, pollfd, POLLIN};
 | 
			
		||||
 | 
			
		||||
#[cfg(feature = "event-stream")]
 | 
			
		||||
@ -23,7 +21,7 @@ struct WakePipe {
 | 
			
		||||
 | 
			
		||||
#[cfg(feature = "event-stream")]
 | 
			
		||||
impl WakePipe {
 | 
			
		||||
    fn new() -> Result<Self> {
 | 
			
		||||
    fn new() -> io::Result<Self> {
 | 
			
		||||
        let (receiver, sender) = nonblocking_unix_pair()?;
 | 
			
		||||
        Ok(WakePipe {
 | 
			
		||||
            receiver,
 | 
			
		||||
@ -46,7 +44,7 @@ pub(crate) struct UnixInternalEventSource {
 | 
			
		||||
    wake_pipe: WakePipe,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fn nonblocking_unix_pair() -> Result<(UnixStream, UnixStream)> {
 | 
			
		||||
fn nonblocking_unix_pair() -> io::Result<(UnixStream, UnixStream)> {
 | 
			
		||||
    let (receiver, sender) = UnixStream::pair()?;
 | 
			
		||||
    receiver.set_nonblocking(true)?;
 | 
			
		||||
    sender.set_nonblocking(true)?;
 | 
			
		||||
@ -54,11 +52,11 @@ fn nonblocking_unix_pair() -> Result<(UnixStream, UnixStream)> {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl UnixInternalEventSource {
 | 
			
		||||
    pub fn new() -> Result<Self> {
 | 
			
		||||
    pub fn new() -> io::Result<Self> {
 | 
			
		||||
        UnixInternalEventSource::from_file_descriptor(tty_fd()?)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    pub(crate) fn from_file_descriptor(input_fd: FileDesc) -> Result<Self> {
 | 
			
		||||
    pub(crate) fn from_file_descriptor(input_fd: FileDesc) -> io::Result<Self> {
 | 
			
		||||
        Ok(UnixInternalEventSource {
 | 
			
		||||
            parser: Parser::default(),
 | 
			
		||||
            tty_buffer: [0u8; TTY_BUFFER_SIZE],
 | 
			
		||||
@ -80,7 +78,7 @@ impl UnixInternalEventSource {
 | 
			
		||||
///
 | 
			
		||||
/// Similar to `std::io::Read::read_to_end`, except this function
 | 
			
		||||
/// only fills the given buffer and does not read beyond that.
 | 
			
		||||
fn read_complete(fd: &FileDesc, buf: &mut [u8]) -> Result<usize> {
 | 
			
		||||
fn read_complete(fd: &FileDesc, buf: &mut [u8]) -> io::Result<usize> {
 | 
			
		||||
    loop {
 | 
			
		||||
        match fd.read(buf, buf.len()) {
 | 
			
		||||
            Ok(x) => return Ok(x),
 | 
			
		||||
@ -94,7 +92,7 @@ fn read_complete(fd: &FileDesc, buf: &mut [u8]) -> Result<usize> {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl EventSource for UnixInternalEventSource {
 | 
			
		||||
    fn try_read(&mut self, timeout: Option<Duration>) -> Result<Option<InternalEvent>> {
 | 
			
		||||
    fn try_read(&mut self, timeout: Option<Duration>) -> io::Result<Option<InternalEvent>> {
 | 
			
		||||
        let timeout = PollTimeout::new(timeout);
 | 
			
		||||
 | 
			
		||||
        fn make_pollfd<F: AsRawFd>(fd: &F) -> pollfd {
 | 
			
		||||
 | 
			
		||||
@ -24,7 +24,7 @@ pub(crate) struct WindowsEventSource {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl WindowsEventSource {
 | 
			
		||||
    pub(crate) fn new() -> crate::Result<WindowsEventSource> {
 | 
			
		||||
    pub(crate) fn new() -> std::io::Result<WindowsEventSource> {
 | 
			
		||||
        let console = Console::from(Handle::current_in_handle()?);
 | 
			
		||||
        Ok(WindowsEventSource {
 | 
			
		||||
            console,
 | 
			
		||||
@ -41,7 +41,7 @@ impl WindowsEventSource {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl EventSource for WindowsEventSource {
 | 
			
		||||
    fn try_read(&mut self, timeout: Option<Duration>) -> crate::Result<Option<InternalEvent>> {
 | 
			
		||||
    fn try_read(&mut self, timeout: Option<Duration>) -> std::io::Result<Option<InternalEvent>> {
 | 
			
		||||
        let poll_timeout = PollTimeout::new(timeout);
 | 
			
		||||
 | 
			
		||||
        loop {
 | 
			
		||||
 | 
			
		||||
@ -1,4 +1,5 @@
 | 
			
		||||
use std::{
 | 
			
		||||
    io,
 | 
			
		||||
    pin::Pin,
 | 
			
		||||
    sync::{
 | 
			
		||||
        atomic::{AtomicBool, Ordering},
 | 
			
		||||
@ -12,8 +13,6 @@ use std::{
 | 
			
		||||
 | 
			
		||||
use futures_core::stream::Stream;
 | 
			
		||||
 | 
			
		||||
use crate::Result;
 | 
			
		||||
 | 
			
		||||
use crate::event::{
 | 
			
		||||
    filter::EventFilter, lock_internal_event_reader, poll_internal, read_internal, sys::Waker,
 | 
			
		||||
    Event, InternalEvent,
 | 
			
		||||
@ -100,7 +99,7 @@ struct Task {
 | 
			
		||||
// We have to wake up the poll_internal (force it to return Ok(false)) and quit
 | 
			
		||||
// the thread before we drop.
 | 
			
		||||
impl Stream for EventStream {
 | 
			
		||||
    type Item = Result<Event>;
 | 
			
		||||
    type Item = io::Result<Event>;
 | 
			
		||||
 | 
			
		||||
    fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
 | 
			
		||||
        let result = match poll_internal(Some(Duration::from_secs(0)), &EventFilter) {
 | 
			
		||||
 | 
			
		||||
@ -1,12 +1,8 @@
 | 
			
		||||
use std::io;
 | 
			
		||||
 | 
			
		||||
use crate::{
 | 
			
		||||
    event::{
 | 
			
		||||
        Event, KeyCode, KeyEvent, KeyEventKind, KeyEventState, KeyModifiers,
 | 
			
		||||
        KeyboardEnhancementFlags, MediaKeyCode, ModifierKeyCode, MouseButton, MouseEvent,
 | 
			
		||||
        MouseEventKind,
 | 
			
		||||
    },
 | 
			
		||||
    ErrorKind, Result,
 | 
			
		||||
use crate::event::{
 | 
			
		||||
    Event, KeyCode, KeyEvent, KeyEventKind, KeyEventState, KeyModifiers, KeyboardEnhancementFlags,
 | 
			
		||||
    MediaKeyCode, ModifierKeyCode, MouseButton, MouseEvent, MouseEventKind,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
use super::super::super::InternalEvent;
 | 
			
		||||
@ -23,11 +19,14 @@ use super::super::super::InternalEvent;
 | 
			
		||||
// Ok(Some(event)) -> we have event, clear the buffer
 | 
			
		||||
//
 | 
			
		||||
 | 
			
		||||
fn could_not_parse_event_error() -> ErrorKind {
 | 
			
		||||
fn could_not_parse_event_error() -> io::Error {
 | 
			
		||||
    io::Error::new(io::ErrorKind::Other, "Could not parse an event.")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub(crate) fn parse_event(buffer: &[u8], input_available: bool) -> Result<Option<InternalEvent>> {
 | 
			
		||||
pub(crate) fn parse_event(
 | 
			
		||||
    buffer: &[u8],
 | 
			
		||||
    input_available: bool,
 | 
			
		||||
) -> io::Result<Option<InternalEvent>> {
 | 
			
		||||
    if buffer.is_empty() {
 | 
			
		||||
        return Ok(None);
 | 
			
		||||
    }
 | 
			
		||||
@ -135,7 +134,7 @@ fn char_code_to_event(code: KeyCode) -> KeyEvent {
 | 
			
		||||
    KeyEvent::new(code, modifiers)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub(crate) fn parse_csi(buffer: &[u8]) -> Result<Option<InternalEvent>> {
 | 
			
		||||
pub(crate) fn parse_csi(buffer: &[u8]) -> io::Result<Option<InternalEvent>> {
 | 
			
		||||
    assert!(buffer.starts_with(&[b'\x1B', b'['])); // ESC [
 | 
			
		||||
 | 
			
		||||
    if buffer.len() == 2 {
 | 
			
		||||
@ -214,7 +213,7 @@ pub(crate) fn parse_csi(buffer: &[u8]) -> Result<Option<InternalEvent>> {
 | 
			
		||||
    Ok(input_event.map(InternalEvent::Event))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub(crate) fn next_parsed<T>(iter: &mut dyn Iterator<Item = &str>) -> Result<T>
 | 
			
		||||
pub(crate) fn next_parsed<T>(iter: &mut dyn Iterator<Item = &str>) -> io::Result<T>
 | 
			
		||||
where
 | 
			
		||||
    T: std::str::FromStr,
 | 
			
		||||
{
 | 
			
		||||
@ -224,7 +223,7 @@ where
 | 
			
		||||
        .map_err(|_| could_not_parse_event_error())
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fn modifier_and_kind_parsed(iter: &mut dyn Iterator<Item = &str>) -> Result<(u8, u8)> {
 | 
			
		||||
fn modifier_and_kind_parsed(iter: &mut dyn Iterator<Item = &str>) -> io::Result<(u8, u8)> {
 | 
			
		||||
    let mut sub_split = iter
 | 
			
		||||
        .next()
 | 
			
		||||
        .ok_or_else(could_not_parse_event_error)?
 | 
			
		||||
@ -239,7 +238,7 @@ fn modifier_and_kind_parsed(iter: &mut dyn Iterator<Item = &str>) -> Result<(u8,
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub(crate) fn parse_csi_cursor_position(buffer: &[u8]) -> Result<Option<InternalEvent>> {
 | 
			
		||||
pub(crate) fn parse_csi_cursor_position(buffer: &[u8]) -> io::Result<Option<InternalEvent>> {
 | 
			
		||||
    // ESC [ Cy ; Cx R
 | 
			
		||||
    //   Cy - cursor row number (starting from 1)
 | 
			
		||||
    //   Cx - cursor column number (starting from 1)
 | 
			
		||||
@ -257,7 +256,7 @@ pub(crate) fn parse_csi_cursor_position(buffer: &[u8]) -> Result<Option<Internal
 | 
			
		||||
    Ok(Some(InternalEvent::CursorPosition(x, y)))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fn parse_csi_keyboard_enhancement_flags(buffer: &[u8]) -> Result<Option<InternalEvent>> {
 | 
			
		||||
fn parse_csi_keyboard_enhancement_flags(buffer: &[u8]) -> io::Result<Option<InternalEvent>> {
 | 
			
		||||
    // ESC [ ? flags u
 | 
			
		||||
    assert!(buffer.starts_with(&[b'\x1B', b'[', b'?'])); // ESC [ ?
 | 
			
		||||
    assert!(buffer.ends_with(&[b'u']));
 | 
			
		||||
@ -289,7 +288,7 @@ fn parse_csi_keyboard_enhancement_flags(buffer: &[u8]) -> Result<Option<Internal
 | 
			
		||||
    Ok(Some(InternalEvent::KeyboardEnhancementFlags(flags)))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fn parse_csi_primary_device_attributes(buffer: &[u8]) -> Result<Option<InternalEvent>> {
 | 
			
		||||
fn parse_csi_primary_device_attributes(buffer: &[u8]) -> io::Result<Option<InternalEvent>> {
 | 
			
		||||
    // ESC [ 64 ; attr1 ; attr2 ; ... ; attrn ; c
 | 
			
		||||
    assert!(buffer.starts_with(&[b'\x1B', b'[', b'?']));
 | 
			
		||||
    assert!(buffer.ends_with(&[b'c']));
 | 
			
		||||
@ -346,7 +345,7 @@ fn parse_key_event_kind(kind: u8) -> KeyEventKind {
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub(crate) fn parse_csi_modifier_key_code(buffer: &[u8]) -> Result<Option<InternalEvent>> {
 | 
			
		||||
pub(crate) fn parse_csi_modifier_key_code(buffer: &[u8]) -> io::Result<Option<InternalEvent>> {
 | 
			
		||||
    assert!(buffer.starts_with(&[b'\x1B', b'['])); // ESC [
 | 
			
		||||
                                                   //
 | 
			
		||||
    let s = std::str::from_utf8(&buffer[2..buffer.len() - 1])
 | 
			
		||||
@ -495,7 +494,7 @@ fn translate_functional_key_code(codepoint: u32) -> Option<(KeyCode, KeyEventSta
 | 
			
		||||
    None
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub(crate) fn parse_csi_u_encoded_key_code(buffer: &[u8]) -> Result<Option<InternalEvent>> {
 | 
			
		||||
pub(crate) fn parse_csi_u_encoded_key_code(buffer: &[u8]) -> io::Result<Option<InternalEvent>> {
 | 
			
		||||
    assert!(buffer.starts_with(&[b'\x1B', b'['])); // ESC [
 | 
			
		||||
    assert!(buffer.ends_with(&[b'u']));
 | 
			
		||||
 | 
			
		||||
@ -617,7 +616,7 @@ pub(crate) fn parse_csi_u_encoded_key_code(buffer: &[u8]) -> Result<Option<Inter
 | 
			
		||||
    Ok(Some(InternalEvent::Event(input_event)))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub(crate) fn parse_csi_special_key_code(buffer: &[u8]) -> Result<Option<InternalEvent>> {
 | 
			
		||||
pub(crate) fn parse_csi_special_key_code(buffer: &[u8]) -> io::Result<Option<InternalEvent>> {
 | 
			
		||||
    assert!(buffer.starts_with(&[b'\x1B', b'['])); // ESC [
 | 
			
		||||
    assert!(buffer.ends_with(&[b'~']));
 | 
			
		||||
 | 
			
		||||
@ -661,7 +660,7 @@ pub(crate) fn parse_csi_special_key_code(buffer: &[u8]) -> Result<Option<Interna
 | 
			
		||||
    Ok(Some(InternalEvent::Event(input_event)))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub(crate) fn parse_csi_rxvt_mouse(buffer: &[u8]) -> Result<Option<InternalEvent>> {
 | 
			
		||||
pub(crate) fn parse_csi_rxvt_mouse(buffer: &[u8]) -> io::Result<Option<InternalEvent>> {
 | 
			
		||||
    // rxvt mouse encoding:
 | 
			
		||||
    // ESC [ Cb ; Cx ; Cy ; M
 | 
			
		||||
 | 
			
		||||
@ -688,7 +687,7 @@ pub(crate) fn parse_csi_rxvt_mouse(buffer: &[u8]) -> Result<Option<InternalEvent
 | 
			
		||||
    }))))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub(crate) fn parse_csi_normal_mouse(buffer: &[u8]) -> Result<Option<InternalEvent>> {
 | 
			
		||||
pub(crate) fn parse_csi_normal_mouse(buffer: &[u8]) -> io::Result<Option<InternalEvent>> {
 | 
			
		||||
    // Normal mouse encoding: ESC [ M CB Cx Cy (6 characters only).
 | 
			
		||||
 | 
			
		||||
    assert!(buffer.starts_with(&[b'\x1B', b'[', b'M'])); // ESC [ M
 | 
			
		||||
@ -716,7 +715,7 @@ pub(crate) fn parse_csi_normal_mouse(buffer: &[u8]) -> Result<Option<InternalEve
 | 
			
		||||
    }))))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub(crate) fn parse_csi_sgr_mouse(buffer: &[u8]) -> Result<Option<InternalEvent>> {
 | 
			
		||||
pub(crate) fn parse_csi_sgr_mouse(buffer: &[u8]) -> io::Result<Option<InternalEvent>> {
 | 
			
		||||
    // ESC [ < Cb ; Cx ; Cy (;) (M or m)
 | 
			
		||||
 | 
			
		||||
    assert!(buffer.starts_with(&[b'\x1B', b'[', b'<'])); // ESC [ <
 | 
			
		||||
@ -774,7 +773,7 @@ pub(crate) fn parse_csi_sgr_mouse(buffer: &[u8]) -> Result<Option<InternalEvent>
 | 
			
		||||
/// - mouse is dragging
 | 
			
		||||
/// - button number
 | 
			
		||||
/// - button number
 | 
			
		||||
fn parse_cb(cb: u8) -> Result<(MouseEventKind, KeyModifiers)> {
 | 
			
		||||
fn parse_cb(cb: u8) -> io::Result<(MouseEventKind, KeyModifiers)> {
 | 
			
		||||
    let button_number = (cb & 0b0000_0011) | ((cb & 0b1100_0000) >> 4);
 | 
			
		||||
    let dragging = cb & 0b0010_0000 == 0b0010_0000;
 | 
			
		||||
 | 
			
		||||
@ -809,7 +808,7 @@ fn parse_cb(cb: u8) -> Result<(MouseEventKind, KeyModifiers)> {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[cfg(feature = "bracketed-paste")]
 | 
			
		||||
pub(crate) fn parse_csi_bracketed_paste(buffer: &[u8]) -> Result<Option<InternalEvent>> {
 | 
			
		||||
pub(crate) fn parse_csi_bracketed_paste(buffer: &[u8]) -> io::Result<Option<InternalEvent>> {
 | 
			
		||||
    // ESC [ 2 0 0 ~ pasted text ESC 2 0 1 ~
 | 
			
		||||
    assert!(buffer.starts_with(b"\x1B[200~"));
 | 
			
		||||
 | 
			
		||||
@ -821,7 +820,7 @@ pub(crate) fn parse_csi_bracketed_paste(buffer: &[u8]) -> Result<Option<Internal
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub(crate) fn parse_utf8_char(buffer: &[u8]) -> Result<Option<char>> {
 | 
			
		||||
pub(crate) fn parse_utf8_char(buffer: &[u8]) -> io::Result<Option<char>> {
 | 
			
		||||
    match std::str::from_utf8(buffer) {
 | 
			
		||||
        Ok(s) => {
 | 
			
		||||
            let ch = s.chars().next().ok_or_else(could_not_parse_event_error)?;
 | 
			
		||||
 | 
			
		||||
@ -2,8 +2,6 @@ use std::sync::{Arc, Mutex};
 | 
			
		||||
 | 
			
		||||
use ::mio::{Registry, Token};
 | 
			
		||||
 | 
			
		||||
use crate::Result;
 | 
			
		||||
 | 
			
		||||
/// Allows to wake up the `mio::Poll::poll()` method.
 | 
			
		||||
/// This type wraps `mio::Waker`, for more information see its documentation.
 | 
			
		||||
#[derive(Clone, Debug)]
 | 
			
		||||
@ -13,7 +11,7 @@ pub(crate) struct Waker {
 | 
			
		||||
 | 
			
		||||
impl Waker {
 | 
			
		||||
    /// Create a new `Waker`.
 | 
			
		||||
    pub(crate) fn new(registry: &Registry, waker_token: Token) -> Result<Self> {
 | 
			
		||||
    pub(crate) fn new(registry: &Registry, waker_token: Token) -> std::io::Result<Self> {
 | 
			
		||||
        Ok(Self {
 | 
			
		||||
            inner: Arc::new(Mutex::new(mio::Waker::new(registry, waker_token)?)),
 | 
			
		||||
        })
 | 
			
		||||
@ -22,7 +20,7 @@ impl Waker {
 | 
			
		||||
    /// Wake up the [`Poll`] associated with this `Waker`.
 | 
			
		||||
    ///
 | 
			
		||||
    /// Readiness is set to `Ready::readable()`.
 | 
			
		||||
    pub(crate) fn wake(&self) -> Result<()> {
 | 
			
		||||
    pub(crate) fn wake(&self) -> std::io::Result<()> {
 | 
			
		||||
        self.inner.lock().unwrap().wake()
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -30,7 +28,7 @@ impl Waker {
 | 
			
		||||
    ///
 | 
			
		||||
    /// This function is not impl
 | 
			
		||||
    #[allow(dead_code, clippy::clippy::unnecessary_wraps)]
 | 
			
		||||
    pub(crate) fn reset(&self) -> Result<()> {
 | 
			
		||||
    pub(crate) fn reset(&self) -> std::io::Result<()> {
 | 
			
		||||
        Ok(())
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -1,11 +1,9 @@
 | 
			
		||||
use std::{
 | 
			
		||||
    io::Write,
 | 
			
		||||
    io::{self, Write},
 | 
			
		||||
    os::unix::net::UnixStream,
 | 
			
		||||
    sync::{Arc, Mutex},
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
use crate::Result;
 | 
			
		||||
 | 
			
		||||
/// Allows to wake up the EventSource::try_read() method.
 | 
			
		||||
#[derive(Clone, Debug)]
 | 
			
		||||
pub(crate) struct Waker {
 | 
			
		||||
@ -23,16 +21,8 @@ impl Waker {
 | 
			
		||||
    /// Wake up the [`Poll`] associated with this `Waker`.
 | 
			
		||||
    ///
 | 
			
		||||
    /// Readiness is set to `Ready::readable()`.
 | 
			
		||||
    pub(crate) fn wake(&self) -> Result<()> {
 | 
			
		||||
    pub(crate) fn wake(&self) -> io::Result<()> {
 | 
			
		||||
        self.inner.lock().unwrap().write(&[0])?;
 | 
			
		||||
        Ok(())
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// Resets the state so the same waker can be reused.
 | 
			
		||||
    ///
 | 
			
		||||
    /// This function is not impl
 | 
			
		||||
    #[allow(dead_code, clippy::clippy::unnecessary_wraps)]
 | 
			
		||||
    pub(crate) fn reset(&self) -> Result<()> {
 | 
			
		||||
        Ok(())
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -6,8 +6,6 @@ use std::sync::atomic::{AtomicU64, Ordering};
 | 
			
		||||
 | 
			
		||||
use crossterm_winapi::{ConsoleMode, Handle};
 | 
			
		||||
 | 
			
		||||
use crate::Result;
 | 
			
		||||
 | 
			
		||||
pub(crate) mod parse;
 | 
			
		||||
pub(crate) mod poll;
 | 
			
		||||
#[cfg(feature = "event-stream")]
 | 
			
		||||
@ -30,12 +28,12 @@ fn init_original_console_mode(original_mode: u32) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// Returns the original console color, make sure to call `init_console_color` before calling this function. Otherwise this function will panic.
 | 
			
		||||
fn original_console_mode() -> Result<u32> {
 | 
			
		||||
fn original_console_mode() -> std::io::Result<u32> {
 | 
			
		||||
    u32::try_from(ORIGINAL_CONSOLE_MODE.load(Ordering::Relaxed))
 | 
			
		||||
        .map_err(|_| io::Error::new(io::ErrorKind::Other, "Initial console modes not set"))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub(crate) fn enable_mouse_capture() -> Result<()> {
 | 
			
		||||
pub(crate) fn enable_mouse_capture() -> std::io::Result<()> {
 | 
			
		||||
    let mode = ConsoleMode::from(Handle::current_in_handle()?);
 | 
			
		||||
    init_original_console_mode(mode.mode()?);
 | 
			
		||||
    mode.set_mode(ENABLE_MOUSE_MODE)?;
 | 
			
		||||
@ -43,7 +41,7 @@ pub(crate) fn enable_mouse_capture() -> Result<()> {
 | 
			
		||||
    Ok(())
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub(crate) fn disable_mouse_capture() -> Result<()> {
 | 
			
		||||
pub(crate) fn disable_mouse_capture() -> std::io::Result<()> {
 | 
			
		||||
    let mode = ConsoleMode::from(Handle::current_in_handle()?);
 | 
			
		||||
    mode.set_mode(original_console_mode()?)?;
 | 
			
		||||
    Ok(())
 | 
			
		||||
 | 
			
		||||
@ -12,12 +12,8 @@ use winapi::um::{
 | 
			
		||||
    },
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
use crate::{
 | 
			
		||||
    event::{
 | 
			
		||||
        Event, KeyCode, KeyEvent, KeyEventKind, KeyModifiers, MouseButton, MouseEvent,
 | 
			
		||||
        MouseEventKind,
 | 
			
		||||
    },
 | 
			
		||||
    Result,
 | 
			
		||||
use crate::event::{
 | 
			
		||||
    Event, KeyCode, KeyEvent, KeyEventKind, KeyModifiers, MouseButton, MouseEvent, MouseEventKind,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#[derive(Default)]
 | 
			
		||||
@ -301,7 +297,7 @@ fn parse_key_event_record(key_event: &KeyEventRecord) -> Option<WindowsKeyEvent>
 | 
			
		||||
 | 
			
		||||
// The 'y' position of a mouse event or resize event is not relative to the window but absolute to screen buffer.
 | 
			
		||||
// This means that when the mouse cursor is at the top left it will be x: 0, y: 2295 (e.g. y = number of cells conting from the absolute buffer height) instead of relative x: 0, y: 0 to the window.
 | 
			
		||||
pub fn parse_relative_y(y: i16) -> Result<i16> {
 | 
			
		||||
pub fn parse_relative_y(y: i16) -> std::io::Result<i16> {
 | 
			
		||||
    let window_size = ScreenBuffer::current()?.info()?.terminal_window();
 | 
			
		||||
    Ok(y - window_size.top)
 | 
			
		||||
}
 | 
			
		||||
@ -309,7 +305,7 @@ pub fn parse_relative_y(y: i16) -> Result<i16> {
 | 
			
		||||
fn parse_mouse_event_record(
 | 
			
		||||
    event: &crossterm_winapi::MouseEvent,
 | 
			
		||||
    buttons_pressed: &MouseButtonsPressed,
 | 
			
		||||
) -> Result<Option<MouseEvent>> {
 | 
			
		||||
) -> std::io::Result<Option<MouseEvent>> {
 | 
			
		||||
    let modifiers = KeyModifiers::from(&event.control_key_state);
 | 
			
		||||
 | 
			
		||||
    let xpos = event.mouse_position.x as u16;
 | 
			
		||||
 | 
			
		||||
@ -10,8 +10,6 @@ use winapi::{
 | 
			
		||||
    },
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
use crate::Result;
 | 
			
		||||
 | 
			
		||||
#[cfg(feature = "event-stream")]
 | 
			
		||||
pub(crate) use super::waker::Waker;
 | 
			
		||||
 | 
			
		||||
@ -28,7 +26,7 @@ impl WinApiPoll {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    #[cfg(feature = "event-stream")]
 | 
			
		||||
    pub(crate) fn new() -> Result<WinApiPoll> {
 | 
			
		||||
    pub(crate) fn new() -> std::io::Result<WinApiPoll> {
 | 
			
		||||
        Ok(WinApiPoll {
 | 
			
		||||
            waker: Waker::new()?,
 | 
			
		||||
        })
 | 
			
		||||
@ -36,7 +34,7 @@ impl WinApiPoll {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl WinApiPoll {
 | 
			
		||||
    pub fn poll(&mut self, timeout: Option<Duration>) -> Result<Option<bool>> {
 | 
			
		||||
    pub fn poll(&mut self, timeout: Option<Duration>) -> std::io::Result<Option<bool>> {
 | 
			
		||||
        let dw_millis = if let Some(duration) = timeout {
 | 
			
		||||
            duration.as_millis() as u32
 | 
			
		||||
        } else {
 | 
			
		||||
 | 
			
		||||
@ -2,8 +2,6 @@ use std::sync::{Arc, Mutex};
 | 
			
		||||
 | 
			
		||||
use crossterm_winapi::Semaphore;
 | 
			
		||||
 | 
			
		||||
use crate::Result;
 | 
			
		||||
 | 
			
		||||
/// Allows to wake up the `WinApiPoll::poll()` method.
 | 
			
		||||
#[derive(Clone, Debug)]
 | 
			
		||||
pub(crate) struct Waker {
 | 
			
		||||
@ -15,7 +13,7 @@ impl Waker {
 | 
			
		||||
    ///
 | 
			
		||||
    /// `Waker` is based on the `Semaphore`. You have to use the semaphore
 | 
			
		||||
    /// handle along with the `WaitForMultipleObjects`.
 | 
			
		||||
    pub(crate) fn new() -> Result<Self> {
 | 
			
		||||
    pub(crate) fn new() -> std::io::Result<Self> {
 | 
			
		||||
        let inner = Semaphore::new()?;
 | 
			
		||||
 | 
			
		||||
        Ok(Self {
 | 
			
		||||
@ -24,13 +22,13 @@ impl Waker {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// Wakes the `WaitForMultipleObjects`.
 | 
			
		||||
    pub(crate) fn wake(&self) -> Result<()> {
 | 
			
		||||
    pub(crate) fn wake(&self) -> std::io::Result<()> {
 | 
			
		||||
        self.inner.lock().unwrap().release()?;
 | 
			
		||||
        Ok(())
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// Replaces the current semaphore with a new one allowing us to reuse the same `Waker`.
 | 
			
		||||
    pub(crate) fn reset(&self) -> Result<()> {
 | 
			
		||||
    pub(crate) fn reset(&self) -> std::io::Result<()> {
 | 
			
		||||
        *self.inner.lock().unwrap() = Semaphore::new()?;
 | 
			
		||||
        Ok(())
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										28
									
								
								src/lib.rs
									
									
									
									
									
								
							
							
						
						
									
										28
									
								
								src/lib.rs
									
									
									
									
									
								
							@ -1,7 +1,7 @@
 | 
			
		||||
#![deny(unused_imports, unused_must_use)]
 | 
			
		||||
 | 
			
		||||
//! # Cross-platform Terminal Manipulation Library 
 | 
			
		||||
//! 
 | 
			
		||||
//! # Cross-platform Terminal Manipulation Library
 | 
			
		||||
//!
 | 
			
		||||
//! Crossterm is a pure-rust, terminal manipulation library that makes it possible to write cross-platform text-based interfaces (see [features](#features)). It supports all UNIX and Windows terminals down to Windows 7 (not all terminals are tested,
 | 
			
		||||
//! see [Tested Terminals](#tested-terminals) for more info).
 | 
			
		||||
//!
 | 
			
		||||
@ -155,7 +155,7 @@
 | 
			
		||||
//! Macros:
 | 
			
		||||
//!
 | 
			
		||||
//! ```no_run
 | 
			
		||||
//! use std::io::{Write, stdout};
 | 
			
		||||
//! use std::io::{stdout, Write};
 | 
			
		||||
//! use crossterm::{execute, ExecutableCommand, cursor};
 | 
			
		||||
//!
 | 
			
		||||
//! let mut stdout = stdout();
 | 
			
		||||
@ -172,14 +172,14 @@
 | 
			
		||||
//! Functions:
 | 
			
		||||
//!
 | 
			
		||||
//! ```no_run
 | 
			
		||||
//! use std::io::{stdout, Write};
 | 
			
		||||
//! use std::io::{self, Write};
 | 
			
		||||
//! use crossterm::{
 | 
			
		||||
//!     ExecutableCommand, QueueableCommand,
 | 
			
		||||
//!     terminal, cursor, style::{self, Stylize}, Result
 | 
			
		||||
//!     terminal, cursor, style::{self, Stylize}
 | 
			
		||||
//! };
 | 
			
		||||
//!
 | 
			
		||||
//! fn main() -> Result<()> {
 | 
			
		||||
//!   let mut stdout = stdout();
 | 
			
		||||
//! fn main() -> io::Result<()> {
 | 
			
		||||
//!   let mut stdout = io::stdout();
 | 
			
		||||
//!
 | 
			
		||||
//!   stdout.execute(terminal::Clear(terminal::ClearType::All))?;
 | 
			
		||||
//!
 | 
			
		||||
@ -201,14 +201,14 @@
 | 
			
		||||
//! Macros:
 | 
			
		||||
//!
 | 
			
		||||
//! ```no_run
 | 
			
		||||
//! use std::io::{stdout, Write};
 | 
			
		||||
//! use std::io::{self, Write};
 | 
			
		||||
//! use crossterm::{
 | 
			
		||||
//!     execute, queue,
 | 
			
		||||
//!     style::{self, Stylize}, cursor, terminal, Result
 | 
			
		||||
//!     style::{self, Stylize}, cursor, terminal
 | 
			
		||||
//! };
 | 
			
		||||
//!
 | 
			
		||||
//! fn main() -> Result<()> {
 | 
			
		||||
//!   let mut stdout = stdout();
 | 
			
		||||
//! fn main() -> io::Result<()> {
 | 
			
		||||
//!   let mut stdout = io::stdout();
 | 
			
		||||
//!
 | 
			
		||||
//!   execute!(stdout, terminal::Clear(terminal::ClearType::All))?;
 | 
			
		||||
//!
 | 
			
		||||
@ -230,10 +230,7 @@
 | 
			
		||||
//! [stderr]: https://doc.rust-lang.org/std/io/fn.stderr.html
 | 
			
		||||
//! [flush]: https://doc.rust-lang.org/std/io/trait.Write.html#tymethod.flush
 | 
			
		||||
 | 
			
		||||
pub use crate::{
 | 
			
		||||
    command::{Command, ExecutableCommand, QueueableCommand, SynchronizedUpdate},
 | 
			
		||||
    error::{ErrorKind, Result},
 | 
			
		||||
};
 | 
			
		||||
pub use crate::command::{Command, ExecutableCommand, QueueableCommand, SynchronizedUpdate};
 | 
			
		||||
 | 
			
		||||
/// A module to work with the terminal cursor
 | 
			
		||||
pub mod cursor;
 | 
			
		||||
@ -252,7 +249,6 @@ pub mod tty;
 | 
			
		||||
/// A module that exposes one function to check if the current terminal supports ANSI sequences.
 | 
			
		||||
pub mod ansi_support;
 | 
			
		||||
mod command;
 | 
			
		||||
mod error;
 | 
			
		||||
pub(crate) mod macros;
 | 
			
		||||
 | 
			
		||||
#[cfg(all(windows, not(feature = "windows")))]
 | 
			
		||||
 | 
			
		||||
@ -238,11 +238,9 @@ mod tests {
 | 
			
		||||
        use std::fmt;
 | 
			
		||||
 | 
			
		||||
        use std::cell::RefCell;
 | 
			
		||||
        use std::fmt::Debug;
 | 
			
		||||
 | 
			
		||||
        use super::FakeWrite;
 | 
			
		||||
        use crate::command::Command;
 | 
			
		||||
        use crate::error::Result as CrosstermResult;
 | 
			
		||||
 | 
			
		||||
        // We need to test two different APIs: WinAPI and the write api. We
 | 
			
		||||
        // don't know until runtime which we're supporting (via
 | 
			
		||||
@ -274,7 +272,7 @@ mod tests {
 | 
			
		||||
                f.write_str(self.value)
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            fn execute_winapi(&self) -> CrosstermResult<()> {
 | 
			
		||||
            fn execute_winapi(&self) -> std::io::Result<()> {
 | 
			
		||||
                self.stream.borrow_mut().push(self.value);
 | 
			
		||||
                Ok(())
 | 
			
		||||
            }
 | 
			
		||||
@ -293,9 +291,9 @@ mod tests {
 | 
			
		||||
        // If the stream was populated, it tests that the two arrays are equal.
 | 
			
		||||
        // If the writer was populated, it tests that the contents of the
 | 
			
		||||
        // write buffer are equal to the concatenation of `stream_result`.
 | 
			
		||||
        fn test_harness<E: Debug>(
 | 
			
		||||
        fn test_harness(
 | 
			
		||||
            stream_result: &[&'static str],
 | 
			
		||||
            test: impl FnOnce(&mut FakeWrite, &mut WindowsEventStream) -> Result<(), E>,
 | 
			
		||||
            test: impl FnOnce(&mut FakeWrite, &mut WindowsEventStream) -> std::io::Result<()>,
 | 
			
		||||
        ) {
 | 
			
		||||
            let mut stream = WindowsEventStream::default();
 | 
			
		||||
            let mut writer = FakeWrite::default();
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										39
									
								
								src/style.rs
									
									
									
									
									
								
							
							
						
						
									
										39
									
								
								src/style.rs
									
									
									
									
									
								
							@ -28,14 +28,13 @@
 | 
			
		||||
//! Using the Command API to color text.
 | 
			
		||||
//!
 | 
			
		||||
//! ```no_run
 | 
			
		||||
//! use std::io::{stdout, Write};
 | 
			
		||||
//!
 | 
			
		||||
//! use crossterm::{execute, Result};
 | 
			
		||||
//! use std::io::{self, Write};
 | 
			
		||||
//! use crossterm::execute;
 | 
			
		||||
//! use crossterm::style::{Print, SetForegroundColor, SetBackgroundColor, ResetColor, Color, Attribute};
 | 
			
		||||
//!
 | 
			
		||||
//! fn main() -> Result<()> {
 | 
			
		||||
//! fn main() -> io::Result<()> {
 | 
			
		||||
//!     execute!(
 | 
			
		||||
//!         stdout(),
 | 
			
		||||
//!         io::stdout(),
 | 
			
		||||
//!         // Blue foreground
 | 
			
		||||
//!         SetForegroundColor(Color::Blue),
 | 
			
		||||
//!         // Red background
 | 
			
		||||
@ -68,14 +67,14 @@
 | 
			
		||||
//! Using the Command API to set attributes.
 | 
			
		||||
//!
 | 
			
		||||
//! ```no_run
 | 
			
		||||
//! use std::io::{stdout, Write};
 | 
			
		||||
//! use std::io::{self, Write};
 | 
			
		||||
//!
 | 
			
		||||
//! use crossterm::{execute, Result, style::Print};
 | 
			
		||||
//! use crossterm::{execute, style::Print};
 | 
			
		||||
//! use crossterm::style::{SetAttribute, Attribute};
 | 
			
		||||
//!
 | 
			
		||||
//! fn main() -> Result<()> {
 | 
			
		||||
//! fn main() -> io::Result<()> {
 | 
			
		||||
//!     execute!(
 | 
			
		||||
//!         stdout(),
 | 
			
		||||
//!         io::stdout(),
 | 
			
		||||
//!         // Set to bold
 | 
			
		||||
//!         SetAttribute(Attribute::Bold),
 | 
			
		||||
//!         Print("Bold text here.".to_string()),
 | 
			
		||||
@ -118,8 +117,6 @@ use std::{
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
use crate::command::execute_fmt;
 | 
			
		||||
#[cfg(windows)]
 | 
			
		||||
use crate::Result;
 | 
			
		||||
use crate::{csi, impl_display, Command};
 | 
			
		||||
 | 
			
		||||
pub use self::{
 | 
			
		||||
@ -188,7 +185,7 @@ impl Command for SetForegroundColor {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    #[cfg(windows)]
 | 
			
		||||
    fn execute_winapi(&self) -> Result<()> {
 | 
			
		||||
    fn execute_winapi(&self) -> std::io::Result<()> {
 | 
			
		||||
        sys::windows::set_foreground_color(self.0)
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@ -212,7 +209,7 @@ impl Command for SetBackgroundColor {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    #[cfg(windows)]
 | 
			
		||||
    fn execute_winapi(&self) -> Result<()> {
 | 
			
		||||
    fn execute_winapi(&self) -> std::io::Result<()> {
 | 
			
		||||
        sys::windows::set_background_color(self.0)
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@ -236,7 +233,7 @@ impl Command for SetUnderlineColor {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    #[cfg(windows)]
 | 
			
		||||
    fn execute_winapi(&self) -> Result<()> {
 | 
			
		||||
    fn execute_winapi(&self) -> std::io::Result<()> {
 | 
			
		||||
        Err(std::io::Error::new(
 | 
			
		||||
            std::io::ErrorKind::Other,
 | 
			
		||||
            "SetUnderlineColor not supported by winapi.",
 | 
			
		||||
@ -280,7 +277,7 @@ impl Command for SetColors {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    #[cfg(windows)]
 | 
			
		||||
    fn execute_winapi(&self) -> Result<()> {
 | 
			
		||||
    fn execute_winapi(&self) -> std::io::Result<()> {
 | 
			
		||||
        if let Some(color) = self.0.foreground {
 | 
			
		||||
            sys::windows::set_foreground_color(color)?;
 | 
			
		||||
        }
 | 
			
		||||
@ -307,7 +304,7 @@ impl Command for SetAttribute {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    #[cfg(windows)]
 | 
			
		||||
    fn execute_winapi(&self) -> Result<()> {
 | 
			
		||||
    fn execute_winapi(&self) -> std::io::Result<()> {
 | 
			
		||||
        // attributes are not supported by WinAPI.
 | 
			
		||||
        Ok(())
 | 
			
		||||
    }
 | 
			
		||||
@ -334,7 +331,7 @@ impl Command for SetAttributes {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    #[cfg(windows)]
 | 
			
		||||
    fn execute_winapi(&self) -> Result<()> {
 | 
			
		||||
    fn execute_winapi(&self) -> std::io::Result<()> {
 | 
			
		||||
        // attributes are not supported by WinAPI.
 | 
			
		||||
        Ok(())
 | 
			
		||||
    }
 | 
			
		||||
@ -367,7 +364,7 @@ impl Command for SetStyle {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    #[cfg(windows)]
 | 
			
		||||
    fn execute_winapi(&self) -> Result<()> {
 | 
			
		||||
    fn execute_winapi(&self) -> std::io::Result<()> {
 | 
			
		||||
        panic!("tried to execute SetStyle command using WinAPI, use ANSI instead");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -434,7 +431,7 @@ impl<D: Display> Command for PrintStyledContent<D> {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    #[cfg(windows)]
 | 
			
		||||
    fn execute_winapi(&self) -> Result<()> {
 | 
			
		||||
    fn execute_winapi(&self) -> std::io::Result<()> {
 | 
			
		||||
        Ok(())
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@ -453,7 +450,7 @@ impl Command for ResetColor {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    #[cfg(windows)]
 | 
			
		||||
    fn execute_winapi(&self) -> Result<()> {
 | 
			
		||||
    fn execute_winapi(&self) -> std::io::Result<()> {
 | 
			
		||||
        sys::windows::reset()
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@ -470,7 +467,7 @@ impl<T: Display> Command for Print<T> {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    #[cfg(windows)]
 | 
			
		||||
    fn execute_winapi(&self) -> Result<()> {
 | 
			
		||||
    fn execute_winapi(&self) -> std::io::Result<()> {
 | 
			
		||||
        panic!("tried to execute Print command using WinAPI, use ANSI instead");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -4,8 +4,6 @@ use std::sync::atomic::{AtomicU32, Ordering};
 | 
			
		||||
use crossterm_winapi::{Console, Handle, HandleType, ScreenBuffer};
 | 
			
		||||
use winapi::um::wincon;
 | 
			
		||||
 | 
			
		||||
use crate::Result;
 | 
			
		||||
 | 
			
		||||
use super::super::{Color, Colored};
 | 
			
		||||
 | 
			
		||||
const FG_GREEN: u16 = wincon::FOREGROUND_GREEN;
 | 
			
		||||
@ -18,7 +16,7 @@ const BG_RED: u16 = wincon::BACKGROUND_RED;
 | 
			
		||||
const BG_BLUE: u16 = wincon::BACKGROUND_BLUE;
 | 
			
		||||
const BG_INTENSITY: u16 = wincon::BACKGROUND_INTENSITY;
 | 
			
		||||
 | 
			
		||||
pub(crate) fn set_foreground_color(fg_color: Color) -> Result<()> {
 | 
			
		||||
pub(crate) fn set_foreground_color(fg_color: Color) -> std::io::Result<()> {
 | 
			
		||||
    init_console_color()?;
 | 
			
		||||
 | 
			
		||||
    let color_value: u16 = Colored::ForegroundColor(fg_color).into();
 | 
			
		||||
@ -42,7 +40,7 @@ pub(crate) fn set_foreground_color(fg_color: Color) -> Result<()> {
 | 
			
		||||
    Ok(())
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub(crate) fn set_background_color(bg_color: Color) -> Result<()> {
 | 
			
		||||
pub(crate) fn set_background_color(bg_color: Color) -> std::io::Result<()> {
 | 
			
		||||
    init_console_color()?;
 | 
			
		||||
 | 
			
		||||
    let color_value: u16 = Colored::BackgroundColor(bg_color).into();
 | 
			
		||||
@ -66,7 +64,7 @@ pub(crate) fn set_background_color(bg_color: Color) -> Result<()> {
 | 
			
		||||
    Ok(())
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub(crate) fn reset() -> Result<()> {
 | 
			
		||||
pub(crate) fn reset() -> std::io::Result<()> {
 | 
			
		||||
    if let Ok(original_color) = u16::try_from(ORIGINAL_CONSOLE_COLOR.load(Ordering::Relaxed)) {
 | 
			
		||||
        Console::from(Handle::new(HandleType::CurrentOutputHandle)?)
 | 
			
		||||
            .set_text_attribute(original_color)?;
 | 
			
		||||
@ -76,7 +74,7 @@ pub(crate) fn reset() -> Result<()> {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// Initializes the default console color. It will will be skipped if it has already been initialized.
 | 
			
		||||
pub(crate) fn init_console_color() -> Result<()> {
 | 
			
		||||
pub(crate) fn init_console_color() -> std::io::Result<()> {
 | 
			
		||||
    if ORIGINAL_CONSOLE_COLOR.load(Ordering::Relaxed) == u32::MAX {
 | 
			
		||||
        let screen_buffer = ScreenBuffer::current()?;
 | 
			
		||||
        let attr = screen_buffer.info()?.attributes();
 | 
			
		||||
 | 
			
		||||
@ -154,7 +154,7 @@ Attribute! {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl Display for Attribute {
 | 
			
		||||
    fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> std::result::Result<(), std::fmt::Error> {
 | 
			
		||||
    fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> std::fmt::Result {
 | 
			
		||||
        write!(f, "{}", SetAttribute(*self))?;
 | 
			
		||||
        Ok(())
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -1,4 +1,7 @@
 | 
			
		||||
use std::{convert::AsRef, convert::TryFrom, result::Result, str::FromStr};
 | 
			
		||||
use std::{
 | 
			
		||||
    convert::{AsRef, TryFrom},
 | 
			
		||||
    str::FromStr,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#[cfg(feature = "serde")]
 | 
			
		||||
use std::fmt;
 | 
			
		||||
 | 
			
		||||
@ -63,27 +63,27 @@
 | 
			
		||||
//! ## Examples
 | 
			
		||||
//!
 | 
			
		||||
//! ```no_run
 | 
			
		||||
//! use std::io::{stdout, Write};
 | 
			
		||||
//! use crossterm::{execute, Result, terminal::{ScrollUp, SetSize, size}};
 | 
			
		||||
//! use std::io::{self, Write};
 | 
			
		||||
//! use crossterm::{execute, terminal::{ScrollUp, SetSize, size}};
 | 
			
		||||
//!
 | 
			
		||||
//! fn main() -> Result<()> {
 | 
			
		||||
//! fn main() -> io::Result<()> {
 | 
			
		||||
//!     let (cols, rows) = size()?;
 | 
			
		||||
//!     // Resize terminal and scroll up.
 | 
			
		||||
//!     execute!(
 | 
			
		||||
//!         stdout(),
 | 
			
		||||
//!         io::stdout(),
 | 
			
		||||
//!         SetSize(10, 10),
 | 
			
		||||
//!         ScrollUp(5)
 | 
			
		||||
//!     )?;
 | 
			
		||||
//!
 | 
			
		||||
//!     // Be a good citizen, cleanup
 | 
			
		||||
//!     execute!(stdout(), SetSize(cols, rows))?;
 | 
			
		||||
//!     execute!(io::stdout(), SetSize(cols, rows))?;
 | 
			
		||||
//!     Ok(())
 | 
			
		||||
//! }
 | 
			
		||||
//! ```
 | 
			
		||||
//!
 | 
			
		||||
//! For manual execution control check out [crossterm::queue](../macro.queue.html).
 | 
			
		||||
 | 
			
		||||
use std::fmt;
 | 
			
		||||
use std::{fmt, io};
 | 
			
		||||
 | 
			
		||||
#[cfg(windows)]
 | 
			
		||||
use crossterm_winapi::{ConsoleMode, Handle, ScreenBuffer};
 | 
			
		||||
@ -94,7 +94,7 @@ use winapi::um::wincon::ENABLE_WRAP_AT_EOL_OUTPUT;
 | 
			
		||||
 | 
			
		||||
#[doc(no_inline)]
 | 
			
		||||
use crate::Command;
 | 
			
		||||
use crate::{csi, impl_display, Result};
 | 
			
		||||
use crate::{csi, impl_display};
 | 
			
		||||
 | 
			
		||||
pub(crate) mod sys;
 | 
			
		||||
 | 
			
		||||
@ -104,7 +104,7 @@ pub use sys::supports_keyboard_enhancement;
 | 
			
		||||
/// Tells whether the raw mode is enabled.
 | 
			
		||||
///
 | 
			
		||||
/// Please have a look at the [raw mode](./index.html#raw-mode) section.
 | 
			
		||||
pub fn is_raw_mode_enabled() -> Result<bool> {
 | 
			
		||||
pub fn is_raw_mode_enabled() -> io::Result<bool> {
 | 
			
		||||
    #[cfg(unix)]
 | 
			
		||||
    {
 | 
			
		||||
        Ok(sys::is_raw_mode_enabled())
 | 
			
		||||
@ -119,21 +119,21 @@ pub fn is_raw_mode_enabled() -> Result<bool> {
 | 
			
		||||
/// Enables raw mode.
 | 
			
		||||
///
 | 
			
		||||
/// Please have a look at the [raw mode](./index.html#raw-mode) section.
 | 
			
		||||
pub fn enable_raw_mode() -> Result<()> {
 | 
			
		||||
pub fn enable_raw_mode() -> io::Result<()> {
 | 
			
		||||
    sys::enable_raw_mode()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// Disables raw mode.
 | 
			
		||||
///
 | 
			
		||||
/// Please have a look at the [raw mode](./index.html#raw-mode) section.
 | 
			
		||||
pub fn disable_raw_mode() -> Result<()> {
 | 
			
		||||
pub fn disable_raw_mode() -> io::Result<()> {
 | 
			
		||||
    sys::disable_raw_mode()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// Returns the terminal size `(columns, rows)`.
 | 
			
		||||
///
 | 
			
		||||
/// The top left cell is represented `(1, 1)`.
 | 
			
		||||
pub fn size() -> Result<(u16, u16)> {
 | 
			
		||||
pub fn size() -> io::Result<(u16, u16)> {
 | 
			
		||||
    sys::size()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -147,7 +147,7 @@ impl Command for DisableLineWrap {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    #[cfg(windows)]
 | 
			
		||||
    fn execute_winapi(&self) -> Result<()> {
 | 
			
		||||
    fn execute_winapi(&self) -> io::Result<()> {
 | 
			
		||||
        let screen_buffer = ScreenBuffer::current()?;
 | 
			
		||||
        let console_mode = ConsoleMode::from(screen_buffer.handle().clone());
 | 
			
		||||
        let new_mode = console_mode.mode()? & !ENABLE_WRAP_AT_EOL_OUTPUT;
 | 
			
		||||
@ -166,7 +166,7 @@ impl Command for EnableLineWrap {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    #[cfg(windows)]
 | 
			
		||||
    fn execute_winapi(&self) -> Result<()> {
 | 
			
		||||
    fn execute_winapi(&self) -> io::Result<()> {
 | 
			
		||||
        let screen_buffer = ScreenBuffer::current()?;
 | 
			
		||||
        let console_mode = ConsoleMode::from(screen_buffer.handle().clone());
 | 
			
		||||
        let new_mode = console_mode.mode()? | ENABLE_WRAP_AT_EOL_OUTPUT;
 | 
			
		||||
@ -185,15 +185,15 @@ impl Command for EnableLineWrap {
 | 
			
		||||
/// # Examples
 | 
			
		||||
///
 | 
			
		||||
/// ```no_run
 | 
			
		||||
/// use std::io::{stdout, Write};
 | 
			
		||||
/// use crossterm::{execute, Result, terminal::{EnterAlternateScreen, LeaveAlternateScreen}};
 | 
			
		||||
/// use std::io::{self, Write};
 | 
			
		||||
/// use crossterm::{execute, terminal::{EnterAlternateScreen, LeaveAlternateScreen}};
 | 
			
		||||
///
 | 
			
		||||
/// fn main() -> Result<()> {
 | 
			
		||||
///     execute!(stdout(), EnterAlternateScreen)?;
 | 
			
		||||
/// fn main() -> io::Result<()> {
 | 
			
		||||
///     execute!(io::stdout(), EnterAlternateScreen)?;
 | 
			
		||||
///
 | 
			
		||||
///     // Do anything on the alternate screen
 | 
			
		||||
///
 | 
			
		||||
///     execute!(stdout(), LeaveAlternateScreen)
 | 
			
		||||
///     execute!(io::stdout(), LeaveAlternateScreen)
 | 
			
		||||
/// }
 | 
			
		||||
/// ```
 | 
			
		||||
///
 | 
			
		||||
@ -206,7 +206,7 @@ impl Command for EnterAlternateScreen {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    #[cfg(windows)]
 | 
			
		||||
    fn execute_winapi(&self) -> Result<()> {
 | 
			
		||||
    fn execute_winapi(&self) -> io::Result<()> {
 | 
			
		||||
        let alternate_screen = ScreenBuffer::create()?;
 | 
			
		||||
        alternate_screen.show()?;
 | 
			
		||||
        Ok(())
 | 
			
		||||
@ -223,15 +223,15 @@ impl Command for EnterAlternateScreen {
 | 
			
		||||
/// # Examples
 | 
			
		||||
///
 | 
			
		||||
/// ```no_run
 | 
			
		||||
/// use std::io::{stdout, Write};
 | 
			
		||||
/// use crossterm::{execute, Result, terminal::{EnterAlternateScreen, LeaveAlternateScreen}};
 | 
			
		||||
/// use std::io::{self, Write};
 | 
			
		||||
/// use crossterm::{execute, terminal::{EnterAlternateScreen, LeaveAlternateScreen}};
 | 
			
		||||
///
 | 
			
		||||
/// fn main() -> Result<()> {
 | 
			
		||||
///     execute!(stdout(), EnterAlternateScreen)?;
 | 
			
		||||
/// fn main() -> io::Result<()> {
 | 
			
		||||
///     execute!(io::stdout(), EnterAlternateScreen)?;
 | 
			
		||||
///
 | 
			
		||||
///     // Do anything on the alternate screen
 | 
			
		||||
///
 | 
			
		||||
///     execute!(stdout(), LeaveAlternateScreen)
 | 
			
		||||
///     execute!(io::stdout(), LeaveAlternateScreen)
 | 
			
		||||
/// }
 | 
			
		||||
/// ```
 | 
			
		||||
///
 | 
			
		||||
@ -244,7 +244,7 @@ impl Command for LeaveAlternateScreen {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    #[cfg(windows)]
 | 
			
		||||
    fn execute_winapi(&self) -> Result<()> {
 | 
			
		||||
    fn execute_winapi(&self) -> io::Result<()> {
 | 
			
		||||
        let screen_buffer = ScreenBuffer::from(Handle::current_out_handle()?);
 | 
			
		||||
        screen_buffer.show()?;
 | 
			
		||||
        Ok(())
 | 
			
		||||
@ -286,7 +286,7 @@ impl Command for ScrollUp {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    #[cfg(windows)]
 | 
			
		||||
    fn execute_winapi(&self) -> Result<()> {
 | 
			
		||||
    fn execute_winapi(&self) -> io::Result<()> {
 | 
			
		||||
        sys::scroll_up(self.0)
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@ -308,7 +308,7 @@ impl Command for ScrollDown {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    #[cfg(windows)]
 | 
			
		||||
    fn execute_winapi(&self) -> Result<()> {
 | 
			
		||||
    fn execute_winapi(&self) -> io::Result<()> {
 | 
			
		||||
        sys::scroll_down(self.0)
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@ -336,7 +336,7 @@ impl Command for Clear {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    #[cfg(windows)]
 | 
			
		||||
    fn execute_winapi(&self) -> Result<()> {
 | 
			
		||||
    fn execute_winapi(&self) -> io::Result<()> {
 | 
			
		||||
        sys::clear(self.0)
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@ -355,7 +355,7 @@ impl Command for SetSize {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    #[cfg(windows)]
 | 
			
		||||
    fn execute_winapi(&self) -> Result<()> {
 | 
			
		||||
    fn execute_winapi(&self) -> io::Result<()> {
 | 
			
		||||
        sys::set_size(self.0, self.1)
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@ -374,7 +374,7 @@ impl<T: fmt::Display> Command for SetTitle<T> {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    #[cfg(windows)]
 | 
			
		||||
    fn execute_winapi(&self) -> Result<()> {
 | 
			
		||||
    fn execute_winapi(&self) -> io::Result<()> {
 | 
			
		||||
        sys::set_window_title(&self.0)
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@ -399,15 +399,15 @@ impl<T: fmt::Display> Command for SetTitle<T> {
 | 
			
		||||
/// # Examples
 | 
			
		||||
///
 | 
			
		||||
/// ```no_run
 | 
			
		||||
/// use std::io::{stdout, Write};
 | 
			
		||||
/// use crossterm::{execute, Result, terminal::{BeginSynchronizedUpdate, EndSynchronizedUpdate}};
 | 
			
		||||
/// use std::io::{self, Write};
 | 
			
		||||
/// use crossterm::{execute, terminal::{BeginSynchronizedUpdate, EndSynchronizedUpdate}};
 | 
			
		||||
///
 | 
			
		||||
/// fn main() -> Result<()> {
 | 
			
		||||
///     execute!(stdout(), BeginSynchronizedUpdate)?;
 | 
			
		||||
/// fn main() -> io::Result<()> {
 | 
			
		||||
///     execute!(io::stdout(), BeginSynchronizedUpdate)?;
 | 
			
		||||
///
 | 
			
		||||
///     // Anything performed here will not be rendered until EndSynchronizedUpdate is called.
 | 
			
		||||
///
 | 
			
		||||
///     execute!(stdout(), EndSynchronizedUpdate)?;
 | 
			
		||||
///     execute!(io::stdout(), EndSynchronizedUpdate)?;
 | 
			
		||||
///     Ok(())
 | 
			
		||||
/// }
 | 
			
		||||
/// ```
 | 
			
		||||
@ -421,7 +421,7 @@ impl Command for BeginSynchronizedUpdate {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    #[cfg(windows)]
 | 
			
		||||
    fn execute_winapi(&self) -> Result<()> {
 | 
			
		||||
    fn execute_winapi(&self) -> io::Result<()> {
 | 
			
		||||
        Ok(())
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -452,15 +452,15 @@ impl Command for BeginSynchronizedUpdate {
 | 
			
		||||
/// # Examples
 | 
			
		||||
///
 | 
			
		||||
/// ```no_run
 | 
			
		||||
/// use std::io::{stdout, Write};
 | 
			
		||||
/// use crossterm::{execute, Result, terminal::{BeginSynchronizedUpdate, EndSynchronizedUpdate}};
 | 
			
		||||
/// use std::io::{self, Write};
 | 
			
		||||
/// use crossterm::{execute, terminal::{BeginSynchronizedUpdate, EndSynchronizedUpdate}};
 | 
			
		||||
///
 | 
			
		||||
/// fn main() -> Result<()> {
 | 
			
		||||
///     execute!(stdout(), BeginSynchronizedUpdate)?;
 | 
			
		||||
/// fn main() -> io::Result<()> {
 | 
			
		||||
///     execute!(io::stdout(), BeginSynchronizedUpdate)?;
 | 
			
		||||
///
 | 
			
		||||
///     // Anything performed here will not be rendered until EndSynchronizedUpdate is called.
 | 
			
		||||
///
 | 
			
		||||
///     execute!(stdout(), EndSynchronizedUpdate)?;
 | 
			
		||||
///     execute!(io::stdout(), EndSynchronizedUpdate)?;
 | 
			
		||||
///     Ok(())
 | 
			
		||||
/// }
 | 
			
		||||
/// ```
 | 
			
		||||
@ -474,7 +474,7 @@ impl Command for EndSynchronizedUpdate {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    #[cfg(windows)]
 | 
			
		||||
    fn execute_winapi(&self) -> Result<()> {
 | 
			
		||||
    fn execute_winapi(&self) -> io::Result<()> {
 | 
			
		||||
        Ok(())
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -8,8 +8,6 @@ use std::{
 | 
			
		||||
 | 
			
		||||
use libc::size_t;
 | 
			
		||||
 | 
			
		||||
use crate::Result;
 | 
			
		||||
 | 
			
		||||
/// A file descriptor wrapper.
 | 
			
		||||
///
 | 
			
		||||
/// It allows to retrieve raw file descriptor, write to the file descriptor and
 | 
			
		||||
@ -31,7 +29,7 @@ impl FileDesc {
 | 
			
		||||
        FileDesc { fd, close_on_drop }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    pub fn read(&self, buffer: &mut [u8], size: usize) -> Result<usize> {
 | 
			
		||||
    pub fn read(&self, buffer: &mut [u8], size: usize) -> io::Result<usize> {
 | 
			
		||||
        let result = unsafe {
 | 
			
		||||
            libc::read(
 | 
			
		||||
                self.fd,
 | 
			
		||||
@ -73,7 +71,7 @@ impl AsRawFd for FileDesc {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// Creates a file descriptor pointing to the standard input or `/dev/tty`.
 | 
			
		||||
pub fn tty_fd() -> Result<FileDesc> {
 | 
			
		||||
pub fn tty_fd() -> io::Result<FileDesc> {
 | 
			
		||||
    let (fd, close_on_drop) = if unsafe { libc::isatty(libc::STDIN_FILENO) == 1 } {
 | 
			
		||||
        (libc::STDIN_FILENO, false)
 | 
			
		||||
    } else {
 | 
			
		||||
 | 
			
		||||
@ -12,8 +12,6 @@ use std::os::unix::io::{IntoRawFd, RawFd};
 | 
			
		||||
 | 
			
		||||
use std::{io, mem, process};
 | 
			
		||||
 | 
			
		||||
use crate::error::Result;
 | 
			
		||||
 | 
			
		||||
// Some(Termios) -> we're in the raw mode and this is the previous mode
 | 
			
		||||
// None -> we're not in the raw mode
 | 
			
		||||
static TERMINAL_MODE_PRIOR_RAW_MODE: Mutex<Option<Termios>> = parking_lot::const_mutex(None);
 | 
			
		||||
@ -23,7 +21,7 @@ pub(crate) fn is_raw_mode_enabled() -> bool {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[allow(clippy::useless_conversion)]
 | 
			
		||||
pub(crate) fn size() -> Result<(u16, u16)> {
 | 
			
		||||
pub(crate) fn size() -> io::Result<(u16, u16)> {
 | 
			
		||||
    // http://rosettacode.org/wiki/Terminal_control/Dimensions#Library:_BSD_libc
 | 
			
		||||
    let mut size = winsize {
 | 
			
		||||
        ws_row: 0,
 | 
			
		||||
@ -50,7 +48,7 @@ pub(crate) fn size() -> Result<(u16, u16)> {
 | 
			
		||||
    tput_size().ok_or_else(|| std::io::Error::last_os_error().into())
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub(crate) fn enable_raw_mode() -> Result<()> {
 | 
			
		||||
pub(crate) fn enable_raw_mode() -> io::Result<()> {
 | 
			
		||||
    let mut original_mode = TERMINAL_MODE_PRIOR_RAW_MODE.lock();
 | 
			
		||||
 | 
			
		||||
    if original_mode.is_some() {
 | 
			
		||||
@ -76,7 +74,7 @@ pub(crate) fn enable_raw_mode() -> Result<()> {
 | 
			
		||||
/// More precisely, reset the whole termios mode to what it was before the first call
 | 
			
		||||
/// to [enable_raw_mode]. If you don't mess with termios outside of crossterm, it's
 | 
			
		||||
/// effectively disabling the raw mode and doing nothing else.
 | 
			
		||||
pub(crate) fn disable_raw_mode() -> Result<()> {
 | 
			
		||||
pub(crate) fn disable_raw_mode() -> io::Result<()> {
 | 
			
		||||
    let mut original_mode = TERMINAL_MODE_PRIOR_RAW_MODE.lock();
 | 
			
		||||
 | 
			
		||||
    if let Some(original_mode_ios) = original_mode.as_ref() {
 | 
			
		||||
@ -94,7 +92,7 @@ pub(crate) fn disable_raw_mode() -> Result<()> {
 | 
			
		||||
/// On unix systems, this function will block and possibly time out while
 | 
			
		||||
/// [`crossterm::event::read`](crate::event::read) or [`crossterm::event::poll`](crate::event::poll) are being called.
 | 
			
		||||
#[cfg(feature = "events")]
 | 
			
		||||
pub fn supports_keyboard_enhancement() -> Result<bool> {
 | 
			
		||||
pub fn supports_keyboard_enhancement() -> io::Result<bool> {
 | 
			
		||||
    if is_raw_mode_enabled() {
 | 
			
		||||
        read_supports_keyboard_enhancement_raw()
 | 
			
		||||
    } else {
 | 
			
		||||
@ -103,7 +101,7 @@ pub fn supports_keyboard_enhancement() -> Result<bool> {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[cfg(feature = "events")]
 | 
			
		||||
fn read_supports_keyboard_enhancement_flags() -> Result<bool> {
 | 
			
		||||
fn read_supports_keyboard_enhancement_flags() -> io::Result<bool> {
 | 
			
		||||
    enable_raw_mode()?;
 | 
			
		||||
    let flags = read_supports_keyboard_enhancement_raw();
 | 
			
		||||
    disable_raw_mode()?;
 | 
			
		||||
@ -111,7 +109,7 @@ fn read_supports_keyboard_enhancement_flags() -> Result<bool> {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[cfg(feature = "events")]
 | 
			
		||||
fn read_supports_keyboard_enhancement_raw() -> Result<bool> {
 | 
			
		||||
fn read_supports_keyboard_enhancement_raw() -> io::Result<bool> {
 | 
			
		||||
    use crate::event::{
 | 
			
		||||
        filter::{KeyboardEnhancementFlagsFilter, PrimaryDeviceAttributesFilter},
 | 
			
		||||
        poll_internal, read_internal, InternalEvent,
 | 
			
		||||
@ -201,7 +199,7 @@ fn raw_terminal_attr(termios: &mut Termios) {
 | 
			
		||||
    unsafe { cfmakeraw(termios) }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fn get_terminal_attr(fd: RawFd) -> Result<Termios> {
 | 
			
		||||
fn get_terminal_attr(fd: RawFd) -> io::Result<Termios> {
 | 
			
		||||
    unsafe {
 | 
			
		||||
        let mut termios = mem::zeroed();
 | 
			
		||||
        wrap_with_result(tcgetattr(fd, &mut termios))?;
 | 
			
		||||
@ -209,11 +207,11 @@ fn get_terminal_attr(fd: RawFd) -> Result<Termios> {
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fn set_terminal_attr(fd: RawFd, termios: &Termios) -> Result<()> {
 | 
			
		||||
fn set_terminal_attr(fd: RawFd, termios: &Termios) -> io::Result<()> {
 | 
			
		||||
    wrap_with_result(unsafe { tcsetattr(fd, TCSANOW, termios) })
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fn wrap_with_result(result: i32) -> Result<()> {
 | 
			
		||||
fn wrap_with_result(result: i32) -> io::Result<()> {
 | 
			
		||||
    if result == -1 {
 | 
			
		||||
        Err(io::Error::last_os_error())
 | 
			
		||||
    } else {
 | 
			
		||||
 | 
			
		||||
@ -1,7 +1,7 @@
 | 
			
		||||
//! WinAPI related logic for terminal manipulation.
 | 
			
		||||
 | 
			
		||||
use std::fmt::{self, Write};
 | 
			
		||||
use std::io;
 | 
			
		||||
use std::io::{self};
 | 
			
		||||
 | 
			
		||||
use crossterm_winapi::{Console, ConsoleMode, Coord, Handle, ScreenBuffer, Size};
 | 
			
		||||
use winapi::{
 | 
			
		||||
@ -9,12 +9,12 @@ use winapi::{
 | 
			
		||||
    um::wincon::{SetConsoleTitleW, ENABLE_ECHO_INPUT, ENABLE_LINE_INPUT, ENABLE_PROCESSED_INPUT},
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
use crate::{cursor, terminal::ClearType, ErrorKind, Result};
 | 
			
		||||
use crate::{cursor, terminal::ClearType};
 | 
			
		||||
 | 
			
		||||
/// bits which can't be set in raw mode
 | 
			
		||||
const NOT_RAW_MODE_MASK: DWORD = ENABLE_LINE_INPUT | ENABLE_ECHO_INPUT | ENABLE_PROCESSED_INPUT;
 | 
			
		||||
 | 
			
		||||
pub(crate) fn is_raw_mode_enabled() -> Result<bool> {
 | 
			
		||||
pub(crate) fn is_raw_mode_enabled() -> std::io::Result<bool> {
 | 
			
		||||
    let console_mode = ConsoleMode::from(Handle::current_in_handle()?);
 | 
			
		||||
 | 
			
		||||
    let dw_mode = console_mode.mode()?;
 | 
			
		||||
@ -25,7 +25,7 @@ pub(crate) fn is_raw_mode_enabled() -> Result<bool> {
 | 
			
		||||
    )
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub(crate) fn enable_raw_mode() -> Result<()> {
 | 
			
		||||
pub(crate) fn enable_raw_mode() -> std::io::Result<()> {
 | 
			
		||||
    let console_mode = ConsoleMode::from(Handle::current_in_handle()?);
 | 
			
		||||
 | 
			
		||||
    let dw_mode = console_mode.mode()?;
 | 
			
		||||
@ -37,7 +37,7 @@ pub(crate) fn enable_raw_mode() -> Result<()> {
 | 
			
		||||
    Ok(())
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub(crate) fn disable_raw_mode() -> Result<()> {
 | 
			
		||||
pub(crate) fn disable_raw_mode() -> std::io::Result<()> {
 | 
			
		||||
    let console_mode = ConsoleMode::from(Handle::current_in_handle()?);
 | 
			
		||||
 | 
			
		||||
    let dw_mode = console_mode.mode()?;
 | 
			
		||||
@ -49,7 +49,7 @@ pub(crate) fn disable_raw_mode() -> Result<()> {
 | 
			
		||||
    Ok(())
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub(crate) fn size() -> Result<(u16, u16)> {
 | 
			
		||||
pub(crate) fn size() -> io::Result<(u16, u16)> {
 | 
			
		||||
    let terminal_size = ScreenBuffer::current()?.info()?.terminal_size();
 | 
			
		||||
    // windows starts counting at 0, unix at 1, add one to replicated unix behaviour.
 | 
			
		||||
    Ok((
 | 
			
		||||
@ -62,11 +62,11 @@ pub(crate) fn size() -> Result<(u16, u16)> {
 | 
			
		||||
///
 | 
			
		||||
/// This always returns `Ok(false)` on Windows.
 | 
			
		||||
#[cfg(feature = "events")]
 | 
			
		||||
pub fn supports_keyboard_enhancement() -> Result<bool> {
 | 
			
		||||
pub fn supports_keyboard_enhancement() -> std::io::Result<bool> {
 | 
			
		||||
    Ok(false)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub(crate) fn clear(clear_type: ClearType) -> Result<()> {
 | 
			
		||||
pub(crate) fn clear(clear_type: ClearType) -> std::io::Result<()> {
 | 
			
		||||
    let screen_buffer = ScreenBuffer::current()?;
 | 
			
		||||
    let csbi = screen_buffer.info()?;
 | 
			
		||||
 | 
			
		||||
@ -89,7 +89,7 @@ pub(crate) fn clear(clear_type: ClearType) -> Result<()> {
 | 
			
		||||
    Ok(())
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub(crate) fn scroll_up(row_count: u16) -> Result<()> {
 | 
			
		||||
pub(crate) fn scroll_up(row_count: u16) -> std::io::Result<()> {
 | 
			
		||||
    let csbi = ScreenBuffer::current()?;
 | 
			
		||||
    let mut window = csbi.info()?.terminal_window();
 | 
			
		||||
 | 
			
		||||
@ -104,7 +104,7 @@ pub(crate) fn scroll_up(row_count: u16) -> Result<()> {
 | 
			
		||||
    Ok(())
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub(crate) fn scroll_down(row_count: u16) -> Result<()> {
 | 
			
		||||
pub(crate) fn scroll_down(row_count: u16) -> std::io::Result<()> {
 | 
			
		||||
    let screen_buffer = ScreenBuffer::current()?;
 | 
			
		||||
    let csbi = screen_buffer.info()?;
 | 
			
		||||
    let mut window = csbi.terminal_window();
 | 
			
		||||
@ -121,16 +121,16 @@ pub(crate) fn scroll_down(row_count: u16) -> Result<()> {
 | 
			
		||||
    Ok(())
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub(crate) fn set_size(width: u16, height: u16) -> Result<()> {
 | 
			
		||||
pub(crate) fn set_size(width: u16, height: u16) -> std::io::Result<()> {
 | 
			
		||||
    if width <= 1 {
 | 
			
		||||
        return Err(ErrorKind::new(
 | 
			
		||||
        return Err(io::Error::new(
 | 
			
		||||
            io::ErrorKind::InvalidInput,
 | 
			
		||||
            "terminal width must be at least 1",
 | 
			
		||||
        ));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if height <= 1 {
 | 
			
		||||
        return Err(ErrorKind::new(
 | 
			
		||||
        return Err(io::Error::new(
 | 
			
		||||
            io::ErrorKind::InvalidInput,
 | 
			
		||||
            "terminal height must be at least 1",
 | 
			
		||||
        ));
 | 
			
		||||
@ -153,7 +153,7 @@ pub(crate) fn set_size(width: u16, height: u16) -> Result<()> {
 | 
			
		||||
    let width = width as i16;
 | 
			
		||||
    if current_size.width < window.left + width {
 | 
			
		||||
        if window.left >= i16::max_value() - width {
 | 
			
		||||
            return Err(ErrorKind::new(
 | 
			
		||||
            return Err(io::Error::new(
 | 
			
		||||
                io::ErrorKind::InvalidInput,
 | 
			
		||||
                "terminal width too large",
 | 
			
		||||
            ));
 | 
			
		||||
@ -165,7 +165,7 @@ pub(crate) fn set_size(width: u16, height: u16) -> Result<()> {
 | 
			
		||||
    let height = height as i16;
 | 
			
		||||
    if current_size.height < window.top + height {
 | 
			
		||||
        if window.top >= i16::max_value() - height {
 | 
			
		||||
            return Err(ErrorKind::new(
 | 
			
		||||
            return Err(io::Error::new(
 | 
			
		||||
                io::ErrorKind::InvalidInput,
 | 
			
		||||
                "terminal height too large",
 | 
			
		||||
            ));
 | 
			
		||||
@ -194,13 +194,13 @@ pub(crate) fn set_size(width: u16, height: u16) -> Result<()> {
 | 
			
		||||
    let bounds = console.largest_window_size()?;
 | 
			
		||||
 | 
			
		||||
    if width > bounds.x {
 | 
			
		||||
        return Err(ErrorKind::new(
 | 
			
		||||
        return Err(io::Error::new(
 | 
			
		||||
            io::ErrorKind::InvalidInput,
 | 
			
		||||
            format!("terminal width {width} too large"),
 | 
			
		||||
        ));
 | 
			
		||||
    }
 | 
			
		||||
    if height > bounds.y {
 | 
			
		||||
        return Err(ErrorKind::new(
 | 
			
		||||
        return Err(io::Error::new(
 | 
			
		||||
            io::ErrorKind::InvalidInput,
 | 
			
		||||
            format!("terminal height {height} too large"),
 | 
			
		||||
        ));
 | 
			
		||||
@ -209,7 +209,7 @@ pub(crate) fn set_size(width: u16, height: u16) -> Result<()> {
 | 
			
		||||
    Ok(())
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub(crate) fn set_window_title(title: impl fmt::Display) -> Result<()> {
 | 
			
		||||
pub(crate) fn set_window_title(title: impl fmt::Display) -> std::io::Result<()> {
 | 
			
		||||
    struct Utf16Encoder(Vec<u16>);
 | 
			
		||||
    impl Write for Utf16Encoder {
 | 
			
		||||
        fn write_str(&mut self, s: &str) -> fmt::Result {
 | 
			
		||||
@ -227,11 +227,15 @@ pub(crate) fn set_window_title(title: impl fmt::Display) -> Result<()> {
 | 
			
		||||
    if result != 0 {
 | 
			
		||||
        Ok(())
 | 
			
		||||
    } else {
 | 
			
		||||
        Err(ErrorKind::last_os_error())
 | 
			
		||||
        Err(io::Error::last_os_error())
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fn clear_after_cursor(location: Coord, buffer_size: Size, current_attribute: u16) -> Result<()> {
 | 
			
		||||
fn clear_after_cursor(
 | 
			
		||||
    location: Coord,
 | 
			
		||||
    buffer_size: Size,
 | 
			
		||||
    current_attribute: u16,
 | 
			
		||||
) -> std::io::Result<()> {
 | 
			
		||||
    let (mut x, mut y) = (location.x, location.y);
 | 
			
		||||
 | 
			
		||||
    // if cursor position is at the outer right position
 | 
			
		||||
@ -249,7 +253,11 @@ fn clear_after_cursor(location: Coord, buffer_size: Size, current_attribute: u16
 | 
			
		||||
    clear_winapi(start_location, cells_to_write, current_attribute)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fn clear_before_cursor(location: Coord, buffer_size: Size, current_attribute: u16) -> Result<()> {
 | 
			
		||||
fn clear_before_cursor(
 | 
			
		||||
    location: Coord,
 | 
			
		||||
    buffer_size: Size,
 | 
			
		||||
    current_attribute: u16,
 | 
			
		||||
) -> std::io::Result<()> {
 | 
			
		||||
    let (xpos, ypos) = (location.x, location.y);
 | 
			
		||||
 | 
			
		||||
    // one cell after cursor position
 | 
			
		||||
@ -267,7 +275,7 @@ fn clear_before_cursor(location: Coord, buffer_size: Size, current_attribute: u1
 | 
			
		||||
    clear_winapi(start_location, cells_to_write, current_attribute)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fn clear_entire_screen(buffer_size: Size, current_attribute: u16) -> Result<()> {
 | 
			
		||||
fn clear_entire_screen(buffer_size: Size, current_attribute: u16) -> std::io::Result<()> {
 | 
			
		||||
    // get sum cells before cursor
 | 
			
		||||
    let cells_to_write = buffer_size.width as u32 * buffer_size.height as u32;
 | 
			
		||||
 | 
			
		||||
@ -282,7 +290,11 @@ fn clear_entire_screen(buffer_size: Size, current_attribute: u16) -> Result<()>
 | 
			
		||||
    Ok(())
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fn clear_current_line(location: Coord, buffer_size: Size, current_attribute: u16) -> Result<()> {
 | 
			
		||||
fn clear_current_line(
 | 
			
		||||
    location: Coord,
 | 
			
		||||
    buffer_size: Size,
 | 
			
		||||
    current_attribute: u16,
 | 
			
		||||
) -> std::io::Result<()> {
 | 
			
		||||
    // location where to start clearing
 | 
			
		||||
    let start_location = Coord::new(0, location.y);
 | 
			
		||||
 | 
			
		||||
@ -297,7 +309,11 @@ fn clear_current_line(location: Coord, buffer_size: Size, current_attribute: u16
 | 
			
		||||
    Ok(())
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fn clear_until_line(location: Coord, buffer_size: Size, current_attribute: u16) -> Result<()> {
 | 
			
		||||
fn clear_until_line(
 | 
			
		||||
    location: Coord,
 | 
			
		||||
    buffer_size: Size,
 | 
			
		||||
    current_attribute: u16,
 | 
			
		||||
) -> std::io::Result<()> {
 | 
			
		||||
    let (x, y) = (location.x, location.y);
 | 
			
		||||
 | 
			
		||||
    // location where to start clearing
 | 
			
		||||
@ -314,7 +330,11 @@ fn clear_until_line(location: Coord, buffer_size: Size, current_attribute: u16)
 | 
			
		||||
    Ok(())
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fn clear_winapi(start_location: Coord, cells_to_write: u32, current_attribute: u16) -> Result<()> {
 | 
			
		||||
fn clear_winapi(
 | 
			
		||||
    start_location: Coord,
 | 
			
		||||
    cells_to_write: u32,
 | 
			
		||||
    current_attribute: u16,
 | 
			
		||||
) -> std::io::Result<()> {
 | 
			
		||||
    let console = Console::from(Handle::current_out_handle()?);
 | 
			
		||||
    console.fill_whit_character(start_location, cells_to_write, ' ')?;
 | 
			
		||||
    console.fill_whit_attribute(start_location, cells_to_write, current_attribute)?;
 | 
			
		||||
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user