Error handling (#69)

* Implemented an error module for crossterm and fixed a lot of warnings.
This commit is contained in:
Timon 2019-01-01 13:27:50 -08:00 committed by GitHub
parent ff9b5d9a39
commit ad3efbd34d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
27 changed files with 342 additions and 264 deletions

View File

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

View File

@ -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");
}

View File

@ -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(())
}

51
src/common/error.rs Normal file
View File

@ -0,0 +1,51 @@
//! Module containing error handling logic.
use std::{
fmt::{self, Display, Formatter},
io,
};
/// The `crossterm` result type.
pub type Result<T> = std::result::Result<T, ErrorKind>;
/// 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<io::Error> for ErrorKind {
fn from(e: io::Error) -> ErrorKind {
ErrorKind::IoError(e)
}
}
impl From<fmt::Error> for ErrorKind {
fn from(e: fmt::Error) -> ErrorKind {
ErrorKind::FmtError(e)
}
}

View File

@ -64,18 +64,18 @@ pub fn exit_terminal() {
/// If the current platform is unix it will return the ansi implementation.
pub fn get_module<T>(winapi_impl: T, unix_impl: T) -> Option<T> {
let mut term: Option<T> = None;
let does_support = false;
let mut does_support = false;
// if !windows_supportable() {
if !windows_supportable() {
// Try to enable ansi on windows if not than use WINAPI.
// does_support = try_enable_ansi_support();
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);

View File

@ -6,6 +6,7 @@ pub mod commands;
pub mod functions;
pub mod screen;
pub mod traits;
pub mod error;
mod crossterm;

View File

@ -44,8 +44,7 @@ impl AlternateScreen {
functions::get_module::<Box<commands::IAlternateScreenCommand + Sync + Send>>(
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();
}
}

View File

@ -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();
}
}
}

View File

@ -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<bool> = None;
static mut DOES_WINDOWS_SUPPORT_ANSI: Option<bool> = 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(|| {

View File

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

View File

@ -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<u8>) -> io::Result<usize> {
.filter(|&x| x != 10 || x != 13)
.collect::<Vec<u8>>();
buf.write(a);
buf.write(a)?;
Ok(num as usize)
}

View File

@ -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],

View File

