Updated all examples and comments tested unix logic

This commit is contained in:
= 2018-08-13 21:04:07 +02:00
parent f31bb1a656
commit d23ef22a58
24 changed files with 395 additions and 229 deletions

View File

@ -15,12 +15,13 @@ extern crate crossterm;
mod some_types; mod some_types;
mod input; mod input;
fn main() { fn main() {
// call some test module function // call some test module function
terminal::terminal::resize_terminal(); // terminal::terminal::resize_terminal();
input::keyboard::async_input::read_async_demo();
use crossterm::screen::RawScreen; // use crossterm::screen::RawScreen;
// RawScreen::into_raw_mode(); // RawScreen::into_raw_mode();
// RawScreen::disable_raw_modes(); // RawScreen::disable_raw_modes();
} }

View File

@ -42,7 +42,7 @@ pub fn read_async_until() {
} }
} }
/// this will read pressed characters async until `x` is typed . /// this will read pressed characters async until `x` is typed.
pub fn read_async() { pub fn read_async() {
let input = input(&Screen::default()); let input = input(&Screen::default());

View File

@ -127,10 +127,10 @@ impl<'screen> FirstDepthSearch<'screen>
fn find_first_possible_direction(&mut self) fn find_first_possible_direction(&mut self)
{ {
// if there are no elements left in the stack that means we have visited all cell and we van terminate the program. // if there are no elements left in the stack that means we have visited all cell and we van terminate the program.
if let Some(previous_cell) = &self.stack.pop() if let &Some(previous_cell) = &self.stack.pop()
{ {
// update root pos to previous cell and continue searching for new neighbours // update root pos to previous cell and continue searching for new neighbours
self.root_pos = *previous_cell; self.root_pos = previous_cell;
self.choose_random_neighbor(); self.choose_random_neighbor();
} }
else { else {

View File

@ -33,7 +33,7 @@ fn print_wait_screen(screen: &Screen) {
} }
} }
/// print wait screen on alternate screen, then swich back. /// print wait screen on alternate screen, then switch back.
pub fn print_wait_screen_on_alternate_window() { pub fn print_wait_screen_on_alternate_window() {
let screen = Screen::default(); let screen = Screen::default();

View File

@ -22,56 +22,139 @@ use common::commands::win_commands;
use write::Stdout; use write::Stdout;
/// This type could be used to access the `cursor, terminal, color, input, styling` module more easily.
/// You need to pass a reference to the screen where on you want to perform the actions.
///
///
/// #Example
/// If you want to use the default screen you could do it like this:
///
/// ```rust
///
/// extern crate crossterm;
/// use crossterm::{Crossterm, Screen};
///
/// let crossterm = Crossterm::new();
/// let cursor = crossterm.cursor(&Screen::default());
///
/// ```
///
/// If you want to perform actions on the `AlternateScreen` make sure to pass a refrence to the screen of the `AlternateScreen`.
///
/// ```
/// /// extern crate crossterm;
/// use crossterm::{Crossterm, Screen};
///
/// let main_screen = Screen::default();
///
/// if let Ok(alternate_srceen) = main_screen.enable_alternate_modes(false)
/// {
/// let crossterm = Crossterm::new();
/// let cursor = crossterm.cursor(&alternate_screen.screen);
/// }
///
/// ```
pub struct Crossterm { } pub struct Crossterm { }
impl<'crossterm> Crossterm { impl<'crossterm> Crossterm {
/// Create a new instance of `Crossterm`
pub fn new() -> Crossterm { pub fn new() -> Crossterm {
Crossterm {} Crossterm {}
} }
/// Get an TerminalCursor implementation whereon cursor related actions can be performed.
///
/// #Example
///
/// ```rust
///
/// extern crate crossterm;
/// use crossterm::{Crossterm, Screen};
///
/// let crossterm = Crossterm::new();
/// let cursor = crossterm.cursor(&Screen::default());
///
/// ```
pub fn cursor(&self, screen: &'crossterm Screen) -> cursor::TerminalCursor { pub fn cursor(&self, screen: &'crossterm Screen) -> cursor::TerminalCursor {
cursor::TerminalCursor::new(&screen.stdout.clone()) cursor::TerminalCursor::new(&screen.stdout.clone())
} }
/// Get an TerminalInput implementation whereon terminal related actions can be performed.
///
/// #Example
///
/// ```rust
///
/// extern crate crossterm;
/// use crossterm::{Crossterm, Screen};
/// use crossterm::terminal;
///
/// let crossterm = Crossterm::new();
/// let input = crossterm.input(&Screen::default());
///
/// ```
pub fn input(&self, screen: &'crossterm Screen) -> input::TerminalInput { pub fn input(&self, screen: &'crossterm Screen) -> input::TerminalInput {
return input::TerminalInput::new(&screen.stdout); return input::TerminalInput::new(&screen.stdout);
} }
/// Get an Terminal implementation whereon terminal related actions can be performed.
///
/// #Example
///
/// ```rust
///
/// extern crate crossterm;
/// use crossterm::{Crossterm, Screen};
///
/// let crossterm = Crossterm::new();
/// let mut terminal = crossterm.terminal(&Screen::default());
///
/// ```
pub fn terminal(&self, screen: &'crossterm Screen) -> terminal::Terminal { pub fn terminal(&self, screen: &'crossterm Screen) -> terminal::Terminal {
return terminal::Terminal::new(&screen.stdout); return terminal::Terminal::new(&screen.stdout);
} }
/// Get an TerminalColor implementation whereon color related actions can be performed.
///
/// #Example
///
/// ```rust
///
/// extern crate crossterm;
/// use crossterm::{Crossterm, Screen};
///
/// let crossterm = Crossterm::new();
/// let mut terminal = crossterm.terminal(&Screen::default());
///
/// ```
pub fn color(&self, screen: &'crossterm Screen) -> style::TerminalColor { pub fn color(&self, screen: &'crossterm Screen) -> style::TerminalColor {
return style::TerminalColor::new(&screen.stdout); return style::TerminalColor::new(&screen.stdout);
} }
// Wraps an displayable object so it can be formatted with colors and attributes. /// This could be used to style an Displayable with colors and attributes.
// ///
// Check `/examples/color` in the libary for more spesific examples. /// #Example
///
/// ```rust
///
/// use crossterm::{ Screen };
///
/// // get an styled object which could be painted to the terminal.
/// let styled_object = style("Some Blue colored text on black background").with(Color::Blue).on(Color::Black);
///
/// // create an default screen.
/// let screen = Screen::default();
///
/// // print the styled font * times to the current screen.
/// for i in 1..10
/// {
/// styled_object.paint(&screen);
/// }
/// ```
pub fn style<D>(&self, val: D) -> style::StyledObject<D> pub fn style<D>(&self, val: D) -> style::StyledObject<D>
where where
D: Display, { D: Display, {
style::ObjectStyle::new().apply_to(val) style::ObjectStyle::new().apply_to(val)
} }
} }
//impl Write for Crossterm {M
// fn write(&mut self, buf: &[u8]) -> Result<usize> {
// self.active_screen.write_buf(buf)
// }
//
// fn flush(&mut self) -> Result<()> {
// self.active_screen.flush()
// }
//}
//
//impl Drop for Crossterm {
// fn drop(&mut self) {
// if let Some(ref mut screen) = self.alternate_screen {
// screen.disable(&mut self.active_screen);
// }
// if let Some(ref mut raw_terminal) = self.raw_terminal {
// raw_terminal.disable();
// }
// }
//}

