Error handling (#69)
* Implemented an error module for crossterm and fixed a lot of warnings.
This commit is contained in:
parent
ff9b5d9a39
commit
ad3efbd34d
@ -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)
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -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");
|
||||
}
|
||||
|
@ -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
51
src/common/error.rs
Normal 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)
|
||||
}
|
||||
}
|
@ -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() {
|
||||
// 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);
|
||||
|
@ -6,6 +6,7 @@ pub mod commands;
|
||||
pub mod functions;
|
||||
pub mod screen;
|
||||
pub mod traits;
|
||||
pub mod error;
|
||||
|
||||
mod crossterm;
|
||||
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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(|| {
|
||||
|
@ -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,
|
||||
|
@ -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)
|
||||
}
|
||||
|
||||
|
@ -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],
|
||||
|
@ -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(())
|
||||
}
|
||||
}
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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<()>;
|
||||
}
|
||||
|
@ -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(()) }
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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)
|
||||
}
|
||||
|
||||
|
@ -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 {
|
||||
|
@ -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.
|
||||
|
@ -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() {
|
||||
|
@ -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(())
|
||||
}
|
||||
}
|
@ -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
|
||||
|
@ -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>>) {
|
||||
|
@ -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>>);
|
||||
}
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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(())
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user