From ad3efbd34da602a1911c5b627301be4951baf6df Mon Sep 17 00:00:00 2001 From: Timon Date: Tue, 1 Jan 2019 13:27:50 -0800 Subject: [PATCH] Error handling (#69) * Implemented an error module for crossterm and fixed a lot of warnings. --- examples/color/mod.rs | 2 +- examples/examples.rs | 13 +-- src/common/commands/win_commands.rs | 6 +- src/common/error.rs | 51 +++++++++ src/common/functions.rs | 20 ++-- src/common/mod.rs | 3 +- src/common/screen/alternate.rs | 5 +- src/common/screen/screen.rs | 2 +- src/kernel/windows_kernel/ansi_support.rs | 3 +- src/kernel/windows_kernel/mod.rs | 10 +- src/kernel/windows_kernel/reading.rs | 4 +- src/kernel/windows_kernel/writing.rs | 1 + src/modules/cursor/ansi_cursor.rs | 53 +++++---- src/modules/cursor/cursor.rs | 33 +++--- src/modules/cursor/mod.rs | 22 ++-- src/modules/cursor/winapi_cursor.rs | 53 +++++---- src/modules/input/windows_input.rs | 16 ++- src/modules/output/winapi_output.rs | 2 +- src/modules/style/ansi_color.rs | 18 ++-- src/modules/style/color.rs | 12 +-- src/modules/style/mod.rs | 10 +- src/modules/style/styledobject.rs | 39 +++---- src/modules/style/winapi_color.rs | 36 ++++--- src/modules/terminal/ansi_terminal.rs | 31 +++--- src/modules/terminal/mod.rs | 10 +- src/modules/terminal/terminal.rs | 25 ++--- src/modules/terminal/winapi_terminal.rs | 126 +++++++++++----------- 27 files changed, 342 insertions(+), 264 deletions(-) create mode 100644 src/common/error.rs diff --git a/examples/color/mod.rs b/examples/color/mod.rs index 172ee6c..feb027e 100644 --- a/examples/color/mod.rs +++ b/examples/color/mod.rs @@ -18,7 +18,7 @@ pub fn paint_foreground() { // Or print inline println!( "Colored text: {}", - style("Red foreground").with(Color::Blue) + style("Blue foreground").with(Color::Blue) ); } diff --git a/examples/examples.rs b/examples/examples.rs index e29f7f5..7ba3e2f 100644 --- a/examples/examples.rs +++ b/examples/examples.rs @@ -15,14 +15,11 @@ mod input; mod terminal; fn main() { - use input::keyboard::input; + let cursor = crossterm::cursor(); + cursor.goto(5,5); - // color::print_all_foreground_colors(); - // color::print_all_background_colors(); + let integer = 10; + let float: f32 = integert as f32; - use terminal::alternate_screen; - // color::print_all_background_colors(); - // color::print_all_foreground_colors(); - - alternate_screen::print_wait_screen_on_alternate_window(); + println!("5.515151"); } diff --git a/src/common/commands/win_commands.rs b/src/common/commands/win_commands.rs index 34dcb12..25b3208 100644 --- a/src/common/commands/win_commands.rs +++ b/src/common/commands/win_commands.rs @@ -78,7 +78,7 @@ impl RawModeCommand { pub fn enable(&mut self) -> Result<()> { let console_mode = ConsoleMode::new()?; - let mut dw_mode = console_mode.mode()?; + let dw_mode = console_mode.mode()?; let new_mode = dw_mode & !self.mask; @@ -91,7 +91,7 @@ impl RawModeCommand { pub fn disable(&self) -> Result<()> { let console_mode = ConsoleMode::new()?; - let mut dw_mode = console_mode.mode()?; + let dw_mode = console_mode.mode()?; let new_mode = dw_mode | self.mask; @@ -114,7 +114,7 @@ impl ToAlternateScreenCommand { impl IAlternateScreenCommand for ToAlternateScreenCommand { fn enable(&self, _stdout: &mut TerminalOutput) -> Result<()> { let alternate_screen = ScreenBuffer::create(); - alternate_screen.show(); + alternate_screen.show()?; Ok(()) } diff --git a/src/common/error.rs b/src/common/error.rs new file mode 100644 index 0000000..88f295d --- /dev/null +++ b/src/common/error.rs @@ -0,0 +1,51 @@ +//! Module containing error handling logic. + +use std::{ + fmt::{self, Display, Formatter}, + io, +}; + +/// The `crossterm` result type. +pub type Result = std::result::Result; + +/// Wrapper for all errors who could occur in `crossterm`. +#[derive(Debug)] +pub enum ErrorKind { + IoError(io::Error), + FmtError(fmt::Error), + ResizingTerminalFailure(String), + + #[doc(hidden)] + __Nonexhaustive, +} + +impl std::error::Error for ErrorKind { + fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { + match *self { + ErrorKind::IoError(ref e) => Some(e), + _ => None, + } + } +} + +impl Display for ErrorKind { + fn fmt(&self, fmt: &mut Formatter<'_>) -> fmt::Result { + match *self { + ErrorKind::IoError(_) => write!(fmt, "IO-error occurred"), + ErrorKind::ResizingTerminalFailure(_) => write!(fmt, "Cannot resize the terminal"), + _ => write!(fmt, "Some error has occurred"), + } + } +} + +impl From for ErrorKind { + fn from(e: io::Error) -> ErrorKind { + ErrorKind::IoError(e) + } +} + +impl From for ErrorKind { + fn from(e: fmt::Error) -> ErrorKind { + ErrorKind::FmtError(e) + } +} \ No newline at end of file diff --git a/src/common/functions.rs b/src/common/functions.rs index 1d0e43c..b86cd65 100644 --- a/src/common/functions.rs +++ b/src/common/functions.rs @@ -64,18 +64,18 @@ pub fn exit_terminal() { /// If the current platform is unix it will return the ansi implementation. pub fn get_module(winapi_impl: T, unix_impl: T) -> Option { let mut term: Option = None; - let does_support = false; + let mut does_support = false; - // if !windows_supportable() { - // Try to enable ansi on windows if not than use WINAPI. - // does_support = try_enable_ansi_support(); - - // uncomment this line when you want to use the winapi implementation. - // does_support = false; - if !does_support { - term = Some(winapi_impl); + if !windows_supportable() { +// Try to enable ansi on windows if not than use WINAPI. + does_support = try_enable_ansi_support(); +// +// uncomment this line when you want to use the winapi implementation. +// does_support = false; + if !does_support { + term = Some(winapi_impl); + } } - // } if does_support { term = Some(unix_impl); diff --git a/src/common/mod.rs b/src/common/mod.rs index 4c8edfd..dfbe616 100644 --- a/src/common/mod.rs +++ b/src/common/mod.rs @@ -6,8 +6,9 @@ pub mod commands; pub mod functions; pub mod screen; pub mod traits; +pub mod error; mod crossterm; pub use self::crossterm::Crossterm; -use TerminalOutput; +use TerminalOutput; \ No newline at end of file diff --git a/src/common/screen/alternate.rs b/src/common/screen/alternate.rs index 4ebf97a..1ec2a2d 100644 --- a/src/common/screen/alternate.rs +++ b/src/common/screen/alternate.rs @@ -44,8 +44,7 @@ impl AlternateScreen { functions::get_module::>( Box::from(commands::win_commands::ToAlternateScreenCommand::new()), Box::from(commands::shared_commands::ToAlternateScreenCommand::new()), - ) - .unwrap(); + ).unwrap(); #[cfg(not(target_os = "windows"))] let command = Box::from(commands::shared_commands::ToAlternateScreenCommand::new()); @@ -72,6 +71,6 @@ impl AlternateScreen { impl Drop for AlternateScreen { /// This will switch back to main screen on drop. fn drop(&mut self) { - self.to_main_screen(); + self.to_main_screen().unwrap(); } } diff --git a/src/common/screen/screen.rs b/src/common/screen/screen.rs index d49e64a..dbe3a8d 100644 --- a/src/common/screen/screen.rs +++ b/src/common/screen/screen.rs @@ -165,7 +165,7 @@ impl Drop for Screen { /// If the current screen is in raw mode we need to disable it when the instance goes out of scope. fn drop(&mut self) { if self.stdout.is_in_raw_mode && self.drop { - RawScreen::disable_raw_modes(); + RawScreen::disable_raw_modes().unwrap(); } } } diff --git a/src/kernel/windows_kernel/ansi_support.rs b/src/kernel/windows_kernel/ansi_support.rs index 29aa96d..89dd1e6 100644 --- a/src/kernel/windows_kernel/ansi_support.rs +++ b/src/kernel/windows_kernel/ansi_support.rs @@ -5,10 +5,11 @@ use std::sync::{Once, ONCE_INIT}; static mut HAS_BEEN_TRIED_TO_ENABLE: bool = false; static mut IS_ANSI_ON_WINDOWS_ENABLED: Option = None; static mut DOES_WINDOWS_SUPPORT_ANSI: Option = None; -static ENABLE_ANSI: Once = ONCE_INIT; use common::commands::win_commands::EnableAnsiCommand; use common::commands::IEnableAnsiCommand; +static ENABLE_ANSI: Once = ONCE_INIT; + /// Try enable `ANSI escape codes` and return the result. pub fn try_enable_ansi_support() -> bool { ENABLE_ANSI.call_once(|| { diff --git a/src/kernel/windows_kernel/mod.rs b/src/kernel/windows_kernel/mod.rs index 7588c8c..d6d50ff 100644 --- a/src/kernel/windows_kernel/mod.rs +++ b/src/kernel/windows_kernel/mod.rs @@ -1,15 +1,11 @@ //! This module contains the `windows` (unsafe) logic. +#[allow(unused)] +mod reading; pub mod ansi_support; mod cursor; -pub mod reading; pub mod writing; -use winapi::um::{ - wincon::{CONSOLE_SCREEN_BUFFER_INFO, COORD, SMALL_RECT}, - winnt::HANDLE, -}; - pub use self::cursor::Cursor; pub use crossterm_winapi::{ Console, ConsoleMode, Coord, Handle, HandleType, ScreenBuffer, ScreenBufferInfo, Size, @@ -19,4 +15,4 @@ pub use crossterm_winapi::{ /// Exit the current process. pub fn exit() { ::std::process::exit(256); -} +} \ No newline at end of file diff --git a/src/kernel/windows_kernel/reading.rs b/src/kernel/windows_kernel/reading.rs index a17f12e..b84fdd0 100644 --- a/src/kernel/windows_kernel/reading.rs +++ b/src/kernel/windows_kernel/reading.rs @@ -1,4 +1,4 @@ -use crossterm_winapi::{Handle, HandleType}; +use crossterm_winapi::Handle; use std::{ io::{self, Write}, @@ -50,7 +50,7 @@ pub fn read_line(buf: &mut Vec) -> io::Result { .filter(|&x| x != 10 || x != 13) .collect::>(); - buf.write(a); + buf.write(a)?; Ok(num as usize) } diff --git a/src/kernel/windows_kernel/writing.rs b/src/kernel/windows_kernel/writing.rs index feaa176..977346e 100644 --- a/src/kernel/windows_kernel/writing.rs +++ b/src/kernel/windows_kernel/writing.rs @@ -12,6 +12,7 @@ use std::io::{self, Result}; use std::str; /// Write console output. +#[allow(unused)] pub fn write_console_output( write_buffer: &HANDLE, copy_buffer: &mut [CHAR_INFO; 160], diff --git a/src/modules/cursor/ansi_cursor.rs b/src/modules/cursor/ansi_cursor.rs index e8df10a..70431c9 100644 --- a/src/modules/cursor/ansi_cursor.rs +++ b/src/modules/cursor/ansi_cursor.rs @@ -3,6 +3,7 @@ //! Note that the cursor position is 0 based. This means that we start counting at 0 when setting the cursor position etc. use super::*; +use common::error::Result; /// This struct is an ANSI implementation for cursor related actions. pub struct AnsiCursor {} @@ -14,51 +15,61 @@ impl AnsiCursor { } impl ITerminalCursor for AnsiCursor { - fn goto(&self, x: u16, y: u16, stdout: &Option<&Arc>) { - functions::write(stdout, format!(csi!("{};{}H"), y + 1, x + 1)); + fn goto(&self, x: u16, y: u16, stdout: &Option<&Arc>) -> Result<()> { + functions::write(stdout, format!(csi!("{};{}H"), y + 1, x + 1))?; + Ok(()) } fn pos(&self) -> (u16, u16) { functions::get_cursor_position() } - fn move_up(&self, count: u16, stdout: &Option<&Arc>) { - functions::write(stdout, format!(csi!("{}A"), count)); + fn move_up(&self, count: u16, stdout: &Option<&Arc>) -> Result<()> { + functions::write(stdout, format!(csi!("{}A"), count))?; + Ok(()) } - fn move_right(&self, count: u16, stdout: &Option<&Arc>) { - functions::write(stdout, format!(csi!("{}C"), count)); + fn move_right(&self, count: u16, stdout: &Option<&Arc>) -> Result<()> { + functions::write(stdout, format!(csi!("{}C"), count))?; + Ok(()) } - fn move_down(&self, count: u16, stdout: &Option<&Arc>) { - functions::write(stdout, format!(csi!("{}B"), count)); + fn move_down(&self, count: u16, stdout: &Option<&Arc>) -> Result<()> { + functions::write(stdout, format!(csi!("{}B"), count))?; + Ok(()) } - fn move_left(&self, count: u16, stdout: &Option<&Arc>) { - functions::write(stdout, format!(csi!("{}D"), count)); + fn move_left(&self, count: u16, stdout: &Option<&Arc>) -> Result<()> { + functions::write(stdout, format!(csi!("{}D"), count))?; + Ok(()) } - fn save_position(&self, stdout: &Option<&Arc>) { - functions::write_str(stdout, csi!("s")); + fn save_position(&self, stdout: &Option<&Arc>) -> Result<()> { + functions::write_str(stdout, csi!("s"))?; + Ok(()) } - fn reset_position(&self, stdout: &Option<&Arc>) { - functions::write_str(stdout, csi!("u")); + fn reset_position(&self, stdout: &Option<&Arc>)-> Result<()> { + functions::write_str(stdout, csi!("u"))?; + Ok(()) } - fn hide(&self, stdout: &Option<&Arc>) { - functions::write_str(stdout, csi!("?25l")); + fn hide(&self, stdout: &Option<&Arc>)-> Result<()> { + functions::write_str(stdout, csi!("?25l"))?; + Ok(()) } - fn show(&self, stdout: &Option<&Arc>) { - functions::write_str(stdout, csi!("?25h")); + fn show(&self, stdout: &Option<&Arc>) -> Result<()>{ + functions::write_str(stdout, csi!("?25h"))?; + Ok(()) } - fn blink(&self, blink: bool, stdout: &Option<&Arc>) { + fn blink(&self, blink: bool, stdout: &Option<&Arc>) -> Result<()>{ if blink { - functions::write_str(stdout, csi!("?12h")); + functions::write_str(stdout, csi!("?12h"))?; } else { - functions::write_str(stdout, csi!("?12l")); + functions::write_str(stdout, csi!("?12l"))?; } + Ok(()) } } diff --git a/src/modules/cursor/cursor.rs b/src/modules/cursor/cursor.rs index cb581b4..76087ea 100644 --- a/src/modules/cursor/cursor.rs +++ b/src/modules/cursor/cursor.rs @@ -4,6 +4,7 @@ //! Note that positions of the cursor are 0 -based witch means that the coordinates (cells) starts counting from 0 use super::*; +use common::error::Result; use Screen; /// Struct that stores a platform-specific implementation for cursor related actions. @@ -94,8 +95,8 @@ impl<'stdout> TerminalCursor<'stdout> { /// cursor.goto(4,5); /// /// ``` - pub fn goto(&self, x: u16, y: u16) { - self.terminal_cursor.goto(x, y, &self.stdout); + pub fn goto(&self, x: u16, y: u16) -> Result<()> { + self.terminal_cursor.goto(x, y, &self.stdout) } /// Get current cursor position (x,y) in the terminal. @@ -119,7 +120,7 @@ impl<'stdout> TerminalCursor<'stdout> { /// cursor.move_up(3); /// ``` pub fn move_up(&mut self, count: u16) -> &mut TerminalCursor<'stdout> { - self.terminal_cursor.move_up(count, &self.stdout); + self.terminal_cursor.move_up(count, &self.stdout).unwrap(); self } @@ -132,7 +133,7 @@ impl<'stdout> TerminalCursor<'stdout> { /// cursor.move_right(3); /// ``` pub fn move_right(&mut self, count: u16) -> &mut TerminalCursor<'stdout> { - self.terminal_cursor.move_right(count, &self.stdout); + self.terminal_cursor.move_right(count, &self.stdout).unwrap(); self } @@ -145,7 +146,7 @@ impl<'stdout> TerminalCursor<'stdout> { /// cursor.move_down(3); /// ``` pub fn move_down(&mut self, count: u16) -> &mut TerminalCursor<'stdout> { - self.terminal_cursor.move_down(count, &self.stdout); + self.terminal_cursor.move_down(count, &self.stdout).unwrap(); self } @@ -158,7 +159,7 @@ impl<'stdout> TerminalCursor<'stdout> { /// cursor.move_left(3); /// ``` pub fn move_left(&mut self, count: u16) -> &mut TerminalCursor<'stdout> { - self.terminal_cursor.move_left(count, &self.stdout); + self.terminal_cursor.move_left(count, &self.stdout).unwrap(); self } @@ -171,8 +172,8 @@ impl<'stdout> TerminalCursor<'stdout> { /// /// cursor.safe_position(); /// ``` - pub fn save_position(&self) { - self.terminal_cursor.save_position(&self.stdout); + pub fn save_position(&self) -> Result<()> { + self.terminal_cursor.save_position(&self.stdout) } /// Return to saved cursor position @@ -184,8 +185,8 @@ impl<'stdout> TerminalCursor<'stdout> { /// /// cursor.reset_position(); /// ``` - pub fn reset_position(&self) { - self.terminal_cursor.reset_position(&self.stdout); + pub fn reset_position(&self) -> Result<()> { + self.terminal_cursor.reset_position(&self.stdout) } /// Hide de cursor in the console. @@ -194,8 +195,8 @@ impl<'stdout> TerminalCursor<'stdout> { /// let cursor = cursor(); /// cursor.hide(); /// ``` - pub fn hide(&self) { - self.terminal_cursor.hide(&self.stdout); + pub fn hide(&self) -> Result<()> { + self.terminal_cursor.hide(&self.stdout) } /// Show the cursor in the console. @@ -206,8 +207,8 @@ impl<'stdout> TerminalCursor<'stdout> { /// cursor.show(); /// /// ``` - pub fn show(&self) { - self.terminal_cursor.show(&self.stdout); + pub fn show(&self) -> Result<()> { + self.terminal_cursor.show(&self.stdout) } /// Enable or disable blinking of the terminal. @@ -219,8 +220,8 @@ impl<'stdout> TerminalCursor<'stdout> { /// cursor.blink(true); /// cursor.blink(false); /// ``` - pub fn blink(&self, blink: bool) { - self.terminal_cursor.blink(blink, &self.stdout); + pub fn blink(&self, blink: bool) -> Result<()> { + self.terminal_cursor.blink(blink, &self.stdout) } } diff --git a/src/modules/cursor/mod.rs b/src/modules/cursor/mod.rs index 1cb550f..8906966 100644 --- a/src/modules/cursor/mod.rs +++ b/src/modules/cursor/mod.rs @@ -17,7 +17,7 @@ use self::ansi_cursor::AnsiCursor; use self::winapi_cursor::WinApiCursor; pub use self::cursor::{cursor, from_screen, TerminalCursor}; - +use common::error::Result; use super::functions; use std::sync::Arc; use TerminalOutput; @@ -32,25 +32,25 @@ use TerminalOutput; ///! so that cursor related actions can be performed on both UNIX and Windows systems. trait ITerminalCursor: Sync + Send { /// Goto some location (x,y) in the context. - fn goto(&self, x: u16, y: u16, stdout: &Option<&Arc>); + fn goto(&self, x: u16, y: u16, stdout: &Option<&Arc>) -> Result<()>; /// Get the location (x,y) of the current cursor in the context fn pos(&self) -> (u16, u16); /// Move cursor n times up - fn move_up(&self, count: u16, stdout: &Option<&Arc>); + fn move_up(&self, count: u16, stdout: &Option<&Arc>) -> Result<()>; /// Move the cursor `n` times to the right. - fn move_right(&self, count: u16, stdout: &Option<&Arc>); + fn move_right(&self, count: u16, stdout: &Option<&Arc>) -> Result<()>; /// Move the cursor `n` times down. - fn move_down(&self, count: u16, stdout: &Option<&Arc>); + fn move_down(&self, count: u16, stdout: &Option<&Arc>) -> Result<()>; /// Move the cursor `n` times left. - fn move_left(&self, count: u16, stdout: &Option<&Arc>); + fn move_left(&self, count: u16, stdout: &Option<&Arc>) -> Result<()>; /// Save cursor position so that its saved position can be recalled later. Note that this position is stored program based not per instance of the cursor struct. - fn save_position(&self, stdout: &Option<&Arc>); + fn save_position(&self, stdout: &Option<&Arc>) -> Result<()>; /// Return to saved cursor position - fn reset_position(&self, stdout: &Option<&Arc>); + fn reset_position(&self, stdout: &Option<&Arc>) -> Result<()>; /// Hide the terminal cursor. - fn hide(&self, stdout: &Option<&Arc>); + fn hide(&self, stdout: &Option<&Arc>) -> Result<()>; /// Show the terminal cursor - fn show(&self, stdout: &Option<&Arc>); + fn show(&self, stdout: &Option<&Arc>) -> Result<()>; /// Enable or disable the blinking of the cursor. - fn blink(&self, blink: bool, stdout: &Option<&Arc>); + fn blink(&self, blink: bool, stdout: &Option<&Arc>) -> Result<()>; } diff --git a/src/modules/cursor/winapi_cursor.rs b/src/modules/cursor/winapi_cursor.rs index 8ddcec3..d754859 100644 --- a/src/modules/cursor/winapi_cursor.rs +++ b/src/modules/cursor/winapi_cursor.rs @@ -2,8 +2,8 @@ //! This module is used for Windows terminals that do not support ANSI escape codes. //! Note that the cursor position is 0 based. This means that we start counting at 0 when setting the cursor position. -use kernel::windows_kernel::Cursor; - +use kernel::windows_kernel::{Cursor, Handle}; +use common::error::Result; use super::*; /// This struct is a windows implementation for cursor related actions. @@ -16,9 +16,10 @@ impl WinApiCursor { } impl ITerminalCursor for WinApiCursor { - fn goto(&self, x: u16, y: u16, _stdout: &Option<&Arc>) { - let cursor = Cursor::new().unwrap(); - cursor.goto(x as i16, y as i16); + fn goto(&self, x: u16, y: u16, _stdout: &Option<&Arc>) -> Result<()> { + let cursor = Cursor::new()?; + cursor.goto(x as i16, y as i16)?; + Ok(()) } fn pos(&self) -> (u16, u16) { @@ -26,41 +27,49 @@ impl ITerminalCursor for WinApiCursor { cursor.position().unwrap().into() } - fn move_up(&self, count: u16, _stdout: &Option<&Arc>) { + fn move_up(&self, count: u16, _stdout: &Option<&Arc>) -> Result<()> { let (xpos, ypos) = self.pos(); - self.goto(xpos, ypos - count, _stdout); + self.goto(xpos, ypos - count, _stdout)?; + Ok(()) } - fn move_right(&self, count: u16, _stdout: &Option<&Arc>) { + fn move_right(&self, count: u16, _stdout: &Option<&Arc>) -> Result<()> { let (xpos, ypos) = self.pos(); - self.goto(xpos + count, ypos, _stdout); + self.goto(xpos + count, ypos, _stdout)?; + Ok(()) } - fn move_down(&self, count: u16, _stdout: &Option<&Arc>) { + fn move_down(&self, count: u16, _stdout: &Option<&Arc>) -> Result<()> { let (xpos, ypos) = self.pos(); - self.goto(xpos, ypos + count, _stdout); + self.goto(xpos, ypos + count, _stdout)?; + Ok(()) } - fn move_left(&self, count: u16, _stdout: &Option<&Arc>) { + fn move_left(&self, count: u16, _stdout: &Option<&Arc>) -> Result<()> { let (xpos, ypos) = self.pos(); - self.goto(xpos - count, ypos, _stdout); + self.goto(xpos - count, ypos, _stdout)?; + Ok(()) } - fn save_position(&self, _stdout: &Option<&Arc>) { - Cursor::save_cursor_pos(); + fn save_position(&self, _stdout: &Option<&Arc>) -> Result<()> { + Cursor::save_cursor_pos()?; + Ok(()) } - fn reset_position(&self, _stdout: &Option<&Arc>) { - Cursor::reset_to_saved_position(); + fn reset_position(&self, _stdout: &Option<&Arc>) -> Result<()> { + Cursor::reset_to_saved_position()?; + Ok(()) } - fn hide(&self, _stdout: &Option<&Arc>) { - Cursor::new().unwrap().set_visibility(false); + fn hide(&self, _stdout: &Option<&Arc>) -> Result<()> { + Cursor::from(Handle::current_out_handle()?).set_visibility(false)?; + Ok(()) } - fn show(&self, _stdout: &Option<&Arc>) { - Cursor::new().unwrap().set_visibility(true); + fn show(&self, _stdout: &Option<&Arc>) -> Result<()> { + Cursor::from(Handle::current_out_handle()?).set_visibility(true)?; + Ok(()) } - fn blink(&self, _blink: bool, _stdout: &Option<&Arc>) {} + fn blink(&self, _blink: bool, _stdout: &Option<&Arc>) -> Result<()> { Ok(()) } } diff --git a/src/modules/input/windows_input.rs b/src/modules/input/windows_input.rs index d6a1daa..5829d02 100644 --- a/src/modules/input/windows_input.rs +++ b/src/modules/input/windows_input.rs @@ -73,7 +73,9 @@ impl ITerminalInput for WindowsInput { return; } - tx.send(Ok(pressed_char as u8)); + if let Err(_) = tx.send(Ok(pressed_char as u8)) { + println!("Could not send pressed char to receiver.") + } } }); @@ -110,7 +112,9 @@ impl ITerminalInput for WindowsInput { return; } - tx.send(Ok(pressed_char as u8)); + if let Err(_) = tx.send(Ok(pressed_char as u8)) { + println!("Could not send pressed char to receiver.") + } } }); @@ -118,14 +122,6 @@ impl ITerminalInput for WindowsInput { } } -fn is_line_end(key: char) -> bool { - if key as u8 == 13 { - return true; - } - - return false; -} - extern "C" { fn _getwche() -> INT; fn _getwch() -> INT; diff --git a/src/modules/output/winapi_output.rs b/src/modules/output/winapi_output.rs index c8afe7c..5316c32 100644 --- a/src/modules/output/winapi_output.rs +++ b/src/modules/output/winapi_output.rs @@ -18,7 +18,7 @@ impl IStdout for WinApiOutput { } fn write(&self, buf: &[u8]) -> io::Result { - let handle = Handle::current_out_handle().unwrap(); + let handle = Handle::current_out_handle()?; writing::write_char_buffer(&handle, buf) } diff --git a/src/modules/style/ansi_color.rs b/src/modules/style/ansi_color.rs index 9641293..cfd7513 100644 --- a/src/modules/style/ansi_color.rs +++ b/src/modules/style/ansi_color.rs @@ -2,6 +2,7 @@ //! This module is used for Windows 10 terminals and Unix terminals by default. use super::*; +use common::error::Result; /// This struct is an ANSI escape code implementation for color related actions. pub struct AnsiColor; @@ -13,28 +14,31 @@ impl AnsiColor { } impl ITerminalColor for AnsiColor { - fn set_fg(&self, fg_color: Color, stdout: &Option<&Arc>) { + fn set_fg(&self, fg_color: Color, stdout: &Option<&Arc>) -> Result<()> { functions::write( stdout, format!( csi!("{}m"), self.color_value(fg_color, ColorType::Foreground) ), - ); + )?; + Ok(()) } - fn set_bg(&self, bg_color: Color, stdout: &Option<&Arc>) { + fn set_bg(&self, bg_color: Color, stdout: &Option<&Arc>)-> Result<()> { functions::write( stdout, format!( csi!("{}m"), self.color_value(bg_color, ColorType::Background) ), - ); + )?; + Ok(()) } - fn reset(&self, stdout: &Option<&Arc>) { - functions::write_str(stdout, csi!("0m")); + fn reset(&self, stdout: &Option<&Arc>)-> Result<()>{ + functions::write_str(stdout, csi!("0m"))?; + Ok(()) } fn color_value(&self, color: Color, color_type: ColorType) -> String { @@ -77,4 +81,4 @@ impl ITerminalColor for AnsiColor { ansi_value.push_str(color_val); ansi_value } -} +} \ No newline at end of file diff --git a/src/modules/style/color.rs b/src/modules/style/color.rs index 1641e72..0062f58 100644 --- a/src/modules/style/color.rs +++ b/src/modules/style/color.rs @@ -94,8 +94,8 @@ impl<'stdout> TerminalColor<'stdout> { /// // crossterm provides to set the background from &str or String /// colored_terminal.set_fg(Color::from("Red")); /// ``` - pub fn set_fg(&self, color: Color) { - self.color.set_fg(color, &self.stdout); + pub fn set_fg(&self, color: Color)-> Result<()> { + self.color.set_fg(color, &self.stdout) } /// Set the background color to the given color. @@ -108,8 +108,8 @@ impl<'stdout> TerminalColor<'stdout> { /// // crossterm provides to set the background from &str or String /// colored_terminal.set_bg(Color::from("Red")); /// ``` - pub fn set_bg(&self, color: Color) { - self.color.set_bg(color, &self.stdout); + pub fn set_bg(&self, color: Color) -> Result<()>{ + self.color.set_bg(color, &self.stdout) } /// Reset the terminal colors and attributes to default. @@ -118,8 +118,8 @@ impl<'stdout> TerminalColor<'stdout> { /// let colored_terminal = color(); /// colored_terminal.reset(); /// ``` - pub fn reset(&self) { - self.color.reset(&self.stdout); + pub fn reset(&self)-> Result<()> { + self.color.reset(&self.stdout) } /// Get available color count. diff --git a/src/modules/style/mod.rs b/src/modules/style/mod.rs index 1122cb6..0239c52 100644 --- a/src/modules/style/mod.rs +++ b/src/modules/style/mod.rs @@ -22,7 +22,7 @@ pub use self::color::{color, from_screen, TerminalColor}; pub use self::objectstyle::ObjectStyle; pub use self::styledobject::DisplayableObject; pub use self::styledobject::StyledObject; -use super::functions; +use common::{functions, error::Result}; use TerminalOutput; @@ -36,11 +36,11 @@ use TerminalOutput; /// so that color-related actions can be performed on both UNIX and Windows systems. trait ITerminalColor { /// Set the foreground color to the given color. - fn set_fg(&self, fg_color: Color, stdout: &Option<&Arc>); + fn set_fg(&self, fg_color: Color, stdout: &Option<&Arc>) -> Result<()>; /// Set the background color to the given color. - fn set_bg(&self, fg_color: Color, stdout: &Option<&Arc>); + fn set_bg(&self, fg_color: Color, stdout: &Option<&Arc>) -> Result<()>; /// Reset the terminal color to default. - fn reset(&self, stdout: &Option<&Arc>); + fn reset(&self, stdout: &Option<&Arc>) -> Result<()>; /// Gets an value that represents an color from the given `Color` and `ColorType`. fn color_value(&self, color: Color, color_type: ColorType) -> String; } @@ -153,7 +153,7 @@ impl FromStr for Color { type Err = (); /// Convert a string to an Color value - fn from_str(src: &str) -> Result { + fn from_str(src: &str) -> ::std::result::Result { let src = src.to_lowercase(); match src.as_ref() { diff --git a/src/modules/style/styledobject.rs b/src/modules/style/styledobject.rs index bcf3528..efec113 100644 --- a/src/modules/style/styledobject.rs +++ b/src/modules/style/styledobject.rs @@ -5,6 +5,8 @@ use Screen; use std::fmt::{self, Display, Formatter}; use std::io::Write; +use common::error::Result; +use std::result; use super::Attribute; @@ -146,36 +148,37 @@ impl<'a, D: Display + 'a> StyledObject { /// /// You should take not that `StyledObject` implements `Display`. You don't need to call paint unless you are on alternate screen. /// Checkout `into_displayable()` for more information about this. - pub fn paint(&self, screen: &Screen) { + pub fn paint(&self, screen: &Screen) -> Result<()> { let colored_terminal = from_screen(&screen); let mut reset = true; if let Some(bg) = self.object_style.bg_color { - colored_terminal.set_bg(bg); + colored_terminal.set_bg(bg)?; reset = true; } if let Some(fg) = self.object_style.fg_color { - colored_terminal.set_fg(fg); + colored_terminal.set_fg(fg)?; reset = true; } for attr in self.object_style.attrs.iter() { screen .stdout - .write_string(format!(csi!("{}m"), *attr as i16)); + .write_string(format!(csi!("{}m"), *attr as i16))?; reset = true; } use std::fmt::Write; let mut content = String::new(); - write!(content, "{}", self.content).unwrap(); - screen.stdout.write_string(content); - screen.stdout.flush(); + write!(content, "{}", self.content)?; + screen.stdout.write_string(content)?; + screen.stdout.flush()?; if reset { - colored_terminal.reset(); + colored_terminal.reset()?; } + Ok(()) } /// This converts an styled object into an `DisplayableObject` witch implements: `Display` and could be used inside the write function of the standard library. @@ -198,30 +201,30 @@ impl<'a, D: Display + 'a> StyledObject { } impl Display for StyledObject { - fn fmt(&self, f: &mut Formatter) -> Result<(), fmt::Error> { + fn fmt(&self, f: &mut Formatter) -> result::Result<(), fmt::Error> { let colored_terminal = color(); let mut reset = true; if let Some(bg) = self.object_style.bg_color { - colored_terminal.set_bg(bg); + colored_terminal.set_bg(bg).unwrap(); reset = true; } if let Some(fg) = self.object_style.fg_color { - colored_terminal.set_fg(fg); + colored_terminal.set_fg(fg).unwrap(); reset = true; } for attr in self.object_style.attrs.iter() { - write!(f, "{}", format!(csi!("{}m"), *attr as i16)); + write!(f, "{}", format!(csi!("{}m"), *attr as i16))?; reset = true; } fmt::Display::fmt(&self.content, f)?; - std::io::stdout().flush().expect("Flush stdout failed"); + std::io::stdout().flush().unwrap(); if reset { - colored_terminal.reset(); - std::io::stdout().flush().expect("Flush stdout failed"); + colored_terminal.reset().unwrap(); + std::io::stdout().flush().unwrap(); } Ok(()) } @@ -248,8 +251,8 @@ impl<'a, D: Display + 'a> DisplayableObject<'a, D> { } impl<'a, D: Display + 'a> Display for DisplayableObject<'a, D> { - fn fmt(&self, _f: &mut Formatter) -> Result<(), fmt::Error> { - self.styled_object.paint(&self.screen); + fn fmt(&self, _f: &mut Formatter) -> result::Result<(), fmt::Error> { + self.styled_object.paint(&self.screen).unwrap(); Ok(()) } -} +} \ No newline at end of file diff --git a/src/modules/style/winapi_color.rs b/src/modules/style/winapi_color.rs index e48cccf..6658594 100644 --- a/src/modules/style/winapi_color.rs +++ b/src/modules/style/winapi_color.rs @@ -6,6 +6,7 @@ use kernel::windows_kernel::{Console, Handle, HandleType, ScreenBuffer}; use std::io; use std::sync::{Once, ONCE_INIT}; use winapi::um::wincon; +use common::error::Result; /// This struct is a WinApi implementation for color related actions. pub struct WinApiColor; @@ -17,14 +18,14 @@ impl WinApiColor { } impl ITerminalColor for WinApiColor { - fn set_fg(&self, fg_color: Color, _stdout: &Option<&Arc>) { + fn set_fg(&self, fg_color: Color, _stdout: &Option<&Arc>) -> Result<()>{ // init the original color in case it is not set. - let _ = init_console_color().unwrap(); + let _ = init_console_color()?; let color_value = &self.color_value(fg_color, ColorType::Foreground); - let screen_buffer = ScreenBuffer::current().unwrap(); - let csbi = screen_buffer.info().unwrap(); + let screen_buffer = ScreenBuffer::current()?; + let csbi = screen_buffer.info()?; // Notice that the color values are stored in wAttribute. // So we need to use bitwise operators to check if the values exists or to get current console colors. @@ -40,18 +41,19 @@ impl ITerminalColor for WinApiColor { } Console::from(**screen_buffer.get_handle()) - .set_text_attribute(color) - .unwrap(); + .set_text_attribute(color)?; + + Ok(()) } - fn set_bg(&self, bg_color: Color, _stdout: &Option<&Arc>) { + fn set_bg(&self, bg_color: Color, _stdout: &Option<&Arc>) -> Result<()> { // init the original color in case it is not set. - let _ = init_console_color().unwrap(); + let _ = init_console_color()?; let color_value = &self.color_value(bg_color, ColorType::Background); - let screen_buffer = ScreenBuffer::current().unwrap(); - let csbi = screen_buffer.info().unwrap(); + let screen_buffer = ScreenBuffer::current()?; + let csbi = screen_buffer.info()?; // Notice that the color values are stored in wAttribute. // So wee need to use bitwise operators to check if the values exists or to get current console colors. @@ -67,16 +69,18 @@ impl ITerminalColor for WinApiColor { } Console::from(**screen_buffer.get_handle()) - .set_text_attribute(color) - .unwrap(); + .set_text_attribute(color)?; + + Ok(()) } - fn reset(&self, _stdout: &Option<&Arc>) { + fn reset(&self, _stdout: &Option<&Arc>) -> Result<()> { // init the original color in case it is not set. let original_color = original_console_color(); - Console::from(Handle::new(HandleType::CurrentOutputHandle).unwrap()) - .set_text_attribute(original_color) - .unwrap(); + Console::from(Handle::new(HandleType::CurrentOutputHandle)?) + .set_text_attribute(original_color)?; + + Ok(()) } /// This will get the winapi color value from the Color and ColorType struct diff --git a/src/modules/terminal/ansi_terminal.rs b/src/modules/terminal/ansi_terminal.rs index c200622..9429114 100644 --- a/src/modules/terminal/ansi_terminal.rs +++ b/src/modules/terminal/ansi_terminal.rs @@ -2,6 +2,7 @@ //! This module is used for windows 10 terminals and unix terminals by default. use super::*; +use common::error::Result; /// This struct is an ansi escape code implementation for terminal related actions. pub struct AnsiTerminal; @@ -14,41 +15,45 @@ impl AnsiTerminal { } impl ITerminal for AnsiTerminal { - fn clear(&self, clear_type: ClearType, stdout: &Option<&Arc>) { + fn clear(&self, clear_type: ClearType, stdout: &Option<&Arc>) -> Result<()> { match clear_type { ClearType::All => { - functions::write_str(&stdout, csi!("2J")); - TerminalCursor::new().goto(0, 0); + functions::write_str(&stdout, csi!("2J"))?; + TerminalCursor::new().goto(0, 0)?; } ClearType::FromCursorDown => { - functions::write_str(&stdout, csi!("J")); + functions::write_str(&stdout, csi!("J"))?; } ClearType::FromCursorUp => { - functions::write_str(&stdout, csi!("1J")); + functions::write_str(&stdout, csi!("1J"))?; } ClearType::CurrentLine => { - functions::write_str(&stdout, csi!("2K")); + functions::write_str(&stdout, csi!("2K"))?; } ClearType::UntilNewLine => { - functions::write_str(&stdout, csi!("K")); + functions::write_str(&stdout, csi!("K"))?; } }; + Ok(()) } fn terminal_size(&self, _stdout: &Option<&Arc>) -> (u16, u16) { functions::get_terminal_size() } - fn scroll_up(&self, count: i16, stdout: &Option<&Arc>) { - functions::write(&stdout, format!(csi!("{}S"), count)); + fn scroll_up(&self, count: i16, stdout: &Option<&Arc>) -> Result<()>{ + functions::write(&stdout, format!(csi!("{}S"), count))?; + Ok(()) } - fn scroll_down(&self, count: i16, stdout: &Option<&Arc>) { - functions::write(&stdout, format!(csi!("{}T"), count)); + fn scroll_down(&self, count: i16, stdout: &Option<&Arc>) -> Result<()> { + functions::write(&stdout, format!(csi!("{}T"), count))?; + Ok(()) } - fn set_size(&self, width: i16, height: i16, stdout: &Option<&Arc>) { - functions::write(&stdout, format!(csi!("8;{};{}t"), height, width)); + fn set_size(&self, width: i16, height: i16, stdout: &Option<&Arc>) -> Result<()> { + functions::write(&stdout, format!(csi!("8;{};{}t"), height, width))?; + Ok(()) } fn exit(&self, stdout: &Option<&Arc>) { diff --git a/src/modules/terminal/mod.rs b/src/modules/terminal/mod.rs index 7f6be3c..4a59c26 100644 --- a/src/modules/terminal/mod.rs +++ b/src/modules/terminal/mod.rs @@ -15,7 +15,7 @@ use self::winapi_terminal::WinApiTerminal; pub use self::terminal::{from_screen, terminal, Terminal}; -use super::functions; +use common::{functions, error}; use std::sync::Arc; use {Screen, TerminalOutput}; @@ -38,15 +38,15 @@ pub enum ClearType { /// so that terminal related actions can be preformed on both Unix and Windows systems. trait ITerminal { /// Clear the current cursor by specifying the clear type - fn clear(&self, clear_type: ClearType, stdout: &Option<&Arc>); + fn clear(&self, clear_type: ClearType, stdout: &Option<&Arc>) -> error::Result<()>; /// Get the terminal size (x,y) fn terminal_size(&self, stdout: &Option<&Arc>) -> (u16, u16); /// Scroll `n` lines up in the current terminal. - fn scroll_up(&self, count: i16, stdout: &Option<&Arc>); + fn scroll_up(&self, count: i16, stdout: &Option<&Arc>) -> error::Result<()>; /// Scroll `n` lines down in the current terminal. - fn scroll_down(&self, count: i16, stdout: &Option<&Arc>); + fn scroll_down(&self, count: i16, stdout: &Option<&Arc>) -> error::Result<()>; /// Resize terminal to the given width and height. - fn set_size(&self, width: i16, height: i16, stdout: &Option<&Arc>); + fn set_size(&self, width: i16, height: i16, stdout: &Option<&Arc>) -> error::Result<()>; /// Close the current terminal fn exit(&self, stdout: &Option<&Arc>); } diff --git a/src/modules/terminal/terminal.rs b/src/modules/terminal/terminal.rs index c03edae..078d88f 100644 --- a/src/modules/terminal/terminal.rs +++ b/src/modules/terminal/terminal.rs @@ -2,7 +2,7 @@ //! Like clearing and scrolling in the terminal or getting the window size from the terminal. use super::*; - +use common::error::Result; use std::fmt; /// Struct that stores a platform-specific platform implementation for terminal related actions. @@ -93,8 +93,8 @@ impl<'stdout> Terminal<'stdout> { /// // clear all cells from cursor position until new line in terminal. /// term.clear(terminal::ClearType::UntilNewLine); /// ``` - pub fn clear(&self, clear_type: ClearType) { - self.terminal.clear(clear_type, &self.screen); + pub fn clear(&self, clear_type: ClearType) -> Result<()> { + self.terminal.clear(clear_type, &self.screen) } /// Get the terminal size (x,y). @@ -117,8 +117,8 @@ impl<'stdout> Terminal<'stdout> { /// // scroll up by 5 lines /// let size = term.scroll_up(5); /// ``` - pub fn scroll_up(&self, count: i16) { - self.terminal.scroll_up(count, &self.screen); + pub fn scroll_up(&self, count: i16) -> Result<()> { + self.terminal.scroll_up(count, &self.screen) } /// Scroll `n` lines up in the current terminal. @@ -129,8 +129,8 @@ impl<'stdout> Terminal<'stdout> { /// // scroll down by 5 lines /// let size = term.scroll_down(5); /// ``` - pub fn scroll_down(&self, count: i16) { - self.terminal.scroll_down(count, &self.screen); + pub fn scroll_down(&self, count: i16) -> Result<()> { + self.terminal.scroll_down(count, &self.screen) } /// Set the terminal size. Note that not all terminals can be set to a very small scale. @@ -141,8 +141,8 @@ impl<'stdout> Terminal<'stdout> { /// // Set of the size to X: 10 and Y: 10 /// let size = term.set_size(10,10); /// ``` - pub fn set_size(&self, width: i16, height: i16) { - self.terminal.set_size(width, height, &self.screen); + pub fn set_size(&self, width: i16, height: i16) -> Result<()> { + self.terminal.set_size(width, height, &self.screen) } /// Exit the current process. @@ -163,11 +163,12 @@ impl<'stdout> Terminal<'stdout> { /// /// let size = term.write("Some text \n Some text on new line"); /// ``` - pub fn write(&self, value: D) { + pub fn write(&self, value: D) -> Result { use std::fmt::Write; let mut string = String::new(); - write!(string, "{}", value).unwrap(); - functions::write(&self.screen, string); + write!(string, "{}", value)?; + let size = functions::write(&self.screen, string)?; + Ok(size) } } diff --git a/src/modules/terminal/winapi_terminal.rs b/src/modules/terminal/winapi_terminal.rs index 0c5f94a..62a6951 100644 --- a/src/modules/terminal/winapi_terminal.rs +++ b/src/modules/terminal/winapi_terminal.rs @@ -4,7 +4,7 @@ //! Windows versions lower then windows 10 are not supporting ANSI codes. Those versions will use this implementation instead. use super::*; - +use common::error::{Result, ErrorKind}; use kernel::windows_kernel::{Console, Coord, Cursor, Handle, ScreenBuffer, Size}; /// This struct is an winapi implementation for terminal related actions. @@ -17,9 +17,9 @@ impl WinApiTerminal { } impl ITerminal for WinApiTerminal { - fn clear(&self, clear_type: ClearType, _stdout: &Option<&Arc>) { - let screen_buffer = ScreenBuffer::current().unwrap(); - let csbi = screen_buffer.info().unwrap(); + fn clear(&self, clear_type: ClearType, _stdout: &Option<&Arc>) -> Result<()> { + let screen_buffer = ScreenBuffer::current()?; + let csbi = screen_buffer.info()?; let pos = csbi.cursor_pos(); let buffer_size = csbi.buffer_size(); @@ -27,13 +27,14 @@ impl ITerminal for WinApiTerminal { match clear_type { ClearType::All => { - clear_entire_screen(buffer_size, current_attribute); + clear_entire_screen(buffer_size, current_attribute)?; } - ClearType::FromCursorDown => clear_after_cursor(pos, buffer_size, current_attribute), - ClearType::FromCursorUp => clear_before_cursor(pos, buffer_size, current_attribute), - ClearType::CurrentLine => clear_current_line(pos, buffer_size, current_attribute), - ClearType::UntilNewLine => clear_until_line(pos, buffer_size, current_attribute), + ClearType::FromCursorDown => clear_after_cursor(pos, buffer_size, current_attribute)?, + ClearType::FromCursorUp => clear_before_cursor(pos, buffer_size, current_attribute)?, + ClearType::CurrentLine => clear_current_line(pos, buffer_size, current_attribute)?, + ClearType::UntilNewLine => clear_until_line(pos, buffer_size, current_attribute)?, }; + Ok(()) } fn terminal_size(&self, _stdout: &Option<&Arc>) -> (u16, u16) { @@ -41,53 +42,51 @@ impl ITerminal for WinApiTerminal { csbi.info().unwrap().terminal_size().into() } - fn scroll_up(&self, count: i16, _stdout: &Option<&Arc>) { - let csbi = ScreenBuffer::current().unwrap(); - let mut window = csbi.info().unwrap().terminal_window(); + fn scroll_up(&self, count: i16, _stdout: &Option<&Arc>) -> Result<()> { + let csbi = ScreenBuffer::current()?; + let mut window = csbi.info()?.terminal_window(); // Check whether the window is too close to the screen buffer top if window.top >= count { window.top -= count; // move top down window.bottom = count; // move bottom down - Console::new() - .unwrap() - .set_console_info(false, window) - .unwrap(); + Console::new()?.set_console_info(false, window)?; } + Ok(()) } - fn scroll_down(&self, count: i16, _stdout: &Option<&Arc>) { - let csbi = ScreenBuffer::current().unwrap(); - let mut window = csbi.info().unwrap().terminal_window(); - let buffer_size = csbi.info().unwrap().buffer_size(); + fn scroll_down(&self, count: i16, _stdout: &Option<&Arc>) -> Result<()>{ + let screen_buffer = ScreenBuffer::current()?; + let csbi = screen_buffer.info()?; + let mut window = csbi.terminal_window(); + let buffer_size =csbi.buffer_size(); // Check whether the window is too close to the screen buffer top if window.bottom < buffer_size.height - count { window.top += count; // move top down window.bottom += count; // move bottom down - Console::new() - .unwrap() - .set_console_info(false, window) - .unwrap(); + Console::new()? + .set_console_info(false, window)?; } + Ok(()) } /// Set the current terminal size - fn set_size(&self, width: i16, height: i16, _stdout: &Option<&Arc>) { + fn set_size(&self, width: i16, height: i16, _stdout: &Option<&Arc>) -> Result<()> { if width <= 0 { - panic!("Cannot set the terminal width lower than 1"); + return Err(ErrorKind::ResizingTerminalFailure(String::from("Cannot set the terminal width lower than 1"))); } if height <= 0 { - panic!("Cannot set the terminal height lower then 1") + return Err(ErrorKind::ResizingTerminalFailure(String::from("Cannot set the terminal height lower then 1"))); } // Get the position of the current console window - let screen_buffer = ScreenBuffer::current().unwrap(); + let screen_buffer = ScreenBuffer::current()?; let console = Console::from(**screen_buffer.get_handle()); - let csbi = screen_buffer.info().unwrap(); + let csbi = screen_buffer.info()?; let current_size = csbi.buffer_size(); let window = csbi.terminal_window(); @@ -100,7 +99,7 @@ impl ITerminal for WinApiTerminal { if current_size.width < window.left + width { if window.left >= i16::max_value() - width { - panic!("Argument out of range when setting terminal width."); + return Err(ErrorKind::ResizingTerminalFailure(String::from("Argument out of range when setting terminal width."))); } new_size.width = window.left + width; @@ -108,7 +107,7 @@ impl ITerminal for WinApiTerminal { } if current_size.height < window.top + height { if window.top >= i16::max_value() - height { - panic!("Argument out of range when setting terminal height"); + return Err(ErrorKind::ResizingTerminalFailure(String::from("Argument out of range when setting terminal height."))); } new_size.height = window.top + height; @@ -117,7 +116,7 @@ impl ITerminal for WinApiTerminal { if resize_buffer { if let Err(_) = screen_buffer.set_size(new_size.width, new_size.height) { - panic!("Something went wrong when setting screen buffer size."); + return Err(ErrorKind::ResizingTerminalFailure(String::from("Something went wrong when setting screen buffer size."))); } } @@ -125,29 +124,25 @@ impl ITerminal for WinApiTerminal { // Preserve the position, but change the size. window.bottom = window.top + height; window.right = window.left + width; - console.set_console_info(true, window).unwrap(); + console.set_console_info(true, window)?; // If we resized the buffer, un-resize it. if resize_buffer { if let Err(_) = screen_buffer.set_size(current_size.width, current_size.height) { - panic!("Something went wrong when setting screen buffer size."); + return Err(ErrorKind::ResizingTerminalFailure(String::from("Something went wrong when setting screen buffer size."))); } } let bounds = console.largest_window_size(); if width > bounds.x { - panic!( - "Argument width: {} out of range when setting terminal width.", - width - ); + return Err(ErrorKind::ResizingTerminalFailure(format!("Argument width: {} out of range when setting terminal width.", width))); } if height > bounds.y { - panic!( - "Argument height: {} out of range when setting terminal height", - height - ); + return Err(ErrorKind::ResizingTerminalFailure(format!("Argument height: {} out of range when setting terminal height", width))); } + + Ok(()) } fn exit(&self, stdout: &Option<&Arc>) { @@ -160,7 +155,7 @@ impl ITerminal for WinApiTerminal { } } -pub fn clear_after_cursor(location: Coord, buffer_size: Size, current_attribute: u16) { +pub fn clear_after_cursor(location: Coord, buffer_size: Size, current_attribute: u16) -> Result<()> { let (mut x, mut y) = (location.x, location.y); // if cursor position is at the outer right position @@ -175,10 +170,10 @@ pub fn clear_after_cursor(location: Coord, buffer_size: Size, current_attribute: // get sum cells before cursor let cells_to_write = buffer_size.width as u32 * buffer_size.height as u32; - clear(start_location, cells_to_write, current_attribute); + clear(start_location, cells_to_write, current_attribute) } -pub fn clear_before_cursor(location: Coord, buffer_size: Size, current_attribute: u16) { +pub fn clear_before_cursor(location: Coord, buffer_size: Size, current_attribute: u16) -> Result<()> { let (xpos, ypos) = (location.x, location.y); // one cell after cursor position @@ -193,10 +188,10 @@ pub fn clear_before_cursor(location: Coord, buffer_size: Size, current_attribute let cells_to_write = (buffer_size.width as u32 * ypos as u32) + (xpos as u32 + 1); // clear everything before cursor position - clear(start_location, cells_to_write, current_attribute); + clear(start_location, cells_to_write, current_attribute) } -pub fn clear_entire_screen(buffer_size: Size, current_attribute: u16) { +pub fn clear_entire_screen(buffer_size: Size, current_attribute: u16) -> Result<()> { // get sum cells before cursor let cells_to_write = buffer_size.width as u32 * buffer_size.height as u32; @@ -204,14 +199,15 @@ pub fn clear_entire_screen(buffer_size: Size, current_attribute: u16) { let start_location = Coord::new(0, 0); // clear the entire screen - clear(start_location, cells_to_write, current_attribute); + clear(start_location, cells_to_write, current_attribute)?; // put the cursor back at cell 0,0 - let cursor = Cursor::new().unwrap(); - cursor.goto(0, 0); + let cursor = Cursor::new()?; + cursor.goto(0, 0)?; + Ok(()) } -pub fn clear_current_line(location: Coord, buffer_size: Size, current_attribute: u16) { +pub fn clear_current_line(location: Coord, buffer_size: Size, current_attribute: u16) -> Result<()> { // location where to start clearing let start_location = Coord::new(0, location.y); @@ -219,14 +215,15 @@ pub fn clear_current_line(location: Coord, buffer_size: Size, current_attribute: let cells_to_write = buffer_size.width as u32; // clear the whole current line - clear(start_location, cells_to_write, current_attribute); + clear(start_location, cells_to_write, current_attribute)?; // put the cursor back at cell 1 on current row - let cursor = Cursor::new().unwrap(); - cursor.goto(0, location.y); + let cursor = Cursor::new()?; + cursor.goto(0, location.y)?; + Ok(()) } -pub fn clear_until_line(location: Coord, buffer_size: Size, current_attribute: u16) { +pub fn clear_until_line(location: Coord, buffer_size: Size, current_attribute: u16) -> Result<()> { let (x, y) = (location.x, location.y); // location where to start clearing @@ -236,19 +233,20 @@ pub fn clear_until_line(location: Coord, buffer_size: Size, current_attribute: u let cells_to_write = (buffer_size.width - x as i16) as u32; // clear until the current line - clear(start_location, cells_to_write, current_attribute); + clear(start_location, cells_to_write, current_attribute)?; // put the cursor back at original cursor position before we did the clearing - let cursor = Cursor::new().unwrap(); - cursor.goto(x, y); + let cursor = Cursor::new()?; + cursor.goto(x, y)?; + Ok(()) } -fn clear(start_location: Coord, cells_to_write: u32, current_attribute: u16) { - let console = Console::from(Handle::current_out_handle().unwrap()); +fn clear(start_location: Coord, cells_to_write: u32, current_attribute: u16) -> Result<()> { + let console = Console::from(Handle::current_out_handle()?); let _ = console - .fill_whit_character(start_location, cells_to_write, ' ') - .unwrap(); + .fill_whit_character(start_location, cells_to_write, ' ')?; console - .fill_whit_attribute(start_location, cells_to_write, current_attribute) - .unwrap(); + .fill_whit_attribute(start_location, cells_to_write, current_attribute)?; + + Ok(()) }