@ -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<TerminalOutput>>) {
functions::write(stdout, format!(csi!("{};{}H"), y + 1, x + 1));
fn goto(&self, x: u16, y: u16, stdout: &Option<&Arc<TerminalOutput>>) -> 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<TerminalOutput>>) {
functions::write(stdout, format!(csi!("{}A"), count));
fn move_up(&self, count: u16, stdout: &Option<&Arc<TerminalOutput>>) -> Result<()> {
functions::write(stdout, format!(csi!("{}A"), count))?;
Ok(())
}
fn move_right(&self, count: u16, stdout: &Option<&Arc<TerminalOutput>>) {
functions::write(stdout, format!(csi!("{}C"), count));
fn move_right(&self, count: u16, stdout: &Option<&Arc<TerminalOutput>>) -> Result<()> {
functions::write(stdout, format!(csi!("{}C"), count))?;
Ok(())
}
fn move_down(&self, count: u16, stdout: &Option<&Arc<TerminalOutput>>) {
functions::write(stdout, format!(csi!("{}B"), count));
fn move_down(&self, count: u16, stdout: &Option<&Arc<TerminalOutput>>) -> Result<()> {
functions::write(stdout, format!(csi!("{}B"), count))?;
Ok(())
}
fn move_left(&self, count: u16, stdout: &Option<&Arc<TerminalOutput>>) {
functions::write(stdout, format!(csi!("{}D"), count));
fn move_left(&self, count: u16, stdout: &Option<&Arc<TerminalOutput>>) -> Result<()> {
functions::write(stdout, format!(csi!("{}D"), count))?;
Ok(())
}
fn save_position(&self, stdout: &Option<&Arc<TerminalOutput>>) {
functions::write_str(stdout, csi!("s"));
fn save_position(&self, stdout: &Option<&Arc<TerminalOutput>>) -> Result<()> {
functions::write_str(stdout, csi!("s"))?;
Ok(())
}
fn reset_position(&self, stdout: &Option<&Arc<TerminalOutput>>) {
functions::write_str(stdout, csi!("u"));
fn reset_position(&self, stdout: &Option<&Arc<TerminalOutput>>)-> Result<()> {
functions::write_str(stdout, csi!("u"))?;
Ok(())
}
fn hide(&self, stdout: &Option<&Arc<TerminalOutput>>) {
functions::write_str(stdout, csi!("?25l"));
fn hide(&self, stdout: &Option<&Arc<TerminalOutput>>)-> Result<()> {
functions::write_str(stdout, csi!("?25l"))?;
Ok(())
}
fn show(&self, stdout: &Option<&Arc<TerminalOutput>>) {
functions::write_str(stdout, csi!("?25h"));
fn show(&self, stdout: &Option<&Arc<TerminalOutput>>) -> Result<()>{
functions::write_str(stdout, csi!("?25h"))?;
Ok(())
}
fn blink(&self, blink: bool, stdout: &Option<&Arc<TerminalOutput>>) {
fn blink(&self, blink: bool, stdout: &Option<&Arc<TerminalOutput>>) -> 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(())
}
}

View File

@ -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)
}
}

View File

@ -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<TerminalOutput>>);
fn goto(&self, x: u16, y: u16, stdout: &Option<&Arc<TerminalOutput>>) -> 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<TerminalOutput>>);
fn move_up(&self, count: u16, stdout: &Option<&Arc<TerminalOutput>>) -> Result<()>;
/// Move the cursor `n` times to the right.
fn move_right(&self, count: u16, stdout: &Option<&Arc<TerminalOutput>>);
fn move_right(&self, count: u16, stdout: &Option<&Arc<TerminalOutput>>) -> Result<()>;
/// Move the cursor `n` times down.
fn move_down(&self, count: u16, stdout: &Option<&Arc<TerminalOutput>>);
fn move_down(&self, count: u16, stdout: &Option<&Arc<TerminalOutput>>) -> Result<()>;
/// Move the cursor `n` times left.
fn move_left(&self, count: u16, stdout: &Option<&Arc<TerminalOutput>>);
fn move_left(&self, count: u16, stdout: &Option<&Arc<TerminalOutput>>) -> 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<TerminalOutput>>);
fn save_position(&self, stdout: &Option<&Arc<TerminalOutput>>) -> Result<()>;
/// Return to saved cursor position
fn reset_position(&self, stdout: &Option<&Arc<TerminalOutput>>);
fn reset_position(&self, stdout: &Option<&Arc<TerminalOutput>>) -> Result<()>;
/// Hide the terminal cursor.
fn hide(&self, stdout: &Option<&Arc<TerminalOutput>>);
fn hide(&self, stdout: &Option<&Arc<TerminalOutput>>) -> Result<()>;
/// Show the terminal cursor
fn show(&self, stdout: &Option<&Arc<TerminalOutput>>);
fn show(&self, stdout: &Option<&Arc<TerminalOutput>>) -> Result<()>;
/// Enable or disable the blinking of the cursor.
fn blink(&self, blink: bool, stdout: &Option<&Arc<TerminalOutput>>);
fn blink(&self, blink: bool, stdout: &Option<&Arc<TerminalOutput>>) -> Result<()>;
}

View File

