added examples and changed comments
This commit is contained in:
parent
6970dfadd8
commit
b3081fd9c0
@ -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);
|
|
||||||
}
|
}
|
||||||
|
@ -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),
|
||||||
|
@ -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<()>;
|
||||||
|
@ -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(())
|
||||||
}
|
}
|
||||||
|
@ -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())
|
||||||
|
// }
|
@ -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>>(
|
||||||
|
@ -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;
|
||||||
|
|
||||||
|
@ -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())
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
|
@ -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};
|
||||||
|
@ -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;
|
||||||
|
@ -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
|
||||||
|
@ -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;
|
||||||
|
@ -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 context = Context::new();
|
|
||||||
///
|
|
||||||
/// // Get the cursor
|
|
||||||
/// let mut cursor = cursor(&context);
|
|
||||||
/// // get the cursor position.
|
|
||||||
/// let (x,y) = cursor.pos();
|
/// 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()
|
|
||||||
/// {
|
|
||||||
/// 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
|
/// // Move the cursor to position 3 times to the up in the terminal
|
||||||
/// cursor.move_up(3);
|
/// 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();
|
|
||||||
///
|
|
||||||
/// // Get the cursor
|
|
||||||
/// let mut cursor = cursor(&context);
|
|
||||||
/// // 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<'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()
|
|
||||||
/// {
|
|
||||||
/// 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
|
/// // 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<'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()
|
|
||||||
/// {
|
|
||||||
/// 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
|
/// // Move the cursor to position 3 times to the left in the terminal
|
||||||
/// cursor.move_left(3);
|
/// 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)
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
|
|
||||||
|
@ -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;
|
||||||
|
|
||||||
|
@ -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)
|
||||||
}
|
}
|
||||||
|
@ -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>>,
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
|
@ -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;
|
||||||
|
@ -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;
|
|
||||||
|
|
||||||
let mut output = mx.lock().unwrap();
|
|
||||||
write!(output, "{}", string)?;
|
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,
|
||||||
}
|
}
|
||||||
|
@ -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()
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
|
@ -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(),
|
||||||
|
@ -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 {
|
||||||
|
@ -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)
|
||||||
}
|
}
|
||||||
|
@ -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,
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
@ -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 {
|
||||||
|
@ -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};
|
||||||
|
@ -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 {
|
||||||
|
@ -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);
|
||||||
|
@ -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)
|
||||||
}
|
}
|
||||||
|
@ -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
6
write_test/Cargo.toml
Normal 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
3
write_test/src/main.rs
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
fn main() {
|
||||||
|
println!("Hello, world!");
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user