added examples and changed comments

This commit is contained in:
TimonPost 2018-07-29 21:30:09 +02:00
parent 6970dfadd8
commit b3081fd9c0
36 changed files with 435 additions and 423 deletions

View File

@ -26,11 +26,9 @@ use crossterm::style::Color;
use std::{thread, time}; use std::{thread, time};
fn main() { fn main() {
let term = Crossterm::new(); use crossterm::Crossterm;
let mut cursor = term.cursor();
cursor.goto(10, 10); let mut term = Crossterm::new();
cursor.print("test"); let cursor = term.cursor();
term.terminal().set_size(20,20); let a = term.color();
let mut color = term.color();
color.set_fg(Color::Red);
} }

View File

@ -1,7 +1,6 @@
extern crate crossterm; extern crate crossterm;
use self::crossterm::input::input; use self::crossterm::Crossterm;
use self::crossterm::Context;
pub fn read_char() { pub fn read_char() {
let context = Context::new(); let context = Context::new();
@ -14,8 +13,8 @@ pub fn read_char() {
} }
pub fn read_line() { pub fn read_line() {
let context = Context::new(); let crossterm = Crossterm::new();
let input = input(&context); let input = crossterm.input();
match input.read_line() { match input.read_line() {
Ok(s) => println!("string typed: {}", s), Ok(s) => println!("string typed: {}", s),

View File

@ -1,7 +1,4 @@
//! This module is used for managing the state changes of the terminal. //! This module contains some commands that could be executed for specific task.
//!
//! If `crossterm` changes some core state of the terminal like: enabling ANSI or enabling raw mode it should be reverted when the current process ends.
//! It would be a little lame to let the terminal in raw mode after the the current process ends for the user of this library.
use super::super::manager::ScreenManager; use super::super::manager::ScreenManager;
use std::io::Result; use std::io::Result;
@ -21,19 +18,20 @@ pub use self::unix_commands::*;
pub use self::shared_commands::*; pub use self::shared_commands::*;
/// This command is used for complex commands whits change the terminal state. /// This trait provides a way to execute some state changing commands.
/// By passing an `Context` instance this command will register it self to notify the terminal state change.
pub trait IStateCommand { pub trait IStateCommand {
fn execute(&mut self) -> bool; fn execute(&mut self) -> bool;
fn undo(&mut self) -> bool; fn undo(&mut self) -> bool;
} }
/// This trait provides an interface for switching to alternate screen and back.
pub trait IAlternateScreenCommand pub trait IAlternateScreenCommand
{ {
fn to_alternate_screen(&self,screen_manager: &mut ScreenManager) -> Result<()>; fn enable(&self,screen_manager: &mut ScreenManager) -> Result<()>;
fn to_main_screen(&self, screen_manager: &mut ScreenManager) -> Result<()>; fn disable(&self, screen_manager: &mut ScreenManager) -> Result<()>;
} }
/// This trait provides an interface for switching to raw mode and back.
pub trait IRawScreenCommand pub trait IRawScreenCommand
{ {
fn enable(&mut self) -> Result<()>; fn enable(&mut self) -> Result<()>;

View File

@ -1,24 +1,27 @@
//! This module contains the commands that can be used for both unix and windows systems. Or else said terminals that support ansi codes. //! This module contains the commands that can be used for both unix and windows 10 systems because they support ANSI escape codes
use super::{IAlternateScreenCommand, ScreenManager}; use super::{IAlternateScreenCommand, ScreenManager};
use std::io::Result; use std::io::Result;
/// This command is used for switching to alternate screen and back to main screen. /// This command is used for switching to alternate screen and back to main screen.
pub struct ToAlternateScreenBufferCommand; pub struct ToAlternateScreenCommand;
impl ToAlternateScreenBufferCommand { impl ToAlternateScreenCommand {
pub fn new() -> Box<ToAlternateScreenBufferCommand> { pub fn new() -> Box<ToAlternateScreenCommand> {
return Box::new(ToAlternateScreenBufferCommand {}); return Box::new(ToAlternateScreenCommand {});
} }
} }
impl IAlternateScreenCommand for ToAlternateScreenBufferCommand { impl IAlternateScreenCommand for ToAlternateScreenCommand {
fn to_alternate_screen(&self, screen_manager: &mut ScreenManager) -> Result<()> { /// enable alternate screen.
fn enable(&self, screen_manager: &mut ScreenManager) -> Result<()> {
screen_manager.write_str(csi!("?1049h")); screen_manager.write_str(csi!("?1049h"));
Ok(()) Ok(())
} }
fn to_main_screen(&self, screen_manager: &mut ScreenManager) -> Result<()> { /// disable alternate screen.
fn disable(&self, screen_manager: &mut ScreenManager) -> Result<()> {
screen_manager.write_str(csi!("?1049l")); screen_manager.write_str(csi!("?1049l"));
Ok(()) Ok(())
} }

View File

@ -14,12 +14,13 @@ use std::io::Result;
pub struct Crossterm { pub struct Crossterm {
raw_mode: bool, raw_mode: bool,
alternate_mode: bool, alternate_mode: bool,
active_screen: manager::ScreenManager, pub active_screen: manager::ScreenManager,
raw_terminal: Option<Box<IRawScreenCommand>>, raw_terminal: Option<Box<IRawScreenCommand>>,
alternate_screen: Option<Box<IAlternateScreenCommand>> alternate_screen: Option<Box<IAlternateScreenCommand>>
} }
impl Crossterm{ impl<'crossterm> Crossterm
{
pub fn new() -> Crossterm pub fn new() -> Crossterm
{ {
Crossterm Crossterm
@ -98,6 +99,7 @@ impl Crossterm{
return Ok(()) return Ok(())
} }
pub fn cursor(&self) -> cursor::TerminalCursor { pub fn cursor(&self) -> cursor::TerminalCursor {
cursor::TerminalCursor::new(&self.active_screen) cursor::TerminalCursor::new(&self.active_screen)
} }
@ -128,3 +130,40 @@ impl Drop for Crossterm
} }
} }
} }
/// Wraps an displayable object so it can be formatted with colors and attributes.
///
/// Check `/examples/color` in the libary for more spesific examples.
///
/// #Example
///
/// ```rust
/// extern crate crossterm;
///
/// use self::crossterm::style::{paint,Color};
///
/// fn main()
/// {
/// // Create an styledobject object from the text 'Unstyled font'
/// // Currently it has the default foregroundcolor and backgroundcolor.
/// println!("{}",paint("Unstyled font"));
///
/// // Create an displayable object from the text 'Colored font',
/// // Paint this with the `Red` foreground color and `Blue` backgroundcolor.
/// // Print the result.
/// let styledobject = paint("Colored font").with(Color::Red).on(Color::Blue);
/// println!("{}", styledobject);
///
/// // Or all in one line
/// println!("{}", paint("Colored font").with(Color::Red).on(Color::Blue));
/// }
///
/// ```
// pub fn paint<D>(&self, val: D) -> style::StyledObject<D>
// where
// D: fmt::Display,
// {
// style::ObjectStyle::new().apply_to(val, self.context.clone())
// }

View File

@ -16,72 +16,11 @@
//! //!
//! When you want to switch to alternate screen there are a couple of things to keep in mind for it to work correctly. //! 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 //! First off some code of how to switch to Alternate screen, for more info check the example folder at github
//!
//!
//! Create alternate screen from `Context`
//!
//! // create context.
//! let context = crossterm::Context::new();
//! // create instance of Alternatescreen by the given context, this wil also switch to it.
//! let mut screen = crossterm::AlternateScreen::from(context.clone());
//! // write to the alternate screen.
//! write!(screen, "test");
//!
//! Create alternate screen from `Crossterm`: //! Create alternate screen from `Crossterm`:
//! //!
//! // create crossterm.
//! let crossterm = ::crossterm::Crossterm::new();
//! // create instance of Alternatescreen by the given refrence to crossterm, this wil also switch to it.
//! let mut screen = crossterm::AlternateScreen::from(&crossterm);
//! // write to the alternate screen.
//! write!(screen, "test");
//! //!
//! When using alternate screen there is one thing to keep in mind. //! Todo: example
//! 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.
//! //!
//!
//! Please check the documentation of `Context` for more info.
//! But basically this Context is a wrapper for a type that provides access to the current screen whether it would be the main screen or alternate screen.
//!
//!
//! An example of what I mean by that:
//!
//! // create context.
//! let context = crossterm::Context::new();
//!
//! let mut cursor = ::crossterm::cursor::cursor(&context);
//! cursor.goto(10,10);
//!
//! // create instance of Alternatescreen by the given refrence to crossterm, this wil also switch to it.
//! let mut screen = crossterm::AlternateScreen::from(&context);
//!
//! // now this cursor will be moving on the alternate screen sice it is using the same context as we have passed to the alternatescreen.
//! cursor.goto(5,4)
//!
//! To make things easier you can better use `Crossterm` type for the interactions with alternate screen.
//! This type will manage the `Context` internally.
//!
//! So when using this type to switch to AlternateScreen. It will use the `Context` from the type `Crossterm` for the `AlternateSceen`.
//!
//! For example:
//!
//! // create crossterm instance.
//! let crossterm = ::crossterm::Crossterm::new();
//!
//! let mut cursor = crossterm.cursor();
//! cursor.goto(10,10);
//!
//! // create instance of Alternatescreen by the given refrence to crossterm, this wil also switch to it.
//! let mut screen = crossterm::AlternateScreen::from(&crossterm);
//!
//! // this cursor will be moving on the alternate screen since the current screen is the alternate screen.
//! let mut cursor = crossterm.cursor();
//! cursor.goto(10,10);
//!
//! As you can see because we are using `Crossterm` we won't have to bother about the `Context`.
use super::{functions, ScreenManager}; use super::{functions, ScreenManager};
use super::commands; use super::commands;
@ -92,9 +31,7 @@ use std::io::{self, Write};
pub struct AlternateScreen; pub struct AlternateScreen;
impl AlternateScreen { impl AlternateScreen {
/// Get the alternate screen from the context. /// Create an new alternate screen type.
/// By calling this method the current screen will be changed to the alternate screen.
/// And you get back an handle for that screen.
pub fn new() -> Box<commands::IAlternateScreenCommand> { pub fn new() -> Box<commands::IAlternateScreenCommand> {
#[cfg(target_os = "windows")] #[cfg(target_os = "windows")]
let command = functions::get_module::<Box<commands::IAlternateScreenCommand>>( let command = functions::get_module::<Box<commands::IAlternateScreenCommand>>(

View File

@ -1,3 +1,5 @@
//! This module provides some modules to work with the terminal screen. Like raw and alternate screen.
mod raw; mod raw;
mod alternate; mod alternate;

View File

@ -26,6 +26,7 @@ use std::io::{self, Write};
pub struct RawScreen; pub struct RawScreen;
impl RawScreen { impl RawScreen {
/// Create a new RawScreen type.
pub fn new() -> Box<commands::IRawScreenCommand> { pub fn new() -> Box<commands::IRawScreenCommand> {
Box::from(EnableRawModeCommand::new()) Box::from(EnableRawModeCommand::new())
} }

View File

@ -1,3 +1,5 @@
//! This contains the logic for working with the console buffer.
use winapi::shared::minwindef::{FALSE, TRUE}; use winapi::shared::minwindef::{FALSE, TRUE};
use winapi::shared::ntdef::NULL; use winapi::shared::ntdef::NULL;
use winapi::um::minwinbase::SECURITY_ATTRIBUTES; use winapi::um::minwinbase::SECURITY_ATTRIBUTES;

View File

@ -1,3 +1,5 @@
//! This module contains some logic for working with the console handle.
use winapi::um::processenv::GetStdHandle; use winapi::um::processenv::GetStdHandle;
use winapi::um::handleapi::INVALID_HANDLE_VALUE; use winapi::um::handleapi::INVALID_HANDLE_VALUE;
use winapi::um::winbase::{STD_INPUT_HANDLE, STD_OUTPUT_HANDLE}; use winapi::um::winbase::{STD_INPUT_HANDLE, STD_OUTPUT_HANDLE};

View File

@ -1,4 +1,4 @@
//! This module is the core of all the `WINAPI` actions. All unsafe `WINAPI` function call are done here. //! This module contains some basic winapi calls.
use winapi::um::consoleapi::{GetConsoleMode, SetConsoleMode}; use winapi::um::consoleapi::{GetConsoleMode, SetConsoleMode};
use winapi::um::winnt::HANDLE; use winapi::um::winnt::HANDLE;

View File

@ -1,3 +1,5 @@
//! This module contains terminal specific logic.
use super::{csbi, handle, ScreenManager}; use super::{csbi, handle, ScreenManager};
/// Get the terminal size /// Get the terminal size

View File

@ -1,3 +1,5 @@
//! This module contains the logic to write to the terminal.
use winapi::ctypes::c_void; use winapi::ctypes::c_void;
use winapi::shared::ntdef::NULL; use winapi::shared::ntdef::NULL;
use winapi::um::consoleapi::WriteConsoleW; use winapi::um::consoleapi::WriteConsoleW;

View File

@ -9,6 +9,30 @@ use std::io::Write;
use std::fmt::Display; use std::fmt::Display;
/// 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.
///
/// #Example
///
/// ```rust
///
/// extern crate crossterm;
/// use self::crossterm::Crossterm;
///
/// let term = Crossterm::new();
/// let mut cursor = term.cursor();
///
/// // Get cursor and goto pos X: 5, Y: 10
/// cursor.goto(5,10);
///
/// cursor.show();
/// cursor.hide();
/// cursor.blink(true);
/// cursor.move_left(2);
///
/// // or in one line
/// cursor.goto(5,5).move_left(2).move_right(2).print("10");
/// ```
pub struct TerminalCursor<'cursor> { pub struct TerminalCursor<'cursor> {
screen_manager: &'cursor ScreenManager, screen_manager: &'cursor ScreenManager,
terminal_cursor: Box<ITerminalCursor>, terminal_cursor: Box<ITerminalCursor>,
@ -38,19 +62,11 @@ impl<'cursor> TerminalCursor<'cursor> {
/// ///
/// ```rust /// ```rust
/// ///
/// extern crate crossterm; /// let crossterm = Crossterm::new();
/// use self::crossterm::Context; /// let cursor = crossterm.cursor();
/// use self::crossterm::cursor;
/// ///
/// pub fn goto() /// // change the cursor to position, x: 4 and y: 5
/// { /// cursor.goto(4,5);
/// let context = Context::new();
///
/// // Get the cursor
/// let mut cursor = cursor(&context);
/// // Set the cursor to position X: 10, Y: 5 in the terminal
/// cursor.goto(10,5);
/// }
/// ///
/// ``` /// ```
pub fn goto(&mut self, x: u16, y: u16) -> &mut TerminalCursor<'cursor> { pub fn goto(&mut self, x: u16, y: u16) -> &mut TerminalCursor<'cursor> {
@ -64,19 +80,11 @@ impl<'cursor> TerminalCursor<'cursor> {
/// ///
/// ```rust /// ```rust
/// ///
/// extern crate crossterm; /// let crossterm = Crossterm::new();
/// use self::crossterm::Context; /// let cursor = crossterm.cursor();
/// use self::crossterm::cursor;
/// ///
/// pub fn pos() /// // get the current cursor pos
/// { /// let (x,y) = cursor.pos();
/// let context = Context::new();
///
/// // Get the cursor
/// let mut cursor = cursor(&context);
/// // get the cursor position.
/// let (x,y) = cursor.pos();
/// }
/// ///
/// ``` /// ```
pub fn pos(&self) -> (u16, u16) { pub fn pos(&self) -> (u16, u16) {
@ -84,24 +92,15 @@ impl<'cursor> TerminalCursor<'cursor> {
} }
/// Move the current cursor position `n` times up. /// Move the current cursor position `n` times up.
///
/// #Example /// #Example
/// ///
/// ```rust /// ```rust
/// ///
/// extern crate crossterm; /// let crossterm = Crossterm::new();
/// use self::crossterm::Context; /// let cursor = crossterm.cursor();
/// use self::crossterm::cursor;
/// ///
/// pub fn move_up() /// // Move the cursor to position 3 times to the up in the terminal
/// { /// cursor.move_up(3);
/// let context = Context::new();
///
/// // Get the cursor
/// let mut cursor = cursor(&context);
/// // 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<'cursor> { pub fn move_up(&mut self, count: u16) -> &mut TerminalCursor<'cursor> {
@ -114,19 +113,12 @@ impl<'cursor> TerminalCursor<'cursor> {
/// #Example /// #Example
/// ///
/// ```rust /// ```rust
/// extern crate crossterm;
/// use self::crossterm::Context;
/// use self::crossterm::cursor;
/// ///
/// pub fn move_right() /// let crossterm = Crossterm::new();
/// { /// let cursor = crossterm.cursor();
/// let context = Context::new(); /// // Move the cursor to position 3 times to the right in the terminal
/// cursor.move_right(3);
/// ///
/// // Get the cursor
/// let mut cursor = cursor(&context);
/// // Move the cursor to position 3 times to the right in the terminal
/// cursor.move_right(3);
/// }
/// ``` /// ```
pub fn move_right(&mut self, count: u16) -> &mut TerminalCursor<'cursor> { pub fn move_right(&mut self, count: u16) -> &mut TerminalCursor<'cursor> {
self.terminal_cursor.move_right(count, &self.screen_manager); self.terminal_cursor.move_right(count, &self.screen_manager);
@ -139,19 +131,11 @@ impl<'cursor> TerminalCursor<'cursor> {
/// ///
/// ```rust /// ```rust
/// ///
/// extern crate crossterm; /// let crossterm = Crossterm::new();
/// use self::crossterm::Context; /// let cursor = crossterm.cursor();
/// use self::crossterm::cursor;
/// ///
/// pub fn move_down() /// // Move the cursor to position 3 times to the down in the terminal
/// { /// cursor.move_down(3);
/// let context = Context::new();
///
/// // Get the cursor
/// let mut cursor = cursor(&context);
/// // Move the cursor to position 3 times to the down in the terminal
/// cursor.move_down(3);
/// }
/// ///
/// ``` /// ```
pub fn move_down(&mut self, count: u16) -> &mut TerminalCursor<'cursor> { pub fn move_down(&mut self, count: u16) -> &mut TerminalCursor<'cursor> {
@ -165,19 +149,11 @@ impl<'cursor> TerminalCursor<'cursor> {
/// ///
/// ```rust /// ```rust
/// ///
/// extern crate crossterm; /// let crossterm = Crossterm::new();
/// use self::crossterm::Context; /// let cursor = crossterm.cursor();
/// use self::crossterm::cursor;
/// ///
/// pub fn move_left() /// // Move the cursor to position 3 times to the left in the terminal
/// { /// cursor.move_left(3);
/// let context = Context::new();
///
/// // Get the cursor
/// let mut cursor = cursor(&context);
/// // Move the cursor to position 3 times to the left in the terminal
/// cursor.move_left(3);
/// }
/// ///
/// ``` /// ```
pub fn move_left(&mut self, count: u16) -> &mut TerminalCursor<'cursor> { pub fn move_left(&mut self, count: u16) -> &mut TerminalCursor<'cursor> {
@ -208,10 +184,11 @@ impl<'cursor> TerminalCursor<'cursor> {
/// use std; /// use std;
/// use std::io::Write; /// use std::io::Write;
/// ///
/// let context = Context::new(); /// let crossterm = Crossterm::new();
/// let cursor = crossterm.cursor();
/// ///
/// // of course we can just do this. /// // of course we can just do this.
/// cursor::cursor(&context).goto(10,10); /// cursor.goto(10,10);
/// print!("@"); /// print!("@");
/// std::io::stdout().flush(); /// std::io::stdout().flush();
/// ///
@ -239,12 +216,10 @@ impl<'cursor> TerminalCursor<'cursor> {
/// ///
/// ```rust /// ```rust
/// ///
/// extern crate crossterm; /// let crossterm = Crossterm::new();
/// use self::crossterm::Context; /// let cursor = crossterm.cursor();
/// use self::crossterm::cursor;
/// ///
/// let context = Context::new(); /// cursor.safe_position();
/// cursor::cursor(&context).safe_position();
/// ///
/// ``` /// ```
pub fn save_position(&self) { pub fn save_position(&self) {
@ -259,12 +234,10 @@ impl<'cursor> TerminalCursor<'cursor> {
/// ///
/// ```rust /// ```rust
/// ///
/// extern crate crossterm; /// let crossterm = Crossterm::new();
/// use self::crossterm::cursor::cursor; /// let cursor = crossterm.cursor();
/// use self::crossterm::Context;
/// ///
/// let context = Context::new(); /// cursor.reset_position();
/// cursor(&context).reset_position();
/// ///
/// ``` /// ```
pub fn reset_position(&self) { pub fn reset_position(&self) {
@ -277,12 +250,10 @@ impl<'cursor> TerminalCursor<'cursor> {
/// ///
/// ```rust /// ```rust
/// ///
/// extern crate crossterm; /// let crossterm = Crossterm::new();
/// use self::crossterm::cursor::cursor; /// let cursor = crossterm.cursor();
/// use self::crossterm::Context;
/// ///
/// let context = Context::new(); /// cursor.hide();
/// cursor(&context).hide();
/// ///
/// ``` /// ```
pub fn hide(&self) { pub fn hide(&self) {
@ -295,12 +266,10 @@ impl<'cursor> TerminalCursor<'cursor> {
/// ///
/// ```rust /// ```rust
/// ///
/// extern crate crossterm; /// let crossterm = Crossterm::new();
/// use self::crossterm::cursor::cursor; /// let cursor = crossterm.cursor();
/// use self::crossterm::Context;
/// ///
/// let context = Context::new(); /// cursor.show();
/// cursor(&context).show();
/// ///
/// ``` /// ```
pub fn show(&self) { pub fn show(&self) {
@ -315,12 +284,9 @@ impl<'cursor> TerminalCursor<'cursor> {
/// ///
/// ```rust /// ```rust
/// ///
/// extern crate crossterm; /// let crossterm = Crossterm::new();
/// use self::crossterm::cursor::cursor; /// let cursor = crossterm.cursor();
/// use self::crossterm::Context;
/// ///
/// let context = Context::new();
/// let cursor = cursor(&context);
/// cursor.blink(true); /// cursor.blink(true);
/// cursor.blink(false); /// cursor.blink(false);
/// ///
@ -330,33 +296,7 @@ impl<'cursor> TerminalCursor<'cursor> {
} }
} }
// Get an TerminalCursor implementation whereon cursor related actions can be performed. /// Get an TerminalCursor implementation whereon cursor related actions can be performed.
//
// Check `/examples/version/cursor` in the libary for more spesific examples.
//
// #Example
//
// ```rust
//
// extern crate crossterm;
// use self::crossterm::Context;
// use self::crossterm::cursor;
//
// let context = Context::new();
//
// // Get cursor and goto pos X: 5, Y: 10
// let mut cursor = cursor::cursor(&context);
// cursor.goto(5,10);
//
// cursor.show();
// cursor.hide();
// cursor.blink();
// cursor.move_left(2);
//
// //Or you can do it in one line.
// cursor::cursor(&context).goto(5,10);
//
// ```
pub fn cursor(screen_manager: &ScreenManager) -> TerminalCursor { pub fn cursor(screen_manager: &ScreenManager) -> TerminalCursor {
TerminalCursor::new(screen_manager) TerminalCursor::new(screen_manager)
} }

View File

@ -1,12 +1,5 @@
//! This trait defines the actions that can be preformed with the terminal cursor. //! With this module you can perform actions that are cursor related.
//! This trait can be implemented so that an concrete implementation of the ITerminalCursor can for fill //! Like moving the cursor position;saving and resetting the cursor position; hiding showing and control the blinking of the cursor.
//! the wishes to work on an specific platform.
//!
//! ## For example:
//!
//! This trait is implemented to work with WINAPI (Windows specific) and ANSI (Unix specific),
//! so that the cursor related actions can be preformed on both unix and windows systems.
//!
mod cursor; mod cursor;

View File

@ -1,6 +1,7 @@
//! This is an WINAPI specific implementation for cursor related action. //! This is an WINAPI specific implementation for cursor related action.
//! 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 ect. //! Note that the cursor position is 0 based. This means that we start counting at 0 when setting the cursor position ect.
use super::super::manager::{ScreenManager, WinApiScreenManager}; use super::super::manager::{ScreenManager, WinApiScreenManager};
use super::ITerminalCursor; use super::ITerminalCursor;

View File

@ -1,13 +1,36 @@
//! With this module you can perform actions that are input related.
//! Like reading a line, reading a character and reading asynchronously.
use std::io; use std::io;
use super::*; use super::*;
/// Struct that stores an specific platform implementation for input related actions.
///
/// Check `/examples/version/input` the examples folder on github for more info.
///
/// #Example
///
/// ```rust
///
/// extern crate crossterm;
/// use self::crossterm::Crossterm;
///
/// let crossterm = Crossterm::new();
/// let input = crossterm.input();
///
/// let result = input.read_line();
/// let pressed_char = input.read_char();
///
/// ```
pub struct TerminalInput<'terminal> { pub struct TerminalInput<'terminal> {
terminal_input: Box<ITerminalInput>, terminal_input: Box<ITerminalInput>,
screen_manager: &'terminal ScreenManager screen_manager: &'terminal ScreenManager
} }
impl<'terminal> TerminalInput<'terminal> { impl<'terminal> TerminalInput<'terminal> {
/// Create new instance of TerminalInput whereon input related actions could be preformed.
pub fn new(screen_manager: &'terminal ScreenManager) -> TerminalInput<'terminal> { pub fn new(screen_manager: &'terminal ScreenManager) -> TerminalInput<'terminal> {
#[cfg(target_os = "windows")] #[cfg(target_os = "windows")]
let input = Box::from(WindowsInput::new()); let input = Box::from(WindowsInput::new());
@ -21,23 +44,111 @@ impl<'terminal> TerminalInput<'terminal> {
} }
} }
/// Read one line from the user input.
///
/// #Example
///
/// ```rust
/// let crossterm = Crossterm::new();
/// match crossterm.input().read_line() {
/// Ok(s) => println!("string typed: {}", s),
/// Err(e) => println!("error: {}", e),
/// }
///
/// ```
pub fn read_line(&self) -> io::Result<String> { pub fn read_line(&self) -> io::Result<String> {
self.terminal_input.read_line(&self.screen_manager) self.terminal_input.read_line(&self.screen_manager)
} }
/// Read one character from the user input
///
/// #Example
///
/// ```rust
/// let crossterm = Crossterm::new();
/// match crossterm.input().read_char() {
/// Ok(c) => println!("character pressed: {}", c),
/// Err(e) => println!("error: {}", e),
// }
///
/// ```
pub fn read_char(&self) -> io::Result<char> { pub fn read_char(&self) -> io::Result<char> {
return self.terminal_input.read_char(&self.screen_manager); return self.terminal_input.read_char(&self.screen_manager);
} }
/// Read the input asynchronously from the user.
///
/// #Example
///
/// ```rust
/// let crossterm = Crossterm::new();
///
/// // 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 mut stdin = crossterm.input().read_async().bytes();
///
/// for i in 0..100 {
///
/// // Get the next character typed. This is None if nothing is pressed. And Some(Ok(u8 value of character))
/// let a = stdin.next();
///
/// println!("pressed key: {:?}", a);
///
/// if let Some(Ok(b'x')) = a {
/// println!("The key: `x` was pressed and program is terminated.");
/// break;
/// }
/// // simulate some timeout so that we can see the character on the screen.
/// thread::sleep(time::Duration::from_millis(50));
/// }
///
/// ```
pub fn read_async(&self) -> AsyncReader { pub fn read_async(&self) -> AsyncReader {
self.terminal_input.read_async(&self.screen_manager) self.terminal_input.read_async(&self.screen_manager)
} }
/// Read the input asynchronously until a certain character is hit.
///
/// #Example
///
/// ```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.
/// crossterm.enable_raw_mode();
///
/// let mut stdin = input.read_until_async(b'\r').bytes();
///
/// for i in 0..100 {
/// terminal.clear(ClearType::All);
/// cursor.goto(1, 1);
/// let a = stdin.next();
///
/// println!("pressed key: {:?}", a);
///
/// if let Some(Ok(b'\r')) = a {
/// println!("The enter key is hit and program is not listening to input anymore.");
/// break;
/// }
///
/// if let Some(Ok(b'x')) = a {
/// println!("The key: x was pressed and program is terminated.");
/// break;
/// }
///
/// thread::sleep(time::Duration::from_millis(100));
/// }
/// ```
pub fn read_until_async(&self, delimiter: u8) -> AsyncReader { pub fn read_until_async(&self, delimiter: u8) -> AsyncReader {
self.terminal_input.read_until_async(delimiter,&self.screen_manager) self.terminal_input.read_until_async(delimiter,&self.screen_manager)
} }
} }
/// Get an Terminal Input implementation whereon input related actions can be performed.
pub fn input(screen_manager: &ScreenManager) -> TerminalInput { pub fn input(screen_manager: &ScreenManager) -> TerminalInput {
return TerminalInput::new(screen_manager) return TerminalInput::new(screen_manager)
} }

View File

@ -1,3 +1,6 @@
//! With this module you can perform actions that are input related.
//! Like reading a line, reading a character and reading asynchronously.
mod input; mod input;
#[cfg(not(target_os = "windows"))] #[cfg(not(target_os = "windows"))]
@ -16,15 +19,28 @@ use super::ScreenManager;
use std::io::{Read, self}; use std::io::{Read, self};
use std::sync::mpsc; use std::sync::mpsc;
/// This trait defines the actions that can be preformed with the terminal color.
/// This trait can be implemented so that an concrete implementation of the ITerminalColor can forfill
/// the wishes to work on an specific platform.
///
/// ## For example:
///
/// This trait is implemented for Windows and UNIX systems.
/// Unix is using the tty and windows is using libc C functions to read the input.
trait ITerminalInput { trait ITerminalInput {
/// Read one line from the user input
fn read_line(&self, screen_manger: &ScreenManager) -> io::Result<String>; fn read_line(&self, screen_manger: &ScreenManager) -> io::Result<String>;
/// Read one character from the user input
fn read_char(&self, screen_manger: &ScreenManager) -> io::Result<char>; fn read_char(&self, screen_manger: &ScreenManager) -> io::Result<char>;
/// Read the input asynchronously from the user.
fn read_async(&self, screen_manger: &ScreenManager) -> AsyncReader; fn read_async(&self, screen_manger: &ScreenManager) -> AsyncReader;
/// Read the input asynchronously until a certain character is hit.
fn read_until_async(&self, delimiter: u8, screen_manger: &ScreenManager) -> AsyncReader; fn read_until_async(&self, delimiter: u8, screen_manger: &ScreenManager) -> AsyncReader;
} }
/// This is a wrapper for reading from the input asynchronously.
/// This wrapper has a channel receiver that receives the input from the user whenever it typed something.
/// You only need to check whether there are new characters available.
pub struct AsyncReader { pub struct AsyncReader {
recv: mpsc::Receiver<io::Result<u8>>, recv: mpsc::Receiver<io::Result<u8>>,
} }

View File

@ -1,3 +1,5 @@
//! This is an UNIX specific implementation for input related action.
use std::char; use std::char;
use std::io::{self, Read, Write}; use std::io::{self, Read, Write};
use std::sync::mpsc; use std::sync::mpsc;

View File

@ -1,3 +1,5 @@
//! This is an WINDOWS specific implementation for input related action.
use std::char; use std::char;
use std::io::{self,Write}; use std::io::{self,Write};
use std::sync::mpsc; use std::sync::mpsc;
@ -78,7 +80,6 @@ impl ITerminalInput for WindowsInput {
thread::spawn(move || { thread::spawn(move || {
loop { loop {
// _getwch is without echo and _getwche is with echo // _getwch is without echo and _getwche is with echo
let pressed_char = unsafe { if is_raw_screen { _getwch() } else { _getwche() } }; let pressed_char = unsafe { if is_raw_screen { _getwch() } else { _getwche() } };
@ -123,7 +124,6 @@ impl ITerminalInput for WindowsInput {
} }
} }
fn is_line_end(key: char) -> bool { fn is_line_end(key: char) -> bool {
if key as u8 == 13 { if key as u8 == 13 {
return true; return true;

View File

@ -6,13 +6,14 @@ use super::IScreenManager;
use std::any::Any; use std::any::Any;
use std::io::{self, Read, Write}; use std::io::{self, Read, Write};
use std::sync::Mutex; use std::cell::RefCell ;
use std::str::from_utf8; use std::str::from_utf8;
/// This struct is an ANSI escape code implementation for screen related actions.
pub struct AnsiScreenManager { pub struct AnsiScreenManager {
is_alternate_screen: bool, is_alternate_screen: bool,
is_raw_screen: bool, is_raw_screen: bool,
output: Mutex<Box<Write>> output: RefCell<Box<Write>>
} }
impl IScreenManager for AnsiScreenManager { impl IScreenManager for AnsiScreenManager {
@ -33,28 +34,21 @@ impl IScreenManager for AnsiScreenManager {
} }
fn write_str(&self, string: &str) -> io::Result<usize> { fn write_str(&self, string: &str) -> io::Result<usize> {
{ let mut output = self.output.borrow_mut();
let mx = &self.output; write!(output, "{}", string)?;
let mut output = mx.lock().unwrap();
write!(output, "{}", string)?;
}
self.flush();
Ok(0) Ok(0)
} }
fn write(&self, buf: &[u8]) -> io::Result<usize> { fn write(&self, buf: &[u8]) -> io::Result<usize> {
{ {
let mx = &self.output; let mut output = self.output.borrow_mut();
let mut output = mx.lock().unwrap();
output.write(buf)?; output.write(buf)?;
} }
Ok(0) Ok(0)
} }
fn flush(&self) -> io::Result<()> { fn flush(&self) -> io::Result<()> {
let mx = &self.output; let mut output = self.output.borrow_mut();
let mut output = mx.lock().unwrap();
output.flush() output.flush()
} }
@ -70,7 +64,7 @@ impl IScreenManager for AnsiScreenManager {
impl AnsiScreenManager { impl AnsiScreenManager {
pub fn new() -> Self { pub fn new() -> Self {
AnsiScreenManager { AnsiScreenManager {
output: Mutex::new(Box::from(io::stdout()) as Box<Write>), output: RefCell::new(Box::from(io::stdout()) as Box<Write>),
is_alternate_screen: false, is_alternate_screen: false,
is_raw_screen: false, is_raw_screen: false,
} }

View File

@ -1,5 +1,22 @@
//! This module provides an interface for working with the screen. With that I mean that you can get or wirte to the handle of the current screen. stdout. //! This module provides one place to work with the screen.
//! Because crossterm can work with alternate screen, we need a place that holds the handle to the current screen so we can write to that screen. //!
//! 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.
use super::*; use super::*;
@ -28,7 +45,7 @@ impl ScreenManager {
let screen_manager = Box::from(AnsiScreenManager::new()) as Box<IScreenManager>; let screen_manager = Box::from(AnsiScreenManager::new()) as Box<IScreenManager>;
ScreenManager { ScreenManager {
screen_manager: screen_manager, screen_manager,
} }
} }
@ -68,12 +85,12 @@ impl ScreenManager {
self.screen_manager.write_str(string) self.screen_manager.write_str(string)
} }
/// Can be used to get an specific implementation used for the current platform. /// Can be used to get an reference to an specific implementation used for the current platform.
pub fn as_any(&self) -> &Any { pub fn as_any(&self) -> &Any {
self.screen_manager.as_any() self.screen_manager.as_any()
} }
/// Can be used to get an specific implementation used for the current platform. /// Can be used to get an mutable reference to an specific implementation used for the current platform.
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()
} }

View File

@ -16,7 +16,7 @@
//! //!
//! 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. //! 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. //! 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 manager; mod manager;
@ -34,6 +34,14 @@ use super::functions;
use std::any::Any; use std::any::Any;
use std::io; use std::io;
/// This trait defines the actions that could be preformed on the current screen.
/// This trait can be implemented so that an concrete implementation of the IScreenManager can forfill
/// the wishes to work on an specific platform.
///
/// ## For example:
///
/// 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.
pub trait IScreenManager { pub trait IScreenManager {
fn set_is_raw_screen(&mut self, value: bool); fn set_is_raw_screen(&mut self, value: bool);
fn set_is_alternate_screen(&mut self, value: bool); fn set_is_alternate_screen(&mut self, value: bool);

View File

@ -6,6 +6,7 @@ use winapi::um::winnt::HANDLE;
use std::any::Any; use std::any::Any;
use std::io::{self, Write}; use std::io::{self, Write};
/// This struct is an WINAPI implementation for screen related actions.
pub struct WinApiScreenManager { pub struct WinApiScreenManager {
is_alternate_screen: bool, is_alternate_screen: bool,
is_raw_screen: bool, is_raw_screen: bool,
@ -54,8 +55,9 @@ impl IScreenManager for WinApiScreenManager {
} }
} }
// for winapi we have some custom implementation that will be used by windows only. You can get a reference to this implementation by using the any and that cast it to this struct. // for winapi we have some custom implementation that will be used by windows only. You can get a reference to this implementation by using the `as_any()` and that cast it to this struct.
impl WinApiScreenManager { impl WinApiScreenManager {
/// Create a new instance.
pub fn new() -> Self { pub fn new() -> Self {
WinApiScreenManager { WinApiScreenManager {
output: handle::get_output_handle().unwrap(), output: handle::get_output_handle().unwrap(),

View File

@ -3,7 +3,7 @@
use super::{ITerminalColor, Color, ScreenManager, ColorType}; use super::{ITerminalColor, Color, ScreenManager, ColorType};
/// This struct is an ansi implementation for color related actions. /// This struct is an ANSI escape code implementation for color related actions.
pub struct AnsiColor; pub struct AnsiColor;
impl AnsiColor { impl AnsiColor {

View File

@ -2,10 +2,27 @@
//! Like styling the font, foreground color and background. //! Like styling the font, foreground color and background.
use super::*; use super::*;
use std::io; use std::io;
/// Struct that stores an specific platform implementation for color related actions. /// Struct that stores an specific platform implementation for color related actions.
///
/// Check `/examples/version/color` in the library for more specific examples.
///
/// #Example
///
/// ```rust
///
/// let crossterm = Crossterm::new();
/// let colored_terminal = crossterm.color();
///
/// // set foreground color
/// colored_terminal.set_fg(Color::Red);
/// // set background color
/// colored_terminal.set_bg(Color::Red);
/// // reset color to default
/// colored_terminal.reset();
///
/// ```
pub struct TerminalColor<'terminal> { pub struct TerminalColor<'terminal> {
color: Box<ITerminalColor>, color: Box<ITerminalColor>,
screen_manager: &'terminal ScreenManager screen_manager: &'terminal ScreenManager
@ -34,15 +51,8 @@ impl<'terminal> TerminalColor<'terminal> {
/// #Example /// #Example
/// ///
/// ```rust /// ```rust
/// extern crate crossterm; /// let crossterm = Crossterm::new();
/// /// let colored_terminal = crossterm.color();
/// use self::crossterm::style::{ color, Color};
/// use crossterm::Context;
///
/// let context = Context::new();
///
/// // Get colored terminal instance
/// let mut colored_terminal = color(&context);
/// ///
/// // Set foreground color of the font /// // Set foreground color of the font
/// colored_terminal.set_fg(Color::Red); /// colored_terminal.set_fg(Color::Red);
@ -60,15 +70,8 @@ impl<'terminal> TerminalColor<'terminal> {
/// ///
/// ```rust /// ```rust
/// ///
/// extern crate crossterm; /// let crossterm = Crossterm::new();
/// /// let colored_terminal = crossterm.color();
/// use self::crossterm::style::{ color, Color};
/// use crossterm::Context;
///
/// let context = Context::new();
///
/// // Get colored terminal instance
/// let mut colored_terminal = color(&context);
/// ///
/// // Set background color of the font /// // Set background color of the font
/// colored_terminal.set_bg(Color::Red); /// colored_terminal.set_bg(Color::Red);
@ -84,15 +87,9 @@ impl<'terminal> TerminalColor<'terminal> {
/// # Example /// # Example
/// ///
/// ```rust /// ```rust
/// extern crate crossterm;
/// ///
/// use self::crossterm::style::color; /// let crossterm = Crossterm::new();
/// use crossterm::Context; /// let colored_terminal = crossterm.color();
///
/// let context = Context::new();
///
/// // Get colored terminal instance
/// let mut colored_terminal = color(&context);
/// ///
/// colored_terminal.reset(); /// colored_terminal.reset();
/// ///
@ -118,10 +115,7 @@ impl<'terminal> TerminalColor<'terminal> {
} }
} }
/// Get an Color implementation whereon color related actions can be performed. /// Get an Terminal Color implementation whereon color related actions can be performed.
///
/// Check `/examples/version/color` in the library for more specific examples.
///
pub fn color(screen_manager: &ScreenManager) -> TerminalColor { pub fn color(screen_manager: &ScreenManager) -> TerminalColor {
TerminalColor::new(screen_manager) TerminalColor::new(screen_manager)
} }

View File

@ -1,3 +1,5 @@
//! Module that contains all the actions related to the styling of the terminal. like coloring adding attributes etc.
pub mod color; pub mod color;
pub mod objectstyle; pub mod objectstyle;
pub mod styledobject; pub mod styledobject;
@ -18,14 +20,14 @@ pub use self::styledobject::StyledObject;
pub use self::objectstyle::ObjectStyle; pub use self::objectstyle::ObjectStyle;
use super::{ScreenManager, functions}; use super::{ScreenManager, functions};
///! This trait defines the actions that can be preformed with the terminal color. /// This trait defines the actions that can be preformed with the terminal color.
///! This trait can be implemented so that an concrete implementation of the ITerminalColor can forfill /// This trait can be implemented so that an concrete implementation of the ITerminalColor can forfill
///! the wishes to work on an specific platform. /// the wishes to work on an specific platform.
///! ///
///! ## For example: /// ## For example:
///! ///
///! 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 ITerminalColor { pub 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, screen_manager: &ScreenManager); fn set_fg(&self, fg_color: Color, screen_manager: &ScreenManager);
@ -37,6 +39,7 @@ pub trait ITerminalColor {
fn color_value(&self, color: Color, color_type: ColorType) -> String; fn color_value(&self, color: Color, color_type: ColorType) -> String;
} }
/// Attributes that could be applied on some text.
#[derive(Copy, Clone, Debug, PartialEq, Eq, Ord, PartialOrd)] #[derive(Copy, Clone, Debug, PartialEq, Eq, Ord, PartialOrd)]
pub enum Attribute { pub enum Attribute {
Bold = 1, Bold = 1,
@ -50,7 +53,7 @@ pub enum Attribute {
CrossedOut = 9, CrossedOut = 9,
} }
/// Colors that are available for coloring the termainal font. /// Colors that are available for coloring the terminal font.
#[derive(Debug, Copy, Clone)] #[derive(Debug, Copy, Clone)]
pub enum Color { pub enum Color {
Black, Black,

View File

@ -30,7 +30,7 @@ impl Default for ObjectStyle {
impl ObjectStyle { impl ObjectStyle {
/// Apply an `StyledObject` to the passed displayable object. /// Apply an `StyledObject` to the passed displayable object.
pub fn apply_to<'style, D: Display>(&self, val: D, screen_manager: &'style ScreenManager) -> StyledObject<'style,D> { pub fn apply_to<'style, D: Display>(&self, val: D, screen_manager: &'style mut ScreenManager) -> StyledObject<'style,D> {
StyledObject { StyledObject {
object_style: self.clone(), object_style: self.clone(),
screen_manager: screen_manager, screen_manager: screen_manager,
@ -61,6 +61,7 @@ impl ObjectStyle {
} }
#[cfg(unix)] #[cfg(unix)]
/// Add an attribute to the current text. Like italic or bold.
pub fn add_attr(&mut self, attr: Attribute) { pub fn add_attr(&mut self, attr: Attribute) {
self.attrs.push(attr); self.attrs.push(attr);
} }

View File

@ -1,4 +1,5 @@
//! This module contains the logic to style an object that contains some state witch can be styled. //! This module contains the logic to style an object that contains some state witch can be styled.
use super::{ScreenManager, ObjectStyle, Color}; use super::{ScreenManager, ObjectStyle, Color};
use std::fmt::{self, Display}; use std::fmt::{self, Display};
@ -14,7 +15,7 @@ use super::super::super::manager::WinApiScreenManager;
pub struct StyledObject<'terminal, D: Display> { pub struct StyledObject<'terminal, D: Display> {
pub object_style: ObjectStyle, pub object_style: ObjectStyle,
pub content: D, pub content: D,
pub screen_manager: &'terminal ScreenManager, pub screen_manager: &'terminal mut ScreenManager,
} }
impl<'terminal,D: Display> StyledObject<'terminal,D> { impl<'terminal,D: Display> StyledObject<'terminal,D> {
@ -144,7 +145,7 @@ impl<'terminal,D: Display> StyledObject<'terminal,D> {
impl<'terminal, D: Display> Display for StyledObject<'terminal,D> { impl<'terminal, D: Display> Display for StyledObject<'terminal,D> {
fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
let mut colored_terminal = super::super::super::style::color::color(&self.screen_manager); let mut colored_terminal = super::super::super::style::color::color(self.screen_manager);
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 {

View File

@ -1,3 +1,8 @@
//! This is an `WINAPI` specific implementation for styling related action.
//! This module is used for non supporting `ANSI` windows terminals.
//!
//! Windows versions lower then windows 10 are not supporting ANSI codes. Those versions will use this implementation instead.
use super::super::super::manager::WinApiScreenManager; use super::super::super::manager::WinApiScreenManager;
use super::{Color, ColorType, ITerminalColor, ScreenManager}; use super::{Color, ColorType, ITerminalColor, ScreenManager};
use kernel::windows_kernel::{csbi, kernel}; use kernel::windows_kernel::{csbi, kernel};

View File

@ -4,7 +4,7 @@
use super::super::cursor::cursor; use super::super::cursor::cursor;
use super::{ClearType, ITerminal, ScreenManager, functions}; use super::{ClearType, ITerminal, ScreenManager, functions};
/// This struct is an ansi implementation for terminal related actions. /// This struct is an ansi escape code implementation for terminal related actions.
pub struct AnsiTerminal; pub struct AnsiTerminal;
impl AnsiTerminal { impl AnsiTerminal {

View File

@ -1,10 +1,4 @@
//! Module that contains all the actions related to the terminal. //! Module that contains all the actions related to the terminal. like clearing, resizing and scrolling the terminal.
//!
//! We can think of:
//! - alternate screen
//! - raw mode
//! - clearing resizing scrolling the terminal.
//!
pub mod terminal; pub mod terminal;
@ -19,7 +13,7 @@ use self::ansi_terminal::AnsiTerminal;
pub use self::terminal::Terminal; pub use self::terminal::Terminal;
use super::{ ScreenManager, functions }; use super::{ ScreenManager, functions };
/// Enum that can be used for the kind of clearing that can be done in the terminal. /// Enum that specifies a way of clearing.
pub enum ClearType { pub enum ClearType {
All, All,
FromCursorDown, FromCursorDown,
@ -28,14 +22,14 @@ pub enum ClearType {
UntilNewLine, UntilNewLine,
} }
///! This trait defines the actions that can be preformed with the terminal. /// This trait defines the actions that can be preformed with the terminal color.
///! This trait can be implemented so that an concrete implementation of the ITerminal can forfill /// This trait can be implemented so that an concrete implementation of the ITerminalColor can forfill
///! the wishes to work on an specific platform. /// the wishes to work on an specific platform.
///! ///
///! ## For example: /// ## For example:
///! ///
///! 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 cursor 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 ITerminal { pub 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, screen_manager: &ScreenManager); fn clear(&self, clear_type: ClearType, screen_manager: &ScreenManager);

View File

@ -7,6 +7,21 @@ use std::fmt;
use std::io::Write; use std::io::Write;
/// Struct that stores an specific platform implementation for terminal related actions. /// Struct that stores an specific platform implementation for terminal related actions.
///
/// Check `/examples/version/terminal` in the library for more specific examples.
///
/// #Example
///
/// ```rust
///
/// let crossterm = Crossterm::new();
/// let term = crossterm.terminal();
///
/// term.scroll_down(5);
/// term.scroll_up(4);
/// let (with, height) = term.terminal_size();
///
/// ```
pub struct Terminal<'terminal> { pub struct Terminal<'terminal> {
terminal: Box<ITerminal>, terminal: Box<ITerminal>,
screen_manager: &'terminal ScreenManager, screen_manager: &'terminal ScreenManager,
@ -36,12 +51,8 @@ impl<'terminal> Terminal<'terminal> {
/// ///
/// ```rust /// ```rust
/// ///
/// extern crate crossterm; /// let crossterm = Crossterm::new();
/// use crossterm::terminal; /// let term = crossterm.terminal();
/// use crossterm::Context;
///
/// let context = Context::new();
/// let mut term = terminal::terminal(&context);
/// ///
/// // clear all cells in terminal. /// // clear all cells in terminal.
/// term.clear(terminal::ClearType::All); /// term.clear(terminal::ClearType::All);
@ -55,8 +66,8 @@ impl<'terminal> Terminal<'terminal> {
/// term.clear(terminal::ClearType::UntilNewLine); /// term.clear(terminal::ClearType::UntilNewLine);
/// ///
/// ``` /// ```
pub fn clear(&self, clear_type: ClearType) { pub fn clear(&mut self, clear_type: ClearType) {
self.terminal.clear(clear_type, &self.screen_manager); self.terminal.clear(clear_type, &mut self.screen_manager);
} }
/// Get the terminal size (x,y). /// Get the terminal size (x,y).
@ -69,8 +80,8 @@ impl<'terminal> Terminal<'terminal> {
/// use crossterm::terminal; /// use crossterm::terminal;
/// use crossterm::Context; /// use crossterm::Context;
/// ///
/// let context = Context::new(); /// let crossterm = Crossterm::new();
/// let mut term = terminal::terminal(&context); /// let term = crossterm.terminal();
/// ///
/// let size = term.terminal_size(); /// let size = term.terminal_size();
/// println!("{:?}", size); /// println!("{:?}", size);
@ -86,12 +97,8 @@ impl<'terminal> Terminal<'terminal> {
/// ///
/// ```rust /// ```rust
/// ///
/// extern crate crossterm; /// let crossterm = Crossterm::new();
/// use crossterm::terminal; /// let term = crossterm.terminal();
/// use crossterm::Context;
///
/// let context = Context::new();
/// let mut term = terminal::terminal(&context);
/// ///
/// // scroll up by 5 lines /// // scroll up by 5 lines
/// let size = term.scroll_up(5); /// let size = term.scroll_up(5);
@ -107,12 +114,8 @@ impl<'terminal> Terminal<'terminal> {
/// ///
/// ```rust /// ```rust
/// ///
/// extern crate crossterm; /// let crossterm = Crossterm::new();
/// use crossterm::terminal; /// let term = crossterm.terminal();
/// use crossterm::Context;
///
/// let context = Context::new();
/// let mut term = terminal::terminal(&context);
/// ///
/// // scroll down by 5 lines /// // scroll down by 5 lines
/// let size = term.scroll_down(5); /// let size = term.scroll_down(5);
@ -128,12 +131,8 @@ impl<'terminal> Terminal<'terminal> {
/// ///
/// ```rust /// ```rust
/// ///
/// extern crate crossterm; /// let crossterm = Crossterm::new();
/// use crossterm::terminal; /// let term = crossterm.terminal();
/// use crossterm::Context;
///
/// let context = Context::new();
/// let mut term = terminal::terminal(&context);
/// ///
/// // 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);
@ -143,53 +142,14 @@ impl<'terminal> Terminal<'terminal> {
self.terminal.set_size(width, height,&self.screen_manager); self.terminal.set_size(width, height,&self.screen_manager);
} }
/// Wraps an displayable object so it can be formatted with colors and attributes.
///
/// Check `/examples/color` in the libary for more spesific examples.
///
/// #Example
///
/// ```rust
/// extern crate crossterm;
///
/// use self::crossterm::style::{paint,Color};
///
/// fn main()
/// {
/// // Create an styledobject object from the text 'Unstyled font'
/// // Currently it has the default foregroundcolor and backgroundcolor.
/// println!("{}",paint("Unstyled font"));
///
/// // Create an displayable object from the text 'Colored font',
/// // Paint this with the `Red` foreground color and `Blue` backgroundcolor.
/// // Print the result.
/// let styledobject = paint("Colored font").with(Color::Red).on(Color::Blue);
/// println!("{}", styledobject);
///
/// // Or all in one line
/// println!("{}", paint("Colored font").with(Color::Red).on(Color::Blue));
/// }
///
/// ```
// pub fn paint<D>(&self, val: D) -> style::StyledObject<D>
// where
// D: fmt::Display,
// {
// style::ObjectStyle::new().apply_to(val, self.context.clone())
// }
/// Exit the current process. /// Exit the current process.
/// ///
/// #Example /// #Example
/// ///
/// ```rust /// ```rust
/// ///
/// extern crate crossterm; /// let crossterm = Crossterm::new();
/// use crossterm::terminal; /// let term = crossterm.terminal();
/// use crossterm::Context;
///
/// let context = Context::new();
/// let mut term = terminal::terminal(&context);
/// ///
/// let size = term.exit(); /// let size = term.exit();
/// ///
@ -204,12 +164,8 @@ impl<'terminal> Terminal<'terminal> {
/// ///
/// ```rust /// ```rust
/// ///
/// extern crate crossterm; /// let crossterm = Crossterm::new();
/// use crossterm::terminal; /// let term = crossterm.terminal();
/// use crossterm::Context;
///
/// let context = Context::new();
/// let mut term = terminal::terminal(&context);
/// ///
/// let size = term.write("Some text \n Some text on new line"); /// let size = term.write("Some text \n Some text on new line");
/// ///
@ -222,27 +178,7 @@ impl<'terminal> Terminal<'terminal> {
} }
} }
/// Get an Terminal implementation whereon terminal related actions can be performed. /// Get an terminal implementation whereon terminal related actions could performed
/// pub fn terminal(screen_manager: &mut ScreenManager) -> Terminal {
/// Check `/examples/version/terminal` in the libary for more spesific examples.
///
/// #Example
///
/// ```rust
///
/// extern crate crossterm;
/// use crossterm::terminal;
/// use crossterm::Context;
///
/// let context = Context::new();
///
/// let mut term = terminal::terminal(&context);
///
/// // scroll down by 5 lines
/// let size = term.scroll_down(5);
///
/// ```
///
pub fn terminal(screen_manager: &ScreenManager) -> Terminal {
Terminal::new(screen_manager) Terminal::new(screen_manager)
} }

View File

@ -1,12 +1,14 @@
//! This is an `WINAPI` specific implementation for terminal related action. //! This is an `WINAPI` specific implementation for terminal related action.
//! This module is used for non supporting `ANSI` windows terminals. //! This module is used for non supporting `ANSI` windows terminals.
//!
//! Windows versions lower then windows 10 are not supporting ANSI codes. Those versions will use this implementation instead.
use super::{ClearType, ITerminal, ScreenManager, functions}; use super::{ClearType, ITerminal, ScreenManager, functions};
use super::super::super::cursor::cursor; use super::super::super::cursor::cursor;
use kernel::windows_kernel::{csbi, kernel, terminal, writing}; use kernel::windows_kernel::{csbi, kernel, terminal, writing};
use winapi::um::wincon::{CONSOLE_SCREEN_BUFFER_INFO, COORD, SMALL_RECT}; use winapi::um::wincon::{CONSOLE_SCREEN_BUFFER_INFO, COORD, SMALL_RECT};
/// This struct is an windows implementation for terminal related actions. /// This struct is an winapi implementation for terminal related actions.
pub struct WinApiTerminal; pub struct WinApiTerminal;
impl WinApiTerminal { impl WinApiTerminal {
@ -21,7 +23,7 @@ impl ITerminal for WinApiTerminal {
let pos = cursor(screen_manager).pos(); let pos = cursor(screen_manager).pos();
match clear_type { match clear_type {
ClearType::All => clear_entire_screen(csbi, &screen_manager), ClearType::All => { clear_entire_screen(csbi, screen_manager); },
ClearType::FromCursorDown => clear_after_cursor(pos, csbi, screen_manager), ClearType::FromCursorDown => clear_after_cursor(pos, csbi, screen_manager),
ClearType::FromCursorUp => clear_before_cursor(pos, csbi, screen_manager), ClearType::FromCursorUp => clear_before_cursor(pos, csbi, screen_manager),
ClearType::CurrentLine => clear_current_line(pos, csbi, screen_manager), ClearType::CurrentLine => clear_current_line(pos, csbi, screen_manager),
@ -57,8 +59,6 @@ impl ITerminal for WinApiTerminal {
// Set srctWindow to the current window size and location. // Set srctWindow to the current window size and location.
let mut srct_window = csbi.srWindow; let mut srct_window = csbi.srWindow;
// panic!("window top: {} , window bottom: {} | {}, {}", srct_window.Top, srct_window.Bottom, csbi.dwSize.Y, csbi.dwSize.X);
// Set srctWindow to the current window size and location. // Set srctWindow to the current window size and location.
srct_window = csbi.srWindow; srct_window = csbi.srWindow;
@ -201,7 +201,7 @@ pub fn clear_before_cursor(
// get sum cells before cursor // get sum cells before cursor
let cells_to_write = (csbi.dwSize.X as u32 * ypos as u32) + (xpos as u32 + 1); let cells_to_write = (csbi.dwSize.X as u32 * ypos as u32) + (xpos as u32 + 1);
clear(start_location, cells_to_write, &screen_manager); clear(start_location, cells_to_write, screen_manager);
} }
pub fn clear_entire_screen(csbi: CONSOLE_SCREEN_BUFFER_INFO, screen_manager: &ScreenManager) { pub fn clear_entire_screen(csbi: CONSOLE_SCREEN_BUFFER_INFO, screen_manager: &ScreenManager) {
@ -222,7 +222,7 @@ pub fn clear_entire_screen(csbi: CONSOLE_SCREEN_BUFFER_INFO, screen_manager: &Sc
clear(start_location, cells_to_write, &screen_manager); clear(start_location, cells_to_write, &screen_manager);
// put the cursor back at (0, 0) // put the cursor back at (0, 0)
cursor(&screen_manager).goto(0, 0); cursor(screen_manager).goto(0, 0);
} }
pub fn clear_current_line( pub fn clear_current_line(
@ -247,7 +247,7 @@ pub fn clear_current_line(
clear(start_location, cells_to_write, screen_manager); clear(start_location, cells_to_write, screen_manager);
// put the cursor back at 1 cell on current row // put the cursor back at 1 cell on current row
cursor(&screen_manager).goto(0, y); cursor(screen_manager).goto(0, y);
} }
pub fn clear_until_line(pos: (u16, u16), csbi: CONSOLE_SCREEN_BUFFER_INFO, screen_manager: &ScreenManager) { pub fn clear_until_line(pos: (u16, u16), csbi: CONSOLE_SCREEN_BUFFER_INFO, screen_manager: &ScreenManager) {
@ -264,7 +264,7 @@ pub fn clear_until_line(pos: (u16, u16), csbi: CONSOLE_SCREEN_BUFFER_INFO, scree
clear(start_location, cells_to_write, &screen_manager); clear(start_location, cells_to_write, &screen_manager);
// put the cursor back at original cursor position // put the cursor back at original cursor position
cursor(&screen_manager).goto(x, y); cursor(screen_manager).goto(x, y);
} }
fn clear(start_loaction: COORD, cells_to_write: u32, screen_manager: &ScreenManager) { fn clear(start_loaction: COORD, cells_to_write: u32, screen_manager: &ScreenManager) {
@ -292,6 +292,6 @@ fn clear(start_loaction: COORD, cells_to_write: u32, screen_manager: &ScreenMana
); );
if !success { if !success {
panic!("Couldnot reset attributes after cursor"); panic!("Could not reset attributes after cursor");
} }
} }

6
write_test/Cargo.toml Normal file
View File

@ -0,0 +1,6 @@
[package]
name = "write_test"
version = "0.1.0"
authors = ["TimonPost <timonpost@hotmail.nl>"]
[dependencies]

3
write_test/src/main.rs Normal file
View File

@ -0,0 +1,3 @@
fn main() {
println!("Hello, world!");
}