Unwrap crossterm::Result<T, ErrorKind> to std::io::Result. (#765)

This commit is contained in:
gibbz00 2023-04-07 18:17:10 +02:00 committed by GitHub
parent 41901c6382
commit a2c9350ff2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
43 changed files with 365 additions and 430 deletions

View File

@ -109,7 +109,7 @@ use crossterm::{
event, event,
}; };
fn main() -> Result<()> { fn main() -> std::io::Result<()> {
// using the macro // using the macro
execute!( execute!(
stdout(), stdout(),

View File

@ -2,14 +2,13 @@
//! //!
//! cargo run --example event-poll-read //! cargo run --example event-poll-read
use std::{io::stdout, time::Duration}; use std::{io, time::Duration};
use crossterm::{ use crossterm::{
cursor::position, cursor::position,
event::{poll, read, DisableMouseCapture, EnableMouseCapture, Event, KeyCode}, event::{poll, read, DisableMouseCapture, EnableMouseCapture, Event, KeyCode},
execute, execute,
terminal::{disable_raw_mode, enable_raw_mode}, terminal::{disable_raw_mode, enable_raw_mode},
Result,
}; };
const HELP: &str = r#"Blocking poll() & non-blocking read() 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 - Use Esc to quit
"#; "#;
fn print_events() -> Result<()> { fn print_events() -> io::Result<()> {
loop { loop {
// Wait up to 1s for another event // Wait up to 1s for another event
if poll(Duration::from_millis(1_000))? { if poll(Duration::from_millis(1_000))? {
@ -44,12 +43,12 @@ fn print_events() -> Result<()> {
Ok(()) Ok(())
} }
fn main() -> Result<()> { fn main() -> io::Result<()> {
println!("{}", HELP); println!("{}", HELP);
enable_raw_mode()?; enable_raw_mode()?;
let mut stdout = stdout(); let mut stdout = io::stdout();
execute!(stdout, EnableMouseCapture)?; execute!(stdout, EnableMouseCapture)?;
if let Err(e) = print_events() { if let Err(e) = print_events() {

View File

@ -3,12 +3,11 @@
//! //!
//! cargo run --example event-read-char-line //! cargo run --example event-read-char-line
use crossterm::{ use std::io;
event::{self, Event, KeyCode, KeyEvent},
Result,
};
pub fn read_char() -> Result<char> { use crossterm::event::{self, Event, KeyCode, KeyEvent};
pub fn read_char() -> io::Result<char> {
loop { loop {
if let Event::Key(KeyEvent { if let Event::Key(KeyEvent {
code: KeyCode::Char(c), 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(); let mut line = String::new();
while let Event::Key(KeyEvent { code, .. }) = event::read()? { while let Event::Key(KeyEvent { code, .. }) = event::read()? {
match code { match code {

View File

@ -2,7 +2,7 @@
//! //!
//! cargo run --example event-read //! cargo run --example event-read
use std::io::stdout; use std::io;
use crossterm::event::{ use crossterm::event::{
poll, KeyboardEnhancementFlags, PopKeyboardEnhancementFlags, PushKeyboardEnhancementFlags, poll, KeyboardEnhancementFlags, PopKeyboardEnhancementFlags, PushKeyboardEnhancementFlags,
@ -15,7 +15,6 @@ use crossterm::{
}, },
execute, queue, execute, queue,
terminal::{disable_raw_mode, enable_raw_mode}, terminal::{disable_raw_mode, enable_raw_mode},
Result,
}; };
use std::time::Duration; use std::time::Duration;
@ -25,7 +24,7 @@ const HELP: &str = r#"Blocking read()
- Use Esc to quit - Use Esc to quit
"#; "#;
fn print_events() -> Result<()> { fn print_events() -> io::Result<()> {
loop { loop {
// Blocking read // Blocking read
let event = read()?; let event = read()?;
@ -63,12 +62,12 @@ fn flush_resize_events(first_resize: (u16, u16)) -> ((u16, u16), (u16, u16)) {
(first_resize, last_resize) (first_resize, last_resize)
} }
fn main() -> Result<()> { fn main() -> io::Result<()> {
println!("{}", HELP); println!("{}", HELP);
enable_raw_mode()?; enable_raw_mode()?;
let mut stdout = stdout(); let mut stdout = io::stdout();
let supports_keyboard_enhancement = matches!( let supports_keyboard_enhancement = matches!(
crossterm::terminal::supports_keyboard_enhancement(), crossterm::terminal::supports_keyboard_enhancement(),

View File

@ -12,7 +12,6 @@ use crossterm::{
event::{DisableMouseCapture, EnableMouseCapture, Event, EventStream, KeyCode}, event::{DisableMouseCapture, EnableMouseCapture, Event, EventStream, KeyCode},
execute, execute,
terminal::{disable_raw_mode, enable_raw_mode}, terminal::{disable_raw_mode, enable_raw_mode},
Result,
}; };
const HELP: &str = r#"EventStream based on futures_util::stream::Stream with async-std 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); println!("{}", HELP);
enable_raw_mode()?; enable_raw_mode()?;

View File

@ -12,7 +12,6 @@ use crossterm::{
event::{DisableMouseCapture, EnableMouseCapture, Event, EventStream, KeyCode}, event::{DisableMouseCapture, EnableMouseCapture, Event, EventStream, KeyCode},
execute, execute,
terminal::{disable_raw_mode, enable_raw_mode}, terminal::{disable_raw_mode, enable_raw_mode},
Result,
}; };
const HELP: &str = r#"EventStream based on futures_util::Stream with tokio const HELP: &str = r#"EventStream based on futures_util::Stream with tokio
@ -53,7 +52,7 @@ async fn print_events() {
} }
#[tokio::main] #[tokio::main]
async fn main() -> Result<()> { async fn main() -> std::io::Result<()> {
println!("{}", HELP); println!("{}", HELP);
enable_raw_mode()?; enable_raw_mode()?;

View File

@ -1,6 +1,6 @@
#![allow(clippy::cognitive_complexity)] #![allow(clippy::cognitive_complexity)]
use std::io::{self, Write}; use std::io;
use crossterm::event::KeyEventKind; use crossterm::event::KeyEventKind;
pub use crossterm::{ pub use crossterm::{
@ -8,7 +8,7 @@ pub use crossterm::{
event::{self, Event, KeyCode, KeyEvent}, event::{self, Event, KeyCode, KeyEvent},
execute, queue, style, execute, queue, style,
terminal::{self, ClearType}, terminal::{self, ClearType},
Command, Result, Command,
}; };
#[macro_use] #[macro_use]
@ -33,9 +33,9 @@ Available tests:
Select test to run ('1', '2', ...) or hit 'q' to quit. 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 where
W: Write, W: io::Write,
{ {
execute!(w, terminal::EnterAlternateScreen)?; execute!(w, terminal::EnterAlternateScreen)?;
@ -80,7 +80,7 @@ where
terminal::disable_raw_mode() terminal::disable_raw_mode()
} }
pub fn read_char() -> Result<char> { pub fn read_char() -> std::io::Result<char> {
loop { loop {
if let Ok(Event::Key(KeyEvent { if let Ok(Event::Key(KeyEvent {
code: KeyCode::Char(c), 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() terminal::size()
} }
fn main() -> Result<()> { fn main() -> std::io::Result<()> {
let mut stdout = io::stdout(); let mut stdout = io::stdout();
run(&mut stdout) run(&mut stdout)
} }

View File

@ -21,7 +21,7 @@ const ATTRIBUTES: [(style::Attribute, style::Attribute); 10] = [
(style::Attribute::SlowBlink, style::Attribute::NoBlink), (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 where
W: Write, W: Write,
{ {
@ -48,7 +48,7 @@ where
Ok(()) Ok(())
} }
pub fn run<W>(w: &mut W) -> Result<()> pub fn run<W>(w: &mut W) -> std::io::Result<()>
where where
W: Write, W: Write,
{ {

View File

@ -28,7 +28,7 @@ const COLORS: [Color; 21] = [
Color::Rgb { r: 0, g: 0, b: 255 }, 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 where
W: Write, W: Write,
{ {
@ -63,7 +63,7 @@ where
Ok(()) Ok(())
} }
fn test_set_background_color<W>(w: &mut W) -> Result<()> fn test_set_background_color<W>(w: &mut W) -> std::io::Result<()>
where where
W: Write, W: Write,
{ {
@ -98,7 +98,7 @@ where
Ok(()) 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 where
W: Write, W: Write,
F: Fn(u16, u16) -> Color, F: Fn(u16, u16) -> Color,
@ -140,7 +140,7 @@ where
Ok(()) Ok(())
} }
fn test_color_ansi_values<W>(w: &mut W) -> Result<()> fn test_color_ansi_values<W>(w: &mut W) -> std::io::Result<()>
where where
W: Write, 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 where
W: Write, 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 where
W: Write, 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 where
W: Write, 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 where
W: Write, W: Write,
{ {

View File

@ -2,40 +2,39 @@
use std::io::Write; use std::io::Write;
use crate::Result;
use crossterm::{cursor, execute, queue, style, Command, style::Stylize}; use crossterm::{cursor, execute, queue, style, Command, style::Stylize};
use std::thread; use std::thread;
use std::time::Duration; 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 where
W: Write, W: Write,
{ {
draw_cursor_box(w, "Move Up (2)", |_, _| cursor::MoveUp(2)) 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 where
W: Write, W: Write,
{ {
draw_cursor_box(w, "Move Down (2)", |_, _| cursor::MoveDown(2)) 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 where
W: Write, W: Write,
{ {
draw_cursor_box(w, "Move Left (2)", |_, _| cursor::MoveLeft(2)) 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 where
W: Write, W: Write,
{ {
draw_cursor_box(w, "Move Right (2)", |_, _| cursor::MoveRight(2)) 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 where
W: Write, 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 where
W: Write, W: Write,
{ {
draw_cursor_box(w, "MoveToNextLine (1)", |_, _| cursor::MoveToNextLine(1)) 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 where
W: Write, 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 where
W: Write, W: Write,
{ {
execute!(w, style::Print("HideCursor"), cursor::Hide) 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 where
W: Write, W: Write,
{ {
execute!(w, style::Print("ShowCursor"), cursor::Show) 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 where
W: Write, 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 where
W: Write, 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 where
W: Write, 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 where
W: Write, 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 where
W: Write, 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. /// 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 where
W: Write, W: Write,
F: Fn(u16, u16) -> T, F: Fn(u16, u16) -> T,
@ -199,7 +198,7 @@ where
Ok(()) Ok(())
} }
pub fn run<W>(w: &mut W) -> Result<()> pub fn run<W>(w: &mut W) -> std::io::Result<()>
where where
W: Write, W: Write,
{ {

View File

@ -3,13 +3,13 @@
use crossterm::{ use crossterm::{
cursor::position, cursor::position,
event::{read, DisableMouseCapture, EnableMouseCapture, Event, KeyCode}, 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 where
W: Write, W: io::Write,
{ {
execute!(w, EnableMouseCapture)?; execute!(w, EnableMouseCapture)?;
@ -33,7 +33,7 @@ where
Ok(()) Ok(())
} }
pub fn run<W>(w: &mut W) -> Result<()> pub fn run<W>(w: &mut W) -> std::io::Result<()>
where where
W: Write, W: Write,
{ {

View File

@ -2,9 +2,7 @@ use std::io::Write;
use crossterm::{cursor, execute, style::Print, SynchronizedUpdate}; use crossterm::{cursor, execute, style::Print, SynchronizedUpdate};
use crate::Result; fn render_slowly<W>(w: &mut W) -> std::io::Result<()>
fn render_slowly<W>(w: &mut W) -> Result<()>
where where
W: Write, W: Write,
{ {
@ -15,7 +13,7 @@ where
Ok(()) Ok(())
} }
fn test_slow_rendering<W>(w: &mut W) -> Result<()> fn test_slow_rendering<W>(w: &mut W) -> std::io::Result<()>
where where
W: Write, W: Write,
{ {
@ -34,7 +32,7 @@ where
Ok(()) Ok(())
} }
pub fn run<W>(w: &mut W) -> Result<()> pub fn run<W>(w: &mut W) -> std::io::Result<()>
where where
W: Write, W: Write,
{ {

View File

@ -8,7 +8,7 @@
//! //!
//! cargo run --example stderr //! cargo run --example stderr
use std::io::{stderr, Write}; use std::io;
use crossterm::{ use crossterm::{
cursor::{Hide, MoveTo, Show}, cursor::{Hide, MoveTo, Show},
@ -17,7 +17,6 @@ use crossterm::{
execute, queue, execute, queue,
style::Print, style::Print,
terminal::{self, EnterAlternateScreen, LeaveAlternateScreen}, terminal::{self, EnterAlternateScreen, LeaveAlternateScreen},
Result,
}; };
const TEXT: &str = r#" 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) 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 where
W: Write, W: io::Write,
{ {
queue!( queue!(
write, write,
@ -73,7 +72,7 @@ where
Ok(user_char) Ok(user_char)
} }
pub fn read_char() -> Result<char> { pub fn read_char() -> io::Result<char> {
loop { loop {
if let Event::Key(KeyEvent { if let Event::Key(KeyEvent {
code: KeyCode::Char(c), code: KeyCode::Char(c),
@ -87,7 +86,7 @@ pub fn read_char() -> Result<char> {
// cargo run --example stderr // cargo run --example stderr
fn main() { fn main() {
match run_app(&mut stderr()).unwrap() { match run_app(&mut io::stderr()).unwrap() {
'1' => print!(".."), '1' => print!(".."),
'2' => print!("/"), '2' => print!("/"),
'3' => print!("~"), '3' => print!("~"),

View File

@ -4,8 +4,6 @@ use crossterm_winapi::{ConsoleMode, Handle};
use parking_lot::Once; use parking_lot::Once;
use winapi::um::wincon::ENABLE_VIRTUAL_TERMINAL_PROCESSING; use winapi::um::wincon::ENABLE_VIRTUAL_TERMINAL_PROCESSING;
use crate::Result;
/// Enable virtual terminal processing. /// Enable virtual terminal processing.
/// ///
/// This method attempts to enable virtual terminal processing for this /// 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 /// When virtual terminal processing is enabled, characters emitted to the
/// console are parsed for VT100 and similar control character sequences /// console are parsed for VT100 and similar control character sequences
/// that control color and other similar operations. /// 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 mask = ENABLE_VIRTUAL_TERMINAL_PROCESSING;
let console_mode = ConsoleMode::from(Handle::current_out_handle()?); let console_mode = ConsoleMode::from(Handle::current_out_handle()?);

View File

@ -3,8 +3,6 @@ use std::io::{self, Write};
use crate::terminal::{BeginSynchronizedUpdate, EndSynchronizedUpdate}; use crate::terminal::{BeginSynchronizedUpdate, EndSynchronizedUpdate};
use super::error::Result;
/// An interface for a command that performs an action on the terminal. /// An interface for a command that performs an action on the terminal.
/// ///
/// Crossterm provides a set of commands, /// 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) /// 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)] #[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. /// 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] #[inline]
#[cfg(windows)] #[cfg(windows)]
fn execute_winapi(&self) -> Result<()> { fn execute_winapi(&self) -> io::Result<()> {
T::execute_winapi(self) 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. /// An interface for types that can queue commands for further execution.
pub trait QueueableCommand { pub trait QueueableCommand {
/// Queues the given command for further execution. /// 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. /// An interface for types that can directly execute commands.
pub trait ExecutableCommand { pub trait ExecutableCommand {
/// Executes the given command directly. /// 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 { impl<T: Write + ?Sized> QueueableCommand for T {
@ -86,12 +84,11 @@ impl<T: Write + ?Sized> QueueableCommand for T {
/// # Examples /// # Examples
/// ///
/// ```rust /// ```rust
/// use std::io::{Write, stdout}; /// use std::io::{self, Write};
/// use crossterm::{QueueableCommand, style::Print};
/// ///
/// use crossterm::{Result, QueueableCommand, style::Print}; /// fn main() -> io::Result<()> {
/// /// let mut stdout = io::stdout();
/// fn main() -> Result<()> {
/// let mut stdout = stdout();
/// ///
/// // `Print` will executed executed when `flush` is called. /// // `Print` will executed executed when `flush` is called.
/// stdout /// stdout
@ -121,7 +118,7 @@ impl<T: Write + ?Sized> QueueableCommand for T {
/// and can therefore not be written to the given `writer`. /// and can therefore not be written to the given `writer`.
/// Therefore, there is no difference between [execute](./trait.ExecutableCommand.html) /// Therefore, there is no difference between [execute](./trait.ExecutableCommand.html)
/// and [queue](./trait.QueueableCommand.html) for those old Windows versions. /// 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)] #[cfg(windows)]
if !command.is_ansi_code_supported() { if !command.is_ansi_code_supported() {
// There may be queued commands in this writer, but `execute_winapi` will execute the // 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 /// # Example
/// ///
/// ```rust /// ```rust
/// use std::io::{Write, stdout}; /// use std::io;
/// use crossterm::{ExecutableCommand, style::Print};
/// ///
/// use crossterm::{Result, ExecutableCommand, style::Print}; /// fn main() -> io::Result<()> {
///
/// fn main() -> Result<()> {
/// // will be executed directly /// // will be executed directly
/// stdout() /// io::stdout()
/// .execute(Print("sum:\n".to_string()))? /// .execute(Print("sum:\n".to_string()))?
/// .execute(Print(format!("1 + 1= {} ", 1 + 1)))?; /// .execute(Print(format!("1 + 1= {} ", 1 + 1)))?;
/// ///
@ -179,7 +175,7 @@ impl<T: Write + ?Sized> ExecutableCommand for T {
/// and can therefore not be written to the given `writer`. /// and can therefore not be written to the given `writer`.
/// Therefore, there is no difference between [execute](./trait.ExecutableCommand.html) /// Therefore, there is no difference between [execute](./trait.ExecutableCommand.html)
/// and [queue](./trait.QueueableCommand.html) for those old Windows versions. /// 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.queue(command)?;
self.flush()?; self.flush()?;
Ok(self) Ok(self)
@ -189,7 +185,7 @@ impl<T: Write + ?Sized> ExecutableCommand for T {
/// An interface for types that support synchronized updates. /// An interface for types that support synchronized updates.
pub trait SynchronizedUpdate { pub trait SynchronizedUpdate {
/// Performs a set of actions against the given type. /// 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 { impl<W: std::io::Write + ?Sized> SynchronizedUpdate for W {
@ -207,19 +203,18 @@ impl<W: std::io::Write + ?Sized> SynchronizedUpdate for W {
/// # Examples /// # Examples
/// ///
/// ```rust /// ```rust
/// use std::io::{Write, stdout}; /// use std::io;
/// use crossterm::{ExecutableCommand, SynchronizedUpdate, style::Print};
/// ///
/// use crossterm::{Result, ExecutableCommand, SynchronizedUpdate, style::Print}; /// fn main() -> io::Result<()> {
/// /// let mut stdout = io::stdout();
/// fn main() -> Result<()> {
/// let mut stdout = stdout();
/// ///
/// stdout.sync_update(|stdout| { /// stdout.sync_update(|stdout| {
/// stdout.execute(Print("foo 1\n".to_string()))?; /// stdout.execute(Print("foo 1\n".to_string()))?;
/// stdout.execute(Print("foo 2".to_string()))?; /// stdout.execute(Print("foo 2".to_string()))?;
/// // The effects of the print command will not be present in the terminal /// // The effects of the print command will not be present in the terminal
/// // buffer, but not visible 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. /// // 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 /// 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. /// 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)?; self.queue(BeginSynchronizedUpdate)?;
let result = operations(self); let result = operations(self);
self.execute(EndSynchronizedUpdate)?; self.execute(EndSynchronizedUpdate)?;

View File

@ -13,17 +13,17 @@
//! Please have a look at [command documentation](../index.html#command-api) for a more detailed documentation. //! Please have a look at [command documentation](../index.html#command-api) for a more detailed documentation.
//! //!
//! ```no_run //! ```no_run
//! use std::io::{stdout, Write}; //! use std::io::{self, Write};
//! //!
//! use crossterm::{ //! use crossterm::{
//! ExecutableCommand, execute, Result, //! ExecutableCommand, execute,
//! cursor::{DisableBlinking, EnableBlinking, MoveTo, RestorePosition, SavePosition} //! cursor::{DisableBlinking, EnableBlinking, MoveTo, RestorePosition, SavePosition}
//! }; //! };
//! //!
//! fn main() -> Result<()> { //! fn main() -> io::Result<()> {
//! // with macro //! // with macro
//! execute!( //! execute!(
//! stdout(), //! io::stdout(),
//! SavePosition, //! SavePosition,
//! MoveTo(10, 10), //! MoveTo(10, 10),
//! EnableBlinking, //! EnableBlinking,
@ -32,7 +32,7 @@
//! ); //! );
//! //!
//! // with function //! // with function
//! stdout() //! io::stdout()
//! .execute(MoveTo(11,11))? //! .execute(MoveTo(11,11))?
//! .execute(RestorePosition); //! .execute(RestorePosition);
//! //!
@ -44,8 +44,6 @@
use std::fmt; use std::fmt;
#[cfg(windows)]
use crate::Result;
use crate::{csi, impl_display, Command}; use crate::{csi, impl_display, Command};
pub(crate) mod sys; pub(crate) mod sys;
@ -67,7 +65,7 @@ impl Command for MoveTo {
} }
#[cfg(windows)] #[cfg(windows)]
fn execute_winapi(&self) -> Result<()> { fn execute_winapi(&self) -> std::io::Result<()> {
sys::move_to(self.0, self.1) sys::move_to(self.0, self.1)
} }
} }
@ -89,7 +87,7 @@ impl Command for MoveToNextLine {
} }
#[cfg(windows)] #[cfg(windows)]
fn execute_winapi(&self) -> Result<()> { fn execute_winapi(&self) -> std::io::Result<()> {
if self.0 != 0 { if self.0 != 0 {
sys::move_to_next_line(self.0)?; sys::move_to_next_line(self.0)?;
} }
@ -114,7 +112,7 @@ impl Command for MoveToPreviousLine {
} }
#[cfg(windows)] #[cfg(windows)]
fn execute_winapi(&self) -> Result<()> { fn execute_winapi(&self) -> std::io::Result<()> {
if self.0 != 0 { if self.0 != 0 {
sys::move_to_previous_line(self.0)?; sys::move_to_previous_line(self.0)?;
} }
@ -137,7 +135,7 @@ impl Command for MoveToColumn {
} }
#[cfg(windows)] #[cfg(windows)]
fn execute_winapi(&self) -> Result<()> { fn execute_winapi(&self) -> std::io::Result<()> {
sys::move_to_column(self.0) sys::move_to_column(self.0)
} }
} }
@ -157,7 +155,7 @@ impl Command for MoveToRow {
} }
#[cfg(windows)] #[cfg(windows)]
fn execute_winapi(&self) -> Result<()> { fn execute_winapi(&self) -> std::io::Result<()> {
sys::move_to_row(self.0) sys::move_to_row(self.0)
} }
} }
@ -178,7 +176,7 @@ impl Command for MoveUp {
} }
#[cfg(windows)] #[cfg(windows)]
fn execute_winapi(&self) -> Result<()> { fn execute_winapi(&self) -> std::io::Result<()> {
sys::move_up(self.0) sys::move_up(self.0)
} }
} }
@ -199,7 +197,7 @@ impl Command for MoveRight {
} }
#[cfg(windows)] #[cfg(windows)]
fn execute_winapi(&self) -> Result<()> { fn execute_winapi(&self) -> std::io::Result<()> {
sys::move_right(self.0) sys::move_right(self.0)
} }
} }
@ -220,7 +218,7 @@ impl Command for MoveDown {
} }
#[cfg(windows)] #[cfg(windows)]
fn execute_winapi(&self) -> Result<()> { fn execute_winapi(&self) -> std::io::Result<()> {
sys::move_down(self.0) sys::move_down(self.0)
} }
} }
@ -241,7 +239,7 @@ impl Command for MoveLeft {
} }
#[cfg(windows)] #[cfg(windows)]
fn execute_winapi(&self) -> Result<()> { fn execute_winapi(&self) -> std::io::Result<()> {
sys::move_left(self.0) sys::move_left(self.0)
} }
} }
@ -263,7 +261,7 @@ impl Command for SavePosition {
} }
#[cfg(windows)] #[cfg(windows)]
fn execute_winapi(&self) -> Result<()> { fn execute_winapi(&self) -> std::io::Result<()> {
sys::save_position() sys::save_position()
} }
} }
@ -285,7 +283,7 @@ impl Command for RestorePosition {
} }
#[cfg(windows)] #[cfg(windows)]
fn execute_winapi(&self) -> Result<()> { fn execute_winapi(&self) -> std::io::Result<()> {
sys::restore_position() sys::restore_position()
} }
} }
@ -304,7 +302,7 @@ impl Command for Hide {
} }
#[cfg(windows)] #[cfg(windows)]
fn execute_winapi(&self) -> Result<()> { fn execute_winapi(&self) -> std::io::Result<()> {
sys::show_cursor(false) sys::show_cursor(false)
} }
} }
@ -323,7 +321,7 @@ impl Command for Show {
} }
#[cfg(windows)] #[cfg(windows)]
fn execute_winapi(&self) -> Result<()> { fn execute_winapi(&self) -> std::io::Result<()> {
sys::show_cursor(true) sys::show_cursor(true)
} }
} }
@ -342,7 +340,7 @@ impl Command for EnableBlinking {
f.write_str(csi!("?12h")) f.write_str(csi!("?12h"))
} }
#[cfg(windows)] #[cfg(windows)]
fn execute_winapi(&self) -> Result<()> { fn execute_winapi(&self) -> std::io::Result<()> {
Ok(()) Ok(())
} }
} }
@ -361,7 +359,7 @@ impl Command for DisableBlinking {
f.write_str(csi!("?12l")) f.write_str(csi!("?12l"))
} }
#[cfg(windows)] #[cfg(windows)]
fn execute_winapi(&self) -> Result<()> { fn execute_winapi(&self) -> std::io::Result<()> {
Ok(()) Ok(())
} }
} }
@ -404,7 +402,7 @@ impl Command for SetCursorStyle {
} }
#[cfg(windows)] #[cfg(windows)]
fn execute_winapi(&self) -> Result<()> { fn execute_winapi(&self) -> std::io::Result<()> {
Ok(()) Ok(())
} }
} }

View File

@ -6,7 +6,6 @@ use std::{
use crate::{ use crate::{
event::{filter::CursorPositionFilter, poll_internal, read_internal, InternalEvent}, event::{filter::CursorPositionFilter, poll_internal, read_internal, InternalEvent},
terminal::{disable_raw_mode, enable_raw_mode, sys::is_raw_mode_enabled}, terminal::{disable_raw_mode, enable_raw_mode, sys::is_raw_mode_enabled},
Result,
}; };
/// Returns the cursor position (column, row). /// Returns the cursor position (column, row).
@ -15,7 +14,7 @@ use crate::{
/// ///
/// On unix systems, this function will block and possibly time out while /// 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. /// [`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() { if is_raw_mode_enabled() {
read_position_raw() read_position_raw()
} else { } 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()?; enable_raw_mode()?;
let pos = read_position_raw(); let pos = read_position_raw();
disable_raw_mode()?; disable_raw_mode()?;
pos 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. // Use `ESC [ 6 n` to and retrieve the cursor position.
let mut stdout = io::stdout(); let mut stdout = io::stdout();
stdout.write_all(b"\x1B[6n")?; stdout.write_all(b"\x1B[6n")?;

View File

@ -10,8 +10,6 @@ use winapi::{
um::wincon::{SetConsoleCursorInfo, SetConsoleCursorPosition, CONSOLE_CURSOR_INFO, COORD}, um::wincon::{SetConsoleCursorInfo, SetConsoleCursorPosition, CONSOLE_CURSOR_INFO, COORD},
}; };
use crate::Result;
/// The position of the cursor, written when you save the cursor's position. /// 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 /// 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. // 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. // 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. // 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 = ScreenBuffer::current()?.info()?;
let window_size = window.terminal_window(); 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). /// Returns the cursor position (column, row).
/// ///
/// The top left cell is represented `0,0`. /// 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 cursor = ScreenBufferCursor::output()?;
let mut position = cursor.position()?; let mut position = cursor.position()?;
// if position.y != 0 { // if position.y != 0 {
@ -46,70 +44,70 @@ pub fn position() -> Result<(u16, u16)> {
Ok(position.into()) 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) 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()?; let cursor = ScreenBufferCursor::output()?;
cursor.move_to(column as i16, row as i16)?; cursor.move_to(column as i16, row as i16)?;
Ok(()) Ok(())
} }
pub(crate) fn move_up(count: u16) -> Result<()> { pub(crate) fn move_up(count: u16) -> std::io::Result<()> {
let (column, row) = position()?; let (column, row) = position()?;
move_to(column, row - count)?; move_to(column, row - count)?;
Ok(()) Ok(())
} }
pub(crate) fn move_right(count: u16) -> Result<()> { pub(crate) fn move_right(count: u16) -> std::io::Result<()> {
let (column, row) = position()?; let (column, row) = position()?;
move_to(column + count, row)?; move_to(column + count, row)?;
Ok(()) Ok(())
} }
pub(crate) fn move_down(count: u16) -> Result<()> { pub(crate) fn move_down(count: u16) -> std::io::Result<()> {
let (column, row) = position()?; let (column, row) = position()?;
move_to(column, row + count)?; move_to(column, row + count)?;
Ok(()) Ok(())
} }
pub(crate) fn move_left(count: u16) -> Result<()> { pub(crate) fn move_left(count: u16) -> std::io::Result<()> {
let (column, row) = position()?; let (column, row) = position()?;
move_to(column - count, row)?; move_to(column - count, row)?;
Ok(()) 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()?; let (_, row) = position()?;
move_to(new_column, row)?; move_to(new_column, row)?;
Ok(()) 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()?; let (col, _) = position()?;
move_to(col, new_row)?; move_to(col, new_row)?;
Ok(()) 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()?; let (_, row) = position()?;
move_to(0, row + count)?; move_to(0, row + count)?;
Ok(()) 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()?; let (_, row) = position()?;
move_to(0, row - count)?; move_to(0, row - count)?;
Ok(()) Ok(())
} }
pub(crate) fn save_position() -> Result<()> { pub(crate) fn save_position() -> std::io::Result<()> {
ScreenBufferCursor::output()?.save_position()?; ScreenBufferCursor::output()?.save_position()?;
Ok(()) Ok(())
} }
pub(crate) fn restore_position() -> Result<()> { pub(crate) fn restore_position() -> std::io::Result<()> {
ScreenBufferCursor::output()?.restore_position()?; ScreenBufferCursor::output()?.restore_position()?;
Ok(()) Ok(())
} }
@ -120,17 +118,17 @@ struct ScreenBufferCursor {
} }
impl ScreenBufferCursor { impl ScreenBufferCursor {
fn output() -> Result<ScreenBufferCursor> { fn output() -> std::io::Result<ScreenBufferCursor> {
Ok(ScreenBufferCursor { Ok(ScreenBufferCursor {
screen_buffer: ScreenBuffer::from(Handle::new(HandleType::CurrentOutputHandle)?), 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()) 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 { if x < 0 {
return Err(io::Error::new( return Err(io::Error::new(
io::ErrorKind::Other, io::ErrorKind::Other,
@ -160,7 +158,7 @@ impl ScreenBufferCursor {
Ok(()) Ok(())
} }
fn set_visibility(&self, visible: bool) -> Result<()> { fn set_visibility(&self, visible: bool) -> std::io::Result<()> {
let cursor_info = CONSOLE_CURSOR_INFO { let cursor_info = CONSOLE_CURSOR_INFO {
dwSize: 100, dwSize: 100,
bVisible: if visible { TRUE } else { FALSE }, bVisible: if visible { TRUE } else { FALSE },
@ -179,7 +177,7 @@ impl ScreenBufferCursor {
Ok(()) 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)) { if let Ok(val) = u32::try_from(SAVED_CURSOR_POS.load(Ordering::Relaxed)) {
let x = (val >> 16) as i16; let x = (val >> 16) as i16;
let y = val as i16; let y = val as i16;
@ -189,7 +187,7 @@ impl ScreenBufferCursor {
Ok(()) Ok(())
} }
fn save_position(&self) -> Result<()> { fn save_position(&self) -> std::io::Result<()> {
let position = self.position()?; let position = self.position()?;
let bits = u64::from(u32::from(position.x as u16) << 16 | u32::from(position.y as u16)); let bits = u64::from(u32::from(position.x as u16) << 16 | u32::from(position.y as u16));

View File

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

View File

@ -30,7 +30,7 @@
//! ```no_run //! ```no_run
//! use crossterm::event::{read, Event}; //! use crossterm::event::{read, Event};
//! //!
//! fn print_events() -> crossterm::Result<()> { //! fn print_events() -> std::io::Result<()> {
//! loop { //! loop {
//! // `read()` blocks until an `Event` is available //! // `read()` blocks until an `Event` is available
//! match read()? { //! match read()? {
@ -50,11 +50,11 @@
//! Non-blocking read: //! Non-blocking read:
//! //!
//! ```no_run //! ```no_run
//! use std::time::Duration; //! use std::{time::Duration, io};
//! //!
//! use crossterm::event::{poll, read, Event}; //! use crossterm::event::{poll, read, Event};
//! //!
//! fn print_events() -> crossterm::Result<()> { //! fn print_events() -> io::Result<()> {
//! loop { //! loop {
//! // `poll()` waits for an `Event` for a given time period //! // `poll()` waits for an `Event` for a given time period
//! if poll(Duration::from_millis(500))? { //! if poll(Duration::from_millis(500))? {
@ -141,11 +141,10 @@ fn try_lock_internal_event_reader_for(
/// Return immediately: /// Return immediately:
/// ///
/// ```no_run /// ```no_run
/// use std::time::Duration; /// use std::{time::Duration, io};
/// use crossterm::{event::poll};
/// ///
/// use crossterm::{event::poll, Result}; /// fn is_event_available() -> io::Result<bool> {
///
/// fn is_event_available() -> Result<bool> {
/// // Zero duration says that the `poll` function must return immediately /// // Zero duration says that the `poll` function must return immediately
/// // with an `Event` availability information /// // with an `Event` availability information
/// poll(Duration::from_secs(0)) /// poll(Duration::from_secs(0))
@ -155,17 +154,17 @@ fn try_lock_internal_event_reader_for(
/// Wait up to 100ms: /// Wait up to 100ms:
/// ///
/// ```no_run /// ```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 /// // Wait for an `Event` availability for 100ms. It returns immediately
/// // if an `Event` is/becomes available. /// // if an `Event` is/becomes available.
/// poll(Duration::from_millis(100)) /// 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) poll_internal(Some(timeout), &EventFilter)
} }
@ -179,9 +178,10 @@ pub fn poll(timeout: Duration) -> crate::Result<bool> {
/// Blocking read: /// Blocking read:
/// ///
/// ```no_run /// ```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 { /// loop {
/// // Blocks until an `Event` is available /// // Blocks until an `Event` is available
/// println!("{:?}", read()?); /// println!("{:?}", read()?);
@ -193,10 +193,11 @@ pub fn poll(timeout: Duration) -> crate::Result<bool> {
/// ///
/// ```no_run /// ```no_run
/// use std::time::Duration; /// 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 { /// loop {
/// if poll(Duration::from_millis(100))? { /// if poll(Duration::from_millis(100))? {
/// // It's guaranteed that `read` won't block, because `poll` returned /// // 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)? { match read_internal(&EventFilter)? {
InternalEvent::Event(event) => Ok(event), InternalEvent::Event(event) => Ok(event),
#[cfg(unix)] #[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. /// 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 where
F: Filter, F: Filter,
{ {
@ -235,7 +236,7 @@ where
} }
/// Reads a single `InternalEvent`. /// 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 where
F: Filter, F: Filter,
{ {
@ -296,7 +297,7 @@ impl Command for EnableMouseCapture {
} }
#[cfg(windows)] #[cfg(windows)]
fn execute_winapi(&self) -> crate::Result<()> { fn execute_winapi(&self) -> std::io::Result<()> {
sys::windows::enable_mouse_capture() sys::windows::enable_mouse_capture()
} }
@ -325,7 +326,7 @@ impl Command for DisableMouseCapture {
} }
#[cfg(windows)] #[cfg(windows)]
fn execute_winapi(&self) -> crate::Result<()> { fn execute_winapi(&self) -> std::io::Result<()> {
sys::windows::disable_mouse_capture() sys::windows::disable_mouse_capture()
} }
@ -349,7 +350,7 @@ impl Command for EnableFocusChange {
} }
#[cfg(windows)] #[cfg(windows)]
fn execute_winapi(&self) -> crate::Result<()> { fn execute_winapi(&self) -> std::io::Result<()> {
// Focus events are always enabled on Windows // Focus events are always enabled on Windows
Ok(()) Ok(())
} }
@ -365,7 +366,7 @@ impl Command for DisableFocusChange {
} }
#[cfg(windows)] #[cfg(windows)]
fn execute_winapi(&self) -> crate::Result<()> { fn execute_winapi(&self) -> std::io::Result<()> {
// Focus events can't be disabled on Windows // Focus events can't be disabled on Windows
Ok(()) Ok(())
} }
@ -388,7 +389,7 @@ impl Command for EnableBracketedPaste {
} }
#[cfg(windows)] #[cfg(windows)]
fn execute_winapi(&self) -> crate::Result<()> { fn execute_winapi(&self) -> std::io::Result<()> {
Err(std::io::Error::new( Err(std::io::Error::new(
std::io::ErrorKind::Unsupported, std::io::ErrorKind::Unsupported,
"Bracketed paste not implemented in the legacy Windows API.", "Bracketed paste not implemented in the legacy Windows API.",
@ -408,7 +409,7 @@ impl Command for DisableBracketedPaste {
} }
#[cfg(windows)] #[cfg(windows)]
fn execute_winapi(&self) -> crate::Result<()> { fn execute_winapi(&self) -> std::io::Result<()> {
Ok(()) Ok(())
} }
} }
@ -458,7 +459,7 @@ impl Command for PushKeyboardEnhancementFlags {
} }
#[cfg(windows)] #[cfg(windows)]
fn execute_winapi(&self) -> crate::Result<()> { fn execute_winapi(&self) -> std::io::Result<()> {
use std::io; use std::io;
Err(io::Error::new( Err(io::Error::new(
@ -487,7 +488,7 @@ impl Command for PopKeyboardEnhancementFlags {
} }
#[cfg(windows)] #[cfg(windows)]
fn execute_winapi(&self) -> crate::Result<()> { fn execute_winapi(&self) -> std::io::Result<()> {
use std::io; use std::io;
Err(io::Error::new( Err(io::Error::new(

View File

@ -7,7 +7,6 @@ use crate::event::source::windows::WindowsEventSource;
#[cfg(feature = "event-stream")] #[cfg(feature = "event-stream")]
use crate::event::sys::Waker; use crate::event::sys::Waker;
use crate::event::{filter::Filter, source::EventSource, timeout::PollTimeout, InternalEvent}; use crate::event::{filter::Filter, source::EventSource, timeout::PollTimeout, InternalEvent};
use crate::Result;
/// Can be used to read `InternalEvent`s. /// Can be used to read `InternalEvent`s.
pub(crate) struct InternalEventReader { pub(crate) struct InternalEventReader {
@ -40,7 +39,7 @@ impl InternalEventReader {
self.source.as_ref().expect("reader source not set").waker() 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 where
F: Filter, 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 where
F: Filter, F: Filter,
{ {
@ -131,8 +130,6 @@ mod tests {
use std::io; use std::io;
use std::{collections::VecDeque, time::Duration}; use std::{collections::VecDeque, time::Duration};
use crate::ErrorKind;
#[cfg(unix)] #[cfg(unix)]
use super::super::filter::CursorPositionFilter; use super::super::filter::CursorPositionFilter;
use super::{ use super::{
@ -312,11 +309,9 @@ mod tests {
#[test] #[test]
fn test_poll_propagates_error() { fn test_poll_propagates_error() {
let source = FakeSource::with_error(ErrorKind::from(io::ErrorKind::Other));
let mut reader = InternalEventReader { let mut reader = InternalEventReader {
events: VecDeque::new(), events: VecDeque::new(),
source: Some(Box::new(source)), source: Some(Box::new(FakeSource::new(&[]))),
skipped_events: Vec::with_capacity(32), skipped_events: Vec::with_capacity(32),
}; };
@ -324,18 +319,16 @@ mod tests {
reader reader
.poll(Some(Duration::from_secs(0)), &InternalEventFilter) .poll(Some(Duration::from_secs(0)), &InternalEventFilter)
.err() .err()
.map(|e| format!("{:?}", &e)), .map(|e| format!("{:?}", &e.kind())),
Some(format!("{:?}", ErrorKind::from(io::ErrorKind::Other))) Some(format!("{:?}", io::ErrorKind::Other))
); );
} }
#[test] #[test]
fn test_read_propagates_error() { fn test_read_propagates_error() {
let source = FakeSource::with_error(ErrorKind::from(io::ErrorKind::Other));
let mut reader = InternalEventReader { let mut reader = InternalEventReader {
events: VecDeque::new(), events: VecDeque::new(),
source: Some(Box::new(source)), source: Some(Box::new(FakeSource::new(&[]))),
skipped_events: Vec::with_capacity(32), skipped_events: Vec::with_capacity(32),
}; };
@ -343,8 +336,8 @@ mod tests {
reader reader
.read(&InternalEventFilter) .read(&InternalEventFilter)
.err() .err()
.map(|e| format!("{:?}", &e)), .map(|e| format!("{:?}", &e.kind())),
Some(format!("{:?}", ErrorKind::from(io::ErrorKind::Other))) Some(format!("{:?}", io::ErrorKind::Other))
); );
} }
@ -352,7 +345,7 @@ mod tests {
fn test_poll_continues_after_error() { fn test_poll_continues_after_error() {
const EVENT: InternalEvent = InternalEvent::Event(Event::Resize(10, 10)); 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 { let mut reader = InternalEventReader {
events: VecDeque::new(), events: VecDeque::new(),
@ -371,7 +364,7 @@ mod tests {
fn test_read_continues_after_error() { fn test_read_continues_after_error() {
const EVENT: InternalEvent = InternalEvent::Event(Event::Resize(10, 10)); 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 { let mut reader = InternalEventReader {
events: VecDeque::new(), events: VecDeque::new(),
@ -387,14 +380,14 @@ mod tests {
#[derive(Default)] #[derive(Default)]
struct FakeSource { struct FakeSource {
events: VecDeque<InternalEvent>, events: VecDeque<InternalEvent>,
error: Option<ErrorKind>, error: Option<io::Error>,
} }
impl FakeSource { impl FakeSource {
fn new(events: &[InternalEvent], error: ErrorKind) -> FakeSource { fn new(events: &[InternalEvent]) -> FakeSource {
FakeSource { FakeSource {
events: events.to_vec().into(), events: events.to_vec().into(),
error: Some(error), error: Some(io::Error::new(io::ErrorKind::Other, "")),
} }
} }
@ -404,20 +397,10 @@ mod tests {
error: None, error: None,
} }
} }
fn with_error(error: ErrorKind) -> FakeSource {
FakeSource {
events: VecDeque::new(),
error: Some(error),
}
}
} }
impl EventSource for FakeSource { impl EventSource for FakeSource {
fn try_read( fn try_read(&mut self, _timeout: Option<Duration>) -> io::Result<Option<InternalEvent>> {
&mut self,
_timeout: Option<Duration>,
) -> Result<Option<InternalEvent>, ErrorKind> {
// Return error if set in case there's just one remaining event // Return error if set in case there's just one remaining event
if self.events.len() == 1 { if self.events.len() == 1 {
if let Some(error) = self.error.take() { if let Some(error) = self.error.take() {

View File

@ -1,4 +1,4 @@
use std::time::Duration; use std::{io, time::Duration};
#[cfg(feature = "event-stream")] #[cfg(feature = "event-stream")]
use super::sys::Waker; use super::sys::Waker;
@ -19,7 +19,7 @@ pub(crate) trait EventSource: Sync + Send {
/// for the given timeout /// for the given timeout
/// ///
/// Returns `Ok(None)` if there's no event available and timeout expires. /// 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)`. /// Returns a `Waker` allowing to wake/force the `try_read` method to return `Ok(None)`.
#[cfg(feature = "event-stream")] #[cfg(feature = "event-stream")]

View File

@ -3,8 +3,6 @@ use std::{collections::VecDeque, io, time::Duration};
use mio::{unix::SourceFd, Events, Interest, Poll, Token}; use mio::{unix::SourceFd, Events, Interest, Poll, Token};
use signal_hook_mio::v0_8::Signals; use signal_hook_mio::v0_8::Signals;
use crate::Result;
#[cfg(feature = "event-stream")] #[cfg(feature = "event-stream")]
use crate::event::sys::Waker; use crate::event::sys::Waker;
use crate::event::{ use crate::event::{
@ -35,11 +33,11 @@ pub(crate) struct UnixInternalEventSource {
} }
impl UnixInternalEventSource { impl UnixInternalEventSource {
pub fn new() -> Result<Self> { pub fn new() -> io::Result<Self> {
UnixInternalEventSource::from_file_descriptor(tty_fd()?) 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 poll = Poll::new()?;
let registry = poll.registry(); let registry = poll.registry();
@ -67,7 +65,7 @@ impl UnixInternalEventSource {
} }
impl EventSource for 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() { if let Some(event) = self.parser.next() {
return Ok(Some(event)); return Ok(Some(event));
} }

View File

@ -5,8 +5,6 @@ use signal_hook::low_level::pipe;
use crate::event::timeout::PollTimeout; use crate::event::timeout::PollTimeout;
use crate::event::Event; use crate::event::Event;
use crate::Result;
use filedescriptor::{poll, pollfd, POLLIN}; use filedescriptor::{poll, pollfd, POLLIN};
#[cfg(feature = "event-stream")] #[cfg(feature = "event-stream")]
@ -23,7 +21,7 @@ struct WakePipe {
#[cfg(feature = "event-stream")] #[cfg(feature = "event-stream")]
impl WakePipe { impl WakePipe {
fn new() -> Result<Self> { fn new() -> io::Result<Self> {
let (receiver, sender) = nonblocking_unix_pair()?; let (receiver, sender) = nonblocking_unix_pair()?;
Ok(WakePipe { Ok(WakePipe {
receiver, receiver,
@ -46,7 +44,7 @@ pub(crate) struct UnixInternalEventSource {
wake_pipe: WakePipe, wake_pipe: WakePipe,
} }
fn nonblocking_unix_pair() -> Result<(UnixStream, UnixStream)> { fn nonblocking_unix_pair() -> io::Result<(UnixStream, UnixStream)> {
let (receiver, sender) = UnixStream::pair()?; let (receiver, sender) = UnixStream::pair()?;
receiver.set_nonblocking(true)?; receiver.set_nonblocking(true)?;
sender.set_nonblocking(true)?; sender.set_nonblocking(true)?;
@ -54,11 +52,11 @@ fn nonblocking_unix_pair() -> Result<(UnixStream, UnixStream)> {
} }
impl UnixInternalEventSource { impl UnixInternalEventSource {
pub fn new() -> Result<Self> { pub fn new() -> io::Result<Self> {
UnixInternalEventSource::from_file_descriptor(tty_fd()?) 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 { Ok(UnixInternalEventSource {
parser: Parser::default(), parser: Parser::default(),
tty_buffer: [0u8; TTY_BUFFER_SIZE], tty_buffer: [0u8; TTY_BUFFER_SIZE],
@ -80,7 +78,7 @@ impl UnixInternalEventSource {
/// ///
/// Similar to `std::io::Read::read_to_end`, except this function /// Similar to `std::io::Read::read_to_end`, except this function
/// only fills the given buffer and does not read beyond that. /// 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 { loop {
match fd.read(buf, buf.len()) { match fd.read(buf, buf.len()) {
Ok(x) => return Ok(x), Ok(x) => return Ok(x),
@ -94,7 +92,7 @@ fn read_complete(fd: &FileDesc, buf: &mut [u8]) -> Result<usize> {
} }
impl EventSource for 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>> {
let timeout = PollTimeout::new(timeout); let timeout = PollTimeout::new(timeout);
fn make_pollfd<F: AsRawFd>(fd: &F) -> pollfd { fn make_pollfd<F: AsRawFd>(fd: &F) -> pollfd {

View File

@ -24,7 +24,7 @@ pub(crate) struct WindowsEventSource {
} }
impl 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()?); let console = Console::from(Handle::current_in_handle()?);
Ok(WindowsEventSource { Ok(WindowsEventSource {
console, console,
@ -41,7 +41,7 @@ impl WindowsEventSource {
} }
impl EventSource for 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); let poll_timeout = PollTimeout::new(timeout);
loop { loop {

View File

@ -1,4 +1,5 @@
use std::{ use std::{
io,
pin::Pin, pin::Pin,
sync::{ sync::{
atomic::{AtomicBool, Ordering}, atomic::{AtomicBool, Ordering},
@ -12,8 +13,6 @@ use std::{
use futures_core::stream::Stream; use futures_core::stream::Stream;
use crate::Result;
use crate::event::{ use crate::event::{
filter::EventFilter, lock_internal_event_reader, poll_internal, read_internal, sys::Waker, filter::EventFilter, lock_internal_event_reader, poll_internal, read_internal, sys::Waker,
Event, InternalEvent, Event, InternalEvent,
@ -100,7 +99,7 @@ struct Task {
// We have to wake up the poll_internal (force it to return Ok(false)) and quit // We have to wake up the poll_internal (force it to return Ok(false)) and quit
// the thread before we drop. // the thread before we drop.
impl Stream for EventStream { 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>> { 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) { let result = match poll_internal(Some(Duration::from_secs(0)), &EventFilter) {

View File

@ -1,12 +1,8 @@
use std::io; use std::io;
use crate::{ use crate::event::{
event::{ Event, KeyCode, KeyEvent, KeyEventKind, KeyEventState, KeyModifiers, KeyboardEnhancementFlags,
Event, KeyCode, KeyEvent, KeyEventKind, KeyEventState, KeyModifiers, MediaKeyCode, ModifierKeyCode, MouseButton, MouseEvent, MouseEventKind,
KeyboardEnhancementFlags, MediaKeyCode, ModifierKeyCode, MouseButton, MouseEvent,
MouseEventKind,
},
ErrorKind, Result,
}; };
use super::super::super::InternalEvent; use super::super::super::InternalEvent;
@ -23,11 +19,14 @@ use super::super::super::InternalEvent;
// Ok(Some(event)) -> we have event, clear the buffer // 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.") 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() { if buffer.is_empty() {
return Ok(None); return Ok(None);
} }
@ -135,7 +134,7 @@ fn char_code_to_event(code: KeyCode) -> KeyEvent {
KeyEvent::new(code, modifiers) 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 [ assert!(buffer.starts_with(&[b'\x1B', b'['])); // ESC [
if buffer.len() == 2 { if buffer.len() == 2 {
@ -214,7 +213,7 @@ pub(crate) fn parse_csi(buffer: &[u8]) -> Result<Option<InternalEvent>> {
Ok(input_event.map(InternalEvent::Event)) 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 where
T: std::str::FromStr, T: std::str::FromStr,
{ {
@ -224,7 +223,7 @@ where
.map_err(|_| could_not_parse_event_error()) .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 let mut sub_split = iter
.next() .next()
.ok_or_else(could_not_parse_event_error)? .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 // ESC [ Cy ; Cx R
// Cy - cursor row number (starting from 1) // Cy - cursor row number (starting from 1)
// Cx - cursor column 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))) 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 // ESC [ ? flags u
assert!(buffer.starts_with(&[b'\x1B', b'[', b'?'])); // ESC [ ? assert!(buffer.starts_with(&[b'\x1B', b'[', b'?'])); // ESC [ ?
assert!(buffer.ends_with(&[b'u'])); 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))) 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 // ESC [ 64 ; attr1 ; attr2 ; ... ; attrn ; c
assert!(buffer.starts_with(&[b'\x1B', b'[', b'?'])); assert!(buffer.starts_with(&[b'\x1B', b'[', b'?']));
assert!(buffer.ends_with(&[b'c'])); 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 [ assert!(buffer.starts_with(&[b'\x1B', b'['])); // ESC [
// //
let s = std::str::from_utf8(&buffer[2..buffer.len() - 1]) 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 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.starts_with(&[b'\x1B', b'['])); // ESC [
assert!(buffer.ends_with(&[b'u'])); 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))) 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.starts_with(&[b'\x1B', b'['])); // ESC [
assert!(buffer.ends_with(&[b'~'])); 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))) 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: // rxvt mouse encoding:
// ESC [ Cb ; Cx ; Cy ; M // 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). // Normal mouse encoding: ESC [ M CB Cx Cy (6 characters only).
assert!(buffer.starts_with(&[b'\x1B', b'[', b'M'])); // ESC [ M 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) // ESC [ < Cb ; Cx ; Cy (;) (M or m)
assert!(buffer.starts_with(&[b'\x1B', b'[', b'<'])); // ESC [ < 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 /// - mouse is dragging
/// - button number /// - button number
/// - 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 button_number = (cb & 0b0000_0011) | ((cb & 0b1100_0000) >> 4);
let dragging = cb & 0b0010_0000 == 0b0010_0000; let dragging = cb & 0b0010_0000 == 0b0010_0000;
@ -809,7 +808,7 @@ fn parse_cb(cb: u8) -> Result<(MouseEventKind, KeyModifiers)> {
} }
#[cfg(feature = "bracketed-paste")] #[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 ~ // ESC [ 2 0 0 ~ pasted text ESC 2 0 1 ~
assert!(buffer.starts_with(b"\x1B[200~")); 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) { match std::str::from_utf8(buffer) {
Ok(s) => { Ok(s) => {
let ch = s.chars().next().ok_or_else(could_not_parse_event_error)?; let ch = s.chars().next().ok_or_else(could_not_parse_event_error)?;

View File

@ -2,8 +2,6 @@ use std::sync::{Arc, Mutex};
use ::mio::{Registry, Token}; use ::mio::{Registry, Token};
use crate::Result;
/// Allows to wake up the `mio::Poll::poll()` method. /// Allows to wake up the `mio::Poll::poll()` method.
/// This type wraps `mio::Waker`, for more information see its documentation. /// This type wraps `mio::Waker`, for more information see its documentation.
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
@ -13,7 +11,7 @@ pub(crate) struct Waker {
impl Waker { impl Waker {
/// Create a new `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 { Ok(Self {
inner: Arc::new(Mutex::new(mio::Waker::new(registry, waker_token)?)), 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`. /// Wake up the [`Poll`] associated with this `Waker`.
/// ///
/// Readiness is set to `Ready::readable()`. /// 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() self.inner.lock().unwrap().wake()
} }
@ -30,7 +28,7 @@ impl Waker {
/// ///
/// This function is not impl /// This function is not impl
#[allow(dead_code, clippy::clippy::unnecessary_wraps)] #[allow(dead_code, clippy::clippy::unnecessary_wraps)]
pub(crate) fn reset(&self) -> Result<()> { pub(crate) fn reset(&self) -> std::io::Result<()> {
Ok(()) Ok(())
} }
} }

View File

@ -1,11 +1,9 @@
use std::{ use std::{
io::Write, io::{self, Write},
os::unix::net::UnixStream, os::unix::net::UnixStream,
sync::{Arc, Mutex}, sync::{Arc, Mutex},
}; };
use crate::Result;
/// Allows to wake up the EventSource::try_read() method. /// Allows to wake up the EventSource::try_read() method.
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub(crate) struct Waker { pub(crate) struct Waker {
@ -23,16 +21,8 @@ impl Waker {
/// Wake up the [`Poll`] associated with this `Waker`. /// Wake up the [`Poll`] associated with this `Waker`.
/// ///
/// Readiness is set to `Ready::readable()`. /// 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])?; self.inner.lock().unwrap().write(&[0])?;
Ok(()) 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(())
}
} }

View File

@ -6,8 +6,6 @@ use std::sync::atomic::{AtomicU64, Ordering};
use crossterm_winapi::{ConsoleMode, Handle}; use crossterm_winapi::{ConsoleMode, Handle};
use crate::Result;
pub(crate) mod parse; pub(crate) mod parse;
pub(crate) mod poll; pub(crate) mod poll;
#[cfg(feature = "event-stream")] #[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. /// 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)) u32::try_from(ORIGINAL_CONSOLE_MODE.load(Ordering::Relaxed))
.map_err(|_| io::Error::new(io::ErrorKind::Other, "Initial console modes not set")) .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()?); let mode = ConsoleMode::from(Handle::current_in_handle()?);
init_original_console_mode(mode.mode()?); init_original_console_mode(mode.mode()?);
mode.set_mode(ENABLE_MOUSE_MODE)?; mode.set_mode(ENABLE_MOUSE_MODE)?;
@ -43,7 +41,7 @@ pub(crate) fn enable_mouse_capture() -> Result<()> {
Ok(()) 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()?); let mode = ConsoleMode::from(Handle::current_in_handle()?);
mode.set_mode(original_console_mode()?)?; mode.set_mode(original_console_mode()?)?;
Ok(()) Ok(())

View File

@ -12,12 +12,8 @@ use winapi::um::{
}, },
}; };
use crate::{ use crate::event::{
event::{ Event, KeyCode, KeyEvent, KeyEventKind, KeyModifiers, MouseButton, MouseEvent, MouseEventKind,
Event, KeyCode, KeyEvent, KeyEventKind, KeyModifiers, MouseButton, MouseEvent,
MouseEventKind,
},
Result,
}; };
#[derive(Default)] #[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. // 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. // 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(); let window_size = ScreenBuffer::current()?.info()?.terminal_window();
Ok(y - window_size.top) Ok(y - window_size.top)
} }
@ -309,7 +305,7 @@ pub fn parse_relative_y(y: i16) -> Result<i16> {
fn parse_mouse_event_record( fn parse_mouse_event_record(
event: &crossterm_winapi::MouseEvent, event: &crossterm_winapi::MouseEvent,
buttons_pressed: &MouseButtonsPressed, buttons_pressed: &MouseButtonsPressed,
) -> Result<Option<MouseEvent>> { ) -> std::io::Result<Option<MouseEvent>> {
let modifiers = KeyModifiers::from(&event.control_key_state); let modifiers = KeyModifiers::from(&event.control_key_state);
let xpos = event.mouse_position.x as u16; let xpos = event.mouse_position.x as u16;

View File

@ -10,8 +10,6 @@ use winapi::{
}, },
}; };
use crate::Result;
#[cfg(feature = "event-stream")] #[cfg(feature = "event-stream")]
pub(crate) use super::waker::Waker; pub(crate) use super::waker::Waker;
@ -28,7 +26,7 @@ impl WinApiPoll {
} }
#[cfg(feature = "event-stream")] #[cfg(feature = "event-stream")]
pub(crate) fn new() -> Result<WinApiPoll> { pub(crate) fn new() -> std::io::Result<WinApiPoll> {
Ok(WinApiPoll { Ok(WinApiPoll {
waker: Waker::new()?, waker: Waker::new()?,
}) })
@ -36,7 +34,7 @@ impl WinApiPoll {
} }
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 { let dw_millis = if let Some(duration) = timeout {
duration.as_millis() as u32 duration.as_millis() as u32
} else { } else {

View File

@ -2,8 +2,6 @@ use std::sync::{Arc, Mutex};
use crossterm_winapi::Semaphore; use crossterm_winapi::Semaphore;
use crate::Result;
/// Allows to wake up the `WinApiPoll::poll()` method. /// Allows to wake up the `WinApiPoll::poll()` method.
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub(crate) struct Waker { pub(crate) struct Waker {
@ -15,7 +13,7 @@ impl Waker {
/// ///
/// `Waker` is based on the `Semaphore`. You have to use the semaphore /// `Waker` is based on the `Semaphore`. You have to use the semaphore
/// handle along with the `WaitForMultipleObjects`. /// handle along with the `WaitForMultipleObjects`.
pub(crate) fn new() -> Result<Self> { pub(crate) fn new() -> std::io::Result<Self> {
let inner = Semaphore::new()?; let inner = Semaphore::new()?;
Ok(Self { Ok(Self {
@ -24,13 +22,13 @@ impl Waker {
} }
/// Wakes the `WaitForMultipleObjects`. /// Wakes the `WaitForMultipleObjects`.
pub(crate) fn wake(&self) -> Result<()> { pub(crate) fn wake(&self) -> std::io::Result<()> {
self.inner.lock().unwrap().release()?; self.inner.lock().unwrap().release()?;
Ok(()) Ok(())
} }
/// Replaces the current semaphore with a new one allowing us to reuse the same `Waker`. /// 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()?; *self.inner.lock().unwrap() = Semaphore::new()?;
Ok(()) Ok(())
} }

View File

@ -155,7 +155,7 @@
//! Macros: //! Macros:
//! //!
//! ```no_run //! ```no_run
//! use std::io::{Write, stdout}; //! use std::io::{stdout, Write};
//! use crossterm::{execute, ExecutableCommand, cursor}; //! use crossterm::{execute, ExecutableCommand, cursor};
//! //!
//! let mut stdout = stdout(); //! let mut stdout = stdout();
@ -172,14 +172,14 @@
//! Functions: //! Functions:
//! //!
//! ```no_run //! ```no_run
//! use std::io::{stdout, Write}; //! use std::io::{self, Write};
//! use crossterm::{ //! use crossterm::{
//! ExecutableCommand, QueueableCommand, //! ExecutableCommand, QueueableCommand,
//! terminal, cursor, style::{self, Stylize}, Result //! terminal, cursor, style::{self, Stylize}
//! }; //! };
//! //!
//! fn main() -> Result<()> { //! fn main() -> io::Result<()> {
//! let mut stdout = stdout(); //! let mut stdout = io::stdout();
//! //!
//! stdout.execute(terminal::Clear(terminal::ClearType::All))?; //! stdout.execute(terminal::Clear(terminal::ClearType::All))?;
//! //!
@ -201,14 +201,14 @@
//! Macros: //! Macros:
//! //!
//! ```no_run //! ```no_run
//! use std::io::{stdout, Write}; //! use std::io::{self, Write};
//! use crossterm::{ //! use crossterm::{
//! execute, queue, //! execute, queue,
//! style::{self, Stylize}, cursor, terminal, Result //! style::{self, Stylize}, cursor, terminal
//! }; //! };
//! //!
//! fn main() -> Result<()> { //! fn main() -> io::Result<()> {
//! let mut stdout = stdout(); //! let mut stdout = io::stdout();
//! //!
//! execute!(stdout, terminal::Clear(terminal::ClearType::All))?; //! execute!(stdout, terminal::Clear(terminal::ClearType::All))?;
//! //!
@ -230,10 +230,7 @@
//! [stderr]: https://doc.rust-lang.org/std/io/fn.stderr.html //! [stderr]: https://doc.rust-lang.org/std/io/fn.stderr.html
//! [flush]: https://doc.rust-lang.org/std/io/trait.Write.html#tymethod.flush //! [flush]: https://doc.rust-lang.org/std/io/trait.Write.html#tymethod.flush
pub use crate::{ pub use crate::command::{Command, ExecutableCommand, QueueableCommand, SynchronizedUpdate};
command::{Command, ExecutableCommand, QueueableCommand, SynchronizedUpdate},
error::{ErrorKind, Result},
};
/// A module to work with the terminal cursor /// A module to work with the terminal cursor
pub mod 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. /// A module that exposes one function to check if the current terminal supports ANSI sequences.
pub mod ansi_support; pub mod ansi_support;
mod command; mod command;
mod error;
pub(crate) mod macros; pub(crate) mod macros;
#[cfg(all(windows, not(feature = "windows")))] #[cfg(all(windows, not(feature = "windows")))]

View File

@ -238,11 +238,9 @@ mod tests {
use std::fmt; use std::fmt;
use std::cell::RefCell; use std::cell::RefCell;
use std::fmt::Debug;
use super::FakeWrite; use super::FakeWrite;
use crate::command::Command; use crate::command::Command;
use crate::error::Result as CrosstermResult;
// We need to test two different APIs: WinAPI and the write api. We // We need to test two different APIs: WinAPI and the write api. We
// don't know until runtime which we're supporting (via // don't know until runtime which we're supporting (via
@ -274,7 +272,7 @@ mod tests {
f.write_str(self.value) f.write_str(self.value)
} }
fn execute_winapi(&self) -> CrosstermResult<()> { fn execute_winapi(&self) -> std::io::Result<()> {
self.stream.borrow_mut().push(self.value); self.stream.borrow_mut().push(self.value);
Ok(()) Ok(())
} }
@ -293,9 +291,9 @@ mod tests {
// If the stream was populated, it tests that the two arrays are equal. // 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 // If the writer was populated, it tests that the contents of the
// write buffer are equal to the concatenation of `stream_result`. // write buffer are equal to the concatenation of `stream_result`.
fn test_harness<E: Debug>( fn test_harness(
stream_result: &[&'static str], 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 stream = WindowsEventStream::default();
let mut writer = FakeWrite::default(); let mut writer = FakeWrite::default();

View File

@ -28,14 +28,13 @@
//! Using the Command API to color text. //! Using the Command API to color text.
//! //!
//! ```no_run //! ```no_run
//! use std::io::{stdout, Write}; //! use std::io::{self, Write};
//! //! use crossterm::execute;
//! use crossterm::{execute, Result};
//! use crossterm::style::{Print, SetForegroundColor, SetBackgroundColor, ResetColor, Color, Attribute}; //! use crossterm::style::{Print, SetForegroundColor, SetBackgroundColor, ResetColor, Color, Attribute};
//! //!
//! fn main() -> Result<()> { //! fn main() -> io::Result<()> {
//! execute!( //! execute!(
//! stdout(), //! io::stdout(),
//! // Blue foreground //! // Blue foreground
//! SetForegroundColor(Color::Blue), //! SetForegroundColor(Color::Blue),
//! // Red background //! // Red background
@ -68,14 +67,14 @@
//! Using the Command API to set attributes. //! Using the Command API to set attributes.
//! //!
//! ```no_run //! ```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}; //! use crossterm::style::{SetAttribute, Attribute};
//! //!
//! fn main() -> Result<()> { //! fn main() -> io::Result<()> {
//! execute!( //! execute!(
//! stdout(), //! io::stdout(),
//! // Set to bold //! // Set to bold
//! SetAttribute(Attribute::Bold), //! SetAttribute(Attribute::Bold),
//! Print("Bold text here.".to_string()), //! Print("Bold text here.".to_string()),
@ -118,8 +117,6 @@ use std::{
}; };
use crate::command::execute_fmt; use crate::command::execute_fmt;
#[cfg(windows)]
use crate::Result;
use crate::{csi, impl_display, Command}; use crate::{csi, impl_display, Command};
pub use self::{ pub use self::{
@ -188,7 +185,7 @@ impl Command for SetForegroundColor {
} }
#[cfg(windows)] #[cfg(windows)]
fn execute_winapi(&self) -> Result<()> { fn execute_winapi(&self) -> std::io::Result<()> {
sys::windows::set_foreground_color(self.0) sys::windows::set_foreground_color(self.0)
} }
} }
@ -212,7 +209,7 @@ impl Command for SetBackgroundColor {
} }
#[cfg(windows)] #[cfg(windows)]
fn execute_winapi(&self) -> Result<()> { fn execute_winapi(&self) -> std::io::Result<()> {
sys::windows::set_background_color(self.0) sys::windows::set_background_color(self.0)
} }
} }
@ -236,7 +233,7 @@ impl Command for SetUnderlineColor {
} }
#[cfg(windows)] #[cfg(windows)]
fn execute_winapi(&self) -> Result<()> { fn execute_winapi(&self) -> std::io::Result<()> {
Err(std::io::Error::new( Err(std::io::Error::new(
std::io::ErrorKind::Other, std::io::ErrorKind::Other,
"SetUnderlineColor not supported by winapi.", "SetUnderlineColor not supported by winapi.",
@ -280,7 +277,7 @@ impl Command for SetColors {
} }
#[cfg(windows)] #[cfg(windows)]
fn execute_winapi(&self) -> Result<()> { fn execute_winapi(&self) -> std::io::Result<()> {
if let Some(color) = self.0.foreground { if let Some(color) = self.0.foreground {
sys::windows::set_foreground_color(color)?; sys::windows::set_foreground_color(color)?;
} }
@ -307,7 +304,7 @@ impl Command for SetAttribute {
} }
#[cfg(windows)] #[cfg(windows)]
fn execute_winapi(&self) -> Result<()> { fn execute_winapi(&self) -> std::io::Result<()> {
// attributes are not supported by WinAPI. // attributes are not supported by WinAPI.
Ok(()) Ok(())
} }
@ -334,7 +331,7 @@ impl Command for SetAttributes {
} }
#[cfg(windows)] #[cfg(windows)]
fn execute_winapi(&self) -> Result<()> { fn execute_winapi(&self) -> std::io::Result<()> {
// attributes are not supported by WinAPI. // attributes are not supported by WinAPI.
Ok(()) Ok(())
} }
@ -367,7 +364,7 @@ impl Command for SetStyle {
} }
#[cfg(windows)] #[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"); panic!("tried to execute SetStyle command using WinAPI, use ANSI instead");
} }
@ -434,7 +431,7 @@ impl<D: Display> Command for PrintStyledContent<D> {
} }
#[cfg(windows)] #[cfg(windows)]
fn execute_winapi(&self) -> Result<()> { fn execute_winapi(&self) -> std::io::Result<()> {
Ok(()) Ok(())
} }
} }
@ -453,7 +450,7 @@ impl Command for ResetColor {
} }
#[cfg(windows)] #[cfg(windows)]
fn execute_winapi(&self) -> Result<()> { fn execute_winapi(&self) -> std::io::Result<()> {
sys::windows::reset() sys::windows::reset()
} }
} }
@ -470,7 +467,7 @@ impl<T: Display> Command for Print<T> {
} }
#[cfg(windows)] #[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"); panic!("tried to execute Print command using WinAPI, use ANSI instead");
} }

View File

@ -4,8 +4,6 @@ use std::sync::atomic::{AtomicU32, Ordering};
use crossterm_winapi::{Console, Handle, HandleType, ScreenBuffer}; use crossterm_winapi::{Console, Handle, HandleType, ScreenBuffer};
use winapi::um::wincon; use winapi::um::wincon;
use crate::Result;
use super::super::{Color, Colored}; use super::super::{Color, Colored};
const FG_GREEN: u16 = wincon::FOREGROUND_GREEN; 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_BLUE: u16 = wincon::BACKGROUND_BLUE;
const BG_INTENSITY: u16 = wincon::BACKGROUND_INTENSITY; 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()?; init_console_color()?;
let color_value: u16 = Colored::ForegroundColor(fg_color).into(); let color_value: u16 = Colored::ForegroundColor(fg_color).into();
@ -42,7 +40,7 @@ pub(crate) fn set_foreground_color(fg_color: Color) -> Result<()> {
Ok(()) 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()?; init_console_color()?;
let color_value: u16 = Colored::BackgroundColor(bg_color).into(); let color_value: u16 = Colored::BackgroundColor(bg_color).into();
@ -66,7 +64,7 @@ pub(crate) fn set_background_color(bg_color: Color) -> Result<()> {
Ok(()) 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)) { if let Ok(original_color) = u16::try_from(ORIGINAL_CONSOLE_COLOR.load(Ordering::Relaxed)) {
Console::from(Handle::new(HandleType::CurrentOutputHandle)?) Console::from(Handle::new(HandleType::CurrentOutputHandle)?)
.set_text_attribute(original_color)?; .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. /// 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 { if ORIGINAL_CONSOLE_COLOR.load(Ordering::Relaxed) == u32::MAX {
let screen_buffer = ScreenBuffer::current()?; let screen_buffer = ScreenBuffer::current()?;
let attr = screen_buffer.info()?.attributes(); let attr = screen_buffer.info()?.attributes();

View File

@ -154,7 +154,7 @@ Attribute! {
} }
impl Display for 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))?; write!(f, "{}", SetAttribute(*self))?;
Ok(()) Ok(())
} }

View File

@ -1,4 +1,7 @@
use std::{convert::AsRef, convert::TryFrom, result::Result, str::FromStr}; use std::{
convert::{AsRef, TryFrom},
str::FromStr,
};
#[cfg(feature = "serde")] #[cfg(feature = "serde")]
use std::fmt; use std::fmt;

View File

@ -63,27 +63,27 @@
//! ## Examples //! ## Examples
//! //!
//! ```no_run //! ```no_run
//! use std::io::{stdout, Write}; //! use std::io::{self, Write};
//! use crossterm::{execute, Result, terminal::{ScrollUp, SetSize, size}}; //! use crossterm::{execute, terminal::{ScrollUp, SetSize, size}};
//! //!
//! fn main() -> Result<()> { //! fn main() -> io::Result<()> {
//! let (cols, rows) = size()?; //! let (cols, rows) = size()?;
//! // Resize terminal and scroll up. //! // Resize terminal and scroll up.
//! execute!( //! execute!(
//! stdout(), //! io::stdout(),
//! SetSize(10, 10), //! SetSize(10, 10),
//! ScrollUp(5) //! ScrollUp(5)
//! )?; //! )?;
//! //!
//! // Be a good citizen, cleanup //! // Be a good citizen, cleanup
//! execute!(stdout(), SetSize(cols, rows))?; //! execute!(io::stdout(), SetSize(cols, rows))?;
//! Ok(()) //! Ok(())
//! } //! }
//! ``` //! ```
//! //!
//! For manual execution control check out [crossterm::queue](../macro.queue.html). //! For manual execution control check out [crossterm::queue](../macro.queue.html).
use std::fmt; use std::{fmt, io};
#[cfg(windows)] #[cfg(windows)]
use crossterm_winapi::{ConsoleMode, Handle, ScreenBuffer}; use crossterm_winapi::{ConsoleMode, Handle, ScreenBuffer};
@ -94,7 +94,7 @@ use winapi::um::wincon::ENABLE_WRAP_AT_EOL_OUTPUT;
#[doc(no_inline)] #[doc(no_inline)]
use crate::Command; use crate::Command;
use crate::{csi, impl_display, Result}; use crate::{csi, impl_display};
pub(crate) mod sys; pub(crate) mod sys;
@ -104,7 +104,7 @@ pub use sys::supports_keyboard_enhancement;
/// Tells whether the raw mode is enabled. /// Tells whether the raw mode is enabled.
/// ///
/// Please have a look at the [raw mode](./index.html#raw-mode) section. /// 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)] #[cfg(unix)]
{ {
Ok(sys::is_raw_mode_enabled()) Ok(sys::is_raw_mode_enabled())
@ -119,21 +119,21 @@ pub fn is_raw_mode_enabled() -> Result<bool> {
/// Enables raw mode. /// Enables raw mode.
/// ///
/// Please have a look at the [raw mode](./index.html#raw-mode) section. /// 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() sys::enable_raw_mode()
} }
/// Disables raw mode. /// Disables raw mode.
/// ///
/// Please have a look at the [raw mode](./index.html#raw-mode) section. /// 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() sys::disable_raw_mode()
} }
/// Returns the terminal size `(columns, rows)`. /// Returns the terminal size `(columns, rows)`.
/// ///
/// The top left cell is represented `(1, 1)`. /// The top left cell is represented `(1, 1)`.
pub fn size() -> Result<(u16, u16)> { pub fn size() -> io::Result<(u16, u16)> {
sys::size() sys::size()
} }
@ -147,7 +147,7 @@ impl Command for DisableLineWrap {
} }
#[cfg(windows)] #[cfg(windows)]
fn execute_winapi(&self) -> Result<()> { fn execute_winapi(&self) -> io::Result<()> {
let screen_buffer = ScreenBuffer::current()?; let screen_buffer = ScreenBuffer::current()?;
let console_mode = ConsoleMode::from(screen_buffer.handle().clone()); let console_mode = ConsoleMode::from(screen_buffer.handle().clone());
let new_mode = console_mode.mode()? & !ENABLE_WRAP_AT_EOL_OUTPUT; let new_mode = console_mode.mode()? & !ENABLE_WRAP_AT_EOL_OUTPUT;
@ -166,7 +166,7 @@ impl Command for EnableLineWrap {
} }
#[cfg(windows)] #[cfg(windows)]
fn execute_winapi(&self) -> Result<()> { fn execute_winapi(&self) -> io::Result<()> {
let screen_buffer = ScreenBuffer::current()?; let screen_buffer = ScreenBuffer::current()?;
let console_mode = ConsoleMode::from(screen_buffer.handle().clone()); let console_mode = ConsoleMode::from(screen_buffer.handle().clone());
let new_mode = console_mode.mode()? | ENABLE_WRAP_AT_EOL_OUTPUT; let new_mode = console_mode.mode()? | ENABLE_WRAP_AT_EOL_OUTPUT;
@ -185,15 +185,15 @@ impl Command for EnableLineWrap {
/// # Examples /// # Examples
/// ///
/// ```no_run /// ```no_run
/// use std::io::{stdout, Write}; /// use std::io::{self, Write};
/// use crossterm::{execute, Result, terminal::{EnterAlternateScreen, LeaveAlternateScreen}}; /// use crossterm::{execute, terminal::{EnterAlternateScreen, LeaveAlternateScreen}};
/// ///
/// fn main() -> Result<()> { /// fn main() -> io::Result<()> {
/// execute!(stdout(), EnterAlternateScreen)?; /// execute!(io::stdout(), EnterAlternateScreen)?;
/// ///
/// // Do anything on the alternate screen /// // Do anything on the alternate screen
/// ///
/// execute!(stdout(), LeaveAlternateScreen) /// execute!(io::stdout(), LeaveAlternateScreen)
/// } /// }
/// ``` /// ```
/// ///
@ -206,7 +206,7 @@ impl Command for EnterAlternateScreen {
} }
#[cfg(windows)] #[cfg(windows)]
fn execute_winapi(&self) -> Result<()> { fn execute_winapi(&self) -> io::Result<()> {
let alternate_screen = ScreenBuffer::create()?; let alternate_screen = ScreenBuffer::create()?;
alternate_screen.show()?; alternate_screen.show()?;
Ok(()) Ok(())
@ -223,15 +223,15 @@ impl Command for EnterAlternateScreen {
/// # Examples /// # Examples
/// ///
/// ```no_run /// ```no_run
/// use std::io::{stdout, Write}; /// use std::io::{self, Write};
/// use crossterm::{execute, Result, terminal::{EnterAlternateScreen, LeaveAlternateScreen}}; /// use crossterm::{execute, terminal::{EnterAlternateScreen, LeaveAlternateScreen}};
/// ///
/// fn main() -> Result<()> { /// fn main() -> io::Result<()> {
/// execute!(stdout(), EnterAlternateScreen)?; /// execute!(io::stdout(), EnterAlternateScreen)?;
/// ///
/// // Do anything on the alternate screen /// // Do anything on the alternate screen
/// ///
/// execute!(stdout(), LeaveAlternateScreen) /// execute!(io::stdout(), LeaveAlternateScreen)
/// } /// }
/// ``` /// ```
/// ///
@ -244,7 +244,7 @@ impl Command for LeaveAlternateScreen {
} }
#[cfg(windows)] #[cfg(windows)]
fn execute_winapi(&self) -> Result<()> { fn execute_winapi(&self) -> io::Result<()> {
let screen_buffer = ScreenBuffer::from(Handle::current_out_handle()?); let screen_buffer = ScreenBuffer::from(Handle::current_out_handle()?);
screen_buffer.show()?; screen_buffer.show()?;
Ok(()) Ok(())
@ -286,7 +286,7 @@ impl Command for ScrollUp {
} }
#[cfg(windows)] #[cfg(windows)]
fn execute_winapi(&self) -> Result<()> { fn execute_winapi(&self) -> io::Result<()> {
sys::scroll_up(self.0) sys::scroll_up(self.0)
} }
} }
@ -308,7 +308,7 @@ impl Command for ScrollDown {
} }
#[cfg(windows)] #[cfg(windows)]
fn execute_winapi(&self) -> Result<()> { fn execute_winapi(&self) -> io::Result<()> {
sys::scroll_down(self.0) sys::scroll_down(self.0)
} }
} }
@ -336,7 +336,7 @@ impl Command for Clear {
} }
#[cfg(windows)] #[cfg(windows)]
fn execute_winapi(&self) -> Result<()> { fn execute_winapi(&self) -> io::Result<()> {
sys::clear(self.0) sys::clear(self.0)
} }
} }
@ -355,7 +355,7 @@ impl Command for SetSize {
} }
#[cfg(windows)] #[cfg(windows)]
fn execute_winapi(&self) -> Result<()> { fn execute_winapi(&self) -> io::Result<()> {
sys::set_size(self.0, self.1) sys::set_size(self.0, self.1)
} }
} }
@ -374,7 +374,7 @@ impl<T: fmt::Display> Command for SetTitle<T> {
} }
#[cfg(windows)] #[cfg(windows)]
fn execute_winapi(&self) -> Result<()> { fn execute_winapi(&self) -> io::Result<()> {
sys::set_window_title(&self.0) sys::set_window_title(&self.0)
} }
} }
@ -399,15 +399,15 @@ impl<T: fmt::Display> Command for SetTitle<T> {
/// # Examples /// # Examples
/// ///
/// ```no_run /// ```no_run
/// use std::io::{stdout, Write}; /// use std::io::{self, Write};
/// use crossterm::{execute, Result, terminal::{BeginSynchronizedUpdate, EndSynchronizedUpdate}}; /// use crossterm::{execute, terminal::{BeginSynchronizedUpdate, EndSynchronizedUpdate}};
/// ///
/// fn main() -> Result<()> { /// fn main() -> io::Result<()> {
/// execute!(stdout(), BeginSynchronizedUpdate)?; /// execute!(io::stdout(), BeginSynchronizedUpdate)?;
/// ///
/// // Anything performed here will not be rendered until EndSynchronizedUpdate is called. /// // Anything performed here will not be rendered until EndSynchronizedUpdate is called.
/// ///
/// execute!(stdout(), EndSynchronizedUpdate)?; /// execute!(io::stdout(), EndSynchronizedUpdate)?;
/// Ok(()) /// Ok(())
/// } /// }
/// ``` /// ```
@ -421,7 +421,7 @@ impl Command for BeginSynchronizedUpdate {
} }
#[cfg(windows)] #[cfg(windows)]
fn execute_winapi(&self) -> Result<()> { fn execute_winapi(&self) -> io::Result<()> {
Ok(()) Ok(())
} }
@ -452,15 +452,15 @@ impl Command for BeginSynchronizedUpdate {
/// # Examples /// # Examples
/// ///
/// ```no_run /// ```no_run
/// use std::io::{stdout, Write}; /// use std::io::{self, Write};
/// use crossterm::{execute, Result, terminal::{BeginSynchronizedUpdate, EndSynchronizedUpdate}}; /// use crossterm::{execute, terminal::{BeginSynchronizedUpdate, EndSynchronizedUpdate}};
/// ///
/// fn main() -> Result<()> { /// fn main() -> io::Result<()> {
/// execute!(stdout(), BeginSynchronizedUpdate)?; /// execute!(io::stdout(), BeginSynchronizedUpdate)?;
/// ///
/// // Anything performed here will not be rendered until EndSynchronizedUpdate is called. /// // Anything performed here will not be rendered until EndSynchronizedUpdate is called.
/// ///
/// execute!(stdout(), EndSynchronizedUpdate)?; /// execute!(io::stdout(), EndSynchronizedUpdate)?;
/// Ok(()) /// Ok(())
/// } /// }
/// ``` /// ```
@ -474,7 +474,7 @@ impl Command for EndSynchronizedUpdate {
} }
#[cfg(windows)] #[cfg(windows)]
fn execute_winapi(&self) -> Result<()> { fn execute_winapi(&self) -> io::Result<()> {
Ok(()) Ok(())
} }

View File

@ -8,8 +8,6 @@ use std::{
use libc::size_t; use libc::size_t;
use crate::Result;
/// A file descriptor wrapper. /// A file descriptor wrapper.
/// ///
/// It allows to retrieve raw file descriptor, write to the file descriptor and /// It allows to retrieve raw file descriptor, write to the file descriptor and
@ -31,7 +29,7 @@ impl FileDesc {
FileDesc { fd, close_on_drop } 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 { let result = unsafe {
libc::read( libc::read(
self.fd, self.fd,
@ -73,7 +71,7 @@ impl AsRawFd for FileDesc {
} }
/// Creates a file descriptor pointing to the standard input or `/dev/tty`. /// 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 } { let (fd, close_on_drop) = if unsafe { libc::isatty(libc::STDIN_FILENO) == 1 } {
(libc::STDIN_FILENO, false) (libc::STDIN_FILENO, false)
} else { } else {

View File

@ -12,8 +12,6 @@ use std::os::unix::io::{IntoRawFd, RawFd};
use std::{io, mem, process}; use std::{io, mem, process};
use crate::error::Result;
// Some(Termios) -> we're in the raw mode and this is the previous mode // Some(Termios) -> we're in the raw mode and this is the previous mode
// None -> we're not in the raw mode // None -> we're not in the raw mode
static TERMINAL_MODE_PRIOR_RAW_MODE: Mutex<Option<Termios>> = parking_lot::const_mutex(None); 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)] #[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 // http://rosettacode.org/wiki/Terminal_control/Dimensions#Library:_BSD_libc
let mut size = winsize { let mut size = winsize {
ws_row: 0, 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()) 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(); let mut original_mode = TERMINAL_MODE_PRIOR_RAW_MODE.lock();
if original_mode.is_some() { 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 /// 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 /// 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. /// 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(); let mut original_mode = TERMINAL_MODE_PRIOR_RAW_MODE.lock();
if let Some(original_mode_ios) = original_mode.as_ref() { 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 /// 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. /// [`crossterm::event::read`](crate::event::read) or [`crossterm::event::poll`](crate::event::poll) are being called.
#[cfg(feature = "events")] #[cfg(feature = "events")]
pub fn supports_keyboard_enhancement() -> Result<bool> { pub fn supports_keyboard_enhancement() -> io::Result<bool> {
if is_raw_mode_enabled() { if is_raw_mode_enabled() {
read_supports_keyboard_enhancement_raw() read_supports_keyboard_enhancement_raw()
} else { } else {
@ -103,7 +101,7 @@ pub fn supports_keyboard_enhancement() -> Result<bool> {
} }
#[cfg(feature = "events")] #[cfg(feature = "events")]
fn read_supports_keyboard_enhancement_flags() -> Result<bool> { fn read_supports_keyboard_enhancement_flags() -> io::Result<bool> {
enable_raw_mode()?; enable_raw_mode()?;
let flags = read_supports_keyboard_enhancement_raw(); let flags = read_supports_keyboard_enhancement_raw();
disable_raw_mode()?; disable_raw_mode()?;
@ -111,7 +109,7 @@ fn read_supports_keyboard_enhancement_flags() -> Result<bool> {
} }
#[cfg(feature = "events")] #[cfg(feature = "events")]
fn read_supports_keyboard_enhancement_raw() -> Result<bool> { fn read_supports_keyboard_enhancement_raw() -> io::Result<bool> {
use crate::event::{ use crate::event::{
filter::{KeyboardEnhancementFlagsFilter, PrimaryDeviceAttributesFilter}, filter::{KeyboardEnhancementFlagsFilter, PrimaryDeviceAttributesFilter},
poll_internal, read_internal, InternalEvent, poll_internal, read_internal, InternalEvent,
@ -201,7 +199,7 @@ fn raw_terminal_attr(termios: &mut Termios) {
unsafe { cfmakeraw(termios) } unsafe { cfmakeraw(termios) }
} }
fn get_terminal_attr(fd: RawFd) -> Result<Termios> { fn get_terminal_attr(fd: RawFd) -> io::Result<Termios> {
unsafe { unsafe {
let mut termios = mem::zeroed(); let mut termios = mem::zeroed();
wrap_with_result(tcgetattr(fd, &mut termios))?; 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) }) 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 { if result == -1 {
Err(io::Error::last_os_error()) Err(io::Error::last_os_error())
} else { } else {

View File

@ -1,7 +1,7 @@
//! WinAPI related logic for terminal manipulation. //! WinAPI related logic for terminal manipulation.
use std::fmt::{self, Write}; use std::fmt::{self, Write};
use std::io; use std::io::{self};
use crossterm_winapi::{Console, ConsoleMode, Coord, Handle, ScreenBuffer, Size}; use crossterm_winapi::{Console, ConsoleMode, Coord, Handle, ScreenBuffer, Size};
use winapi::{ use winapi::{
@ -9,12 +9,12 @@ use winapi::{
um::wincon::{SetConsoleTitleW, ENABLE_ECHO_INPUT, ENABLE_LINE_INPUT, ENABLE_PROCESSED_INPUT}, 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 /// bits which can't be set in raw mode
const NOT_RAW_MODE_MASK: DWORD = ENABLE_LINE_INPUT | ENABLE_ECHO_INPUT | ENABLE_PROCESSED_INPUT; 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 console_mode = ConsoleMode::from(Handle::current_in_handle()?);
let dw_mode = console_mode.mode()?; 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 console_mode = ConsoleMode::from(Handle::current_in_handle()?);
let dw_mode = console_mode.mode()?; let dw_mode = console_mode.mode()?;
@ -37,7 +37,7 @@ pub(crate) fn enable_raw_mode() -> Result<()> {
Ok(()) 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 console_mode = ConsoleMode::from(Handle::current_in_handle()?);
let dw_mode = console_mode.mode()?; let dw_mode = console_mode.mode()?;
@ -49,7 +49,7 @@ pub(crate) fn disable_raw_mode() -> Result<()> {
Ok(()) Ok(())
} }
pub(crate) fn size() -> Result<(u16, u16)> { pub(crate) fn size() -> io::Result<(u16, u16)> {
let terminal_size = ScreenBuffer::current()?.info()?.terminal_size(); let terminal_size = ScreenBuffer::current()?.info()?.terminal_size();
// windows starts counting at 0, unix at 1, add one to replicated unix behaviour. // windows starts counting at 0, unix at 1, add one to replicated unix behaviour.
Ok(( Ok((
@ -62,11 +62,11 @@ pub(crate) fn size() -> Result<(u16, u16)> {
/// ///
/// This always returns `Ok(false)` on Windows. /// This always returns `Ok(false)` on Windows.
#[cfg(feature = "events")] #[cfg(feature = "events")]
pub fn supports_keyboard_enhancement() -> Result<bool> { pub fn supports_keyboard_enhancement() -> std::io::Result<bool> {
Ok(false) 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 screen_buffer = ScreenBuffer::current()?;
let csbi = screen_buffer.info()?; let csbi = screen_buffer.info()?;
@ -89,7 +89,7 @@ pub(crate) fn clear(clear_type: ClearType) -> Result<()> {
Ok(()) 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 csbi = ScreenBuffer::current()?;
let mut window = csbi.info()?.terminal_window(); let mut window = csbi.info()?.terminal_window();
@ -104,7 +104,7 @@ pub(crate) fn scroll_up(row_count: u16) -> Result<()> {
Ok(()) 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 screen_buffer = ScreenBuffer::current()?;
let csbi = screen_buffer.info()?; let csbi = screen_buffer.info()?;
let mut window = csbi.terminal_window(); let mut window = csbi.terminal_window();
@ -121,16 +121,16 @@ pub(crate) fn scroll_down(row_count: u16) -> Result<()> {
Ok(()) 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 { if width <= 1 {
return Err(ErrorKind::new( return Err(io::Error::new(
io::ErrorKind::InvalidInput, io::ErrorKind::InvalidInput,
"terminal width must be at least 1", "terminal width must be at least 1",
)); ));
} }
if height <= 1 { if height <= 1 {
return Err(ErrorKind::new( return Err(io::Error::new(
io::ErrorKind::InvalidInput, io::ErrorKind::InvalidInput,
"terminal height must be at least 1", "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; let width = width as i16;
if current_size.width < window.left + width { if current_size.width < window.left + width {
if window.left >= i16::max_value() - width { if window.left >= i16::max_value() - width {
return Err(ErrorKind::new( return Err(io::Error::new(
io::ErrorKind::InvalidInput, io::ErrorKind::InvalidInput,
"terminal width too large", "terminal width too large",
)); ));
@ -165,7 +165,7 @@ pub(crate) fn set_size(width: u16, height: u16) -> Result<()> {
let height = height as i16; let height = height as i16;
if current_size.height < window.top + height { if current_size.height < window.top + height {
if window.top >= i16::max_value() - height { if window.top >= i16::max_value() - height {
return Err(ErrorKind::new( return Err(io::Error::new(
io::ErrorKind::InvalidInput, io::ErrorKind::InvalidInput,
"terminal height too large", "terminal height too large",
)); ));
@ -194,13 +194,13 @@ pub(crate) fn set_size(width: u16, height: u16) -> Result<()> {
let bounds = console.largest_window_size()?; let bounds = console.largest_window_size()?;
if width > bounds.x { if width > bounds.x {
return Err(ErrorKind::new( return Err(io::Error::new(
io::ErrorKind::InvalidInput, io::ErrorKind::InvalidInput,
format!("terminal width {width} too large"), format!("terminal width {width} too large"),
)); ));
} }
if height > bounds.y { if height > bounds.y {
return Err(ErrorKind::new( return Err(io::Error::new(
io::ErrorKind::InvalidInput, io::ErrorKind::InvalidInput,
format!("terminal height {height} too large"), format!("terminal height {height} too large"),
)); ));
@ -209,7 +209,7 @@ pub(crate) fn set_size(width: u16, height: u16) -> Result<()> {
Ok(()) 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>); struct Utf16Encoder(Vec<u16>);
impl Write for Utf16Encoder { impl Write for Utf16Encoder {
fn write_str(&mut self, s: &str) -> fmt::Result { 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 { if result != 0 {
Ok(()) Ok(())
} else { } 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); let (mut x, mut y) = (location.x, location.y);
// if cursor position is at the outer right position // 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) 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); let (xpos, ypos) = (location.x, location.y);
// one cell after cursor position // 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) 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 // get sum cells before cursor
let cells_to_write = buffer_size.width as u32 * buffer_size.height as u32; 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(()) 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 // location where to start clearing
let start_location = Coord::new(0, location.y); 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(()) 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); let (x, y) = (location.x, location.y);
// location where to start clearing // location where to start clearing
@ -314,7 +330,11 @@ fn clear_until_line(location: Coord, buffer_size: Size, current_attribute: u16)
Ok(()) 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()?); let console = Console::from(Handle::current_out_handle()?);
console.fill_whit_character(start_location, cells_to_write, ' ')?; console.fill_whit_character(start_location, cells_to_write, ' ')?;
console.fill_whit_attribute(start_location, cells_to_write, current_attribute)?; console.fill_whit_attribute(start_location, cells_to_write, current_attribute)?;