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
|
// Or print inline
|
||||||
println!(
|
println!(
|
||||||
"Colored text: {}",
|
"Colored text: {}",
|
||||||
style("Red foreground").with(Color::Blue)
|
style("Blue foreground").with(Color::Blue)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -15,14 +15,11 @@ mod input;
|
|||||||
mod terminal;
|
mod terminal;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
use input::keyboard::input;
|
let cursor = crossterm::cursor();
|
||||||
|
cursor.goto(5,5);
|
||||||
|
|
||||||
// color::print_all_foreground_colors();
|
let integer = 10;
|
||||||
// color::print_all_background_colors();
|
let float: f32 = integert as f32;
|
||||||
|
|
||||||
use terminal::alternate_screen;
|
println!("5.515151");
|
||||||
// color::print_all_background_colors();
|
|
||||||
// color::print_all_foreground_colors();
|
|
||||||
|
|
||||||
alternate_screen::print_wait_screen_on_alternate_window();
|
|
||||||
}
|
}
|
||||||
|
@ -78,7 +78,7 @@ impl RawModeCommand {
|
|||||||
pub fn enable(&mut self) -> Result<()> {
|
pub fn enable(&mut self) -> Result<()> {
|
||||||
let console_mode = ConsoleMode::new()?;
|
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;
|
let new_mode = dw_mode & !self.mask;
|
||||||
|
|
||||||
@ -91,7 +91,7 @@ impl RawModeCommand {
|
|||||||
pub fn disable(&self) -> Result<()> {
|
pub fn disable(&self) -> Result<()> {
|
||||||
let console_mode = ConsoleMode::new()?;
|
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;
|
let new_mode = dw_mode | self.mask;
|
||||||
|
|
||||||
@ -114,7 +114,7 @@ impl ToAlternateScreenCommand {
|
|||||||
impl IAlternateScreenCommand for ToAlternateScreenCommand {
|
impl IAlternateScreenCommand for ToAlternateScreenCommand {
|
||||||
fn enable(&self, _stdout: &mut TerminalOutput) -> Result<()> {
|
fn enable(&self, _stdout: &mut TerminalOutput) -> Result<()> {
|
||||||
let alternate_screen = ScreenBuffer::create();
|
let alternate_screen = ScreenBuffer::create();
|
||||||
alternate_screen.show();
|
alternate_screen.show()?;
|
||||||
Ok(())
|
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.
|
/// 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> {
|
pub fn get_module<T>(winapi_impl: T, unix_impl: T) -> Option<T> {
|
||||||
let mut term: Option<T> = None;
|
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.
|
// 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.
|
// uncomment this line when you want to use the winapi implementation.
|
||||||
// does_support = false;
|
// does_support = false;
|
||||||
if !does_support {
|
if !does_support {
|
||||||
term = Some(winapi_impl);
|
term = Some(winapi_impl);
|
||||||
}
|
}
|
||||||
// }
|
}
|
||||||
|
|
||||||
if does_support {
|
if does_support {
|
||||||
term = Some(unix_impl);
|
term = Some(unix_impl);
|
||||||
|
@ -6,6 +6,7 @@ pub mod commands;
|
|||||||
pub mod functions;
|
pub mod functions;
|
||||||
pub mod screen;
|
pub mod screen;
|
||||||
pub mod traits;
|
pub mod traits;
|
||||||
|
pub mod error;
|
||||||
|
|
||||||
mod crossterm;
|
mod crossterm;
|
||||||
|
|
||||||
|
@ -44,8 +44,7 @@ impl AlternateScreen {
|
|||||||
functions::get_module::<Box<commands::IAlternateScreenCommand + Sync + Send>>(
|
functions::get_module::<Box<commands::IAlternateScreenCommand + Sync + Send>>(
|
||||||
Box::from(commands::win_commands::ToAlternateScreenCommand::new()),
|
Box::from(commands::win_commands::ToAlternateScreenCommand::new()),
|
||||||
Box::from(commands::shared_commands::ToAlternateScreenCommand::new()),
|
Box::from(commands::shared_commands::ToAlternateScreenCommand::new()),
|
||||||
)
|
).unwrap();
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
#[cfg(not(target_os = "windows"))]
|
#[cfg(not(target_os = "windows"))]
|
||||||
let command = Box::from(commands::shared_commands::ToAlternateScreenCommand::new());
|
let command = Box::from(commands::shared_commands::ToAlternateScreenCommand::new());
|
||||||
@ -72,6 +71,6 @@ impl AlternateScreen {
|
|||||||
impl Drop for AlternateScreen {
|
impl Drop for AlternateScreen {
|
||||||
/// This will switch back to main screen on drop.
|
/// This will switch back to main screen on drop.
|
||||||
fn drop(&mut self) {
|
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.
|
/// If the current screen is in raw mode we need to disable it when the instance goes out of scope.
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
if self.stdout.is_in_raw_mode && self.drop {
|
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 HAS_BEEN_TRIED_TO_ENABLE: bool = false;
|
||||||
static mut IS_ANSI_ON_WINDOWS_ENABLED: Option<bool> = None;
|
static mut IS_ANSI_ON_WINDOWS_ENABLED: Option<bool> = None;
|
||||||
static mut DOES_WINDOWS_SUPPORT_ANSI: 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::win_commands::EnableAnsiCommand;
|
||||||
use common::commands::IEnableAnsiCommand;
|
use common::commands::IEnableAnsiCommand;
|
||||||
|
|
||||||
|
static ENABLE_ANSI: Once = ONCE_INIT;
|
||||||
|
|
||||||
/// Try enable `ANSI escape codes` and return the result.
|
/// Try enable `ANSI escape codes` and return the result.
|
||||||
pub fn try_enable_ansi_support() -> bool {
|
pub fn try_enable_ansi_support() -> bool {
|
||||||
ENABLE_ANSI.call_once(|| {
|
ENABLE_ANSI.call_once(|| {
|
||||||
|
@ -1,15 +1,11 @@
|
|||||||
//! This module contains the `windows` (unsafe) logic.
|
//! This module contains the `windows` (unsafe) logic.
|
||||||
|
|
||||||
|
#[allow(unused)]
|
||||||
|
mod reading;
|
||||||
pub mod ansi_support;
|
pub mod ansi_support;
|
||||||
mod cursor;
|
mod cursor;
|
||||||
pub mod reading;
|
|
||||||
pub mod writing;
|
pub mod writing;
|
||||||
|
|
||||||
use winapi::um::{
|
|
||||||
wincon::{CONSOLE_SCREEN_BUFFER_INFO, COORD, SMALL_RECT},
|
|
||||||
winnt::HANDLE,
|
|
||||||
};
|
|
||||||
|
|
||||||
pub use self::cursor::Cursor;
|
pub use self::cursor::Cursor;
|
||||||
pub use crossterm_winapi::{
|
pub use crossterm_winapi::{
|
||||||
Console, ConsoleMode, Coord, Handle, HandleType, ScreenBuffer, ScreenBufferInfo, Size,
|
Console, ConsoleMode, Coord, Handle, HandleType, ScreenBuffer, ScreenBufferInfo, Size,
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
use crossterm_winapi::{Handle, HandleType};
|
use crossterm_winapi::Handle;
|
||||||
|
|
||||||
use std::{
|
use std::{
|
||||||
io::{self, Write},
|
io::{self, Write},
|
||||||
@ -50,7 +50,7 @@ pub fn read_line(buf: &mut Vec<u8>) -> io::Result<usize> {
|
|||||||
.filter(|&x| x != 10 || x != 13)
|
.filter(|&x| x != 10 || x != 13)
|
||||||
.collect::<Vec<u8>>();
|
.collect::<Vec<u8>>();
|
||||||
|
|
||||||
buf.write(a);
|
buf.write(a)?;
|
||||||
Ok(num as usize)
|
Ok(num as usize)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -12,6 +12,7 @@ use std::io::{self, Result};
|
|||||||
use std::str;
|
use std::str;
|
||||||
|
|
||||||
/// Write console output.
|
/// Write console output.
|
||||||
|
#[allow(unused)]
|
||||||
pub fn write_console_output(
|
pub fn write_console_output(
|
||||||
write_buffer: &HANDLE,
|
write_buffer: &HANDLE,
|
||||||
copy_buffer: &mut [CHAR_INFO; 160],
|
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.
|
//! 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 super::*;
|
||||||
|
use common::error::Result;
|
||||||
|
|
||||||
/// This struct is an ANSI implementation for cursor related actions.
|
/// This struct is an ANSI implementation for cursor related actions.
|
||||||
pub struct AnsiCursor {}
|
pub struct AnsiCursor {}
|
||||||
@ -14,51 +15,61 @@ impl AnsiCursor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl ITerminalCursor for AnsiCursor {
|
impl ITerminalCursor for AnsiCursor {
|
||||||
fn goto(&self, x: u16, y: u16, stdout: &Option<&Arc<TerminalOutput>>) {
|
fn goto(&self, x: u16, y: u16, stdout: &Option<&Arc<TerminalOutput>>) -> Result<()> {
|
||||||
functions::write(stdout, format!(csi!("{};{}H"), y + 1, x + 1));
|
functions::write(stdout, format!(csi!("{};{}H"), y + 1, x + 1))?;
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn pos(&self) -> (u16, u16) {
|
fn pos(&self) -> (u16, u16) {
|
||||||
functions::get_cursor_position()
|
functions::get_cursor_position()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn move_up(&self, count: u16, stdout: &Option<&Arc<TerminalOutput>>) {
|
fn move_up(&self, count: u16, stdout: &Option<&Arc<TerminalOutput>>) -> Result<()> {
|
||||||
functions::write(stdout, format!(csi!("{}A"), count));
|
functions::write(stdout, format!(csi!("{}A"), count))?;
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn move_right(&self, count: u16, stdout: &Option<&Arc<TerminalOutput>>) {
|
fn move_right(&self, count: u16, stdout: &Option<&Arc<TerminalOutput>>) -> Result<()> {
|
||||||
functions::write(stdout, format!(csi!("{}C"), count));
|
functions::write(stdout, format!(csi!("{}C"), count))?;
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn move_down(&self, count: u16, stdout: &Option<&Arc<TerminalOutput>>) {
|
fn move_down(&self, count: u16, stdout: &Option<&Arc<TerminalOutput>>) -> Result<()> {
|
||||||
functions::write(stdout, format!(csi!("{}B"), count));
|
functions::write(stdout, format!(csi!("{}B"), count))?;
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn move_left(&self, count: u16, stdout: &Option<&Arc<TerminalOutput>>) {
|
fn move_left(&self, count: u16, stdout: &Option<&Arc<TerminalOutput>>) -> Result<()> {
|
||||||
functions::write(stdout, format!(csi!("{}D"), count));
|
functions::write(stdout, format!(csi!("{}D"), count))?;
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn save_position(&self, stdout: &Option<&Arc<TerminalOutput>>) {
|
fn save_position(&self, stdout: &Option<&Arc<TerminalOutput>>) -> Result<()> {
|
||||||
functions::write_str(stdout, csi!("s"));
|
functions::write_str(stdout, csi!("s"))?;
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn reset_position(&self, stdout: &Option<&Arc<TerminalOutput>>) {
|
fn reset_position(&self, stdout: &Option<&Arc<TerminalOutput>>)-> Result<()> {
|
||||||
functions::write_str(stdout, csi!("u"));
|
functions::write_str(stdout, csi!("u"))?;
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn hide(&self, stdout: &Option<&Arc<TerminalOutput>>) {
|
fn hide(&self, stdout: &Option<&Arc<TerminalOutput>>)-> Result<()> {
|
||||||
functions::write_str(stdout, csi!("?25l"));
|
functions::write_str(stdout, csi!("?25l"))?;
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn show(&self, stdout: &Option<&Arc<TerminalOutput>>) {
|
fn show(&self, stdout: &Option<&Arc<TerminalOutput>>) -> Result<()>{
|
||||||
functions::write_str(stdout, csi!("?25h"));
|
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 {
|
if blink {
|
||||||
functions::write_str(stdout, csi!("?12h"));
|
functions::write_str(stdout, csi!("?12h"))?;
|
||||||
} else {
|
} 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
|
//! Note that positions of the cursor are 0 -based witch means that the coordinates (cells) starts counting from 0
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
|
use common::error::Result;
|
||||||
use Screen;
|
use Screen;
|
||||||
|
|
||||||
/// Struct that stores a platform-specific implementation for cursor related actions.
|
/// Struct that stores a platform-specific implementation for cursor related actions.
|
||||||
@ -94,8 +95,8 @@ impl<'stdout> TerminalCursor<'stdout> {
|
|||||||
/// cursor.goto(4,5);
|
/// cursor.goto(4,5);
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
pub fn goto(&self, x: u16, y: u16) {
|
pub fn goto(&self, x: u16, y: u16) -> Result<()> {
|
||||||
self.terminal_cursor.goto(x, y, &self.stdout);
|
self.terminal_cursor.goto(x, y, &self.stdout)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get current cursor position (x,y) in the terminal.
|
/// Get current cursor position (x,y) in the terminal.
|
||||||
@ -119,7 +120,7 @@ impl<'stdout> TerminalCursor<'stdout> {
|
|||||||
/// cursor.move_up(3);
|
/// cursor.move_up(3);
|
||||||
/// ```
|
/// ```
|
||||||
pub fn move_up(&mut self, count: u16) -> &mut TerminalCursor<'stdout> {
|
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
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -132,7 +133,7 @@ impl<'stdout> TerminalCursor<'stdout> {
|
|||||||
/// cursor.move_right(3);
|
/// cursor.move_right(3);
|
||||||
/// ```
|
/// ```
|
||||||
pub fn move_right(&mut self, count: u16) -> &mut TerminalCursor<'stdout> {
|
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
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -145,7 +146,7 @@ impl<'stdout> TerminalCursor<'stdout> {
|
|||||||
/// cursor.move_down(3);
|
/// cursor.move_down(3);
|
||||||
/// ```
|
/// ```
|
||||||
pub fn move_down(&mut self, count: u16) -> &mut TerminalCursor<'stdout> {
|
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
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -158,7 +159,7 @@ impl<'stdout> TerminalCursor<'stdout> {
|
|||||||
/// cursor.move_left(3);
|
/// cursor.move_left(3);
|
||||||
/// ```
|
/// ```
|
||||||
pub fn move_left(&mut self, count: u16) -> &mut TerminalCursor<'stdout> {
|
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
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -171,8 +172,8 @@ impl<'stdout> TerminalCursor<'stdout> {
|
|||||||
///
|
///
|
||||||
/// cursor.safe_position();
|
/// cursor.safe_position();
|
||||||
/// ```
|
/// ```
|
||||||
pub fn save_position(&self) {
|
pub fn save_position(&self) -> Result<()> {
|
||||||
self.terminal_cursor.save_position(&self.stdout);
|
self.terminal_cursor.save_position(&self.stdout)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return to saved cursor position
|
/// Return to saved cursor position
|
||||||
@ -184,8 +185,8 @@ impl<'stdout> TerminalCursor<'stdout> {
|
|||||||
///
|
///
|
||||||
/// cursor.reset_position();
|
/// cursor.reset_position();
|
||||||
/// ```
|
/// ```
|
||||||
pub fn reset_position(&self) {
|
pub fn reset_position(&self) -> Result<()> {
|
||||||
self.terminal_cursor.reset_position(&self.stdout);
|
self.terminal_cursor.reset_position(&self.stdout)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Hide de cursor in the console.
|
/// Hide de cursor in the console.
|
||||||
@ -194,8 +195,8 @@ impl<'stdout> TerminalCursor<'stdout> {
|
|||||||
/// let cursor = cursor();
|
/// let cursor = cursor();
|
||||||
/// cursor.hide();
|
/// cursor.hide();
|
||||||
/// ```
|
/// ```
|
||||||
pub fn hide(&self) {
|
pub fn hide(&self) -> Result<()> {
|
||||||
self.terminal_cursor.hide(&self.stdout);
|
self.terminal_cursor.hide(&self.stdout)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Show the cursor in the console.
|
/// Show the cursor in the console.
|
||||||
@ -206,8 +207,8 @@ impl<'stdout> TerminalCursor<'stdout> {
|
|||||||
/// cursor.show();
|
/// cursor.show();
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
pub fn show(&self) {
|
pub fn show(&self) -> Result<()> {
|
||||||
self.terminal_cursor.show(&self.stdout);
|
self.terminal_cursor.show(&self.stdout)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Enable or disable blinking of the terminal.
|
/// Enable or disable blinking of the terminal.
|
||||||
@ -219,8 +220,8 @@ impl<'stdout> TerminalCursor<'stdout> {
|
|||||||
/// cursor.blink(true);
|
/// cursor.blink(true);
|
||||||
/// cursor.blink(false);
|
/// cursor.blink(false);
|
||||||
/// ```
|
/// ```
|
||||||
pub fn blink(&self, blink: bool) {
|
pub fn blink(&self, blink: bool) -> Result<()> {
|
||||||
self.terminal_cursor.blink(blink, &self.stdout);
|
self.terminal_cursor.blink(blink, &self.stdout)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -17,7 +17,7 @@ use self::ansi_cursor::AnsiCursor;
|
|||||||
use self::winapi_cursor::WinApiCursor;
|
use self::winapi_cursor::WinApiCursor;
|
||||||
|
|
||||||
pub use self::cursor::{cursor, from_screen, TerminalCursor};
|
pub use self::cursor::{cursor, from_screen, TerminalCursor};
|
||||||
|
use common::error::Result;
|
||||||
use super::functions;
|
use super::functions;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use TerminalOutput;
|
use TerminalOutput;
|
||||||
@ -32,25 +32,25 @@ use TerminalOutput;
|
|||||||
///! so that cursor related actions can be performed on both UNIX and Windows systems.
|
///! so that cursor related actions can be performed on both UNIX and Windows systems.
|
||||||
trait ITerminalCursor: Sync + Send {
|
trait ITerminalCursor: Sync + Send {
|
||||||
/// Goto some location (x,y) in the context.
|
/// 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
|
/// Get the location (x,y) of the current cursor in the context
|
||||||
fn pos(&self) -> (u16, u16);
|
fn pos(&self) -> (u16, u16);
|
||||||
/// Move cursor n times up
|
/// 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.
|
/// 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.
|
/// 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.
|
/// 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.
|
/// 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
|
/// 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.
|
/// Hide the terminal cursor.
|
||||||
fn hide(&self, stdout: &Option<&Arc<TerminalOutput>>);
|
fn hide(&self, stdout: &Option<&Arc<TerminalOutput>>) -> Result<()>;
|
||||||
/// Show the terminal cursor
|
/// 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.
|
/// 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.
|
//! 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.
|
//! 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::*;
|
use super::*;
|
||||||
|
|
||||||
/// This struct is a windows implementation for cursor related actions.
|
/// This struct is a windows implementation for cursor related actions.
|
||||||
@ -16,9 +16,10 @@ impl WinApiCursor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl ITerminalCursor for WinApiCursor {
|
impl ITerminalCursor for WinApiCursor {
|
||||||
fn goto(&self, x: u16, y: u16, _stdout: &Option<&Arc<TerminalOutput>>) {
|
fn goto(&self, x: u16, y: u16, _stdout: &Option<&Arc<TerminalOutput>>) -> Result<()> {
|
||||||
let cursor = Cursor::new().unwrap();
|
let cursor = Cursor::new()?;
|
||||||
cursor.goto(x as i16, y as i16);
|
cursor.goto(x as i16, y as i16)?;
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn pos(&self) -> (u16, u16) {
|
fn pos(&self) -> (u16, u16) {
|
||||||
@ -26,41 +27,49 @@ impl ITerminalCursor for WinApiCursor {
|
|||||||
cursor.position().unwrap().into()
|
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();
|
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();
|
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();
|
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();
|
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>>) {
|
fn save_position(&self, _stdout: &Option<&Arc<TerminalOutput>>) -> Result<()> {
|
||||||
Cursor::save_cursor_pos();
|
Cursor::save_cursor_pos()?;
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn reset_position(&self, _stdout: &Option<&Arc<TerminalOutput>>) {
|
fn reset_position(&self, _stdout: &Option<&Arc<TerminalOutput>>) -> Result<()> {
|
||||||
Cursor::reset_to_saved_position();
|
Cursor::reset_to_saved_position()?;
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn hide(&self, _stdout: &Option<&Arc<TerminalOutput>>) {
|
fn hide(&self, _stdout: &Option<&Arc<TerminalOutput>>) -> Result<()> {
|
||||||
Cursor::new().unwrap().set_visibility(false);
|
Cursor::from(Handle::current_out_handle()?).set_visibility(false)?;
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn show(&self, _stdout: &Option<&Arc<TerminalOutput>>) {
|
fn show(&self, _stdout: &Option<&Arc<TerminalOutput>>) -> Result<()> {
|
||||||
Cursor::new().unwrap().set_visibility(true);
|
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;
|
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;
|
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" {
|
extern "C" {
|
||||||
fn _getwche() -> INT;
|
fn _getwche() -> INT;
|
||||||
fn _getwch() -> INT;
|
fn _getwch() -> INT;
|
||||||
|
@ -18,7 +18,7 @@ impl IStdout for WinApiOutput {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn write(&self, buf: &[u8]) -> io::Result<usize> {
|
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)
|
writing::write_char_buffer(&handle, buf)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
//! This module is used for Windows 10 terminals and Unix terminals by default.
|
//! This module is used for Windows 10 terminals and Unix terminals by default.
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
|
use common::error::Result;
|
||||||
|
|
||||||
/// This struct is an ANSI escape code implementation for color related actions.
|
/// This struct is an ANSI escape code implementation for color related actions.
|
||||||
pub struct AnsiColor;
|
pub struct AnsiColor;
|
||||||
@ -13,28 +14,31 @@ impl AnsiColor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl ITerminalColor for 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(
|
functions::write(
|
||||||
stdout,
|
stdout,
|
||||||
format!(
|
format!(
|
||||||
csi!("{}m"),
|
csi!("{}m"),
|
||||||
self.color_value(fg_color, ColorType::Foreground)
|
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(
|
functions::write(
|
||||||
stdout,
|
stdout,
|
||||||
format!(
|
format!(
|
||||||
csi!("{}m"),
|
csi!("{}m"),
|
||||||
self.color_value(bg_color, ColorType::Background)
|
self.color_value(bg_color, ColorType::Background)
|
||||||
),
|
),
|
||||||
);
|
)?;
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn reset(&self, stdout: &Option<&Arc<TerminalOutput>>) {
|
fn reset(&self, stdout: &Option<&Arc<TerminalOutput>>)-> Result<()>{
|
||||||
functions::write_str(stdout, csi!("0m"));
|
functions::write_str(stdout, csi!("0m"))?;
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn color_value(&self, color: Color, color_type: ColorType) -> String {
|
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
|
/// // crossterm provides to set the background from &str or String
|
||||||
/// colored_terminal.set_fg(Color::from("Red"));
|
/// colored_terminal.set_fg(Color::from("Red"));
|
||||||
/// ```
|
/// ```
|
||||||
pub fn set_fg(&self, color: Color) {
|
pub fn set_fg(&self, color: Color)-> Result<()> {
|
||||||
self.color.set_fg(color, &self.stdout);
|
self.color.set_fg(color, &self.stdout)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Set the background color to the given color.
|
/// 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
|
/// // crossterm provides to set the background from &str or String
|
||||||
/// colored_terminal.set_bg(Color::from("Red"));
|
/// colored_terminal.set_bg(Color::from("Red"));
|
||||||
/// ```
|
/// ```
|
||||||
pub fn set_bg(&self, color: Color) {
|
pub fn set_bg(&self, color: Color) -> Result<()>{
|
||||||
self.color.set_bg(color, &self.stdout);
|
self.color.set_bg(color, &self.stdout)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Reset the terminal colors and attributes to default.
|
/// Reset the terminal colors and attributes to default.
|
||||||
@ -118,8 +118,8 @@ impl<'stdout> TerminalColor<'stdout> {
|
|||||||
/// let colored_terminal = color();
|
/// let colored_terminal = color();
|
||||||
/// colored_terminal.reset();
|
/// colored_terminal.reset();
|
||||||
/// ```
|
/// ```
|
||||||
pub fn reset(&self) {
|
pub fn reset(&self)-> Result<()> {
|
||||||
self.color.reset(&self.stdout);
|
self.color.reset(&self.stdout)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get available color count.
|
/// Get available color count.
|
||||||
|
@ -22,7 +22,7 @@ pub use self::color::{color, from_screen, TerminalColor};
|
|||||||
pub use self::objectstyle::ObjectStyle;
|
pub use self::objectstyle::ObjectStyle;
|
||||||
pub use self::styledobject::DisplayableObject;
|
pub use self::styledobject::DisplayableObject;
|
||||||
pub use self::styledobject::StyledObject;
|
pub use self::styledobject::StyledObject;
|
||||||
use super::functions;
|
use common::{functions, error::Result};
|
||||||
|
|
||||||
use TerminalOutput;
|
use TerminalOutput;
|
||||||
|
|
||||||
@ -36,11 +36,11 @@ use TerminalOutput;
|
|||||||
/// so that color-related actions can be performed on both UNIX and Windows systems.
|
/// so that color-related actions can be performed on both UNIX and Windows systems.
|
||||||
trait ITerminalColor {
|
trait ITerminalColor {
|
||||||
/// Set the foreground color to the given color.
|
/// 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.
|
/// 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.
|
/// 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`.
|
/// Gets an value that represents an color from the given `Color` and `ColorType`.
|
||||||
fn color_value(&self, color: Color, color_type: ColorType) -> String;
|
fn color_value(&self, color: Color, color_type: ColorType) -> String;
|
||||||
}
|
}
|
||||||
@ -153,7 +153,7 @@ impl FromStr for Color {
|
|||||||
type Err = ();
|
type Err = ();
|
||||||
|
|
||||||
/// Convert a string to an Color value
|
/// 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();
|
let src = src.to_lowercase();
|
||||||
|
|
||||||
match src.as_ref() {
|
match src.as_ref() {
|
||||||
|
@ -5,6 +5,8 @@ use Screen;
|
|||||||
|
|
||||||
use std::fmt::{self, Display, Formatter};
|
use std::fmt::{self, Display, Formatter};
|
||||||
use std::io::Write;
|
use std::io::Write;
|
||||||
|
use common::error::Result;
|
||||||
|
use std::result;
|
||||||
|
|
||||||
use super::Attribute;
|
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.
|
/// 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.
|
/// 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 colored_terminal = from_screen(&screen);
|
||||||
let mut reset = true;
|
let mut reset = true;
|
||||||
|
|
||||||
if let Some(bg) = self.object_style.bg_color {
|
if let Some(bg) = self.object_style.bg_color {
|
||||||
colored_terminal.set_bg(bg);
|
colored_terminal.set_bg(bg)?;
|
||||||
reset = true;
|
reset = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(fg) = self.object_style.fg_color {
|
if let Some(fg) = self.object_style.fg_color {
|
||||||
colored_terminal.set_fg(fg);
|
colored_terminal.set_fg(fg)?;
|
||||||
reset = true;
|
reset = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
for attr in self.object_style.attrs.iter() {
|
for attr in self.object_style.attrs.iter() {
|
||||||
screen
|
screen
|
||||||
.stdout
|
.stdout
|
||||||
.write_string(format!(csi!("{}m"), *attr as i16));
|
.write_string(format!(csi!("{}m"), *attr as i16))?;
|
||||||
reset = true;
|
reset = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
use std::fmt::Write;
|
use std::fmt::Write;
|
||||||
let mut content = String::new();
|
let mut content = String::new();
|
||||||
write!(content, "{}", self.content).unwrap();
|
write!(content, "{}", self.content)?;
|
||||||
screen.stdout.write_string(content);
|
screen.stdout.write_string(content)?;
|
||||||
screen.stdout.flush();
|
screen.stdout.flush()?;
|
||||||
|
|
||||||
if reset {
|
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.
|
/// 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> {
|
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 colored_terminal = color();
|
||||||
let mut reset = true;
|
let mut reset = true;
|
||||||
|
|
||||||
if let Some(bg) = self.object_style.bg_color {
|
if let Some(bg) = self.object_style.bg_color {
|
||||||
colored_terminal.set_bg(bg);
|
colored_terminal.set_bg(bg).unwrap();
|
||||||
reset = true;
|
reset = true;
|
||||||
}
|
}
|
||||||
if let Some(fg) = self.object_style.fg_color {
|
if let Some(fg) = self.object_style.fg_color {
|
||||||
colored_terminal.set_fg(fg);
|
colored_terminal.set_fg(fg).unwrap();
|
||||||
reset = true;
|
reset = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
for attr in self.object_style.attrs.iter() {
|
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;
|
reset = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
fmt::Display::fmt(&self.content, f)?;
|
fmt::Display::fmt(&self.content, f)?;
|
||||||
std::io::stdout().flush().expect("Flush stdout failed");
|
std::io::stdout().flush().unwrap();
|
||||||
|
|
||||||
if reset {
|
if reset {
|
||||||
colored_terminal.reset();
|
colored_terminal.reset().unwrap();
|
||||||
std::io::stdout().flush().expect("Flush stdout failed");
|
std::io::stdout().flush().unwrap();
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@ -248,8 +251,8 @@ impl<'a, D: Display + 'a> DisplayableObject<'a, D> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, D: Display + 'a> Display for DisplayableObject<'a, D> {
|
impl<'a, D: Display + 'a> Display for DisplayableObject<'a, D> {
|
||||||
fn fmt(&self, _f: &mut Formatter) -> Result<(), fmt::Error> {
|
fn fmt(&self, _f: &mut Formatter) -> result::Result<(), fmt::Error> {
|
||||||
self.styled_object.paint(&self.screen);
|
self.styled_object.paint(&self.screen).unwrap();
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -6,6 +6,7 @@ use kernel::windows_kernel::{Console, Handle, HandleType, ScreenBuffer};
|
|||||||
use std::io;
|
use std::io;
|
||||||
use std::sync::{Once, ONCE_INIT};
|
use std::sync::{Once, ONCE_INIT};
|
||||||
use winapi::um::wincon;
|
use winapi::um::wincon;
|
||||||
|
use common::error::Result;
|
||||||
|
|
||||||
/// This struct is a WinApi implementation for color related actions.
|
/// This struct is a WinApi implementation for color related actions.
|
||||||
pub struct WinApiColor;
|
pub struct WinApiColor;
|
||||||
@ -17,14 +18,14 @@ impl WinApiColor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl ITerminalColor for 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.
|
// 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 color_value = &self.color_value(fg_color, ColorType::Foreground);
|
||||||
|
|
||||||
let screen_buffer = ScreenBuffer::current().unwrap();
|
let screen_buffer = ScreenBuffer::current()?;
|
||||||
let csbi = screen_buffer.info().unwrap();
|
let csbi = screen_buffer.info()?;
|
||||||
|
|
||||||
// Notice that the color values are stored in wAttribute.
|
// 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.
|
// 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())
|
Console::from(**screen_buffer.get_handle())
|
||||||
.set_text_attribute(color)
|
.set_text_attribute(color)?;
|
||||||
.unwrap();
|
|
||||||
|
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.
|
// 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 color_value = &self.color_value(bg_color, ColorType::Background);
|
||||||
|
|
||||||
let screen_buffer = ScreenBuffer::current().unwrap();
|
let screen_buffer = ScreenBuffer::current()?;
|
||||||
let csbi = screen_buffer.info().unwrap();
|
let csbi = screen_buffer.info()?;
|
||||||
|
|
||||||
// Notice that the color values are stored in wAttribute.
|
// 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.
|
// 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())
|
Console::from(**screen_buffer.get_handle())
|
||||||
.set_text_attribute(color)
|
.set_text_attribute(color)?;
|
||||||
.unwrap();
|
|
||||||
|
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.
|
// init the original color in case it is not set.
|
||||||
let original_color = original_console_color();
|
let original_color = original_console_color();
|
||||||
Console::from(Handle::new(HandleType::CurrentOutputHandle).unwrap())
|
Console::from(Handle::new(HandleType::CurrentOutputHandle)?)
|
||||||
.set_text_attribute(original_color)
|
.set_text_attribute(original_color)?;
|
||||||
.unwrap();
|
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// This will get the winapi color value from the Color and ColorType struct
|
/// 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.
|
//! This module is used for windows 10 terminals and unix terminals by default.
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
|
use common::error::Result;
|
||||||
|
|
||||||
/// This struct is an ansi escape code implementation for terminal related actions.
|
/// This struct is an ansi escape code implementation for terminal related actions.
|
||||||
pub struct AnsiTerminal;
|
pub struct AnsiTerminal;
|
||||||
@ -14,41 +15,45 @@ impl AnsiTerminal {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl ITerminal for 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 {
|
match clear_type {
|
||||||
ClearType::All => {
|
ClearType::All => {
|
||||||
functions::write_str(&stdout, csi!("2J"));
|
functions::write_str(&stdout, csi!("2J"))?;
|
||||||
TerminalCursor::new().goto(0, 0);
|
TerminalCursor::new().goto(0, 0)?;
|
||||||
}
|
}
|
||||||
ClearType::FromCursorDown => {
|
ClearType::FromCursorDown => {
|
||||||
functions::write_str(&stdout, csi!("J"));
|
functions::write_str(&stdout, csi!("J"))?;
|
||||||
}
|
}
|
||||||
ClearType::FromCursorUp => {
|
ClearType::FromCursorUp => {
|
||||||
functions::write_str(&stdout, csi!("1J"));
|
functions::write_str(&stdout, csi!("1J"))?;
|
||||||
}
|
}
|
||||||
ClearType::CurrentLine => {
|
ClearType::CurrentLine => {
|
||||||
functions::write_str(&stdout, csi!("2K"));
|
functions::write_str(&stdout, csi!("2K"))?;
|
||||||
}
|
}
|
||||||
ClearType::UntilNewLine => {
|
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) {
|
fn terminal_size(&self, _stdout: &Option<&Arc<TerminalOutput>>) -> (u16, u16) {
|
||||||
functions::get_terminal_size()
|
functions::get_terminal_size()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn scroll_up(&self, count: i16, stdout: &Option<&Arc<TerminalOutput>>) {
|
fn scroll_up(&self, count: i16, stdout: &Option<&Arc<TerminalOutput>>) -> Result<()>{
|
||||||
functions::write(&stdout, format!(csi!("{}S"), count));
|
functions::write(&stdout, format!(csi!("{}S"), count))?;
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn scroll_down(&self, count: i16, stdout: &Option<&Arc<TerminalOutput>>) {
|
fn scroll_down(&self, count: i16, stdout: &Option<&Arc<TerminalOutput>>) -> Result<()> {
|
||||||
functions::write(&stdout, format!(csi!("{}T"), count));
|
functions::write(&stdout, format!(csi!("{}T"), count))?;
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
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<()> {
|
||||||
functions::write(&stdout, format!(csi!("8;{};{}t"), height, width));
|
functions::write(&stdout, format!(csi!("8;{};{}t"), height, width))?;
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn exit(&self, stdout: &Option<&Arc<TerminalOutput>>) {
|
fn exit(&self, stdout: &Option<&Arc<TerminalOutput>>) {
|
||||||
|
@ -15,7 +15,7 @@ use self::winapi_terminal::WinApiTerminal;
|
|||||||
|
|
||||||
pub use self::terminal::{from_screen, terminal, Terminal};
|
pub use self::terminal::{from_screen, terminal, Terminal};
|
||||||
|
|
||||||
use super::functions;
|
use common::{functions, error};
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use {Screen, TerminalOutput};
|
use {Screen, TerminalOutput};
|
||||||
|
|
||||||
@ -38,15 +38,15 @@ pub enum ClearType {
|
|||||||
/// so that terminal related actions can be preformed on both Unix and Windows systems.
|
/// so that terminal related actions can be preformed on both Unix and Windows systems.
|
||||||
trait ITerminal {
|
trait ITerminal {
|
||||||
/// Clear the current cursor by specifying the clear type
|
/// 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)
|
/// Get the terminal size (x,y)
|
||||||
fn terminal_size(&self, stdout: &Option<&Arc<TerminalOutput>>) -> (u16, u16);
|
fn terminal_size(&self, stdout: &Option<&Arc<TerminalOutput>>) -> (u16, u16);
|
||||||
/// Scroll `n` lines up in the current terminal.
|
/// 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.
|
/// 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.
|
/// 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
|
/// Close the current terminal
|
||||||
fn exit(&self, stdout: &Option<&Arc<TerminalOutput>>);
|
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.
|
//! Like clearing and scrolling in the terminal or getting the window size from the terminal.
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
|
use common::error::Result;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
|
||||||
/// Struct that stores a platform-specific platform implementation for terminal related actions.
|
/// 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.
|
/// // clear all cells from cursor position until new line in terminal.
|
||||||
/// term.clear(terminal::ClearType::UntilNewLine);
|
/// term.clear(terminal::ClearType::UntilNewLine);
|
||||||
/// ```
|
/// ```
|
||||||
pub fn clear(&self, clear_type: ClearType) {
|
pub fn clear(&self, clear_type: ClearType) -> Result<()> {
|
||||||
self.terminal.clear(clear_type, &self.screen);
|
self.terminal.clear(clear_type, &self.screen)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the terminal size (x,y).
|
/// Get the terminal size (x,y).
|
||||||
@ -117,8 +117,8 @@ impl<'stdout> Terminal<'stdout> {
|
|||||||
/// // scroll up by 5 lines
|
/// // scroll up by 5 lines
|
||||||
/// let size = term.scroll_up(5);
|
/// let size = term.scroll_up(5);
|
||||||
/// ```
|
/// ```
|
||||||
pub fn scroll_up(&self, count: i16) {
|
pub fn scroll_up(&self, count: i16) -> Result<()> {
|
||||||
self.terminal.scroll_up(count, &self.screen);
|
self.terminal.scroll_up(count, &self.screen)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Scroll `n` lines up in the current terminal.
|
/// Scroll `n` lines up in the current terminal.
|
||||||
@ -129,8 +129,8 @@ impl<'stdout> Terminal<'stdout> {
|
|||||||
/// // scroll down by 5 lines
|
/// // scroll down by 5 lines
|
||||||
/// let size = term.scroll_down(5);
|
/// let size = term.scroll_down(5);
|
||||||
/// ```
|
/// ```
|
||||||
pub fn scroll_down(&self, count: i16) {
|
pub fn scroll_down(&self, count: i16) -> Result<()> {
|
||||||
self.terminal.scroll_down(count, &self.screen);
|
self.terminal.scroll_down(count, &self.screen)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Set the terminal size. Note that not all terminals can be set to a very small scale.
|
/// 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
|
/// // Set of the size to X: 10 and Y: 10
|
||||||
/// let size = term.set_size(10,10);
|
/// let size = term.set_size(10,10);
|
||||||
/// ```
|
/// ```
|
||||||
pub fn set_size(&self, width: i16, height: i16) {
|
pub fn set_size(&self, width: i16, height: i16) -> Result<()> {
|
||||||
self.terminal.set_size(width, height, &self.screen);
|
self.terminal.set_size(width, height, &self.screen)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Exit the current process.
|
/// Exit the current process.
|
||||||
@ -163,11 +163,12 @@ impl<'stdout> Terminal<'stdout> {
|
|||||||
///
|
///
|
||||||
/// let size = term.write("Some text \n Some text on new line");
|
/// 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;
|
use std::fmt::Write;
|
||||||
let mut string = String::new();
|
let mut string = String::new();
|
||||||
write!(string, "{}", value).unwrap();
|
write!(string, "{}", value)?;
|
||||||
functions::write(&self.screen, string);
|
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.
|
//! Windows versions lower then windows 10 are not supporting ANSI codes. Those versions will use this implementation instead.
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
|
use common::error::{Result, ErrorKind};
|
||||||
use kernel::windows_kernel::{Console, Coord, Cursor, Handle, ScreenBuffer, Size};
|
use kernel::windows_kernel::{Console, Coord, Cursor, Handle, ScreenBuffer, Size};
|
||||||
|
|
||||||
/// This struct is an winapi implementation for terminal related actions.
|
/// This struct is an winapi implementation for terminal related actions.
|
||||||
@ -17,9 +17,9 @@ impl WinApiTerminal {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl ITerminal for WinApiTerminal {
|
impl ITerminal for WinApiTerminal {
|
||||||
fn clear(&self, clear_type: ClearType, _stdout: &Option<&Arc<TerminalOutput>>) {
|
fn clear(&self, clear_type: ClearType, _stdout: &Option<&Arc<TerminalOutput>>) -> Result<()> {
|
||||||
let screen_buffer = ScreenBuffer::current().unwrap();
|
let screen_buffer = ScreenBuffer::current()?;
|
||||||
let csbi = screen_buffer.info().unwrap();
|
let csbi = screen_buffer.info()?;
|
||||||
|
|
||||||
let pos = csbi.cursor_pos();
|
let pos = csbi.cursor_pos();
|
||||||
let buffer_size = csbi.buffer_size();
|
let buffer_size = csbi.buffer_size();
|
||||||
@ -27,13 +27,14 @@ impl ITerminal for WinApiTerminal {
|
|||||||
|
|
||||||
match clear_type {
|
match clear_type {
|
||||||
ClearType::All => {
|
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::FromCursorDown => clear_after_cursor(pos, buffer_size, current_attribute)?,
|
||||||
ClearType::FromCursorUp => clear_before_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::CurrentLine => clear_current_line(pos, buffer_size, current_attribute)?,
|
||||||
ClearType::UntilNewLine => clear_until_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) {
|
fn terminal_size(&self, _stdout: &Option<&Arc<TerminalOutput>>) -> (u16, u16) {
|
||||||
@ -41,53 +42,51 @@ impl ITerminal for WinApiTerminal {
|
|||||||
csbi.info().unwrap().terminal_size().into()
|
csbi.info().unwrap().terminal_size().into()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn scroll_up(&self, count: i16, _stdout: &Option<&Arc<TerminalOutput>>) {
|
fn scroll_up(&self, count: i16, _stdout: &Option<&Arc<TerminalOutput>>) -> Result<()> {
|
||||||
let csbi = ScreenBuffer::current().unwrap();
|
let csbi = ScreenBuffer::current()?;
|
||||||
let mut window = csbi.info().unwrap().terminal_window();
|
let mut window = csbi.info()?.terminal_window();
|
||||||
|
|
||||||
// Check whether the window is too close to the screen buffer top
|
// Check whether the window is too close to the screen buffer top
|
||||||
if window.top >= count {
|
if window.top >= count {
|
||||||
window.top -= count; // move top down
|
window.top -= count; // move top down
|
||||||
window.bottom = count; // move bottom down
|
window.bottom = count; // move bottom down
|
||||||
|
|
||||||
Console::new()
|
Console::new()?.set_console_info(false, window)?;
|
||||||
.unwrap()
|
|
||||||
.set_console_info(false, window)
|
|
||||||
.unwrap();
|
|
||||||
}
|
}
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn scroll_down(&self, count: i16, _stdout: &Option<&Arc<TerminalOutput>>) {
|
fn scroll_down(&self, count: i16, _stdout: &Option<&Arc<TerminalOutput>>) -> Result<()>{
|
||||||
let csbi = ScreenBuffer::current().unwrap();
|
let screen_buffer = ScreenBuffer::current()?;
|
||||||
let mut window = csbi.info().unwrap().terminal_window();
|
let csbi = screen_buffer.info()?;
|
||||||
let buffer_size = csbi.info().unwrap().buffer_size();
|
let mut window = csbi.terminal_window();
|
||||||
|
let buffer_size =csbi.buffer_size();
|
||||||
|
|
||||||
// Check whether the window is too close to the screen buffer top
|
// Check whether the window is too close to the screen buffer top
|
||||||
if window.bottom < buffer_size.height - count {
|
if window.bottom < buffer_size.height - count {
|
||||||
window.top += count; // move top down
|
window.top += count; // move top down
|
||||||
window.bottom += count; // move bottom down
|
window.bottom += count; // move bottom down
|
||||||
|
|
||||||
Console::new()
|
Console::new()?
|
||||||
.unwrap()
|
.set_console_info(false, window)?;
|
||||||
.set_console_info(false, window)
|
|
||||||
.unwrap();
|
|
||||||
}
|
}
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Set the current terminal size
|
/// 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 {
|
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 {
|
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
|
// 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 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 current_size = csbi.buffer_size();
|
||||||
let window = csbi.terminal_window();
|
let window = csbi.terminal_window();
|
||||||
@ -100,7 +99,7 @@ impl ITerminal for WinApiTerminal {
|
|||||||
|
|
||||||
if current_size.width < window.left + width {
|
if current_size.width < window.left + width {
|
||||||
if window.left >= i16::max_value() - width {
|
if window.left >= i16::max_value() - width {
|
||||||
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;
|
new_size.width = window.left + width;
|
||||||
@ -108,7 +107,7 @@ impl ITerminal for WinApiTerminal {
|
|||||||
}
|
}
|
||||||
if current_size.height < window.top + height {
|
if current_size.height < window.top + height {
|
||||||
if window.top >= i16::max_value() - height {
|
if window.top >= i16::max_value() - height {
|
||||||
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;
|
new_size.height = window.top + height;
|
||||||
@ -117,7 +116,7 @@ impl ITerminal for WinApiTerminal {
|
|||||||
|
|
||||||
if resize_buffer {
|
if resize_buffer {
|
||||||
if let Err(_) = screen_buffer.set_size(new_size.width, new_size.height) {
|
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.
|
// Preserve the position, but change the size.
|
||||||
window.bottom = window.top + height;
|
window.bottom = window.top + height;
|
||||||
window.right = window.left + width;
|
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 we resized the buffer, un-resize it.
|
||||||
if resize_buffer {
|
if resize_buffer {
|
||||||
if let Err(_) = screen_buffer.set_size(current_size.width, current_size.height) {
|
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();
|
let bounds = console.largest_window_size();
|
||||||
|
|
||||||
if width > bounds.x {
|
if width > bounds.x {
|
||||||
panic!(
|
return Err(ErrorKind::ResizingTerminalFailure(format!("Argument width: {} out of range when setting terminal width.", width)));
|
||||||
"Argument width: {} out of range when setting terminal width.",
|
|
||||||
width
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
if height > bounds.y {
|
if height > bounds.y {
|
||||||
panic!(
|
return Err(ErrorKind::ResizingTerminalFailure(format!("Argument height: {} out of range when setting terminal height", width)));
|
||||||
"Argument height: {} out of range when setting terminal height",
|
|
||||||
height
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn exit(&self, stdout: &Option<&Arc<TerminalOutput>>) {
|
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);
|
let (mut x, mut y) = (location.x, location.y);
|
||||||
|
|
||||||
// if cursor position is at the outer right position
|
// if cursor position is at the outer right position
|
||||||
@ -175,10 +170,10 @@ pub fn clear_after_cursor(location: Coord, buffer_size: Size, current_attribute:
|
|||||||
// get sum cells before cursor
|
// get sum cells before cursor
|
||||||
let cells_to_write = buffer_size.width as u32 * buffer_size.height as u32;
|
let cells_to_write = buffer_size.width as u32 * buffer_size.height as u32;
|
||||||
|
|
||||||
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);
|
let (xpos, ypos) = (location.x, location.y);
|
||||||
|
|
||||||
// one cell after cursor position
|
// 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);
|
let cells_to_write = (buffer_size.width as u32 * ypos as u32) + (xpos as u32 + 1);
|
||||||
|
|
||||||
// clear everything before cursor position
|
// 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
|
// get sum cells before cursor
|
||||||
let cells_to_write = buffer_size.width as u32 * buffer_size.height as u32;
|
let cells_to_write = buffer_size.width as u32 * buffer_size.height as u32;
|
||||||
|
|
||||||
@ -204,14 +199,15 @@ pub fn clear_entire_screen(buffer_size: Size, current_attribute: u16) {
|
|||||||
let start_location = Coord::new(0, 0);
|
let start_location = Coord::new(0, 0);
|
||||||
|
|
||||||
// clear the entire screen
|
// 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
|
// put the cursor back at cell 0,0
|
||||||
let cursor = Cursor::new().unwrap();
|
let cursor = Cursor::new()?;
|
||||||
cursor.goto(0, 0);
|
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
|
// location where to start clearing
|
||||||
let start_location = Coord::new(0, location.y);
|
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;
|
let cells_to_write = buffer_size.width as u32;
|
||||||
|
|
||||||
// clear the whole current line
|
// 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
|
// put the cursor back at cell 1 on current row
|
||||||
let cursor = Cursor::new().unwrap();
|
let cursor = Cursor::new()?;
|
||||||
cursor.goto(0, location.y);
|
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);
|
let (x, y) = (location.x, location.y);
|
||||||
|
|
||||||
// location where to start clearing
|
// 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;
|
let cells_to_write = (buffer_size.width - x as i16) as u32;
|
||||||
|
|
||||||
// clear until the current line
|
// 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
|
// put the cursor back at original cursor position before we did the clearing
|
||||||
let cursor = Cursor::new().unwrap();
|
let cursor = Cursor::new()?;
|
||||||
cursor.goto(x, y);
|
cursor.goto(x, y)?;
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn clear(start_location: Coord, cells_to_write: u32, current_attribute: u16) {
|
fn clear(start_location: Coord, cells_to_write: u32, current_attribute: u16) -> Result<()> {
|
||||||
let console = Console::from(Handle::current_out_handle().unwrap());
|
let console = Console::from(Handle::current_out_handle()?);
|
||||||
let _ = console
|
let _ = console
|
||||||
.fill_whit_character(start_location, cells_to_write, ' ')
|
.fill_whit_character(start_location, cells_to_write, ' ')?;
|
||||||
.unwrap();
|
|
||||||
console
|
console
|
||||||
.fill_whit_attribute(start_location, cells_to_write, current_attribute)
|
.fill_whit_attribute(start_location, cells_to_write, current_attribute)?;
|
||||||
.unwrap();
|
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user