Crossterm works for unix now, refactored all comments and refactored code. Changed names, Making things ready for crossterm release 0.1

This commit is contained in:
Timon Post 2018-01-17 23:06:45 +01:00
parent 2bdeeafded
commit 6c4f39a0ce
44 changed files with 1094 additions and 613 deletions

View File

@ -4,12 +4,11 @@ version = "0.1.0"
authors = ["T <timonpost@hotmail.nl>"] authors = ["T <timonpost@hotmail.nl>"]
[dependencies] [dependencies]
[target.'cfg(target_os = "windows")'.dependencies] [target.'cfg(windows)'.dependencies]
winapi = "0.2.8" winapi = "0.2.8"
kernel32-sys = "0.2.1" kernel32-sys = "0.2.1"
[[bin]] [target.'cfg(unix)'.dependencies]
name="a" libc = "0.2"
path="examples\\bin.rs"

127
README.md
View File

@ -1,5 +1,126 @@
# crossterm # Crossterm | crossplatform terminal library written in rust.
Ever got disappointed when a terminal library for rust was only written for unix systems?
Crossterm provides the same terminal functionality for both windows and unix systems.
Crossterm aims to be simple and easy to call in code.
True the simplicty of crossterm you do not have to worry about the platform your working with.
You can just call some module and unther water it will check what to do based on the current platform.
## Getting Started
Add the crossterm package to your `Cargo.toml` file.
```
[dependencies]
crossterm = "*"
```
Add the crate to your solution.
And use the crossterm modules withs you want to use.
```
extern crate crossterm;
// this module is used for styling the terminal
use self::crossterm::crossterm_style::*;
// this module is used for cursor related actions
use self::crossterm::crossterm_cursor::*;
// this mudule is used for terminal related actions
use self::crossterm::crossterm_terminal::*;
```
## Documentation
Documentation for the code can be found here ...
## Examples
For detailed examples of all crossterm functionalities check the `./examples/` direcory.
### Styled font
```
// Pass an string to the `paint()` method with you want to paint.
// This will give you an object back wits can be styled and displayed.
let mut styledobject = paint("Red font on blue background color");
// Set the foreground color.
styledobject = styledobject.with(Color::Red);
// Set the background color.
styledobject = styledobject.on(Color::Blue);
// Print the styled object with the foregroundcolor `Red` and backgroundcolor `Blue`
println!("{}", styledobject);
// Crossterm provides method chaining so that the above points can be inlined.
println!("{}", paint("Red font on blue background color").with(Color::Red).on(Color::Blue));
```
### Cursor
### Terminal
## Features crossterm 0.1
- Cursor movement.
- Up, Down, Left, Right.
- Goto an certain position.
- Styled output
- Foreground color (16 base colors)
- Background color (16 base colors)
- Terminal
- Clearing
- Scrolling
- Size
- Detailed documentation on every item.
- Full examples for every call.
## Tested terminals
- Windows Powershell
- Windows 10 (pro)
- Windows CMD
- Windows 10 (pro)
- Ubuntu Desktop Terminal
- Ubuntu 17.10
The above terminals have been tested.
Crossterm should works also for windows 7, 8 consoles and all ansi suportable consoles.
But these are yet to be tested.
If you have used this library for an terminal other than the above list without issues feel free to add it to the above list.
## Notice
This library is not totaly stable **yet**. There will not be changed mutch in the code design so do not worry to mutch.
If there are any changes that affect previous versions I will describe what to change when upgrading crossterm to new version.
## Todo crossterm 0.2
- Handling mouse events
- Inplementing 256 colors for terminals that support those colors.
- Handling key events
- Tests
## Contributing
Please read [CONTRIBUTING.md](https://gist.github.com/PurpleBooth/b24679402957c63ec426) for details on our code of conduct, and the process for submitting pull requests to us.
## Versioning
The current version is crossterm 0.1, every merge I do the version go's up like 0.1.0 -> 0.1.1 -> 0.1.2.
When new features arive the packages will go up like 0.1 -> 0.2 -> 0.3
## Authors
* **Timon Post** - *Project Owner*
See also the list of [contributors](https://github.com/your/project/contributors) who participated in this project.
## License
This project is licensed under the MIT License - see the [LICENSE.md](LICENSE.md) file for details
Cross platform terminal library written in rust
Ever got disappointed when a terminal library was only written for unix systems? You are not the only one... This library provides alot of the same functionality as termion but then for both windows and unix systems in an client friendly interface.

View File

@ -1,49 +1,18 @@
extern crate crossterm; extern crate crossterm;
use self::crossterm::terminal_style::*; use self::crossterm::crossterm_style::*;
use self::crossterm::terminal_cursor::*; use self::crossterm::crossterm_cursor::*;
use self::crossterm::terminal::*; use self::crossterm::crossterm_terminal::*;
use std::io::{stdin, stdout, Write}; use std::io::{stdin, stdout, Write};
pub mod color;
pub mod cursor;
pub mod terminal;
fn main() { fn main() {
terminal::get().clear(ClearType::All);
for y in 0..21 { terminal_cursor::get().goto(5,5);
for x in 0..21 {
if (x == 0 || y == 0) || (x == 20 || y == 20) {
print!("{}", paint("").with(Color::Red));
} else {
print!("{}", paint(" ").with(Color::Blue).on(Color::Blue));
}
}
println!(); println!();
}
let mut curs = cursor::get();
{
curs.goto(4, 1).print("@");
}
let mut terminal = terminal::get();
// clear all cells in terminal.
terminal.clear(ClearType::All);
// clear all cells after the cursor position in terminal.
terminal.clear(ClearType::AfterCursor);
// clear all cells before cursor in terminal.
terminal.clear(ClearType::BeforeCursor);
// clear current line cells in terminal.
terminal.clear(ClearType::CurrentLine);
// clear all cells until new line in terminal.
terminal.clear(ClearType::UntilNewLine);
let size = terminal.terminal_size();
println!("{:?}", size);
// scrolling in terminal
terminal.scroll_up(1);
terminal.scroll_down();
cursor::get().goto(0,30);
} }

100
examples/color/mod.rs Normal file
View File

@ -0,0 +1,100 @@
//!
//! Color Examples
//!
extern crate crossterm;
use self::crossterm::crossterm_style::{paint, Color};
/// print some red font | demonstration.
pub fn paint_foreground()
{
// Pass an string to the `paint()` method with you want to paint.
// This will give you an object back wits can be styled and displayed.
let mut styledobject = paint("Red font");
// Call the method `with()` on the object given by `paint()` and pass in any Color from the Color enum.
styledobject = styledobject.with(Color::Red);
// Print the object to the console and see the result.
println!("{}", styledobject);
// Crossterm provides method chaining so that the above points can be inlined.
println!("{}", paint("Red font").with(Color::Red));
}
/// print some font on red background | demonstration.
pub fn paint_background()
{
// Pass an string to the `paint()` method with you want to paint.
// This will give you an object back wits can be styled and displayed.
let mut styledobject = paint("Red background color");
// Call the method `on()` on the object given by `paint()` and pass in an Color from the Color enum.
styledobject = styledobject.on(Color::Blue);
// Print the object to the console and check see the result
println!("{}", styledobject);
// Crossterm provides method chaining so that the above points can be inlined.
println!("{}", paint("Red background color").on(Color::Red));
}
/// print font with fore- background color | demonstration.
pub fn paint_foreground_and_background()
{
// Pass an string to the `paint()` method with you want to paint.
// This will give you an object back wits can be styled and displayed.
let mut styledobject = paint("Red font on blue background color");
/* Foreground color:
Call the method `with()` on the object given by `paint()`
Pass in an Color from the Color enum.
*/
styledobject = styledobject.with(Color::Red);
/* Background color:
Call the method `on()` on the object given by `paint()`
Pass in an Color from the Color enum.
*/
styledobject = styledobject.on(Color::Blue);
// Print the object to the console and see the result.
println!("{}", styledobject);
// Crossterm provides method chaining so that the above points can be inlined.
println!("{}", paint("Red font on blue background color").with(Color::Red).on(Color::Blue));
}
/// Print all available foreground colors | demonstration.
pub fn print_all_foreground_colors()
{
println!("Black : \t {}", paint("").with(Color::Black));
println!("Red : \t\t {}", paint("").with(Color::Red));
println!("Dark Red: \t {}", paint("").with(Color::DarkRed));
println!("Green : \t {}", paint("").with(Color::Green));
println!("Dark Green : \t {}", paint("").with(Color::DarkGreen));
println!("Yellow : \t {}", paint("").with(Color::Yellow));
println!("Dark Yellow : \t {}", paint("").with(Color::DarkYellow));
println!("Blue : \t\t {}", paint("").with(Color::Blue));
println!("Dark Blue : \t {}", paint("").with(Color::DarkBlue));
println!("Magenta : \t {}", paint("").with(Color::Magenta));
println!("Dark Magenta : \t {}", paint("").with(Color::DarkMagenta));
println!("Cyan : \t\t {}", paint("").with(Color::Cyan));
println!("Dark Cyan : \t {}", paint("").with(Color::DarkCyan));
println!("Grey : \t\t {}", paint("").with(Color::Grey));
println!("White : \t {}", paint("").with(Color::White));
}
/// Print all available foreground colors | demonstration.
pub fn print_all_background_colors()
{
println!("Black : \t {}", paint(" ").on(Color::Black));
println!("Red : \t\t {}", paint(" ").on(Color::Red));
println!("Dark Red: \t {}", paint(" ").on(Color::DarkRed));
println!("Green : \t {}", paint(" ").on(Color::Green));
println!("Dark Green : \t {}", paint(" ").on(Color::DarkGreen));
println!("Yellow : \t {}", paint(" ").on(Color::Yellow));
println!("Dark Yellow : \t {}", paint(" ").on(Color::DarkYellow));
println!("Blue : \t\t {}", paint(" ").on(Color::Blue));
println!("Dark Blue : \t {}", paint(" ").on(Color::DarkBlue));
println!("Magenta : \t {}", paint(" ").on(Color::Magenta));
println!("Dark Magenta : \t {}", paint(" ").on(Color::DarkMagenta));
println!("Cyan : \t\t {}", paint(" ").on(Color::Cyan));
println!("Dark Cyan : \t {}", paint(" ").on(Color::DarkCyan));
println!("Grey : \t\t {}", paint(" ").on(Color::Grey));
println!("White : \t {}", paint(" ").on(Color::White));
}

98
examples/cursor/mod.rs Normal file
View File

@ -0,0 +1,98 @@
//!
//! Cursor Examples
//!
extern crate crossterm;
use self::crossterm::crossterm_cursor::{get, TerminalCursor};
/// Set the cursor to position X: 10, Y: 5 in the terminal.
pub fn goto()
{
// Get the cursor
let mut cursor = get();
// Set the cursor to position X: 10, Y: 5 in the terminal
cursor.goto(10,5);
}
/// Move the cursor 3 up | demonstration.
pub fn move_up()
{
// Get the cursor
let mut cursor = get();
// Move the cursor to position 3 times to the up in the terminal
cursor.move_up(3);
}
/// Move the cursor 3 to the right | demonstration.
pub fn move_right()
{
// Get the cursor
let mut cursor = get();
// Move the cursor to position 3 times to the right in the terminal
cursor.move_right(3);
}
/// Move the cursor 3 down | demonstration.
pub fn move_down()
{
// Get the cursor
let mut cursor = get();
// Move the cursor to position 3 times to the down in the terminal
cursor.move_down(3);
}
/// Move the cursor 3 to the left | demonstration.
pub fn move_left()
{
// Get the cursor
let mut cursor = get();
// Move the cursor to position 3 times to the left in the terminal
cursor.move_left(3);
}
/// Print character at X: 10 Y: 5 | demonstration.
pub fn print()
{
// To print an some displayable content on an certain position.
// Get the cursor
let mut cursor = get();
// Set the cursor to position X: 10, Y: 5 in the terminal
cursor.goto(10,5);
// Print the @ symbol at position X: 10, Y: 5 in the terminal
print!("@");
// Rust is line buffered inorder to print at an certain position we need to clear the buffer first.
use std;
use std::io::Write;
std::io::stdout().flush();
/* Because the above method is a little to mutch code,
you can use the `print()` method for printing an value at an certain position in the terminal.
Crossterm provides method chaining so that the above points can be inlined.
*/
get().goto(10,5).print("@");
}

View File

@ -1,8 +0,0 @@
// extern crate crossterm;
// use self::crossterm::cursor;
// pub fn goto(x: i16, y: i16)
// {
// cursor::get().goto(x,y);
// }

View File

@ -1,24 +0,0 @@
fn main()
{
let mut terminal = terminal::get();
// clear all cells in terminal.
terminal.clear(ClearType::All);
// clear all cells after the cursor position in terminal.
terminal.clear(ClearType::AfterCursor);
// clear all cells before cursor in terminal.
terminal.clear(ClearType::BeforeCursor);
// clear current line cells in terminal.
terminal.clear(ClearType::CurrentLine);
// clear all cells until new line in terminal.
terminal.clear(ClearType::UntilNewLine);
// get terminal size (x,y)
let size = terminal.terminal_size();
println!("{:?}", size);
// scrolling in terminal
terminal.scroll_up();
terminal.scroll_down();
}

118
examples/terminal/mod.rs Normal file
View File

@ -0,0 +1,118 @@
//!
//! Terminal Examples
//!
extern crate crossterm;
use crossterm::crossterm_terminal::{get, Terminal, ClearType};
use crossterm::terminal_cursor;
fn print_test_data()
{
for i in 0..100 {
println!("abcdefghijTest data to test terminal: {}",i);
}
}
/// Clear all lines in terminal | demonstration
pub fn clear_all_lines()
{
// Get terminal
let mut terminal = get();
print_test_data();
// Clear all lines in terminal;
terminal.clear(ClearType::All);
}
/// Clear all lines from cursor position X:4, Y:4 down | demonstration
pub fn clear_from_cursor_down()
{
// Get terminal
let mut terminal = get();
print_test_data();
// Set terminal cursor position (see example for more info).
terminal_cursor::get().goto(4,4);
// Clear all cells from current cursor position down.
terminal.clear(ClearType::FromCursorDown);
}
/// Clear all lines from cursor position X:4, Y:4 up | demonstration
pub fn clear_from_cursor_up()
{
// Get terminal
let mut terminal = get();
print_test_data();
// Set terminal cursor position (see example for more info).
terminal_cursor::get().goto(4,4);
// Clear all cells from current cursor position down.
terminal.clear(ClearType::FromCursorUp);
}
/// Clear all lines from cursor position X:4, Y:4 up | demonstration
pub fn clear_current_line()
{
// Get terminal
let mut terminal = get();
print_test_data();
// Set terminal cursor position (see example for more info).
terminal_cursor::get().goto(4,4);
// Clear current line cells.
terminal.clear(ClearType::CurrentLine);
}
/// Clear all lines from cursor position X:4, Y:4 up | demonstration
pub fn clear_until_new_line()
{
// Get terminal
let mut terminal = get();
print_test_data();
// Set terminal cursor position (see example for more info).
terminal_cursor::get().goto(4,4);
// Clear all the cells until next line.
terminal.clear(ClearType::UntilNewLine);
}
pub fn print_terminal_size()
{
// Get terminal
let mut terminal = get();
// Get terminal size
let terminal_size = terminal.terminal_size().unwrap();
// Print results
print!("X: {}, y: {}", terminal_size.0, terminal_size.1);
}
// scroll down 10 linexs
pub fn scroll_down()
{
print_test_data();
// Get terminal
let mut terminal = get();
// Scroll down 10 lines.
let terminal_size = terminal.scroll_down(10);
}
// scroll down 10 linexs
pub fn scroll_up()
{
print_test_data();
// Get terminal
let mut terminal = get();
// Scroll up 10 lines.
let terminal_size = terminal.scroll_up(2);
}

View File

@ -0,0 +1,47 @@
use std::io;
use std::io::Write;
use Construct;
use super::base_cursor::ITerminalCursor;
/// This struct is an ansi implementation for cursor related actions.
pub struct AnsiCursor;
impl Construct for AnsiCursor {
fn new() -> Box<AnsiCursor> {
Box::from(AnsiCursor {})
}
}
impl ITerminalCursor for AnsiCursor {
fn goto(&self, x: u16, y: u16) {
let mut some_writer = io::stdout();
// ANSI codes are one-based. I want 0 based so we just need to increment and x,y.
write!(&mut some_writer, csi!("{};{}H"), y + 1, x +1);
}
fn pos(&self) -> (i16, i16) {
(0, 0)
}
fn move_up(&self, count: u16) {
let mut some_writer = io::stdout();
write!(&mut some_writer, csi!("{}A"), count);
}
fn move_right(&self, count: u16) {
let mut some_writer = io::stdout();
write!(&mut some_writer, csi!("{}C"), count);
}
fn move_down(&self, count: u16) {
let mut some_writer = io::stdout();
write!(&mut some_writer, csi!("{}B"), count);
}
fn move_left(&self, count: u16) {
let mut some_writer = io::stdout();
write!(&mut some_writer, csi!("{}D"), count);
}
}

View File

@ -0,0 +1,23 @@
//! This trait defines the actions that can be preformed with the termial cursor.
//! This trait can be inplemented so that an concrete inplementation of the ITerminalCursor can forfill
//! the wishes to work on an specific platform.
//!
//! ## For example:
//!
//! This trait is inplemented for winapi (Windows specific) and ansi (Unix specific),
//! so that the cursor related actions can be preformed on both unix and windows systems.
pub trait ITerminalCursor {
/// Goto some location (x,y) in the terminal.
fn goto(&self, x: u16, y: u16);
/// Get the location (x,y) of the current curor in the terminal
fn pos(&self) -> (i16, i16);
/// Move cursor n times up
fn move_up(&self, count: u16);
/// Move the cursor `n` times to the right.
fn move_right(&self, count: u16);
/// Move the cursor `n` times down.
fn move_down(&self, count: u16);
/// Move the cursor `n` times left.
fn move_left(&self, count: u16);
}

View File

@ -1,9 +1,17 @@
//! With this module you can perform actions that are cursor related.
//! Like changing and displaying the position of the cursor in terminal.
use std::fmt::Display; use std::fmt::Display;
use Construct; use Construct;
use super::base_cursor::ITerminalCursor; use super::base_cursor::ITerminalCursor;
use super::{AnsiCursor, NoCursor, WinApiCursor};
/// Struct on wits cursor realated actions can be performed. #[cfg(unix)]
use super::AnsiCursor;
#[cfg(windows)]
use super::WinApiCursor;
/// Struct that stores an specific platform implementation for cursor related actions.
pub struct TerminalCursor { pub struct TerminalCursor {
terminal_cursor: Option<Box<ITerminalCursor>>, terminal_cursor: Option<Box<ITerminalCursor>>,
} }
@ -22,7 +30,11 @@ impl TerminalCursor {
/// ///
/// ```rust /// ```rust
/// ///
/// cursor::get().goto(10,10); /// extern crate crossterm;
///
/// use self::crossterm::crossterm_cursor;
///
/// crossterm_cursor::get().goto(10,10);
/// ///
/// ``` /// ```
pub fn goto(&mut self, x: u16, y: u16) -> &mut TerminalCursor { pub fn goto(&mut self, x: u16, y: u16) -> &mut TerminalCursor {
@ -39,7 +51,11 @@ impl TerminalCursor {
/// ///
/// ```rust /// ```rust
/// ///
/// let pos = cursor::get().pos(); /// extern crate crossterm;
///
/// use self::crossterm::crossterm_cursor;
///
/// let pos = crossterm_cursor::get().pos();
/// println!("{:?}", pos); /// println!("{:?}", pos);
/// ///
/// ``` /// ```
@ -58,11 +74,16 @@ impl TerminalCursor {
/// ///
/// ```rust /// ```rust
/// ///
/// // move 1 time up /// extern crate crossterm;
/// cursor::get().move_up(1); ///
/// use self::crossterm::crossterm_cursor;
///
/// // Move 1 time up
/// crossterm_cursor::get().move_up(1);
///
/// // Move 2 times up
/// crossterm_cursor::get().move_up(2);
/// ///
/// // move 2 time up
/// cursor::get().move_up(2); ///
/// ``` /// ```
pub fn move_up(&mut self, count: u16) -> &mut TerminalCursor { pub fn move_up(&mut self, count: u16) -> &mut TerminalCursor {
&self.init(); &self.init();
@ -78,11 +99,15 @@ impl TerminalCursor {
/// ///
/// ```rust /// ```rust
/// ///
/// // move 1 time right /// extern crate crossterm;
/// cursor::get().move_right(1);
/// ///
/// // move 2 time right /// use self::crossterm::crossterm_cursor;
/// cursor::get().move_right(2); ///
/// // move 1 time right
/// crossterm_cursor::get().move_right(1);
///
/// // move 2 times right
/// crossterm_cursor::get().move_right(2);
/// ///
/// ``` /// ```
pub fn move_right(&mut self, count: u16) -> &mut TerminalCursor { pub fn move_right(&mut self, count: u16) -> &mut TerminalCursor {
@ -99,11 +124,15 @@ impl TerminalCursor {
/// ///
/// ```rust /// ```rust
/// ///
/// // move 1 time down /// extern crate crossterm;
/// cursor::get().move_down(1);
/// ///
/// // move 2 time down /// use self::crossterm::crossterm_cursor;
/// cursor::get().move_down(2); ///
/// // move 1 time down
/// crossterm_cursor::get().move_down(1);
///
/// // move 2 times down
/// crossterm_cursor::get().move_down(2);
/// ///
/// ``` /// ```
pub fn move_down(&mut self, count: u16) -> &mut TerminalCursor { pub fn move_down(&mut self, count: u16) -> &mut TerminalCursor {
@ -120,11 +149,15 @@ impl TerminalCursor {
/// ///
/// ```rust /// ```rust
/// ///
/// extern crate crossterm;
///
/// use self::crossterm::crossterm_cursor;
///
/// // move 1 time left /// // move 1 time left
/// cursor::get().move_left(1); /// crossterm_cursor::get().move_left(1);
/// ///
/// // move 2 time left /// // move 2 time left
/// cursor::get().move_left(2); /// crossterm_cursor::get().move_left(2);
/// ///
/// ``` /// ```
pub fn move_left(&mut self, count: u16) -> &mut TerminalCursor { pub fn move_left(&mut self, count: u16) -> &mut TerminalCursor {
@ -137,19 +170,32 @@ impl TerminalCursor {
/// Print an value at the current cursor position. /// Print an value at the current cursor position.
/// ///
/// This method prints an value and clears the buffer. /// This method prints an value with `print!()` and clears the buffer afterwards.
/// If you do not clear the buffer the character will not be printed at the wished position. /// Rust's standard output is line-buffered. So your text gets sent to the console one line at a time.
/// If you set the curosr position and try to `print!()` at that position and do not clear the buffer, than the character will not be printed at that position.
/// But will be printed when the next `println()` will be done.
///
/// With this method you can print any displayable value at a certain position and the output buffer will be cleared afterwards.
///
/// For more information see the cursor example in /examples/cursor
///
/// #Example /// #Example
/// ///
/// ```rust /// ```rust
/// ///
/// extern crate crossterm;
///
/// use self::crossterm::crossterm_cursor;
/// use std;
/// use std::io::Write;
///
/// // of course we can just do this. /// // of course we can just do this.
/// cursor::get().goto(10,10); /// crossterm_cursor::get().goto(10,10);
/// print!("@"); /// print!("@");
/// std::io::stdout().flush(); /// std::io::stdout().flush();
/// ///
/// // but now we can chain the methods so it looks cleaner and it automatically flushes the buffer. /// // but now we can chain the methods so it looks cleaner and it automatically flushes the buffer.
/// cursor::get() /// crossterm_cursor::get()
/// .goto(10,10) /// .goto(10,10)
/// .print("@"); /// .print("@");
/// ///
@ -166,16 +212,33 @@ impl TerminalCursor {
/// Get the concrete ITerminalCursor implementation based on the current operating system. /// Get the concrete ITerminalCursor implementation based on the current operating system.
fn get_cursor_options() -> Option<Box<ITerminalCursor>> { fn get_cursor_options() -> Option<Box<ITerminalCursor>> {
if cfg!(target_os = "linux") { #[cfg(unix)]
Some(AnsiCursor::new()) return Some(AnsiCursor::new());
} else if cfg!(target_os = "windows") {
Some(WinApiCursor::new()) #[cfg(windows)]
} else { return Some(WinApiCursor::new());
Some(NoCursor::new())
}
} }
/// Get terminal cursor options whereon cursor related actions can be performed. /// Get an TerminalCursor implementation whereon cursor related actions can be performed.
///
/// Check `/examples/cursor` in the libary for more spesific examples.
///
/// #Example
///
/// ```rust
///
/// extern crate crossterm;
///
/// use self::crossterm::crossterm_cursor;
///
/// // Get cursor and goto pos X: 5, Y: 10
/// let mut cursor = crossterm_cursor::get();
/// cursor.goto(5,10);
///
/// //Or you can do it in one line.
/// crossterm_cursor::get().goto(5,10);
///
/// ```
pub fn get() -> Box<TerminalCursor> { pub fn get() -> Box<TerminalCursor> {
Box::from(TerminalCursor { Box::from(TerminalCursor {
terminal_cursor: get_cursor_options(), terminal_cursor: get_cursor_options(),

View File

@ -1,11 +1,15 @@
mod base_cursor; mod base_cursor;
mod no_cursor; mod cursor;
mod ansi_cursor;
mod winapi_cursor;
pub mod cursor;
use self::no_cursor::NoCursor; #[cfg(unix)]
mod ansi_cursor;
#[cfg(windows)]
mod winapi_cursor;
#[cfg(unix)]
use self::ansi_cursor::AnsiCursor; use self::ansi_cursor::AnsiCursor;
#[cfg(windows)]
use self::winapi_cursor::WinApiCursor; use self::winapi_cursor::WinApiCursor;
pub use cursor::{get, TerminalCursor}; pub use self::cursor::{ get, TerminalCursor };

View File

@ -2,7 +2,7 @@ use Construct;
use kernel::windows_kernel::cursor; use kernel::windows_kernel::cursor;
use super::base_cursor::ITerminalCursor; use super::base_cursor::ITerminalCursor;
/// This struct will be used for cursor actions in windows terminals performed by winapi. /// This struct is an windows implementation for cursor related actions.
pub struct WinApiCursor { pub struct WinApiCursor {
has_moved: bool, has_moved: bool,
} }

View File

@ -0,0 +1,58 @@
use std::io;
use std::io::Write;
use std::string::String;
use Construct;
use super::color::{Color, ColorType};
use super::base_color::ITerminalColor;
/// This struct is an ansi implementation for color related actions.
#[derive(Debug)]
pub struct ANSIColor;
impl Construct for ANSIColor {
fn new() -> Box<ANSIColor> {
Box::from(ANSIColor {})
}
}
impl ITerminalColor for ANSIColor {
fn set_fg(&self, fg_color: Color) {
let mut some_writer = io::stdout();
write!(&mut some_writer, csi!("38;5;{}m"), self.color_value(fg_color, ColorType::Foreground));
}
fn set_bg(&self, bg_color: Color) {
let mut some_writer = io::stdout();
write!(&mut some_writer, csi!("48;5;{}m"), self.color_value(bg_color, ColorType::Background));
}
fn reset(&self) {
let mut some_writer = io::stdout();
write!(&mut some_writer, csi!("0m"));
}
fn color_value(&self, color: Color, color_type: ColorType) -> String {
// Construct ANSI escape color code string. ;1 is for the brightness
match color {
Color::Black => "0",
Color::Red => "9",
Color::DarkRed =>"1",
Color::Green => "10",
Color::DarkGreen => "2",
Color::Yellow => "11",
Color::DarkYellow => "3",
Color::Blue => "12",
Color::DarkBlue => "4",
Color::Magenta => "13",
Color::DarkMagenta => "5",
Color::Cyan => "14",
Color::DarkCyan => "6",
Color::Grey => "15",
Color::White => "7",
}.to_string()
}
}

View File

@ -0,0 +1,24 @@
///!
///! This trait defines the actions that can be preformed with the termial color.
///! This trait can be inplemented so that an concrete inplementation of the ITerminalColor can forfill
///! the wishes to work on an specific platform.
///!
///! ## For example:
///!
///! This trait is inplemented for winapi (Windows specific) and ansi (Unix specific),
///! so that the color related actions can be preformed on both unix and windows systems.
///!
use std::fmt;
use super::color::{Color, ColorType};
pub trait ITerminalColor {
/// Set the forground color to the given color.
fn set_fg(&self, fg_color: Color);
/// Set the background color to the given color.
fn set_bg(&self, fg_color: Color);
/// Reset the terminal color to default.
fn reset(&self);
/// Gets an value that represents an color from the given `Color` and `ColorType`.
fn color_value(&self, color: Color, color_type: ColorType) -> String;
}

View File

@ -1,11 +1,18 @@
//! With this module you can perform actions that are color related.
//! Like styling the font, foreground color and background color.
use std::fmt; use std::fmt;
use std::convert::From; use std::convert::From;
use std::str::FromStr; use std::str::FromStr;
use Construct; use Construct;
use super::{ANSIColor, NoTerminalColor, WinApiColor}; use crossterm_style::{ObjectStyle, StyledObject};
use super::base_color::ITerminalColor; use super::base_color::ITerminalColor;
use terminal_style::{ObjectStyle, StyledObject};
#[cfg(unix)]
use super::ANSIColor;
#[cfg(windows)]
use super::WinApiColor;
/// Colors that are available for coloring the termainal font. /// Colors that are available for coloring the termainal font.
#[derive(Debug, Copy, Clone)] #[derive(Debug, Copy, Clone)]
@ -34,7 +41,7 @@ pub enum Color {
White, White,
} }
/// Color types /// Color types that can be used to determine if the Color enum is an Fore- or Background Color
#[derive(Debug, Copy, Clone)] #[derive(Debug, Copy, Clone)]
pub enum ColorType { pub enum ColorType {
Background, Background,
@ -80,7 +87,7 @@ impl FromStr for Color {
} }
} }
/// Struct on wits color realated actions can be performed. /// Struct that stores an specific platform implementation for color related actions.
pub struct TerminalColor { pub struct TerminalColor {
terminal_color: Option<Box<ITerminalColor>>, terminal_color: Option<Box<ITerminalColor>>,
} }
@ -98,9 +105,17 @@ impl TerminalColor {
/// #Example /// #Example
/// ///
/// ```rust /// ```rust
/// extern crate crossterm;
/// ///
/// let mut colored_terminal = colored_terminal(); /// use self::crossterm::crossterm_style::{ get, Color};
///
/// // Get colored terminal instance
/// let mut colored_terminal = get();
///
/// // Set foreground color of the font
/// colored_terminal.set_fg(Color::Red); /// colored_terminal.set_fg(Color::Red);
/// // crossterm provides to set the background from &str or String
/// colored_terminal.set_fg(Color::from("Red"));
/// ///
/// ``` /// ```
pub fn set_fg(&mut self, color: Color) { pub fn set_fg(&mut self, color: Color) {
@ -116,8 +131,17 @@ impl TerminalColor {
/// ///
/// ```rust /// ```rust
/// ///
/// let mut colored_terminal = colored_terminal(); /// extern crate crossterm;
///
/// use self::crossterm::crossterm_style::{ get, Color};
///
/// // Get colored terminal instance
/// let mut colored_terminal = get();
///
/// // Set background color of the font
/// colored_terminal.set_bg(Color::Red); /// colored_terminal.set_bg(Color::Red);
/// // crossterm provides to set the background from &str or String
/// colored_terminal.set_bg(Color::from("Red"));
/// ///
/// ``` /// ```
pub fn set_bg(&mut self, color: Color) { pub fn set_bg(&mut self, color: Color) {
@ -131,8 +155,13 @@ impl TerminalColor {
/// # Example /// # Example
/// ///
/// ```rust /// ```rust
/// extern crate crossterm;
///
/// use self::crossterm::crossterm_style::get;
///
/// // Get colored terminal instance
/// let mut colored_terminal = get();
/// ///
/// let mut colored_terminal = colored_terminal();
/// colored_terminal.reset(); /// colored_terminal.reset();
/// ///
/// ``` /// ```
@ -146,17 +175,30 @@ impl TerminalColor {
/// Get an concrete ITerminalColor implementation based on the current operating system. /// Get an concrete ITerminalColor implementation based on the current operating system.
fn get_color_options() -> Option<Box<ITerminalColor>> { fn get_color_options() -> Option<Box<ITerminalColor>> {
if cfg!(target_os = "linux") { #[cfg(unix)]
Some(ANSIColor::new()) return Some(ANSIColor::new());
} else if cfg!(target_os = "windows") { #[cfg(windows)]
Some(WinApiColor::new()) return Some(WinApiColor::new());
} else {
Some(NoTerminalColor::new())
}
} }
/// Get the terminal options for colors, whereon color related actions can be performed. /// Get an TerminalColor implementation whereon color related actions can be performed.
pub fn colored_terminal() -> Box<TerminalColor> { ///
/// # Example
///
/// ```rust
/// extern crate crossterm;
///
/// use self::crossterm::crossterm_style::{get, Color};
///
/// // Get colored terminal instance
/// let mut colored_terminal = get();
///
/// // preform some actions on the colored terminal
/// colored_terminal.set_fg(Color::Red);
/// colored_terminal.set_bg(Color::Blue);
/// colored_terminal.reset();
/// ```
pub fn get() -> Box<TerminalColor> {
Box::from(TerminalColor { Box::from(TerminalColor {
terminal_color: get_color_options(), terminal_color: get_color_options(),
}) })
@ -164,21 +206,29 @@ pub fn colored_terminal() -> Box<TerminalColor> {
/// Wraps an displayable object so it can be formatted with colors and attributes. /// Wraps an displayable object so it can be formatted with colors and attributes.
/// ///
/// Check `/examples/color` in the libary for more spesific examples.
///
/// #Example /// #Example
/// ///
/// ```rust /// ```rust
/// extern crate crossterm; /// extern crate crossterm;
///
/// use self::crossterm::terminal_style::{paint,Color}; /// use self::crossterm::crossterm_style::{paint,Color};
/// ///
/// fn main() /// fn main()
/// { /// {
/// // default foregroundcolor and backgroundcolor. /// // Create an styledobject object from the text 'Unstyled font'
/// println!("{}",paint("■")); /// // Currently it has the default foregroundcolor and backgroundcolor.
/// println!("{}",paint("Unstyled font"));
/// ///
/// // red foregroundcolor and Blue backgroundcolor /// // Create an displayable object from the text 'Colored font',
/// let styledobject = paint("■").with(Color::Red).on(Color::Blue); /// // 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); /// println!("{}", styledobject);
///
/// // Or all in one line
/// println!("{}", paint("Colored font").with(Color::Red).on(Color::Blue));
/// } /// }
/// ``` /// ```
pub fn paint<D>(val: D) -> StyledObject<D> pub fn paint<D>(val: D) -> StyledObject<D>

View File

@ -1,10 +1,12 @@
mod no_color; pub mod base_color;
pub mod color;
#[cfg(unix)]
mod ansi_color; mod ansi_color;
#[cfg(windows)]
mod winapi_color; mod winapi_color;
pub mod color; #[cfg(unix)]
pub mod base_color;
use self::no_color::NoTerminalColor;
use self::ansi_color::ANSIColor; use self::ansi_color::ANSIColor;
#[cfg(windows)]
use self::winapi_color::WinApiColor; use self::winapi_color::WinApiColor;

View File

@ -1,10 +1,8 @@
extern crate winapi;
use Construct; use Construct;
use super::color::{Color, ColorType}; use super::color::{Color, ColorType};
use super::base_color::ITerminalColor; use super::base_color::ITerminalColor;
use kernel::windows_kernel::{color, kernel};
/// This struct will be used for coloring windows terminals with winapi. /// This struct is an windows implementation for color related actions.
#[derive(Debug)] #[derive(Debug)]
pub struct WinApiColor { pub struct WinApiColor {
original_console_color: u16, original_console_color: u16,

View File

@ -1,7 +1,6 @@
mod color; mod color;
mod styles; mod styles;
pub use self::color::base_color::ITerminalColor;
pub use self::color::color::*; pub use self::color::color::*;
pub use self::styles::objectstyle::ObjectStyle; pub use self::styles::objectstyle::ObjectStyle;

View File

@ -1,7 +1,7 @@
use terminal_style::{Color, StyledObject}; use crossterm_style::{Color, StyledObject};
use std::fmt::Display; use std::fmt::Display;
/// This struct contains the style properties that can be applied to an displayable object. /// Struct that contains the style properties that can be applied to an displayable object.
#[derive(Clone)] #[derive(Clone)]
pub struct ObjectStyle { pub struct ObjectStyle {
pub fg_color: Option<Color>, pub fg_color: Option<Color>,

View File

@ -2,16 +2,16 @@ use std;
use std::fmt; use std::fmt;
use std::io::Write; use std::io::Write;
use terminal_style::{Color, ObjectStyle}; use crossterm_style::{Color, ObjectStyle};
/// Struct that contains both the style and the content wits is styled. /// Struct that contains both the style and the content wits will be styled.
pub struct StyledObject<D> { pub struct StyledObject<D> {
pub object_style: ObjectStyle, pub object_style: ObjectStyle,
pub content: D, pub content: D,
} }
impl<D> StyledObject<D> { impl<D> StyledObject<D> {
/// Paints the foreground color with the passed `Color` /// Sets the foreground of the styled object to the passed `Color`
/// ///
/// #Example /// #Example
/// ///
@ -33,7 +33,7 @@ impl<D> StyledObject<D> {
self self
} }
/// Paints the background color with the passed `Color` /// Sets the background of the styled object to the passed `Color`
/// ///
/// #Example /// #Example
/// ///
@ -65,7 +65,7 @@ macro_rules! impl_fmt
impl<D: fmt::$name> fmt::$name for StyledObject<D> { impl<D: fmt::$name> fmt::$name for StyledObject<D> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result
{ {
let mut colored_terminal = super::super::colored_terminal(); let mut colored_terminal = super::super::get();
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

@ -0,0 +1,53 @@
use std::io;
use std::io::Write;
use Construct;
use super::base_terminal::{ClearType, ITerminal};
use kernel::linux_kernel::terminal::*;
/// This struct is an ansi implementation for terminal related actions.
pub struct UnixTerminal;
impl Construct for UnixTerminal {
fn new() -> Box<UnixTerminal> {
Box::from(UnixTerminal {})
}
}
impl ITerminal for UnixTerminal {
fn clear(&self, clear_type: ClearType) {
let mut some_writer = io::stdout();
match clear_type {
ClearType::All => {
write!(&mut some_writer, csi!("2J"));
},
ClearType::FromCursorDown=> {
write!(&mut some_writer, csi!("J"));
},
ClearType::FromCursorUp => {
write!(&mut some_writer, csi!("1J"));
},
ClearType::CurrentLine => {
write!(&mut some_writer, csi!("2K"));
},
ClearType::UntilNewLine => {
write!(&mut some_writer, csi!("K"));
},
};
}
fn terminal_size(&self) -> Option<(u16, u16)> {
terminal_size()
}
fn scroll_up(&self, count: i16) {
let mut some_writer = io::stdout();
write!(&mut some_writer, csi!("{}S"), count);
}
fn scroll_down(&self, count: i16) {
let mut some_writer = io::stdout();
write!(&mut some_writer, csi!("{}T"), count);
}
}

View File

@ -0,0 +1,19 @@
/// Enum that can be used for the kind of clearing that can be done in the terminal.
pub enum ClearType {
All,
FromCursorDown,
FromCursorUp,
CurrentLine,
UntilNewLine,
}
pub trait ITerminal {
/// Clear the current cursor by specifying the clear type
fn clear(&self, clear_type: ClearType);
/// Get the terminal size (x,y)
fn terminal_size(&self) -> Option<(u16, u16)>;
/// Scroll `n` lines up in the current terminal.
fn scroll_up(&self, count: i16);
/// Scroll `n` lines down in the current terminal.
fn scroll_down(&self, count: i16);
}

View File

@ -0,0 +1,15 @@
mod base_terminal;
mod terminal;
#[cfg(unix)]
mod ansi_terminal;
#[cfg(windows)]
mod winapi_terminal;
#[cfg(unix)]
use self::ansi_terminal::UnixTerminal;
#[cfg(windows)]
use self::winapi_terminal::WinApiTerminal;
pub use self::base_terminal::ClearType;
pub use self::terminal::{ get, Terminal };

View File

@ -0,0 +1,154 @@
//! With this module you can perform actions that are terminal related.
//! Like clearing and scrolling in the terminal or getting the size of the terminal.
use Construct;
use super::base_terminal::{ClearType, ITerminal};
#[cfg(unix)]
use super::UnixTerminal;
#[cfg(windows)]
use super::WinApiTerminal;
/// Struct that stores an specific platform implementation for terminal related actions.
pub struct Terminal {
terminal: Option<Box<ITerminal>>,
}
impl Terminal {
/// Instantiate an color implementation whereon color related actions can be performed.
pub fn init(&mut self) {
if let None = self.terminal {
self.terminal = get_terminal();
}
}
/// Clear the current cursor by specifying the clear type
///
/// #Example
///
/// ```rust
///
/// extern crate crossterm;
/// use crossterm::crossterm_terminal;
///
/// let mut term = crossterm_terminal::get();
///
/// // clear all cells in terminal.
/// term.clear(crossterm_terminal::ClearType::All);
/// //clear all cells from the cursor position downwards in terminal.
/// term.clear(crossterm_terminal::ClearType::FromCursorDown);
/// //clear all cells from the cursor position upwards in terminal.
/// term.clear(crossterm_terminal::ClearType::FromCursorUp);
/// // clear current line cells in terminal.
/// term.clear(crossterm_terminal::ClearType::CurrentLine);
/// // clear all cells from cursor position until new line in terminal.
/// term.clear(crossterm_terminal::ClearType::UntilNewLine);
///
/// ```
pub fn clear(&mut self, clear_type: ClearType) {
&self.init();
if let Some(ref terminal) = self.terminal {
terminal.clear(clear_type);
}
}
/// Get the terminal size (x,y).
///
/// #Example
///
/// ```rust
///
/// extern crate crossterm;
/// use crossterm::crossterm_terminal;
///
/// let mut term = crossterm_terminal::get();
///
/// let size = term.terminal_size();
/// println!("{:?}", size);
///
/// ```
pub fn terminal_size(&mut self) -> Option<(u16, u16)> {
&self.init();
if let Some(ref terminal) = self.terminal {
let a = terminal.terminal_size();
a
} else {
None
}
}
/// Scroll `n` lines up in the current terminal.
///
/// #Example
///
/// ```rust
///
/// extern crate crossterm;
/// use crossterm::crossterm_terminal;
///
/// let mut term = crossterm_terminal::get();
///
/// // scroll up by 5 lines
/// let size = term.scroll_up(5);
///
/// ```
pub fn scroll_up(&mut self, count: i16) {
&self.init();
if let Some(ref terminal) = self.terminal {
terminal.scroll_up(count);
}
}
/// Scroll `n` lines up in the current terminal.
///
/// #Example
///
/// ```rust
///
/// extern crate crossterm;
/// use crossterm::crossterm_terminal;
///
/// let mut term = crossterm_terminal::get();
///
/// // scroll down by 5 lines
/// let size = term.scroll_down(5);
///
/// ```
pub fn scroll_down(&mut self, count: i16) {
&self.init();
if let Some(ref terminal) = self.terminal {
terminal.scroll_down(count);
}
}
}
/// Get the concrete ITerminal implementation based on the current operating system.
fn get_terminal() -> Option<Box<ITerminal>> {
#[cfg(unix)]
return Some(UnixTerminal::new());
#[cfg(windows)]
return Some(WinApiTerminal::new());
}
/// Get an Terminal implementation whereon terminal related actions can be performed.
///
/// Check `/examples/terminal` in the libary for more spesific examples.
///
/// #Example
///
/// ```rust
///
/// extern crate crossterm;
/// use crossterm::crossterm_terminal;
///
/// let mut term = crossterm_terminal::get();
///
/// // scroll down by 5 lines
/// let size = term.scroll_down(5);
///
/// ```
pub fn get() -> Box<Terminal> {
Box::from(Terminal {
terminal: get_terminal(),
})
}

View File

@ -1,9 +1,9 @@
use Construct; use Construct;
use super::base_terminal::{ClearType, ITerminal}; use super::base_terminal::{ClearType, ITerminal};
#[cfg(windows)]
use kernel::windows_kernel::terminal; use kernel::windows_kernel::terminal;
/// This struct will be used for ansi terminals and unix systems.
/// This struct is an windows implementation for terminal related actions.
pub struct WinApiTerminal; pub struct WinApiTerminal;
impl Construct for WinApiTerminal { impl Construct for WinApiTerminal {
@ -17,8 +17,8 @@ impl ITerminal for WinApiTerminal {
match clear_type match clear_type
{ {
ClearType::All => terminal::clear_entire_screen(), ClearType::All => terminal::clear_entire_screen(),
ClearType::AfterCursor => terminal::clear_after_cursor(), ClearType::FromCursorDown => terminal::clear_after_cursor(),
ClearType::BeforeCursor => terminal::clear_before_cursor(), ClearType::FromCursorUp => terminal::clear_before_cursor(),
ClearType::CurrentLine => terminal::clear_current_line(), ClearType::CurrentLine => terminal::clear_current_line(),
ClearType::UntilNewLine => terminal::clear_until_line(), ClearType::UntilNewLine => terminal::clear_until_line(),
}; };

View File

@ -1,28 +1,34 @@
use std::{io, mem}; use libc;
use super::cvt; use self::libc::{STDOUT_FILENO, TIOCGWINSZ, c_ushort};
use super::libc; use self::libc::ioctl;
/// A representation of the size of the current terminal
#[repr(C)] #[repr(C)]
struct TermSize { #[derive(Debug)]
row: libc::c_ushort, pub struct UnixSize {
col: libc::c_ushort, /// number of rows
_x: libc::c_ushort, pub rows: c_ushort,
_y: libc::c_ushort, /// number of columns
pub cols: c_ushort,
x: c_ushort,
y: c_ushort,
} }
pub fn terminal_size() -> Option<(u16, u16)> { /// Gets the current terminal size
unsafe { pub fn terminal_size() -> Option<(u16,u16)> {
if libc::isatty(libc::STDOUT_FILENO) != 1 { // http://rosettacode.org/wiki/Terminal_control/Dimensions#Library:_BSD_libc
return None; let us = UnixSize {
} rows: 0,
cols: 0,
let mut winsize: libc::winsize = mem::zeroed(); x: 0,
libc::ioctl(libc::STDOUT_FILENO, libc::TIOCGWINSZ, &mut winsize); y: 0,
if winsize.ws_row > 0 && winsize.ws_col > 0 { };
Some((winsize.ws_col as u16, winsize.ws_row as u16)) let r = unsafe { ioctl(STDOUT_FILENO, TIOCGWINSZ, &us) };
if r == 0 {
// because crossterm works starts counting at 0 and unix terminal starts at cell 1 you have subtract one to get 0-based results.
Some((us.cols -1, us.rows -1))
} else { } else {
None None
} }
}
} }

View File

@ -1,4 +1,4 @@
#[cfg(windows)]
pub mod windows_kernel;
#[cfg(unix)] #[cfg(unix)]
pub mod linux_kernel; pub mod linux_kernel;
#[cfg(windows)]
pub mod windows_kernel;

View File

@ -12,6 +12,7 @@ pub fn enable_ansi_support() {
/// Set the console mode of the windows terminal. /// Set the console mode of the windows terminal.
fn set_console_mode(handle: winapi::HANDLE, console_mode: u32) { fn set_console_mode(handle: winapi::HANDLE, console_mode: u32) {
unsafe { unsafe {
winapi::SW_HIDE;
kernel32::SetConsoleMode(handle, console_mode); kernel32::SetConsoleMode(handle, console_mode);
} }
} }

View File

@ -1,15 +1,15 @@
#[macro_use] #[macro_use]
pub mod shared; mod shared;
pub mod terminal_cursor;
pub mod terminal_style;
pub mod terminal;
mod kernel; mod kernel;
pub mod crossterm_cursor;
pub mod crossterm_style;
pub mod crossterm_terminal;
use shared::traits::{Construct, Empty}; use shared::traits::{Construct, Empty};
pub use terminal_cursor::cursor;
pub use terminal_style::paint;
#[cfg(windows)] #[cfg(windows)]
extern crate kernel32; extern crate kernel32;
#[cfg(windows)] #[cfg(windows)]
extern crate winapi; extern crate winapi;
#[cfg(unix)]
extern crate libc;

View File

@ -1,14 +0,0 @@
pub enum ClearType {
All,
AfterCursor,
BeforeCursor,
CurrentLine,
UntilNewLine,
}
pub trait ITerminal {
fn clear(&self, clear_type: ClearType);
fn terminal_size(&self) -> Option<(u16, u16)>;
fn scroll_up(&self, count: i16);
fn scroll_down(&self, count: u16);
}

View File

@ -1,12 +0,0 @@
mod base_terminal;
mod no_terminal;
mod unix_terminal;
mod winapi_terminal;
pub mod terminal;
pub use self::terminal::{get, Terminal};
pub use self::base_terminal::ClearType;
use self::unix_terminal::UnixTerminal;
use self::winapi_terminal::WinApiTerminal;
use self::no_terminal::NoTerminal;

View File

@ -1,22 +0,0 @@
use Construct;
use super::base_terminal::{ClearType, ITerminal};
/// This struct will be used for ansi terminals and unix systems.
pub struct NoTerminal;
impl Construct for NoTerminal {
fn new() -> Box<NoTerminal> {
Box::from(NoTerminal {})
}
}
impl ITerminal for NoTerminal {
fn clear(&self, clear_type: ClearType) {}
fn terminal_size(&self) -> Option<(u16, u16)> {
None
}
fn scroll_up(&self, count: i16) {}
fn scroll_down(&self, count: u16) {}
}

View File

@ -1,99 +0,0 @@
use Construct;
use super::base_terminal::{ClearType, ITerminal};
use super::{NoTerminal, UnixTerminal, WinApiTerminal};
/// Struct with the terminal on wits terminal realated actions can be performed.
pub struct Terminal {
terminal: Option<Box<ITerminal>>,
}
impl Terminal {
/// Instantiate an color implementation whereon color related actions can be performed.
pub fn init(&mut self) {
if let None = self.terminal {
self.terminal = get_terminal();
}
}
/// Clear the current cursor by specifying the clear type
///
/// #Example
///
/// ```rust
///
/// let mut terminal = terminal::get();
///
/// // clear all cells in terminal.
/// terminal.clear(ClearType::All);
/// //clear all cells after the cursor position in terminal.
/// terminal.clear(ClearType::AfterCursor);
/// // clear all cells before cursor in terminal.
/// terminal.clear(ClearType::BeforeCursor);
/// // clear current line cells in terminal.
/// terminal.clear(ClearType::CurrentLine);
/// // clear all cells from cursor position until new line in terminal.
/// terminal.clear(ClearType::UntilNewLine);
///
/// ```
pub fn clear(&mut self, clear_type: ClearType) {
&self.init();
if let Some(ref terminal) = self.terminal {
terminal.clear(clear_type);
}
}
/// Get the terminal size (x,y).
///
/// #Example
///
/// ```rust
///
/// let mut terminal = terminal::get();
///
/// let size = terminal.terminal_size();
/// println!("{:?}", size);
///
/// ```
pub fn terminal_size(&mut self) -> Option<(u16, u16)> {
&self.init();
if let Some(ref terminal) = self.terminal {
let a = terminal.terminal_size();
a
} else {
None
}
}
/// Scroll `n` lines up in the current terminal.
pub fn scroll_up(&mut self, count: i16) {
for i in 0..100 {
println!("Ik ben timon en dit is een test {}", i)
}
&self.init();
if let Some(ref terminal) = self.terminal {
terminal.scroll_up(count);
}
}
/// Scroll `n` lines up in the current terminal.
pub fn scroll_down(&self) {}
}
/// Get the concrete ITerminal implementation based on the current operating system.
fn get_terminal() -> Option<Box<ITerminal>> {
if cfg!(target_os = "linux") {
Some(UnixTerminal::new())
} else if cfg!(target_os = "windows") {
Some(WinApiTerminal::new())
} else {
Some(NoTerminal::new())
}
}
/// Get terminal whereon terminal related actions can be performed.
pub fn get() -> Box<Terminal> {
Box::from(Terminal {
terminal: get_terminal(),
})
}

View File

@ -1,40 +0,0 @@
use Construct;
use super::base_terminal::{ClearType, ITerminal};
#[cfg(unix)]
use kernel::linux_kernel::terminal::*;
#[cfg(windows)]
use kernel::windows_kernel::terminal::*;
/// This struct will be used for ansi terminals and unix systems.
pub struct UnixTerminal;
impl Construct for UnixTerminal {
fn new() -> Box<UnixTerminal> {
Box::from(UnixTerminal {})
}
}
impl ITerminal for UnixTerminal {
fn clear(&self, clear_type: ClearType) {
match clear_type {
ClearType::All => format!(csi!("2J")),
ClearType::AfterCursor => format!(csi!("J")),
ClearType::BeforeCursor => format!(csi!("1J")),
ClearType::CurrentLine => format!(csi!("2K")),
ClearType::UntilNewLine => format!(csi!("K")),
};
}
fn terminal_size(&self) -> Option<(u16, u16)> {
terminal_size()
}
fn scroll_up(&self, count: i16) {
format!(csi!("{}S"), count);
}
fn scroll_down(&self, count: u16) {
format!(csi!("{}T"), count);
}
}

View File

@ -1,37 +0,0 @@
use Construct;
use super::base_cursor::ITerminalCursor;
/// This struct will be used for ansi terminals and unix systems.
pub struct AnsiCursor;
impl Construct for AnsiCursor {
fn new() -> Box<AnsiCursor> {
Box::from(AnsiCursor {})
}
}
impl ITerminalCursor for AnsiCursor {
fn goto(&self, x: u16, y: u16) {
format!(csi!("{};{}H"), x, y);
}
fn pos(&self) -> (i16, i16) {
(0, 0)
}
fn move_up(&self, count: u16) {
format!(csi!("{}A"), count);
}
fn move_right(&self, count: u16) {
format!(csi!("{}C"), count);
}
fn move_down(&self, count: u16) {
format!(csi!("{}B"), count);
}
fn move_left(&self, count: u16) {
format!(csi!("{}D"), count);
}
}

View File

@ -1,17 +0,0 @@
/// This trait defines the actions that can be preformed on the termial cursor.
/// This trait can be inplemented so that an concrete inplementation of the ITerminalCursor can forfill
/// the wishes to work on an specific platform.
///
/// ## For example:
///
/// This trait is inplemented for winapi (Windows specific) and ansi (Unix specific),
/// so that the cursor related actions can be preformed on both unix and windows systems.
pub trait ITerminalCursor {
/// Goto some location (x,y) in the terminal.
fn goto(&self, x: u16, y: u16);
fn pos(&self) -> (i16, i16);
fn move_up(&self, count: u16);
fn move_right(&self, count: u16);
fn move_down(&self, count: u16);
fn move_left(&self, count: u16);
}

View File

@ -1,28 +0,0 @@
use Construct;
use super::base_cursor::ITerminalCursor;
/// Struct that will be instantiated when something went wrong or when an platform does not suport
/// the current concrete cursor inplementations.
pub struct NoCursor;
impl Construct for NoCursor {
fn new() -> Box<NoCursor> {
Box::new(NoCursor {})
}
}
impl ITerminalCursor for NoCursor {
fn goto(&self, x: u16, y: u16) {}
fn pos(&self) -> (i16, i16) {
(0, 0)
}
fn move_up(&self, count: u16) {}
fn move_right(&self, count: u16) {}
fn move_down(&self, count: u16) {}
fn move_left(&self, count: u16) {}
}

View File

@ -1,85 +0,0 @@
use std::string::String;
use Construct;
use super::color::{Color, ColorType};
use super::base_color::{ITerminalColor, sum_u16_to_string};
/// This struct will be used for coloring ansi terminals with ansi escape codes.
#[derive(Debug)]
pub struct ANSIColor;
impl Construct for ANSIColor {
fn new() -> Box<ANSIColor> {
Box::from(ANSIColor {})
}
}
impl ITerminalColor for ANSIColor {
fn set_fg(&self, fg_color: Color) {
format!(
csi!("38;2;{}m"),
self.color_value(fg_color, ColorType::Foreground)
);
}
fn set_bg(&self, bg_color: Color) {
format!(
csi!("38;2;{}m"),
self.color_value(bg_color, ColorType::Background)
);
}
fn reset(&self) {
format!(csi!("0m"));
}
fn color_value(&self, color: Color, color_type: ColorType) -> String {
let mut ansi_color_code = String::new();
// The ansi code for forground = 30 and background = 40;
match color_type {
ColorType::Foreground => ansi_color_code.push_str("30"),
ColorType::Background => ansi_color_code.push_str("40"),
}
// Construct ANSI escape color code string. ;1 is for the brightness
match color {
Color::Black => {
sum_u16_to_string(0, &mut ansi_color_code);
}
Color::Red => sum_u16_to_string(1, &mut ansi_color_code),
Color::DarkRed => {
sum_u16_to_string(1, &mut ansi_color_code);
&ansi_color_code.push_str(";1");
}
Color::Green => sum_u16_to_string(2, &mut ansi_color_code),
Color::DarkGreen => {
sum_u16_to_string(2, &mut ansi_color_code);
&ansi_color_code.push_str(";1");
}
Color::Yellow => sum_u16_to_string(3, &mut ansi_color_code),
Color::DarkYellow => {
sum_u16_to_string(3, &mut ansi_color_code);
&ansi_color_code.push_str(";1");
}
Color::Blue => sum_u16_to_string(4, &mut ansi_color_code),
Color::DarkBlue => {
sum_u16_to_string(4, &mut ansi_color_code);
&ansi_color_code.push_str(";1");
}
Color::Magenta => sum_u16_to_string(5, &mut ansi_color_code),
Color::DarkMagenta => {
sum_u16_to_string(5, &mut ansi_color_code);
&ansi_color_code.push_str(";1");
}
Color::Cyan => sum_u16_to_string(6, &mut ansi_color_code),
Color::DarkCyan => {
sum_u16_to_string(6, &mut ansi_color_code);
&ansi_color_code.push_str(";1");
}
Color::Grey => sum_u16_to_string(7, &mut ansi_color_code),
Color::White => sum_u16_to_string(7, &mut ansi_color_code),
}
ansi_color_code
}
}

View File

@ -1,29 +0,0 @@
/// This trait defines the actions that can be preformed on the termial color.
/// This trait can be inplemented so that an concrete inplementation of the ITerminalColor can forfill
/// the wishes to work on an specific platform.
///
/// ## For example:
///
/// This trait is inplemented for winapi (Windows specific) and ansi (Unix specific),
/// so that the color related actions can be preformed on both unix and windows systems.
use super::color::{Color, ColorType};
pub trait ITerminalColor {
/// Set the forground color to the given color.
fn set_fg(&self, fg_color: Color);
/// Set the background color to the given color.
fn set_bg(&self, fg_color: Color);
/// Reset the terminal color to default.
fn reset(&self);
/// Gets an value that represents an color from the given `Color` and `ColorType`.
fn color_value(&self, color: Color, color_type: ColorType) -> String;
}
/// Sum an u16 value with an string (also a numeric value).
pub fn sum_u16_to_string(value: u16, string: &mut String) {
let parsed_string: u16 = string.parse().unwrap();
let new_value: u16 = parsed_string + value;
*string = new_value.to_string();
}

View File

@ -1,26 +0,0 @@
use Construct;
use super::color::{Color, ColorType};
use super::base_color::ITerminalColor;
/// Struct that will be instantiated when something went wrong or when an platform does not suport
/// the current concrete color inplementations.
#[derive(Debug)]
pub struct NoTerminalColor;
impl Construct for NoTerminalColor {
fn new() -> Box<NoTerminalColor> {
Box::from(NoTerminalColor {})
}
}
impl ITerminalColor for NoTerminalColor {
fn set_fg(&self, fg_color: Color) {}
fn set_bg(&self, bg_color: Color) {}
fn reset(&self) {}
fn color_value(&self, color: Color, color_type: ColorType) -> String {
String::from("0")
}
}

1
todo.txt Normal file
View File

@ -0,0 +1 @@
Windows logic clear aan passen before after cursor