View File

@ -49,16 +49,19 @@ pub fn get_module<T>(winapi_impl: T, unix_impl: T) -> Option<T> {
if cfg!(target_os = "windows") { if cfg!(target_os = "windows") {
#[cfg(windows)] #[cfg(windows)]
use kernel::windows_kernel::ansi_support::try_enable_ansi_support; use kernel::windows_kernel::ansi_support::{try_enable_ansi_support, windows_supportable};
// Try to enable ansi on windows if not than use WINAPI. if !windows_supportable()
does_support = try_enable_ansi_support(); {
// 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. // 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 {

View File

@ -5,22 +5,6 @@
//! The alternate buffer is exactly the dimensions of the window, without any scrollback region. //! The alternate buffer is exactly the dimensions of the window, without any scrollback region.
//! For an example of this behavior, consider when vim is launched from bash. //! For an example of this behavior, consider when vim is launched from bash.
//! Vim uses the entirety of the screen to edit the file, then returning to bash leaves the original buffer unchanged. //! Vim uses the entirety of the screen to edit the file, then returning to bash leaves the original buffer unchanged.
//!
//!
//! When using alternate screen there is one thing to keep in mind.
//! To get the functionalities of `cursor, color, terminal` also working on alternate screen.
//! You need to pass it the same `Context` as you have passed to the previous three functions,
//! If you don't use the same `Context` the `cursor(), color(), terminal()` these modules will be using main screen to write to.
//! So you will see nothing on alternate screen.
//!
//!
//! When you want to switch to alternate screen there are a couple of things to keep in mind for it to work correctly.
//! First off some code of how to switch to Alternate screen, for more info check the example folder at github
//! Create alternate screen from `Crossterm`:
//!
//!
//! Todo: example
//!
use super::commands::{self, IAlternateScreenCommand}; use super::commands::{self, IAlternateScreenCommand};
use super::{functions, Screen, Stdout, RawScreen}; use super::{functions, Screen, Stdout, RawScreen};
@ -29,6 +13,7 @@ use std::convert::From;
use std::io::{self, Write}; use std::io::{self, Write};
use std::sync::Mutex; use std::sync::Mutex;
/// With this type you will be able to switch to alternate screen and back to main screen.
pub struct AlternateScreen pub struct AlternateScreen
{ {
command: Box<IAlternateScreenCommand + Send>, command: Box<IAlternateScreenCommand + Send>,
@ -37,11 +22,19 @@ pub struct AlternateScreen
impl AlternateScreen { impl AlternateScreen {
/// Create new instance of alternate screen.
pub fn new(command: Box<IAlternateScreenCommand + Send>, screen: Screen) -> Self pub fn new(command: Box<IAlternateScreenCommand + Send>, screen: Screen) -> Self
{ {
return AlternateScreen { command, screen } return AlternateScreen { command, screen }
} }
/// Switch to alternate screen. This function will return an `AlternateScreen` instance if everything went well this type will give you control over the `AlternateScreen`.
///
/// # What is Alternate screen?
/// *Nix style applications often utilize an alternate screen buffer, so that they can modify the entire contents of the buffer, without affecting the application that started them.
/// The alternate buffer is exactly the dimensions of the window, without any scrollback region.
/// For an example of this behavior, consider when vim is launched from bash.
/// Vim uses the entirety of the screen to edit the file, then returning to bash leaves the original buffer unchanged.
pub fn to_alternate_screen(screen_manager: Stdout) -> io::Result<AlternateScreen> { pub fn to_alternate_screen(screen_manager: Stdout) -> io::Result<AlternateScreen> {
#[cfg(target_os = "windows")] #[cfg(target_os = "windows")]
let command = functions::get_module::<Box<commands::IAlternateScreenCommand + Send>>( let command = functions::get_module::<Box<commands::IAlternateScreenCommand + Send>>(
@ -57,6 +50,7 @@ impl AlternateScreen {
return Ok(AlternateScreen::new(command, Screen::from(stdout))); return Ok(AlternateScreen::new(command, Screen::from(stdout)));
} }
/// Switch the alternate screen back to main screen.
pub fn to_main_screen(&self) -> io::Result<()> { pub fn to_main_screen(&self) -> io::Result<()> {
self.command.disable(&self.screen.stdout)?; self.command.disable(&self.screen.stdout)?;
Ok(()) Ok(())
@ -65,8 +59,8 @@ impl AlternateScreen {
impl Drop for AlternateScreen impl Drop for AlternateScreen
{ {
/// 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();
} }
} }

View File

@ -9,6 +9,8 @@
//! - Characters //! - Characters
//! The characters are not processed by the terminal driver, but are sent straight through. //! The characters are not processed by the terminal driver, but are sent straight through.
//! Special character have no meaning, like backspace will not be interpret as backspace but instead will be directly send to the terminal. //! Special character have no meaning, like backspace will not be interpret as backspace but instead will be directly send to the terminal.
//! - Escape characters
//! Note that in raw modes `\n` will move to the new line but the cursor will be at the same position as before on the new line therefor use `\n\r` to start at the new line at the first cell.
//! //!
//! With these modes you can easier design the terminal screen. //! With these modes you can easier design the terminal screen.
@ -18,16 +20,10 @@ use super::{functions, Screen, Stdout};
use std::io::{self, Write}; use std::io::{self, Write};
/// A wrapper for the raw terminal state. Which can be used to write to. /// A wrapper for the raw terminal state. Which can be used to write to.
pub struct RawScreen pub struct RawScreen;
{
// #[cfg(not(target_os = "windows"))]
// command: unix_command::RawModeCommand,
// #[cfg(not(target_os = "windows"))]
// command: win_commands::RawModeCommand,
}
impl RawScreen { impl RawScreen {
/// Put terminal in raw mode.
pub fn into_raw_mode() -> io::Result<()> pub fn into_raw_mode() -> io::Result<()>
{ {
#[cfg(not(target_os = "windows"))] #[cfg(not(target_os = "windows"))]
@ -35,12 +31,11 @@ impl RawScreen {
#[cfg(target_os = "windows")] #[cfg(target_os = "windows")]
let mut command = win_commands::RawModeCommand::new(); let mut command = win_commands::RawModeCommand::new();
// command::new();
command.enable()?; command.enable()?;
Ok(()) Ok(())
} }
/// Put terminal back in original modes.
pub fn disable_raw_modes() -> io::Result<()> pub fn disable_raw_modes() -> io::Result<()>
{ {
#[cfg(not(target_os = "windows"))] #[cfg(not(target_os = "windows"))]
@ -48,9 +43,7 @@ impl RawScreen {
#[cfg(target_os = "windows")] #[cfg(target_os = "windows")]
let mut command = win_commands::RawModeCommand::new(); let mut command = win_commands::RawModeCommand::new();
let a = command.disable(); command.disable()?;
return Ok(()) return Ok(())
} }
} }

View File

@ -13,6 +13,42 @@ use std::io::Write;
use std::io::Result; use std::io::Result;
use std::sync::Arc; use std::sync::Arc;
/// This type represents an screen.
/// This screen has an stdout which is used by the program to write to or to execute commands with.
///
/// You have to make sure that you pass the correct `Screen` to the modules `cursor, terminal, color, input, style`.
/// Most of the time you just have one screen so you could get an instance of that screen with: `Screen::default()`.
///
/// Also this screen has an buffer where you can write to. When you want to write the buffer to the screen you could flush the screen.
///
/// #Example
///
/// ```rust
/// // create default screen.
/// let screen = Screen::default();
/// // create raw screen.
/// let mut screen = Screen::new(true);
///
/// // write some text to the internal buffer of this type.
/// screen.write(b"Some text");
/// screen.write(b"Some more text");
/// screen.write(b"Some more text");
///
/// // write the above text by flushing the internal buffer of this type.
/// screen.flush();
///
/// // create raw alternate screen from normal screen.
/// let screen = Screen::new();
///
/// if let Ok(alternate_screen) = screen.enable_alternate_modes(true)
/// {
/// let crossterm = Crossterm::new();
///
/// // make sure to pass in the screen of the AlternateScreen.
/// crossterm.cursor(&alternate_screen.screen);
/// }
/// ```
///
pub struct Screen pub struct Screen
{ {
buffer: Vec<u8>, buffer: Vec<u8>,
@ -21,6 +57,8 @@ pub struct Screen
impl Screen impl Screen
{ {
/// Create new instance of the Screen also specify if the current screen should be in raw mode or normal mode. Check out `RawScreen` type for more info.
/// If you are not sure what raw mode is then pass false or use the `Screen::default()` to create an instance.
pub fn new(raw_mode: bool) -> Screen pub fn new(raw_mode: bool) -> Screen
{ {
if raw_mode if raw_mode
@ -32,16 +70,33 @@ impl Screen
return Screen::default(); return Screen::default();
} }
pub fn from(stdout: Stdout) -> Screen /// This method could be used for enabling raw mode for the terminal.
{ ///
return Screen { stdout: Arc::new(stdout), buffer: Vec::new() }; /// What exactly is raw state:
} /// - No line buffering.
/// Normally the terminals uses line buffering. This means that the input will be send to the terminal line by line.
/// With raw mode the input will be send one byte at a time.
/// - Input
/// All input has to be written manually by the programmer.
/// - Characters
/// The characters are not processed by the terminal driver, but are sent straight through.
/// Special character have no meaning, like backspace will not be interpret as backspace but instead will be directly send to the terminal.
/// - Escape characters
/// Note that in raw modes `\n` will move to the new line but the cursor will be at the same position as before on the new line therefor use `\n\r` to start at the new line at the first cell.
///
/// With these modes you can easier design the terminal screen.
pub fn enable_raw_modes(&self) -> Result<()> { pub fn enable_raw_modes(&self) -> Result<()> {
RawScreen::into_raw_mode()?; RawScreen::into_raw_mode()?;
return Ok(()) return Ok(())
} }
/// Switch to alternate screen. This function will return an `AlternateScreen` instance if everything went well this type will give you control over the `AlternateScreen`.
///
/// # What is Alternate screen?
/// *Nix style applications often utilize an alternate screen buffer, so that they can modify the entire contents of the buffer, without affecting the application that started them.
/// The alternate buffer is exactly the dimensions of the window, without any scrollback region.
/// For an example of this behavior, consider when vim is launched from bash.
/// Vim uses the entirety of the screen to edit the file, then returning to bash leaves the original buffer unchanged.
pub fn enable_alternate_modes(&self, raw_mode: bool) -> Result<AlternateScreen> { pub fn enable_alternate_modes(&self, raw_mode: bool) -> Result<AlternateScreen> {
let mut stdout = Stdout::new(raw_mode); let mut stdout = Stdout::new(raw_mode);
@ -55,8 +110,25 @@ impl Screen
} }
} }
impl From<Stdout> for Screen
{
/// Create an screen with the given `Stdout`
fn from(stdout: Stdout) -> Self {
return Screen { stdout: Arc::new(stdout), buffer: Vec::new() };
}
}
impl From<Arc<Stdout>> for Screen
{
/// Create an screen with the given 'Arc<Stdout>'
fn from(stdout: Arc<Stdout>) -> Self {
return Screen { stdout: stdout, buffer: Vec::new() };
}
}
impl Default for Screen impl Default for Screen
{ {
/// Create an new screen which will not be in raw mode or alternate mode.
fn default() -> Self { fn default() -> Self {
return Screen { stdout: Arc::new(Stdout::new(false)), buffer: Vec::new() }; return Screen { stdout: Arc::new(Stdout::new(false)), buffer: Vec::new() };
} }
@ -64,6 +136,7 @@ impl Default for Screen
impl Drop for Screen impl Drop for Screen
{ {
/// If the current screen is in raw mode whe 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 if self.stdout.is_in_raw_mode
{ {
@ -74,11 +147,15 @@ impl Drop for Screen
impl Write for Screen impl Write for Screen
{ {
/// Write buffer to an internal buffer. When you want to write the buffer to screen use `flush()`.
///
/// This function is useful if you want to build up some output and when you are ready you could flush the output to the screen.
fn write(&mut self, buf: &[u8]) -> Result<usize> { fn write(&mut self, buf: &[u8]) -> Result<usize> {
self.buffer.write(buf); self.buffer.write(buf);
Ok(buf.len()) Ok(buf.len())
} }
/// Flush the internal buffer to the screen.
fn flush(&mut self) -> Result<()> { fn flush(&mut self) -> Result<()> {
self.stdout.write_buf(&self.buffer); self.stdout.write_buf(&self.buffer);
self.stdout.flush() self.stdout.flush()

View File

@ -9,6 +9,7 @@ use std::fmt::Display;
use std::io::Write; use std::io::Write;
use std::sync::Arc; use std::sync::Arc;
/// Struct that stores an specific platform implementation for cursor related actions. /// Struct that stores an specific platform implementation for cursor related actions.
/// ///
/// Check `/examples/version/cursor` in the library for more specific examples. /// Check `/examples/version/cursor` in the library for more specific examples.
@ -17,22 +18,19 @@ use std::sync::Arc;
/// ///
/// ```rust /// ```rust
/// ///
/// extern crate crossterm; /// extern crate crossterm;
/// use self::crossterm::Crossterm; /// use self::crossterm::cursor::cursor;
/// ///
/// let term = Crossterm::new(); /// let mut cursor = cursor();
/// let mut cursor = term.cursor();
/// ///
/// // Get cursor and goto pos X: 5, Y: 10 /// // Get cursor and goto pos X: 5, Y: 10
/// cursor.goto(5,10); /// cursor.goto(5,10);
/// ///
/// cursor.show(); /// cursor.show();
/// cursor.hide(); /// cursor.hide();
/// cursor.blink(true); /// cursor.blink(true);
/// cursor.move_left(2); /// cursor.move_left(2);
/// ///
/// // or in one line
/// cursor.goto(5,5).move_left(2).move_right(2).print("10");
/// ``` /// ```
pub struct TerminalCursor { pub struct TerminalCursor {
screen: Arc<Stdout>, screen: Arc<Stdout>,
@ -62,11 +60,10 @@ impl TerminalCursor {
/// ///
/// ```rust /// ```rust
/// ///
/// let crossterm = Crossterm::new(); /// let cursor = cursor(&Screen::default());
/// let cursor = crossterm.cursor();
/// ///
/// // change the cursor to position, x: 4 and y: 5 /// // change the cursor to position, x: 4 and y: 5
/// cursor.goto(4,5); /// cursor.goto(4,5);
/// ///
/// ``` /// ```
pub fn goto(&self, x: u16, y: u16) { pub fn goto(&self, x: u16, y: u16) {
@ -78,12 +75,11 @@ impl TerminalCursor {
/// #Example /// #Example
/// ///
/// ```rust /// ```rust
///
/// let cursor = cursor(&Screen::default());
/// ///
/// let crossterm = Crossterm::new(); /// // get the current cursor pos
/// let cursor = crossterm.cursor(); /// let (x,y) = cursor.pos();
///
/// // get the current cursor pos
/// let (x,y) = cursor.pos();
/// ///
/// ``` /// ```
pub fn pos(&self) -> (u16, u16) { pub fn pos(&self) -> (u16, u16) {
@ -95,11 +91,9 @@ impl TerminalCursor {
/// ///
/// ```rust /// ```rust
/// ///
/// let crossterm = Crossterm::new(); /// let cursor = cursor(&Screen::default());
/// let cursor = crossterm.cursor(); /// // Move the cursor to position 3 times to the up in the terminal
/// /// cursor.move_up(3);
/// // Move the cursor to position 3 times to the up in the terminal
/// cursor.move_up(3);
/// ///
/// ``` /// ```
pub fn move_up(&mut self, count: u16) -> &mut TerminalCursor { pub fn move_up(&mut self, count: u16) -> &mut TerminalCursor {
@ -113,10 +107,10 @@ impl TerminalCursor {
/// ///
/// ```rust /// ```rust
/// ///
/// let crossterm = Crossterm::new(); /// let cursor = cursor(&Screen::default());
/// let cursor = crossterm.cursor(); ///
/// // Move the cursor to position 3 times to the right in the terminal /// // Move the cursor to position 3 times to the right in the terminal
/// cursor.move_right(3); /// cursor.move_right(3);
/// ///
/// ``` /// ```
pub fn move_right(&mut self, count: u16) -> &mut TerminalCursor { pub fn move_right(&mut self, count: u16) -> &mut TerminalCursor {
@ -130,11 +124,10 @@ impl TerminalCursor {
/// ///
/// ```rust /// ```rust
/// ///
/// let crossterm = Crossterm::new(); /// let cursor = cursor(&Screen::default());
/// let cursor = crossterm.cursor();
/// ///
/// // Move the cursor to position 3 times to the down in the terminal /// // Move the cursor to position 3 times to the down in the terminal
/// cursor.move_down(3); /// cursor.move_down(3);
/// ///
/// ``` /// ```
pub fn move_down(&mut self, count: u16) -> &mut TerminalCursor { pub fn move_down(&mut self, count: u16) -> &mut TerminalCursor {
@ -148,8 +141,7 @@ impl TerminalCursor {
/// ///
/// ```rust /// ```rust
/// ///
/// let crossterm = Crossterm::new(); /// let cursor = cursor(&Screen::default());
/// let cursor = crossterm.cursor();
/// ///
/// // Move the cursor to position 3 times to the left in the terminal /// // Move the cursor to position 3 times to the left in the terminal
/// cursor.move_left(3); /// cursor.move_left(3);
@ -168,9 +160,7 @@ impl TerminalCursor {
/// ///
/// ```rust /// ```rust
/// ///
/// let crossterm = Crossterm::new(); /// let cursor = cursor(&Screen::default());
/// let cursor = crossterm.cursor();
///
/// cursor.safe_position(); /// cursor.safe_position();
/// ///
/// ``` /// ```
@ -186,9 +176,7 @@ impl TerminalCursor {
/// ///
/// ```rust /// ```rust
/// ///
/// let crossterm = Crossterm::new(); /// let cursor = cursor(&Screen::default());
/// let cursor = crossterm.cursor();
///
/// cursor.reset_position(); /// cursor.reset_position();
/// ///
/// ``` /// ```
@ -202,9 +190,7 @@ impl TerminalCursor {
/// ///
/// ```rust /// ```rust
/// ///
/// let crossterm = Crossterm::new(); /// let cursor = cursor(&Screen::default());
/// let cursor = crossterm.cursor();
///
/// cursor.hide(); /// cursor.hide();
/// ///
/// ``` /// ```
@ -218,9 +204,7 @@ impl TerminalCursor {
/// ///
/// ```rust /// ```rust
/// ///
/// let crossterm = Crossterm::new(); /// let cursor = cursor(&Screen::default());
/// let cursor = crossterm.cursor();
///
/// cursor.show(); /// cursor.show();
/// ///
/// ``` /// ```
@ -236,9 +220,7 @@ impl TerminalCursor {
/// ///
/// ```rust /// ```rust
/// ///
/// let crossterm = Crossterm::new(); /// let cursor = cursor(&Screen::default());
/// let cursor = crossterm.cursor();
///
/// cursor.blink(true); /// cursor.blink(true);
/// cursor.blink(false); /// cursor.blink(false);
/// ///
@ -249,6 +231,7 @@ impl TerminalCursor {
} }
/// Get an TerminalCursor implementation whereon cursor related actions can be performed. /// Get an TerminalCursor implementation whereon cursor related actions can be performed.
/// Pass the reference to any screen you want this type to perform actions on.
pub fn cursor(screen_manager: &Screen) -> TerminalCursor { pub fn cursor(screen_manager: &Screen) -> TerminalCursor {
TerminalCursor::new(&screen_manager.stdout) TerminalCursor::new(&screen_manager.stdout)
} }

View File

@ -45,6 +45,6 @@ pub trait ITerminalCursor {
fn hide(&self, screen_manager: &Arc<Stdout>); fn hide(&self, screen_manager: &Arc<Stdout>);
/// Show the terminal cursor /// Show the terminal cursor
fn show(&self, screen_manager: &Arc<Stdout>); fn show(&self, screen_manager: &Arc<Stdout>);
/// enable or disable the blinking of the cursor. /// Enable or disable the blinking of the cursor.
fn blink(&self, blink: bool, screen_manager: &Arc<Stdout>); fn blink(&self, blink: bool, screen_manager: &Arc<Stdout>);
} }

View File

@ -7,18 +7,16 @@ use super::*;
/// Struct that stores an specific platform implementation for input related actions. /// Struct that stores an specific platform implementation for input related actions.
/// ///
/// Check `/examples/version/input` the examples folder on github for more info. /// Check `/examples/input` the examples folder on github for more info.
/// ///
/// #Example /// #Example
/// ///
/// ```rust /// ```rust
/// ///
/// extern crate crossterm; /// extern crate crossterm;
/// use self::crossterm::Crossterm; /// use self::crossterm::input::input;
///
/// let crossterm = Crossterm::new();
/// let input = crossterm.input();
/// ///
/// let input = input(&Screen::default());
/// let result = input.read_line(); /// let result = input.read_line();
/// let pressed_char = input.read_char(); /// let pressed_char = input.read_char();
/// ///
@ -48,8 +46,8 @@ impl TerminalInput{
/// #Example /// #Example
/// ///
/// ```rust /// ```rust
/// let crossterm = Crossterm::new(); ///
/// match crossterm.input().read_line() { /// match input(&Screen::default()).read_line() {
/// Ok(s) => println!("string typed: {}", s), /// Ok(s) => println!("string typed: {}", s),
/// Err(e) => println!("error: {}", e), /// Err(e) => println!("error: {}", e),
/// } /// }
@ -64,11 +62,11 @@ impl TerminalInput{
/// #Example /// #Example
/// ///
/// ```rust /// ```rust
/// let crossterm = Crossterm::new(); ///
/// match crossterm.input().read_char() { /// match crossterm.input(&Screen::default()).read_char() {
/// Ok(c) => println!("character pressed: {}", c), /// Ok(c) => println!("character pressed: {}", c),
/// Err(e) => println!("error: {}", e), /// Err(e) => println!("error: {}", e),
// } /// }
/// ///
/// ``` /// ```
pub fn read_char(&self) -> io::Result<char> { pub fn read_char(&self) -> io::Result<char> {
@ -80,12 +78,14 @@ impl TerminalInput{
/// #Example /// #Example
/// ///
/// ```rust /// ```rust
/// let crossterm = Crossterm::new(); ///
/// use crossterm::{Crossterm, Screen}
/// ///
/// // we need to enable raw mode otherwise the characters will be outputted by default before we are able to read them. /// // we need to enable raw mode otherwise the characters will be outputted by default before we are able to read them.
/// crossterm.enable_raw_mode(); /// let screen = Screen::new(true);
/// let crossterm = Crossterm::new();
/// ///
/// let mut stdin = crossterm.input().read_async().bytes(); /// let mut stdin = crossterm.input(&screen).read_async().bytes();
/// ///
/// for i in 0..100 { /// for i in 0..100 {
/// ///
@ -112,13 +112,14 @@ impl TerminalInput{
/// #Example /// #Example
/// ///
/// ```rust /// ```rust
/// let crossterm = Crossterm::new();
/// let input = crossterm.input();
/// let terminal = crossterm.terminal();
/// let mut cursor = crossterm.cursor();
///
/// // we need to enable raw mode otherwise the characters will be outputted by default before we are able to read them. /// // we need to enable raw mode otherwise the characters will be outputted by default before we are able to read them.
/// crossterm.enable_raw_mode(); /// let screen = Screen::new(true);
///
/// let crossterm = Crossterm::new();
/// let input = crossterm.input(&screen);
/// let terminal = crossterm.terminal(&screen);
/// let mut cursor = crossterm.cursor(&screen);
///
/// ///
/// let mut stdin = input.read_until_async(b'\r').bytes(); /// let mut stdin = input.read_until_async(b'\r').bytes();
/// ///
@ -149,6 +150,7 @@ impl TerminalInput{
} }
/// Get an Terminal Input implementation whereon input related actions can be performed. /// Get an Terminal Input implementation whereon input related actions can be performed.
/// Pass the reference to any screen you want this type to perform actions on.
pub fn input(stdout: &Screen) -> TerminalInput { pub fn input(stdout: &Screen) -> TerminalInput {
return TerminalInput::new(&stdout.stdout); return TerminalInput::new(&stdout.stdout);
} }

View File

@ -16,7 +16,7 @@ use self::windows_input::WindowsInput;
pub use self::input::{input, TerminalInput}; pub use self::input::{input, TerminalInput};
use super::Stdout; use super::Stdout;
use std::io::{self, Read}; use std::io::{self, Read, Error, ErrorKind};
use std::sync::{mpsc, Arc}; use std::sync::{mpsc, Arc};
use Screen; use Screen;
@ -60,13 +60,13 @@ impl Read for AsyncReader {
break; break;
} }
match self.recv.try_recv() { match self.recv.try_iter().next() {
Ok(Ok(b)) => { Some(Ok(value)) => {
buf[total] = b; buf[total] = value;
total += 1; total += 1;
} },
Ok(Err(e)) => return Err(e), _ => return Err(Error::new(ErrorKind::Other, "No characters pressed.")),
Err(_) => break,
} }
} }

View File

@ -13,8 +13,8 @@ use Screen;
/// ///
/// ```rust /// ```rust
/// ///
/// let crossterm = Crossterm::new(); /// use crossterm::{Screen, Crossterm}
/// let colored_terminal = crossterm.color(); /// let colored_terminal = crossterm.color(&Screen::default());
/// ///
/// // set foreground color /// // set foreground color
/// colored_terminal.set_fg(Color::Red); /// colored_terminal.set_fg(Color::Red);
@ -52,8 +52,7 @@ impl<'terminal> TerminalColor {
/// #Example /// #Example
/// ///
/// ```rust /// ```rust
/// let crossterm = Crossterm::new(); /// let colored_terminal = crossterm.color(&Screen::default());
/// let colored_terminal = crossterm.color();
/// ///
/// // Set foreground color of the font /// // Set foreground color of the font
/// colored_terminal.set_fg(Color::Red); /// colored_terminal.set_fg(Color::Red);
@ -71,8 +70,7 @@ impl<'terminal> TerminalColor {
/// ///
/// ```rust /// ```rust
/// ///
/// let crossterm = Crossterm::new(); /// let colored_terminal = crossterm.color(&Screen::default());
/// let colored_terminal = crossterm.color();
/// ///
/// // Set background color of the font /// // Set background color of the font
/// colored_terminal.set_bg(Color::Red); /// colored_terminal.set_bg(Color::Red);
@ -89,9 +87,7 @@ impl<'terminal> TerminalColor {
/// ///
/// ```rust /// ```rust
/// ///
/// let crossterm = Crossterm::new(); /// let colored_terminal = crossterm.color(&Screen::default());
/// let colored_terminal = crossterm.color();
///
/// colored_terminal.reset(); /// colored_terminal.reset();
/// ///
/// ``` /// ```
@ -117,6 +113,7 @@ impl<'terminal> TerminalColor {
} }
/// Get an Terminal Color implementation whereon color related actions can be performed. /// Get an Terminal Color implementation whereon color related actions can be performed.
/// Pass the reference to any screen you want this type to perform actions on.
pub fn color(screen: &Screen) -> TerminalColor { pub fn color(screen: &Screen) -> TerminalColor {
TerminalColor::new(&screen.stdout) TerminalColor::new(&screen.stdout)
} }

View File

@ -41,6 +41,26 @@ pub trait ITerminalColor {
fn color_value(&self, color: Color, color_type: ColorType) -> String; fn color_value(&self, color: Color, color_type: ColorType) -> String;
} }
/// This could be used to style an Displayable with colors and attributes.
///
/// #Example
///
/// ```rust
///
/// use crossterm::Screen;
///
/// // get an styled object which could be painted to the terminal.
/// let styled_object = style("Some Blue colored text on black background").with(Color::Blue).on(Color::Black);
///
/// // create an default screen.
/// let screen = Screen::default();
///
/// // print the styled font * times to the current screen.
/// for i in 1..10
/// {
/// styled_object.paint(&screen);
/// }
/// ```
pub fn style<D>(val: D) -> StyledObject<D> pub fn style<D>(val: D) -> StyledObject<D>
where where
D: Display, { D: Display, {
@ -105,12 +125,14 @@ pub enum ColorType {
} }
impl<'a> From<&'a str> for Color { impl<'a> From<&'a str> for Color {
/// Get an color from an &str like `Color::from("blue")`
fn from(src: &str) -> Self { fn from(src: &str) -> Self {
src.parse().unwrap_or(Color::White) src.parse().unwrap_or(Color::White)
} }
} }
impl From<String> for Color { impl From<String> for Color {
/// Get an color from an &str like `Color::from(String::from(blue))`
fn from(src: String) -> Self { fn from(src: String) -> Self {
src.parse().unwrap_or(Color::White) src.parse().unwrap_or(Color::White)
} }
@ -119,6 +141,7 @@ impl From<String> for Color {
impl FromStr for Color { impl FromStr for Color {
type Err = (); type Err = ();
/// Convert a string to an Color value
fn from_str(src: &str) -> Result<Self, Self::Err> { fn from_str(src: &str) -> Result<Self, Self::Err> {
let src = src.to_lowercase(); let src = src.to_lowercase();

View File

@ -24,19 +24,21 @@ impl<D: Display> StyledObject<D> {
/// #Example /// #Example
/// ///
/// ```rust /// ```rust
/// extern crate crossterm; /// use self::crossterm::style::{style,Color};
/// use self::crossterm::style::{paint,Color};
/// ///
/// // create an styled object with the foreground color red. /// // create an styled object with the foreground color red.
/// let styledobject = paint("I am colored red").with(Color::Red); /// let styledobject = style("Some colored text").with(Color::Blue);
/// // create an styled object with the foreground color blue. /// // create an styled object with the foreground color blue.
/// let styledobject1 = paint("I am colored blue").with(Color::Blue); /// let styledobject1 = style("Some colored text").with(Color::Blue);
///
/// let screen = Screen::default();
/// ///
/// // print the styledobject to see the result /// // print the styledobject to see the result
/// println!("{}", styledobject); /// styledobject.paint(&screen);
/// println!("{}", styledobject1); /// styledobject1.paint(&screen);
///
/// // print an styled object directly. /// // print an styled object directly.
/// println!("{}", paint("I am colored green").with(Color::Green)); /// style("Some colored text").with(Color::Blue).paint(&screen);
/// ///
/// ``` /// ```
pub fn with(mut self, foreground_color: Color) -> StyledObject<D> { pub fn with(mut self, foreground_color: Color) -> StyledObject<D> {
@ -49,19 +51,21 @@ impl<D: Display> StyledObject<D> {
/// #Example /// #Example
/// ///
/// ```rust /// ```rust
/// extern crate crossterm; /// use self::crossterm::style::{style,Color};
/// use self::crossterm::style::{paint,Color};
/// ///
/// // create an styled object with the background color red. /// // create an styled object with the background color red.
/// let styledobject = paint("I am colored red").on(Color::Red); /// let styledobject = style("Some colored text").on(Color::Blue);
/// // create an styled object with the background color blue. /// // create an styled object with the foreground color blue.
/// let styledobject1 = paint("I am colored blue").on(Color::Blue); /// let styledobject1 = style("Some colored text").on(Color::Blue);
///
/// let screen = Screen::default();
///
/// // print the styledobject to see the result
/// styledobject.paint(&screen);
/// styledobject1.paint(&screen);
/// ///
/// // print the styledobjects
/// println!("{}", styledobject);
/// println!("{}", styledobject1);
/// // print an styled object directly. /// // print an styled object directly.
/// println!("{}", paint("I am colored green").on(Color::Green)) /// style("Some colored text").on(Color::Blue).paint(&screen);
/// ///
/// ``` /// ```
pub fn on(mut self, background_color: Color) -> StyledObject<D> { pub fn on(mut self, background_color: Color) -> StyledObject<D> {
@ -76,9 +80,9 @@ impl<D: Display> StyledObject<D> {
/// ```rust /// ```rust
/// ///
/// extern crate crossterm; /// extern crate crossterm;
/// use self::crossterm::style::{paint,Attribute}; /// use self::crossterm::style::{style,Attribute};
/// ///
/// println!("{}", paint("Bold").attr(Attribute::Bold)); /// style("Some colored text").attr(Attribute::Bold).paint(&screen);
/// ///
/// ``` /// ```
#[cfg(unix)] #[cfg(unix)]
@ -142,6 +146,14 @@ impl<D: Display> StyledObject<D> {
self.attr(Attribute::CrossedOut) self.attr(Attribute::CrossedOut)
} }
/// This could be used to paint the styled object on the screen. Pass a refrence to the screen whereon you want to perform the painting.
///
/// ``` rust
/// style("Some colored text")
/// .with(Color::Blue)
/// .on(Color::Black)
/// .paint(&screen);
/// ```
pub fn paint(&self, screen: &Screen) pub fn paint(&self, screen: &Screen)
{ {
let mut colored_terminal = super::super::super::style::color::color(&screen); let mut colored_terminal = super::super::super::style::color::color(&screen);

View File

@ -50,7 +50,10 @@ impl ITerminal for AnsiTerminal {
screen_manager.write_string(format!(csi!("8;{};{}t"), width, height)); screen_manager.write_string(format!(csi!("8;{};{}t"), width, height));
} }
fn exit(&self) { fn exit(&self,screen_manager: &Arc<Stdout>) {
// drop the screen with the current stdout. This will make sure when in raw mode this will be disabled first.
let mut screen = Screen::from(screen_manager.clone());
drop(screen);
functions::exit_terminal(); functions::exit_terminal();
} }
} }

View File

@ -44,5 +44,5 @@ pub trait ITerminal {
/// Resize terminal to the given width and height. /// Resize terminal to the given width and height.
fn set_size(&self, width: i16, height: i16, screen_manager: &Arc<Stdout>); fn set_size(&self, width: i16, height: i16, screen_manager: &Arc<Stdout>);
/// Close the current terminal /// Close the current terminal
fn exit(&self); fn exit(&self,screen_manager: &Arc<Stdout>);
} }

View File

@ -14,8 +14,9 @@ use std::io::Write;
/// ///
/// ```rust /// ```rust
/// ///
/// let crossterm = Crossterm::new(); /// use crossterm::terminal::terminal;
/// let term = crossterm.terminal(); ///
/// let term = terminal();
/// ///
/// term.scroll_down(5); /// term.scroll_down(5);
/// term.scroll_up(4); /// term.scroll_up(4);
@ -51,8 +52,7 @@ impl Terminal {
/// ///
/// ```rust /// ```rust
/// ///
/// let crossterm = Crossterm::new(); /// let term = terminal();
/// let term = crossterm.terminal();
/// ///
/// // clear all cells in terminal. /// // clear all cells in terminal.
/// term.clear(terminal::ClearType::All); /// term.clear(terminal::ClearType::All);
@ -76,12 +76,7 @@ impl Terminal {
/// ///
/// ```rust /// ```rust
/// ///
/// extern crate crossterm; /// let term = terminal();
/// use crossterm::terminal;
/// use crossterm::Context;
///
/// let crossterm = Crossterm::new();
/// let term = crossterm.terminal();
/// ///
/// let size = term.terminal_size(); /// let size = term.terminal_size();
/// println!("{:?}", size); /// println!("{:?}", size);
@ -97,8 +92,7 @@ impl Terminal {
/// ///
/// ```rust /// ```rust
/// ///
/// let crossterm = Crossterm::new(); /// let term = terminal();
/// let term = crossterm.terminal();
/// ///
/// // scroll up by 5 lines /// // scroll up by 5 lines
/// let size = term.scroll_up(5); /// let size = term.scroll_up(5);
@ -114,8 +108,7 @@ impl Terminal {
/// ///
/// ```rust /// ```rust
/// ///
/// let crossterm = Crossterm::new(); /// let term = terminal();
/// let term = crossterm.terminal();
/// ///
/// // scroll down by 5 lines /// // scroll down by 5 lines
/// let size = term.scroll_down(5); /// let size = term.scroll_down(5);
@ -131,8 +124,7 @@ impl Terminal {
/// ///
/// ```rust /// ```rust
/// ///
/// let crossterm = Crossterm::new(); /// let term = terminal();
/// let term = crossterm.terminal();
/// ///
/// // 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);
@ -148,14 +140,13 @@ impl Terminal {
/// ///
/// ```rust /// ```rust
/// ///
/// let crossterm = Crossterm::new(); /// let term = terminal();
/// let term = crossterm.terminal();
/// ///
/// let size = term.exit(); /// let size = term.exit();
/// ///
/// ``` /// ```
pub fn exit(&self) { pub fn exit(&self) {
self.terminal.exit(); self.terminal.exit(&self.screen);
} }
/// Write any displayable content to the current terminal screen. /// Write any displayable content to the current terminal screen.
@ -164,8 +155,7 @@ impl Terminal {
/// ///
/// ```rust /// ```rust
/// ///
/// let crossterm = Crossterm::new(); /// let term = terminal();
/// let term = crossterm.terminal();
/// ///
/// let size = term.write("Some text \n Some text on new line"); /// let size = term.write("Some text \n Some text on new line");
/// ///
@ -178,7 +168,8 @@ impl Terminal {
} }
} }
/// Get an terminal implementation whereon terminal related actions could performed /// Get an terminal implementation whereon terminal related actions could performed.
/// Pass the reference to any screen you want this type to perform actions on.
pub fn terminal(screen: &Screen) -> Terminal { pub fn terminal(screen: &Screen) -> Terminal {
Terminal::new(&screen.stdout) Terminal::new(&screen.stdout)
} }

View File

@ -152,7 +152,10 @@ impl ITerminal for WinApiTerminal {
} }
} }
fn exit(&self) { fn exit(&self, screen_manager: &Arc<Stdout>) {
// drop the screen with the current stdout. This will make sure when in raw mode this will be disabled first.
let mut screen = Screen::from(screen_manager.clone());
drop(screen);
functions::exit_terminal(); functions::exit_terminal();
} }
} }

View File

@ -10,7 +10,7 @@ use std::sync::{Arc,Mutex};
use std::io::{self, Read, Write,Stdout, stdout}; use std::io::{self, Read, Write,Stdout, stdout};
use std::str::from_utf8; use std::str::from_utf8;
/// This struct is an ANSI escape code implementation for screen related actions. /// This struct is a wrapper for `Stdout`
pub struct AnsiStdout { pub struct AnsiStdout {
pub handle: Stdout, pub handle: Stdout,
} }
@ -35,7 +35,6 @@ impl IStdout for AnsiStdout {
let out = &self.handle; let out = &self.handle;
let mut handle = out.lock(); let mut handle = out.lock();
handle.flush(); handle.flush();
Ok(()) Ok(())
} }

View File

@ -1,22 +1,4 @@
//! This module provides one place to work with the screen. //! This module provides a way to work with an handle to an screen on different platforms.
//!
//! In Rust we can call `stdout()` to get an handle to the current default console handle.
//! For example when in unix systems you want to print something to the main screen you can use the following code:
//!
//! ```
//! write!(std::io::stdout(), "{}", "some text").
//! ```
//!
//! But things change when we are in alternate screen modes.
//! We can not simply use `stdout()` to get a handle to the alternate screen, since this call returns the current default console handle (mainscreen).
//!
//! Instead we need to store an handle to the screen output.
//! This handle could be used to put into alternate screen modes and back into main screen modes.
//! Through this stored handle Crossterm can execute its command on the current screen whether it be alternate screen or main screen.
//!
//! For unix systems we store the handle gotten from `stdout()` for windows systems that are not supporting ANSI escape codes we store WinApi `HANDLE` struct witch will provide access to the current screen.
//!
//! This is the reason why this module exits: it is to provide access to the current terminal screen whether it will be the alternate screen and main screen.
mod stdout; mod stdout;
@ -35,8 +17,8 @@ use std::io;
use super::{functions}; use super::{functions};
/// This trait defines the actions that could be preformed on the current screen. /// This trait defines represents an stdout of an screen.
/// This trait can be implemented so that an concrete implementation of the IScreenManager can forfill /// This trait can be implemented so that an concrete implementation of the IStdout can forfill
/// the wishes to work on an specific platform. /// the wishes to work on an specific platform.
/// ///
/// ## For example: /// ## For example:
@ -44,7 +26,7 @@ use super::{functions};
/// This trait is implemented for `WINAPI` (Windows specific) and `ANSI` (Unix specific), /// This trait is implemented for `WINAPI` (Windows specific) and `ANSI` (Unix specific),
/// so that color related actions can be preformed on both unix and windows systems. /// so that color related actions can be preformed on both unix and windows systems.
pub trait IStdout { pub trait IStdout {
/// Write a &str to the current stdout. /// Write an &str to the current stdout and flush the screen.
fn write_str(&self, string: &str ) -> io::Result<usize>; fn write_str(&self, string: &str ) -> io::Result<usize>;
/// Write [u8] buffer to console. /// Write [u8] buffer to console.
fn write(&self, buf: &[u8]) -> io::Result<usize>; fn write(&self, buf: &[u8]) -> io::Result<usize>;
@ -52,6 +34,5 @@ pub trait IStdout {
fn flush(&self) -> io::Result<()>; fn flush(&self) -> io::Result<()>;
fn as_any(&self) -> &Any; fn as_any(&self) -> &Any;
fn as_any_mut(&mut self) -> &mut Any; fn as_any_mut(&mut self) -> &mut Any;
} }

View File

@ -23,13 +23,17 @@ use super::*;
use std::any::Any; use std::any::Any;
use std::fmt::Display; use std::fmt::Display;
use std::io::{self, Write}; use std::io::{self, Write};
use std::default::Default;
#[cfg(target_os = "windows")] #[cfg(target_os = "windows")]
use winapi::um::winnt::HANDLE; use winapi::um::winnt::HANDLE;
use std::sync::Arc; use std::sync::Arc;
/// Struct that stores an specific platform implementation for screen related actions. /// Struct that is an handle to an terminal screen.
/// This handle could be used to write to the current screen
///
/// For unix and windows 10 `stdout()` will be used for handle when on windows systems with versions lower than 10 WinApi `HANDLE` will be used.
pub struct Stdout { pub struct Stdout {
screen_manager: Box<IStdout + Send>, screen_manager: Box<IStdout + Send>,
pub is_in_raw_mode:bool, pub is_in_raw_mode:bool,
@ -67,6 +71,7 @@ impl Stdout {
self.screen_manager.write_str(string) self.screen_manager.write_str(string)
} }
/// Write buffer to the screen
pub fn write_buf(&self, buf: &[u8]) -> io::Result<usize> { pub fn write_buf(&self, buf: &[u8]) -> io::Result<usize> {
self.screen_manager.write(buf) self.screen_manager.write(buf)
} }
@ -74,8 +79,24 @@ impl Stdout {
pub fn as_any(&self) -> &Any { pub fn as_any(&self) -> &Any {
self.screen_manager.as_any() self.screen_manager.as_any()
} }
pub fn as_any_mut(&mut self) -> &mut Any { pub fn as_any_mut(&mut self) -> &mut Any {
self.screen_manager.as_any_mut() self.screen_manager.as_any_mut()
} }
} }
impl Default for Stdout
{
/// Get the default handle to the current screen.
fn default() -> Self {
#[cfg(target_os = "windows")]
let screen_manager = functions::get_module::<Box<IStdout + Send>>(
Box::from(WinApiStdout::new()),
Box::from(AnsiStdout::new()),
).unwrap();
#[cfg(not(target_os = "windows"))]
let screen_manager = Box::from(AnsiStdout::new()) as Box<IStdout + Send>;
Stdout { screen_manager , is_in_raw_mode: false}
}
}

View File

@ -8,7 +8,7 @@ use std::any::Any;
use std::io::{self, Write}; use std::io::{self, Write};
use std::sync::Arc; use std::sync::Arc;
/// This struct is an WINAPI implementation for screen related actions. /// This struct is a wrapper for WINAPI `HANDLE`
pub struct WinApiStdout { pub struct WinApiStdout {
pub handle: HANDLE, pub handle: HANDLE,
} }