@ -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<TerminalOutput>>) {
let cursor = Cursor::new().unwrap();
cursor.goto(x as i16, y as i16);
fn goto(&self, x: u16, y: u16, _stdout: &Option<&Arc<TerminalOutput>>) -> 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<TerminalOutput>>) {
fn move_up(&self, count: u16, _stdout: &Option<&Arc<TerminalOutput>>) -> 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<TerminalOutput>>) {
fn move_right(&self, count: u16, _stdout: &Option<&Arc<TerminalOutput>>) -> 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<TerminalOutput>>) {
fn move_down(&self, count: u16, _stdout: &Option<&Arc<TerminalOutput>>) -> 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<TerminalOutput>>) {
fn move_left(&self, count: u16, _stdout: &Option<&Arc<TerminalOutput>>) -> 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<TerminalOutput>>) {
Cursor::save_cursor_pos();
fn save_position(&self, _stdout: &Option<&Arc<TerminalOutput>>) -> Result<()> {
Cursor::save_cursor_pos()?;
Ok(())
}
fn reset_position(&self, _stdout: &Option<&Arc<TerminalOutput>>) {
Cursor::reset_to_saved_position();
fn reset_position(&self, _stdout: &Option<&Arc<TerminalOutput>>) -> Result<()> {
Cursor::reset_to_saved_position()?;
Ok(())
}
fn hide(&self, _stdout: &Option<&Arc<TerminalOutput>>) {
Cursor::new().unwrap().set_visibility(false);
fn hide(&self, _stdout: &Option<&Arc<TerminalOutput>>) -> Result<()> {
Cursor::from(Handle::current_out_handle()?).set_visibility(false)?;
Ok(())
}
fn show(&self, _stdout: &Option<&Arc<TerminalOutput>>) {
Cursor::new().unwrap().set_visibility(true);
fn show(&self, _stdout: &Option<&Arc<TerminalOutput>>) -> Result<()> {
Cursor::from(Handle::current_out_handle()?).set_visibility(true)?;
Ok(())
}
fn blink(&self, _blink: bool, _stdout: &Option<&Arc<TerminalOutput>>) {}
fn blink(&self, _blink: bool, _stdout: &Option<&Arc<TerminalOutput>>) -> Result<()> { Ok(()) }
}

View File

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

View File

@ -18,7 +18,7 @@ impl IStdout for WinApiOutput {
}
fn write(&self, buf: &[u8]) -> io::Result<usize> {
let handle = Handle::current_out_handle().unwrap();
let handle = Handle::current_out_handle()?;
writing::write_char_buffer(&handle, buf)
}

View File

@ -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<TerminalOutput>>) {
fn set_fg(&self, fg_color: Color, stdout: &Option<&Arc<TerminalOutput>>) -> 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<TerminalOutput>>) {
fn set_bg(&self, bg_color: Color, stdout: &Option<&Arc<TerminalOutput>>)-> Result<()> {
functions::write(
stdout,
format!(
csi!("{}m"),
self.color_value(bg_color, ColorType::Background)
),
);
)?;
Ok(())
}
fn reset(&self, stdout: &Option<&Arc<TerminalOutput>>) {
functions::write_str(stdout, csi!("0m"));
fn reset(&self, stdout: &Option<&Arc<TerminalOutput>>)-> Result<()>{
functions::write_str(stdout, csi!("0m"))?;
Ok(())
}
fn color_value(&self, color: Color, color_type: ColorType) -> String {

View File

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

View File

@ -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<TerminalOutput>>);
fn set_fg(&self, fg_color: Color, stdout: &Option<&Arc<TerminalOutput>>) -> Result<()>;
/// Set the background color to the given color.
fn set_bg(&self, fg_color: Color, stdout: &Option<&Arc<TerminalOutput>>);
fn set_bg(&self, fg_color: Color, stdout: &Option<&Arc<TerminalOutput>>) -> Result<()>;
/// Reset the terminal color to default.
fn reset(&self, stdout: &Option<&Arc<TerminalOutput>>);
fn reset(&self, stdout: &Option<&Arc<TerminalOutput>>) -> 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<Self, Self::Err> {
fn from_str(src: &str) -> ::std::result::Result<Self, Self::Err> {
let src = src.to_lowercase();
match src.as_ref() {

View File

@ -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<D> {
///
/// 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<D> {
}
impl<D: Display> Display for StyledObject<D> {
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(())
}
}

View File

@ -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<TerminalOutput>>) {
fn set_fg(&self, fg_color: Color, _stdout: &Option<&Arc<TerminalOutput>>) -> 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<TerminalOutput>>) {
fn set_bg(&self, bg_color: Color, _stdout: &Option<&Arc<TerminalOutput>>) -> 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<TerminalOutput>>) {
fn reset(&self, _stdout: &Option<&Arc<TerminalOutput>>) -> 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

View File

@ -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<TerminalOutput>>) {
fn clear(&self, clear_type: ClearType, stdout: &Option<&Arc<TerminalOutput>>) -> 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<TerminalOutput>>) -> (u16, u16) {
functions::get_terminal_size()
}
fn scroll_up(&self, count: i16, stdout: &Option<&Arc<TerminalOutput>>) {
functions::write(&stdout, format!(csi!("{}S"), count));
fn scroll_up(&self, count: i16, stdout: &Option<&Arc<TerminalOutput>>) -> Result<()>{
functions::write(&stdout, format!(csi!("{}S"), count))?;
Ok(())
}
fn scroll_down(&self, count: i16, stdout: &Option<&Arc<TerminalOutput>>) {
functions::write(&stdout, format!(csi!("{}T"), count));
fn scroll_down(&self, count: i16, stdout: &Option<&Arc<TerminalOutput>>) -> Result<()> {
functions::write(&stdout, format!(csi!("{}T"), count))?;
Ok(())
}
fn set_size(&self, width: i16, height: i16, stdout: &Option<&Arc<TerminalOutput>>) {
functions::write(&stdout, format!(csi!("8;{};{}t"), height, width));
fn set_size(&self, width: i16, height: i16, stdout: &Option<&Arc<TerminalOutput>>) -> Result<()> {
functions::write(&stdout, format!(csi!("8;{};{}t"), height, width))?;
Ok(())
}
fn exit(&self, stdout: &Option<&Arc<TerminalOutput>>) {

View File

@ -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<TerminalOutput>>);
fn clear(&self, clear_type: ClearType, stdout: &Option<&Arc<TerminalOutput>>) -> error::Result<()>;
/// Get the terminal size (x,y)
fn terminal_size(&self, stdout: &Option<&Arc<TerminalOutput>>) -> (u16, u16);
/// Scroll `n` lines up in the current terminal.
fn scroll_up(&self, count: i16, stdout: &Option<&Arc<TerminalOutput>>);
fn scroll_up(&self, count: i16, stdout: &Option<&Arc<TerminalOutput>>) -> error::Result<()>;
/// Scroll `n` lines down in the current terminal.
fn scroll_down(&self, count: i16, stdout: &Option<&Arc<TerminalOutput>>);
fn scroll_down(&self, count: i16, stdout: &Option<&Arc<TerminalOutput>>) -> error::Result<()>;
/// Resize terminal to the given width and height.
fn set_size(&self, width: i16, height: i16, stdout: &Option<&Arc<TerminalOutput>>);
fn set_size(&self, width: i16, height: i16, stdout: &Option<&Arc<TerminalOutput>>) -> error::Result<()>;
/// Close the current terminal
fn exit(&self, stdout: &Option<&Arc<TerminalOutput>>);
}

View File

@ -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<D: fmt::Display>(&self, value: D) {
pub fn write<D: fmt::Display>(&self, value: D) -> Result<usize> {
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)
}
}

View File

@ -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<TerminalOutput>>) {
let screen_buffer = ScreenBuffer::current().unwrap();
let csbi = screen_buffer.info().unwrap();
fn clear(&self, clear_type: ClearType, _stdout: &Option<&Arc<TerminalOutput>>) -> 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<TerminalOutput>>) -> (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<TerminalOutput>>) {
let csbi = ScreenBuffer::current().unwrap();
let mut window = csbi.info().unwrap().terminal_window();
fn scroll_up(&self, count: i16, _stdout: &Option<&Arc<TerminalOutput>>) -> 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<TerminalOutput>>) {
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<TerminalOutput>>) -> 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<TerminalOutput>>) {
fn set_size(&self, width: i16, height: i16, _stdout: &Option<&Arc<TerminalOutput>>) -> 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<TerminalOutput>>) {
@ -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(())
}