Moved files around. Added duplex example (broken). Broke alternate screen trying to add compat.

This commit is contained in:
Jojolepro 2018-07-30 15:35:35 -04:00 committed by Timon
parent 2eb6b1cd55
commit 518dcadd15
98 changed files with 775 additions and 3394 deletions

View File

@ -23,6 +23,14 @@ termios = "0.3.0"
name = "crossterm"
path = "src/lib.rs"
[[bin]]
name = "example_bin"
path = "./examples/Crossterm 0.3.1/bin.rs"
#[[bin]]
# name = "example_bin"
# path = "./examples/Crossterm 0.3.1/bin.rs"
[[example]]
name = "simple"
path = "examples/simple.rs"
[[example]]
name = "duplex"
path = "examples/duplex.rs"

340
README.md
View File

@ -2,11 +2,339 @@
[![Latest Version](https://img.shields.io/crates/v/crossterm.svg)](https://crates.io/crates/crossterm) | [![MIT licensed](https://img.shields.io/badge/license-MIT-blue.svg)](./LICENSE) | [![docs.rs](https://docs.rs/crossterm/badge.svg)](https://docs.rs/crossterm/) | [Examples](https://github.com/TimonPost/crossterm/tree/master/examples) | [Changelog](https://github.com/TimonPost/crossterm/blob/master/docs/UpgradeManual.md) | [Release Nodes](https://github.com/TimonPost/crossterm/tree/master/docs)
|----|----|----|----|----|----
This branch is focusud on getting input working for Crossterm.
TODO:
Ever got disappointed when a terminal library for rust was only written for unix systems?
Crossterm provides the same core functionalities for both windows and unix systems.
Crossterm aims to be simple and easy to call in code.
Though the simplicity of Crossterm, you do not have to worry about the platform you are working with.
You can just call whatever action you want and behind the scenes it will check what to do based on the current platform.
This crate supports all unix and windows terminals down to windows XP (not all terminals are tested see 'Tested Terminals' for more info)
## Table of contents:
- [Getting started](https://github.com/TimonPost/crossterm#getting-started)
- [Useful links](https://github.com/TimonPost/crossterm#useful-links)
- [Features](https://github.com/TimonPost/crossterm#features)
- [Examples](https://github.com/TimonPost/crossterm#examples)
- [Crossterm Wrapper](https://github.com/TimonPost/crossterm#crossterm-wrapper--see-more)
- [Styling](https://github.com/TimonPost/crossterm#styled-font--see-more)
- [Cursor](https://github.com/TimonPost/crossterm#cursor--see-more)
- [Terminal](https://github.com/TimonPost/crossterm#terminal--see-more)
- [Tested Terminals](https://github.com/TimonPost/crossterm#tested-terminals)
- [How it works](https://github.com/TimonPost/crossterm#how-it-works)
- [Notice](https://github.com/TimonPost/crossterm#notice)
- [Todo](https://github.com/TimonPost/crossterm#todo)
- [Contributing](https://github.com/TimonPost/crossterm#contributing)
- [Authors](https://github.com/TimonPost/crossterm#authors)
- [License](https://github.com/TimonPost/crossterm#license)
## Getting Started
This documentation is only for Crossterm version `0.4.0` if you have an older version of Crossterm I suggest you check the [Upgrade Manual](https://github.com/TimonPost/crossterm/blob/master/docs/UpgradeManual.md) for more information about how to upgrade to a newer version or check the [examples](https://github.com/TimonPost/crossterm/tree/master/examples) folders which contains a readme for every specific version. Also, you could take a look at the [examples](https://github.com/TimonPost/crossterm/tree/master/examples) from the previous versions of Crossterm.
Add the Crossterm package to your `Cargo.toml` file.
```
[dependencies]
crossterm = "0.4.0"
```
And import the Crossterm modules you want to use.
```rust
extern crate crossterm;
// this module is used for styling the terminal
use self::crossterm::style::*;
// this module is used for cursor related actions
use self::crossterm::cursor::*;
// this mudule is used for terminal related actions
use self::crossterm::terminal::*;
```
## Useful Links
- Code documentation:
version [0.1.0](https://docs.rs/crossterm/0.1.0/crossterm/),
[0.2.0](https://docs.rs/crossterm/0.2.0/crossterm/),
[0.2.1](https://docs.rs/crossterm/0.2.1/crossterm/)
[0.3.0](https://docs.rs/crossterm/0.3.0/crossterm/)
[0.4.0](https://docs.rs/crossterm/0.4.0/crossterm/)
- Code Examples:
# TO UPDATE
version [0.1.0](https://github.com/TimonPost/crossterm/tree/master/examples/Crossterm%200.1.0),
[0.2.0](https://github.com/TimonPost/crossterm/tree/master/examples/Crossterm%200.2.0),
[0.2.1](https://github.com/TimonPost/crossterm/tree/master/examples/Crossterm%200.2.1)
and [0.3.0](https://github.com/TimonPost/crossterm/tree/master/examples/Crossterm%200.3.0)
- [Cargo Page](https://crates.io/crates/crossterm)
- [Real life examples](https://github.com/TimonPost/crossterm/tree/master/examples/Crossterm%200.3.0/program_examples)
# Features
These are the features from this crate:
- Cursor.
- Moving _n_ times Up, Down, Left, Right.
- Goto a certain position.
- Get cursor position
- Storing the current cursor position and resetting to that stored cursor position later.
- Hiding an showing the cursor.
- Control over blinking of the terminal cursor (only some terminals are supporting this).
- Styled output
- Foreground color (16 base colors)
- Background color (16 base colors)
- 256 color support (unix only).
- Text Attributes like: bold, italic, underscore and crossed word ect (unix only).
- Custom ANSI color code input to set fore- and background color (unix only).
- Terminal
- Clearing (all lines, current line, from cursor down and up, until new line)
- Scrolling (Up, down)
- Get the size of the terminal
- Set the size of the terminal.
- Alternate screen
- Raw screen
- Exit the current process.
- Detailed documentation on every item.
## Examples
For detailed examples of all Crossterm functionalities check the [examples](https://github.com/TimonPost/crossterm/tree/master/examples) directory.
### Crossterm wrapper | [see more](https://github.com/TimonPost/crossterm/blob/master/examples/Crossterm%200.3.0/crossterm_type/mod.rs)
This is a wrapper for the modules crossterm provides. This is introduced to manage the [`Context`](link_to_context) for the user.
```
let crossterm = Crossterm::new();
// get instance of the modules, whereafter you can use the methods the particulary module provides.
let color = crossterm.color();
let cursor = crossterm.cursor();
let terminal = crossterm.terminal();
// write text to console wheter it be the main screen or the alternate screen.
crossterm.write("some text");
// print some styled font.
println!("{}", crossterm.paint("Red font on blue background").with(Color::Red).on(Color::Blue));
```
### Styled font | [see more](https://github.com/TimonPost/crossterm/blob/master/examples/Crossterm%200.3.0/color/mod.rs)
This module provides the functionalities to style the terminal cursor.
```rust
use crossterm::style::{Color};
use crossterm::Crossterm;
// Crossterm provides method chaining so that you can style the font nicely.
// the `with()` methods sets the foreground color and the `on()` methods sets the background color
// You can either store the styled font.
// create instance of `Crossterm`
let crossterm = Crossterm::new();
// store style in styled object and print it
let mut styledobject = crossterm.paint("stored styled font in variable").with(Color::Green).on(Color::Yellow);
println!("{}",styledobject);
// Or you can print it directly.
println!("{}", crossterm.paint("Red font on blue background color").with(Color::Red).on(Color::Blue));
println!("{}", crossterm.paint("Red font on default background color").with(Color::Red));
println!("{}", crossterm.paint("Default font color on Blue background color").on(Color::Blue));
/// The following code can only be used for unix systems:
// Set background Color from RGB
println!("RGB (10,10,10): \t {}", crossterm.paint(" ").on(Color::Rgb {r: 10, g: 10, b: 10}));
// Set background Color from RGB
println!("ANSI value (50): \t {}", crossterm.paint(" ").on(Color::AnsiValue(50)));
// Use attributes to syle the font.
println!("{}", crossterm.paint("Normal text"));
println!("{}", crossterm.paint("Bold text").bold());
println!("{}", crossterm.paint("Italic text").italic());
println!("{}", crossterm.paint("Slow blinking text").slow_blink());
println!("{}", crossterm.paint("Rapid blinking text").rapid_blink());
println!("{}", crossterm.paint("Hidden text").hidden());
println!("{}", crossterm.paint("Underlined text").underlined());
println!("{}", crossterm.paint("Reversed color").reverse());
println!("{}", crossterm.paint("Dim text color").dim());
println!("{}", crossterm.paint("Crossed out font").crossed_out());
```
### Cursor | [see more](https://github.com/TimonPost/crossterm/blob/master/examples/Crossterm%200.3.0/cursor/mod.rs)
This module provides the functionalities to work with the terminal cursor.
```rust
use crossterm::Context;
use crossterm::cursor::cursor;
// create context to pass to the `cursor()` function.
let context = Context::new();
let mut cursor = cursor(&context);
/// Moving the cursor | demo
// Set the cursor to position X: 10, Y: 5 in the terminal
cursor.goto(10,5);
// Move the cursor to position 3 times to the up in the terminal
cursor.move_up(3);
// Move the cursor to position 3 times to the right in the terminal
cursor.move_right(3);
// Move the cursor to position 3 times to the down in the terminal
cursor.move_down(3);
// Move the cursor to position 3 times to the left in the terminal
cursor.move_left(3);
// Print an character at X: 10, Y: 5 (see examples for more explanation why to use this method).
// cursor.goto(10,5).print("@");
/// Safe the current cursor position to recall later | demo
// Goto X: 5 Y: 5
cursor.goto(5,5);
// Safe cursor position: X: 5 Y: 5
cursor.save_position();
// Goto X: 5 Y: 20
cursor.goto(5,20);
// Print at X: 5 Y: 20.
print!("Yea!");
// Reset back to X: 5 Y: 5.
cursor.reset_position();
// Print 'Back' at X: 5 Y: 5.
print!("Back");
// hide cursor
cursor.hide();
// show cursor
cursor.show();
// blink or not blinking of the cursor (not widely supported)
cursor.blink(true)
```
### Terminal | [see more](https://github.com/TimonPost/crossterm/blob/master/examples/Crossterm%200.3.0/terminal/terminal.rs)
This module provides the functionalities to work with the terminal in general.
```rust
use crossterm::terminal::{terminal,ClearType};
use crossterm::Context;
let mut context = Context::new();
let mut terminal = terminal(&context);
// Clear all lines in terminal;
terminal.clear(ClearType::All);
// Clear all cells from current cursor position down.
terminal.clear(ClearType::FromCursorDown);
// Clear all cells from current cursor position down.
terminal.clear(ClearType::FromCursorUp);
// Clear current line cells.
terminal.clear(ClearType::CurrentLine);
// Clear all the cells until next line.
terminal.clear(ClearType::UntilNewLine);
// Get terminal size
let terminal_size = terminal.terminal_size();
// Print results
print!("X: {}, y: {}", terminal_size.0, terminal_size.1);
// Scroll down 10 lines.
terminal.scroll_down(10);
// Scroll up 10 lines.
terminal.scroll_up(10);
// Set terminal size
terminal.set_size(10,10);
// exit the current process.
terminal.exit();
// write to the terminal whether you are on the main screen or alternate screen.
terminal.write("Some text\n Some text on new line");
// use the `paint()` for styling font
println!("{}", terminal.paint("x").with(Color::Red).on(Color::Blue));
```
Check these links: [AlternateScreen](https://github.com/TimonPost/crossterm/blob/master/examples/Crossterm%200.3.0/terminal/alternate_screen.rs) and [RawScreen](https://github.com/TimonPost/crossterm/blob/master/examples/Crossterm%200.3.0/terminal/raw_mode.rs) for information about how to work with these features.
## Tested terminals
- Windows Powershell
- Windows 10 (pro)
- Windows CMD
- Windows 10 (pro)
- Ubuntu Desktop Terminal
- Ubuntu 17.10
- Arch linux Konsole
This crate supports all Unix terminals and windows terminals down to Windows XP but not all of them have been tested.
If you have used this library for a terminal other than the above list without issues feel free to add it to the above list, I really would appreciate it.
## How it works
Crossterm is using ANSI escape codes by default for both Unix and Windows systems.
But for Windows, it is a bit more complicated since Windows versions 8 or lower are not supporting ANSI escape codes. This is why we use WinApi for those machines. For Windows 10 ANSI codes will be the default.
## Notice
This library is not stable yet but I expect it to not to change that much anymore.
And if there are any changes that affect previous versions I will [describe](https://github.com/TimonPost/crossterm/blob/master/docs/UpgradeManual.md) what to change when upgrading Crossterm to a newer version.
## Todo
I still have some things in mind to implement.
- Handling mouse events
I want to be able to do something based on the clicks the user has done with its mouse.
- Handling key events
I want to be able to read key combination inputs.
- reading from the console.
I want to be able to read the input of the console.
- Error handling
Currently, I am not doing that much with returned errors. This is bad since I suspect that everything is working. I want to manage this better. When you build this crate you will see the warnings about not used return values. This is what needs to be improved.
- Tests
Also, I want to have tests for this crate, and yes maybe a little late :). But I find it difficult to test some functionalities because how would you ever test if the screen is indeed int alternate, raw modes or how would you ever test if the terminal cursor is moved certainly.
## Contributing
If you would like to contribute to Crossterm, than please design the code as it is now.
For example, a module like cursor has the following file structure:
- mod.rs
This file contains some trait, in this case, `ITerminalCursor`, for other modules to implement. So that it can work at a specific platform.
- cursor.rs
The end user will call this module to access the cursor functionalities. This module will decide which implementation to use based on the current platform.
- winapi_cursor
This is the cursor trait (located in mod.rs) implementation with WinApi.
- ansi_cursor
This is the cursor trait (located in mod.rs) implementation with ANSI escape codes.
The above structure is the same for the terminal, color, manager modules.
Why I have chosen for this design:
- Because you can easily extend to multiple platforms by implementing the trait int the mod.rs.
- You keep the functionalities for different platforms separated in different files.
- Also, you have one API the user can call like in the `cursor.rs` above. This file should be avoided to change that much. All the other code could change a lot because it has no impact on the user side.
I highly appreciate it when you are contributing to this crate. Also Since my native language is not English my grammar and sentence order will not be perfect. So improving this by correcting these mistakes will help both me and the reader of the docs.
## Authors
* **Timon Post** - *Project Owner & creator*
## License
This project is licensed under the MIT License - see the [LICENSE.md](LICENSE.md) file for details
- Read character input
- Read line
- Read until enter
- Asynchronous key events

View File

@ -1,174 +0,0 @@
# 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 simplicity 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.
```rust
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::*;
```
## Links
Documentation for the code can be found [here](https://atcentra.com/crossterm/index.html)
Documentation for the code can be found [here](https://docs.rs/crossterm/0.1.0/crossterm/)
The Cargo Page can be found [here](https://crates.io/search?q=crossterm)
## Examples
For detailed examples of all crossterm functionalities check the [examples](https://github.com/TimonPost/crossterm/tree/master/examples) direcory.
### Styled font
```rust
use crossterm::crossterm_style::{paint, Color};
// Crossterm provides method chaining so that you can style the font nicely.
// You can either store the styled font.
let mut styledobject = paint("Stored styled font").with(Color::Red).on(Color::Blue);
println!("{}",styledobject);
// Or you can print it directly.
println!("{}", paint("Red font on blue background color").with(Color::Red).on(Color::Blue));
println!("{}", paint("Red font on default background color").with(Color::Red));
println!("{}", paint("Default font color on Blue background color").on(Color::Blue));
```
### Cursor
```rust
use crossterm::crossterm_cursor::get;
let mut cursor = get();
// Set the cursor to position X: 10, Y: 5 in the terminal
cursor.goto(10,5);
// Move the cursor to position 3 times to the up in the terminal
cursor.move_up(3);
// Move the cursor to position 3 times to the right in the terminal
cursor.move_right(3);
// Move the cursor to position 3 times to the down in the terminal
cursor.move_down(3);
// Move the cursor to position 3 times to the left in the terminal
cursor.move_left(3);
// Print an character at X: 10, Y: 5 (see examples for more explanation why to use this method).
// cursor.goto(10,5).print("@");
```
### Terminal
```rust
use crossterm::crossterm_terminal::{get,ClearType};
let mut cursor = get();
// Clear all lines in terminal;
terminal.clear(ClearType::All);
// Clear all cells from current cursor position down.
terminal.clear(ClearType::FromCursorDown);
// Clear all cells from current cursor position down.
terminal.clear(ClearType::FromCursorUp);
// Clear current line cells.
terminal.clear(ClearType::CurrentLine);
// Clear all the cells until next line.
terminal.clear(ClearType::UntilNewLine);
// Get terminal size
let terminal_size = terminal.terminal_size().unwrap();
// Print results
print!("X: {}, y: {}", terminal_size.0, terminal_size.1);
// Scroll down 10 lines.
terminal.scroll_down(10);
// Scroll up 10 lines.
terminal.scroll_up(10);
```
## 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.
- Examples for every client callable code.
## 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 supportable 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 totally 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 features crossterm 0.2
- Handling mouse events
- Inplementing 256 colors for terminals that support those colors.
- Handling key events
- Tests
- Storing and resetting cursor position.
- Text Attributes like: bold,italic, undescore and crossed word.
## Contributing
If you would like to contribute to crossterm, than please design the code as it is now. Each module contains the same structures so we can easely extend to multible platforms. As you study the code you will quiqly see what the architecture is. Maybe later there will be an documentation for how crossterm is design.
## Versioning
The current version is crossterm 0.1, every commit I merge the version go's up like 0.1.0 -> 0.1.1 -> 0.1.2.
When new features arrives the packages will go up like 0.1 -> 0.2 -> 0.3
## Authors
* **Timon Post** - *Project Owner & creator*
## License
This project is licensed under the MIT License - see the [LICENSE.md](LICENSE.md) file for details

View File

@ -1,15 +0,0 @@
extern crate crossterm;
use self::crossterm::crossterm_style::*;
use self::crossterm::crossterm_cursor;
use self::crossterm::crossterm_terminal::*;
use std::io::{stdin, stdout, Write};
pub mod color;
pub mod cursor;
pub mod terminal;
fn main() {
}

View File

@ -1,100 +0,0 @@
//!
//! 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));
}

View File

@ -1,98 +0,0 @@
//!
//! 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,118 +0,0 @@
//!
//! Terminal Examples
//!
extern crate crossterm;
use crossterm::crossterm_terminal::{get, Terminal, ClearType};
use crossterm::crossterm_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).
crossterm_cursor::get().goto(4,8);
// 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).
crossterm_cursor::get().goto(4,8);
// 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).
crossterm_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).
crossterm_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 lines
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 lines
pub fn scroll_up()
{
print_test_data();
// Get terminal
let mut terminal = get();
// Scroll up 10 lines.
let terminal_size = terminal.scroll_up(10);
}

View File

@ -1,217 +0,0 @@
# 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 core functionalities for both windows and unix systems.
Crossterm aims to be simple and easy to call in code. True the simplicity of crossterm you do not have to worry about the platform your working with. You can just call the action you want to preform 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.
```rust
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::*;
```
## Links
Documentation version 0.1.0 can be found [here](https://docs.rs/crossterm/0.1.0/crossterm/)
Documentation version 0.2.0 can be found [here](https://docs.rs/crossterm/0.2.0/crossterm/)
The Cargo Page can be found [here](https://crates.io/search?q=crossterm)
## Examples
For detailed examples of all crossterm functionalities check the [examples](https://github.com/TimonPost/crossterm/tree/master/examples) direcory.
### Styled font
```rust
use crossterm::crossterm_style::{paint, Color};
// Crossterm provides method chaining so that you can style the font nicely.
// the `with()` methods sets the foreground color and the `on()` methods sets the background color
// You can either store the styled font.
let mut styledobject = paint("Stored styled font").with(Color::Red).on(Color::Blue);
println!("{}",styledobject);
// Or you can print it directly.
println!("{}", paint("Red font on blue background color").with(Color::Red).on(Color::Blue));
println!("{}", paint("Red font on default background color").with(Color::Red));
println!("{}", paint("Default font color on Blue background color").on(Color::Blue));
/// The following code can only be used for unix systems:
// Set background Color from RGB
println!("RGB (10,10,10): \t {}", paint(" ").on(Color::Rgb {r: 10, g: 10, b: 10}));
// Set background Color from RGB
println!("ANSI value (50): \t {}", paint(" ").on(Color::AnsiValue(50)));
// Use attributes to syle the font.
println!("{}", paint("Normal text"));
println!("{}", paint("Bold text").bold());
println!("{}", paint("Italic text").italic());
println!("{}", paint("Slow blinking text").slow_blink());
println!("{}", paint("Rapid blinking text").rapid_blink());
println!("{}", paint("Hidden text").hidden());
println!("{}", paint("Underlined text").underlined());
println!("{}", paint("Reversed color").reverse());
println!("{}", paint("Dim text color").dim());
println!("{}", paint("Crossed out font").crossed_out());
```
### Cursor
```rust
use crossterm::crossterm_cursor::get;
let mut cursor = get();
/// Moving the cursor
// Set the cursor to position X: 10, Y: 5 in the terminal
cursor.goto(10,5);
// Move the cursor to position 3 times to the up in the terminal
cursor.move_up(3);
// Move the cursor to position 3 times to the right in the terminal
cursor.move_right(3);
// Move the cursor to position 3 times to the down in the terminal
cursor.move_down(3);
// Move the cursor to position 3 times to the left in the terminal
cursor.move_left(3);
// Print an character at X: 10, Y: 5 (see examples for more explanation why to use this method).
// cursor.goto(10,5).print("@");
/// Safe the current cursor position to recall later
// Goto X: 5 Y: 5
cursor.goto(5,5);
// Safe cursor position: X: 5 Y: 5
cursor.safe_position();
// Goto X: 5 Y: 20
cursor.goto(5,20);
// Print at X: 5 Y: 20.
print!("Yea!");
// Reset back to X: 5 Y: 5.
cursor.reset_position();
// Print 'Back' at X: 5 Y: 5.
print!("Back");
```
### Terminal
```rust
use crossterm::crossterm_terminal::{get,ClearType};
let mut terminal = get();
// Clear all lines in terminal;
terminal.clear(ClearType::All);
// Clear all cells from current cursor position down.
terminal.clear(ClearType::FromCursorDown);
// Clear all cells from current cursor position down.
terminal.clear(ClearType::FromCursorUp);
// Clear current line cells.
terminal.clear(ClearType::CurrentLine);
// Clear all the cells until next line.
terminal.clear(ClearType::UntilNewLine);
// Get terminal size
let terminal_size = terminal.terminal_size().unwrap();
// Print results
print!("X: {}, y: {}", terminal_size.0, terminal_size.1);
// Scroll down 10 lines.
terminal.scroll_down(10);
// Scroll up 10 lines.
terminal.scroll_up(10);
// Set terminal size
terminal.set_size(10,10);
```
## 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.
- Examples for every client callable code.
## Features crossterm 0.2
- 256 color support.
- Text Attributes like: bold, italic, underscore and crossed word ect.
- Custom ANSI color code input to set fore- and background color for unix.
- Storing the current cursor position and resetting to that stored cursor position later.
- Resizing the terminal.
## 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 supportable 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.
## How it works
Crossterm is using `WINAPI` for windows systems and `ANSI escape codes` for unix systems. Crossterm provides one base trait with can be implemented for a platform specific instance. For example, there is an implementation for windows (`WINAPI`) and unix(`ANSI`) for the `cursor module`. To call the platform specific implementation there is one module that rules them all. Thrue this module the client calls some action and the module will deside what to do based on the current platform. And it will execute that action.
## Notice
This library is library is stable. 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 an newer version.
## Todo
- Handling mouse events
- Handling key events
- Tests
## Contributing
If you would like to contribute to crossterm, than please design the code as it is now. Each module contains the same structures so we can easely extend to multible platforms. As you study the code you will quiqly see what the architecture is. Maybe later there will be an documentation for how crossterm is design.
## Versioning
The current version is crossterm 0.1, every commit I merge the version go's up like 0.1.0 -> 0.1.1 -> 0.1.2.
When new features arrives the packages will go up like 0.1 -> 0.2 -> 0.3
## Authors
* **Timon Post** - *Project Owner & creator*
## License
This project is licensed under the MIT License - see the [LICENSE.md](LICENSE.md) file for details

View File

@ -1,29 +0,0 @@
//! This bin folder can be used to try the examples out located in the examples directory.
//!
//! All you need to do is:
//!
//! - Download the crossterm source code.
//! - Add this in the Cargo.toml file:
//! ``` [[bin]]
//! name = "example_bin"
//! path = "./examples/bin.rs"
//! ```
//!
//! - Run program with: `cargo run`
// Import crossterm crate.
extern crate crossterm;
// Add the usings for the crossterms modules to play with crossterm
use self::crossterm::crossterm_style;
use self::crossterm::crossterm_cursor;
use self::crossterm::crossterm_terminal;
// Import the example modules.
pub mod color;
pub mod cursor;
pub mod terminal;
fn main() {
}

View File

@ -1,133 +0,0 @@
//!
//! 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::Red);
// 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));
#[cfg(unix)]
println!("RGB (10,10,10): \t {}", paint(" ").on(Color::Rgb {r: 10, g: 10, b: 10}));
#[cfg(unix)]
println!("RGB (10,10,10): \t {}", paint(" ").on(Color::AnsiValue(50)));
}
/// Print font with all available attributes. Note that this can only be used at unix systems and that some are not supported widely.
#[cfg(unix)]
pub fn print_font_with_attributes()
{
println!("{}", paint("Normal text"));
println!("{}", paint("Bold text").bold());
println!("{}", paint("Italic text").italic());
println!("{}", paint("Slow blinking text").slow_blink());
println!("{}", paint("Rapid blinking text").rapid_blink());
println!("{}", paint("Hidden text").hidden());
println!("{}", paint("Underlined text").underlined());
println!("{}", paint("Reversed color").reverse());
println!("{}", paint("Dim text color").dim());
println!("{}", paint("Crossed out font").crossed_out());
}
/// Print all supported rgb colors
#[cfg(unix)]#[cfg(unix)]
pub fn print_supported_colors()
{
let count = crossterm::crossterm_style::get().get_available_color_count().unwrap();
for i in 0..count
{
println!("{}", paint(format!("Color: {}",i)).with(Color::AnsiValue(i as u8)));
}
}

View File

@ -1,119 +0,0 @@
//!
//! 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("@");
}
/// Save and reset cursor position.
pub fn safe_and_reset_position()
{
let mut cursor = get();
// Goto X: 5 Y: 5
cursor.goto(5,5);
// Safe cursor position: X: 5 Y: 5
cursor.safe_position();
// Goto X: 5 Y: 20
cursor.goto(5,20);
// Print at X: 5 Y: 20.
print!("Yea!");
// Reset back to X: 5 Y: 5.
cursor.reset_position();
// Print Back at X: 5 Y: 5.
print!("Back");
println!()
}

View File

@ -1,135 +0,0 @@
//!
//! Terminal Examples
//!
extern crate crossterm;
use crossterm::crossterm_terminal::{get, Terminal, ClearType};
use crossterm::crossterm_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).
crossterm_cursor::get().goto(4,8);
// 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).
crossterm_cursor::get().goto(4,8);
// 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).
crossterm_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).
crossterm_cursor::get().goto(4,7);
// 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);
}
/// Set the terminal size to width 10, height: 10.
pub fn set_terminal_size()
{
let mut terminal = get();
terminal.set_size(10,10);
}
// scroll down 10 lines
pub fn scroll_down()
{
print_test_data();
// Get terminal
let mut terminal = get();
// Scroll down 10 lines.
terminal.scroll_down(10);
}
// scroll down 10 lines
pub fn scroll_up()
{
print_test_data();
// Get terminal
let mut terminal = get();
// Scroll up 10 lines.
terminal.scroll_up(10);
}
// Resize the terminal to X: 10, Y: 10
pub fn resize_terminal()
{
// Get terminal
let mut terminal = get();
// Get terminal size
terminal.set_size(1,1);
}

View File

@ -1,240 +0,0 @@
# 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 core functionalities for both windows and unix systems.
Crossterm aims to be simple and easy to call in code. True the simplicity of crossterm you do not have to worry about the platform your working with. You can just call the action you want to preform and unther water it will check what to do based on the current platform.
Currently working on the alternatescreen and raw terminal features.
## Getting Started
This documentation is only for the newest version of crossterm. See the [Upgrade manual for more info](https://github.com/TimonPost/crossterm/blob/development/UPGRADE%20Manual)
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.
```rust
extern crate crossterm;
// this module is used for styling the terminal
use self::crossterm::style::*;
// this module is used for cursor related actions
use self::crossterm::cursor::*;
// this mudule is used for terminal related actions
use self::crossterm::terminal::*;
```
## Links
Documentation for the code version 0.1 can be found [here](https://docs.rs/crossterm/0.1.0/crossterm/)
Documentation for the code version 0.2 can be found [here](https://docs.rs/crossterm/0.2.0/crossterm/)
The Cargo Page can be found [here](https://crates.io/search?q=crossterm)
## Examples
For detailed examples of all crossterm functionalities check the [examples](https://github.com/TimonPost/crossterm/tree/master/examples) direcory.
### Styled font
```rust
use crossterm::style::{paint, Color};
// Crossterm provides method chaining so that you can style the font nicely.
// the `with()` methods sets the foreground color and the `on()` methods sets the background color
// You can either store the styled font.
let mut styledobject = paint("Stored styled font").with(Color::Red).on(Color::Blue);
println!("{}",styledobject);
// Or you can print it directly.
println!("{}", paint("Red font on blue background color").with(Color::Red).on(Color::Blue));
println!("{}", paint("Red font on default background color").with(Color::Red));
println!("{}", paint("Default font color on Blue background color").on(Color::Blue));
/// The following code can only be used for unix systems:
// Set background Color from RGB
println!("RGB (10,10,10): \t {}", paint(" ").on(Color::Rgb {r: 10, g: 10, b: 10}));
// Set background Color from RGB
println!("ANSI value (50): \t {}", paint(" ").on(Color::AnsiValue(50)));
// Use attributes to syle the font.
println!("{}", paint("Normal text"));
println!("{}", paint("Bold text").bold());
println!("{}", paint("Italic text").italic());
println!("{}", paint("Slow blinking text").slow_blink());
println!("{}", paint("Rapid blinking text").rapid_blink());
println!("{}", paint("Hidden text").hidden());
println!("{}", paint("Underlined text").underlined());
println!("{}", paint("Reversed color").reverse());
println!("{}", paint("Dim text color").dim());
println!("{}", paint("Crossed out font").crossed_out());
```
### Cursor
```rust
use crossterm::cursor::cursor();
let mut cursor = cursor();
/// Moving the cursor
// Set the cursor to position X: 10, Y: 5 in the terminal
cursor.goto(10,5);
// Move the cursor to position 3 times to the up in the terminal
cursor.move_up(3);
// Move the cursor to position 3 times to the right in the terminal
cursor.move_right(3);
// Move the cursor to position 3 times to the down in the terminal
cursor.move_down(3);
// Move the cursor to position 3 times to the left in the terminal
cursor.move_left(3);
// Print an character at X: 10, Y: 5 (see examples for more explanation why to use this method).
// cursor.goto(10,5).print("@");
/// Safe the current cursor position to recall later
// Goto X: 5 Y: 5
cursor.goto(5,5);
// Safe cursor position: X: 5 Y: 5
cursor.safe_position();
// Goto X: 5 Y: 20
cursor.goto(5,20);
// Print at X: 5 Y: 20.
print!("Yea!");
// Reset back to X: 5 Y: 5.
cursor.reset_position();
// Print 'Back' at X: 5 Y: 5.
print!("Back");
```
### Terminal
```rust
use crossterm::terminal::{terminal,ClearType};
let mut terminal = terminal();
// Clear all lines in terminal;
terminal.clear(ClearType::All);
// Clear all cells from current cursor position down.
terminal.clear(ClearType::FromCursorDown);
// Clear all cells from current cursor position down.
terminal.clear(ClearType::FromCursorUp);
// Clear current line cells.
terminal.clear(ClearType::CurrentLine);
// Clear all the cells until next line.
terminal.clear(ClearType::UntilNewLine);
// Get terminal size
let terminal_size = terminal.terminal_size().unwrap();
// Print results
print!("X: {}, y: {}", terminal_size.0, terminal_size.1);
// Scroll down 10 lines.
terminal.scroll_down(10);
// Scroll up 10 lines.
terminal.scroll_up(10);
// Set terminal size
terminal.set_size(10,10);
```
## 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.
- Examples for every client callable code.
## Features crossterm 0.2
- 256 color support.
- Text Attributes like: bold, italic, underscore and crossed word ect.
- Custom ANSI color code input to set fore- and background color for unix.
- Storing the current cursor position and resetting to that stored cursor position later.
- Resizing the terminal.
### fixes in crossterm 0.2.1
- Default ANSI escape codes for windows machines, if windows does not support ANSI switsh back to WINAPI.
- method grammer mistake fixed [Issue 3](https://github.com/TimonPost/crossterm/issues/3)
- Some Refactorings in method names see [issue 4](https://github.com/TimonPost/crossterm/issues/4)
- Removed bin refrence from crate [Issue 6](https://github.com/TimonPost/crossterm/issues/6)
- The terminal state will be set to its original state when process ends [issue7](https://github.com/TimonPost/crossterm/issues/7).
- Get position unix fixed [issue 8](https://github.com/TimonPost/crossterm/issues/8)
## TODO Features crossterm 0.3
- Raw state implementation [Issue 5](https://github.com/TimonPost/crossterm/issues/5).
- Alternate screen implementation.
- Tests
## 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 supportable 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.
## How it works
Crossterm is using `WINAPI` for windows systems and `ANSI escape codes` for unix systems. Crossterm provides one base trait with can be implemented for a platform specific instance. For example, there is an implementation for windows (`WINAPI`) and unix(`ANSI`) for the `cursor module`. To call the platform specific implementation there is one module that rules them all. Thrue this module the client calls some action and the module will deside what to do based on the current platform. And it will execute that action.
## Notice
This library is library is stable. 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 an newer version.
## Todo
- This library does not support any kind of raw terminal. When an terminal changes some core state of the terminal this state should be revered when the process ends from this library. Currently there are not made any changed to the core state of the terminal with this library. But when some fearures in the furure will be inplemented this will be the case. So there should come an kind of raw state for the terminal and reversable options to redo all the changes made to the core state when the process ends. More information can be found at this [thread](https://www.reddit.com/r/rust/comments/7tg6n2/looking_for_feedback_onmy_cross_platform_terminal/dtf4ilo/)
- Handling mouse events
- Handling key events
- Tests
## Contributing
If you would like to contribute to crossterm, than please design the code as it is now. Each module contains the same structures so we can easely extend to multible platforms. As you study the code you will quiqly see what the architecture is. Maybe later there will be an documentation for how crossterm is design.
## Versioning
The current version is crossterm 0.1, every commit I merge the version go's up like 0.1.0 -> 0.1.1 -> 0.1.2.
When new features arrives the packages will go up like 0.1 -> 0.2 -> 0.3
## Authors
* **Timon Post** - *Project Owner & creator*
## License
This project is licensed under the MIT License - see the [LICENSE.md](LICENSE.md) file for details

View File

@ -1,21 +0,0 @@
//! This bin folder can be used to try the examples out located in the examples directory.
//!
//! All you need to do is:
//!
//! - Download the crossterm source code.
//! - Add this in the Cargo.toml file:
//! ``` [[bin]]
//! name = "example_bin"
//! path = "./examples/bin.rs"
//! ```
//!
//! - Run program with: `cargo run`
mod cursor;
mod terminal;
use terminal::alternate_screen;
fn main() {
alternate_screen::t();
}

View File

@ -1,132 +0,0 @@
//!
//! Color Examples
//!
extern crate crossterm;
use self::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::Red);
// 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));
#[cfg(unix)]
println!("RGB (10,10,10): \t {}", paint(" ").on(Color::Rgb {r: 10, g: 10, b: 10}));
#[cfg(unix)]
println!("RGB (10,10,10): \t {}", paint(" ").on(Color::AnsiValue(50)));
}
/// Print font with all available attributes. Note that this can only be used at unix systems and that some are not supported widely | demonstration..
#[cfg(unix)]
pub fn print_font_with_attributes()
{
println!("{}", paint("Normal text"));
println!("{}", paint("Bold text").bold());
println!("{}", paint("Italic text").italic());
println!("{}", paint("Slow blinking text").slow_blink());
println!("{}", paint("Rapid blinking text").rapid_blink());
println!("{}", paint("Hidden text").hidden());
println!("{}", paint("Underlined text").underlined());
println!("{}", paint("Reversed color").reverse());
println!("{}", paint("Dim text color").dim());
println!("{}", paint("Crossed out font").crossed_out());
}
/// Print all supported rgb colors | demonstration.
#[cfg(unix)]
pub fn print_supported_colors()
{
let count = crossterm::style::color().get_available_color_count().unwrap();
for i in 0..count
{
println!("{}", paint(format!("Color: {}",i)).with(Color::AnsiValue(i as u8)));
}
}

View File

@ -1,128 +0,0 @@
//!
//! Cursor Examples
//!
extern crate crossterm;
use self::crossterm::cursor::{cursor, TerminalCursor};
use self::crossterm::{Context, Terminal };
/// Set the cursor to position X: 10, Y: 5 in the terminal.
pub fn goto()
{
let context = Terminal::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);
}
/// Move the cursor 3 up | demonstration.
pub fn move_up()
{
let context = Terminal::new();
// Get the cursor
let mut cursor = cursor(&context);
// Move the cursor to position 3 times to the up in the terminal
cursor.move_up(3);
}
/// Move the cursor 3 to the right | demonstration.
pub fn move_right()
{
let context = Terminal::new();
// Get the cursor
let mut cursor = cursor(&context);
// Move the cursor to position 3 times to the right in the terminal
cursor.move_right(3);
}
/// Move the cursor 3 down | demonstration.
pub fn move_down()
{
let context = Terminal::new();
// Get the cursor
let mut cursor = cursor(&context);
// Move the cursor to position 3 times to the down in the terminal
cursor.move_down(3);
}
/// Move the cursor 3 to the left | demonstration.
pub fn move_left()
{
let context = Terminal::new();
// Get the cursor
let mut cursor = cursor(&context);
// Move the cursor to position 3 times to the left in the terminal
cursor.move_left(3);
}
/// Print character at X: 10 Y: 5 | demonstration.
pub fn print()
{
let context = Terminal::new();
// To print an some displayable content on an certain position.
// Get the cursor
let mut cursor = cursor(&context);
// 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 much 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.
*/
cursor.goto(10,5).print("@");
}
/// Save and reset cursor position | demonstration..
pub fn safe_and_reset_position()
{
let context = Terminal::new();
let mut cursor = cursor(&context);
// Goto X: 5 Y: 5
cursor.goto(5,5);
// Safe cursor position: X: 5 Y: 5
cursor.save_position();
// Goto X: 5 Y: 20
cursor.goto(5,20);
// Print at X: 5 Y: 20.
println!("Yea!");
// Reset back to X: 5 Y: 5.
cursor.reset_position();
// Print Back at X: 5 Y: 5.
println!("Back");
println!()
}

View File

@ -1,5 +0,0 @@
pub mod alternate_screen;
mod raw_mode;
pub mod terminal;

View File

@ -1,157 +0,0 @@
//!
//! Terminal Examples
//!
extern crate crossterm;
use self::crossterm::terminal::{ ClearType, terminal};
use self::crossterm::cursor;
use self::crossterm::{ Context, Terminal };
fn print_test_data()
{
for i in 0..100 {
println!("Test data to test terminal: {}",i);
}
}
/// Clear all lines in terminal | demonstration
pub fn clear_all_lines()
{
let term = Terminal::new();
// Get terminal
let mut terminal = terminal(&term);
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()
{
let term = Terminal::new();
// Get terminal
let mut terminal = terminal(&term);
print_test_data();
// Set terminal cursor position (see example for more info).
cursor::cursor(&term).goto(4,8);
// 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()
{
let term = Terminal::new();
// Get terminal
let mut terminal = terminal(&term);
print_test_data();
// Set terminal cursor position (see example for more info).
cursor::cursor(&term).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()
{
let term = Terminal::new();
// Get terminal
let mut terminal = terminal(&term);
print_test_data();
// Set terminal cursor position (see example for more info).
cursor::cursor(&term).goto(4,4);
// Clear current line cells.
terminal.clear(ClearType::CurrentLine);
}
/// Clear all lines from cursor position X:4, Y:7 up | demonstration
pub fn clear_until_new_line()
{
let term = Terminal::new();
// Get terminal
let mut terminal = terminal(&term);
print_test_data();
// Set terminal cursor position (see example for more info).
cursor::cursor(&term).goto(4,20);
// Clear all the cells until next line.
terminal.clear(ClearType::UntilNewLine);
}
/// Print the the current terminal size | demonstration.
pub fn print_terminal_size()
{
let term = Terminal::new();
// Get terminal
let mut terminal = terminal(&term);
// Get terminal size
let terminal_size = terminal.terminal_size();
// Print results
print!("X: {}, y: {}", terminal_size.0, terminal_size.1);
}
/// Set the terminal size to width 10, height: 10 | demonstration.
pub fn set_terminal_size()
{
let term = Terminal::new();
let mut terminal = terminal(&term);
terminal.set_size(10,10);
}
/// Scroll down 10 lines | demonstration.
pub fn scroll_down()
{
let term = Terminal::new();
print_test_data();
// Get terminal
let mut terminal = terminal(&term);
// Scroll down 10 lines.
terminal.scroll_down(10);
}
/// Scroll down 10 lines | demonstration.
pub fn scroll_up()
{
let term = Terminal::new();
print_test_data();
// Get terminal
let mut terminal = terminal(&term);
// Scroll up 10 lines.
terminal.scroll_up(10);
}
/// Resize the terminal to X: 10, Y: 10 | demonstration.
pub fn resize_terminal()
{
let term = Terminal::new();
// Get terminal
let mut terminal = terminal(&term);
// Get terminal size
terminal.set_size(10,10);
}

View File

@ -1,71 +0,0 @@
//! This bin folder can be used to try the examples out located in the examples directory.
//!
//! All you need to do is:
//!
//! - Download the crossterm source code.
//! - Add this in the Cargo.toml file:
//! ``` [[bin]]
//! name = "example_bin"
//! path = "./examples/bin.rs"
//! ```
//!
//! - Run program with: `cargo run`
extern crate crossterm;
use crossterm::Context;
// mod terminal;
// mod color;
// mod cursor;
// mod crossterm_type;
use crossterm::raw::IntoRawMode;
use std::{thread, time};
use std::io::Read;
fn main()
{
// let mut rv = String::new();
// {
// let alternate = ::crossterm::screen::AlternateScreen::from(context.clone());
// alternate.into_raw_mode(context.clone());
// thread::spawn(|| {
// let context = Context::new();
// let input = ::crossterm::input::input(&context);
// let result = input.read_async().unwrap();
// println!("input: {:?}",result);
// });
let context = Context::new();
let input = ::crossterm::input::input(&context);
let mut stdin = input.read_until_async(b'\r' as u8).bytes();
for i in 0..100
{
let a = stdin.next();
println!("input: {:?} exptected: {:?}", a,b'\r');
if let Some(Ok(b'q')) = a {
break;
}
thread::sleep(time::Duration::from_millis(50));
// println!("Some data {:?}", b)
}
// ::std::io::stdin().read_line(&mut rv);
// let len = rv.trim_right_matches(&['\r', '\n'][..]).len();
// rv.truncate(len);
// }
}

View File

@ -1,7 +0,0 @@
This folder contains examples for version 0.3.0 Here you will find examples of all the functionalities crossterm offers.
It has 4 modules:
- color (this is about all the styling of the terminal)
- cursor (this is about all the actions you can perform with the cursor)
- terminal (this is about all the actions you can perform on the terminal)
- program examples (this folder will contain some real life examples)

View File

@ -1,206 +0,0 @@
//!
//! Examples of coloring the terminal.
//!
extern crate crossterm;
use self::crossterm::style::Color;
use self::crossterm::terminal;
use self::crossterm::Context;
/// print some red font | demonstration.
pub fn paint_foreground() {
let context = Context::new();
let terminal = terminal::terminal(&context);
// 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 = terminal.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!("{}", terminal.paint("Red font").with(Color::Red));
}
/// print some font on red background | demonstration.
pub fn paint_background() {
let context = Context::new();
let terminal = terminal::terminal(&context);
// 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 = terminal.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::Red);
// 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!("{}", terminal.paint("Red background color").on(Color::Red));
}
/// print font with fore- background color | demonstration.
pub fn paint_foreground_and_background() {
let context = Context::new();
let terminal = terminal::terminal(&context);
// 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 = terminal.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!(
"{}",
terminal
.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() {
let context = Context::new();
let terminal = terminal::terminal(&context);
println!("Black : \t {}", terminal.paint("").with(Color::Black));
println!("Red : \t\t {}", terminal.paint("").with(Color::Red));
println!(
"Dark Red: \t {}",
terminal.paint("").with(Color::DarkRed)
);
println!("Green : \t {}", terminal.paint("").with(Color::Green));
println!(
"Dark Green : \t {}",
terminal.paint("").with(Color::DarkGreen)
);
println!("Yellow : \t {}", terminal.paint("").with(Color::Yellow));
println!(
"Dark Yellow : \t {}",
terminal.paint("").with(Color::DarkYellow)
);
println!("Blue : \t\t {}", terminal.paint("").with(Color::Blue));
println!(
"Dark Blue : \t {}",
terminal.paint("").with(Color::DarkBlue)
);
println!(
"Magenta : \t {}",
terminal.paint("").with(Color::Magenta)
);
println!(
"Dark Magenta : \t {}",
terminal.paint("").with(Color::DarkMagenta)
);
println!("Cyan : \t\t {}", terminal.paint("").with(Color::Cyan));
println!(
"Dark Cyan : \t {}",
terminal.paint("").with(Color::DarkCyan)
);
println!("Grey : \t\t {}", terminal.paint("").with(Color::Grey));
println!("White : \t {}", terminal.paint("").with(Color::White));
}
/// Print all available foreground colors | demonstration.
pub fn print_all_background_colors() {
let context = Context::new();
let terminal = terminal::terminal(&context);
println!("Black : \t {}", terminal.paint(" ").on(Color::Black));
println!("Red : \t\t {}", terminal.paint(" ").on(Color::Red));
println!("Dark Red: \t {}", terminal.paint(" ").on(Color::DarkRed));
println!("Green : \t {}", terminal.paint(" ").on(Color::Green));
println!(
"Dark Green : \t {}",
terminal.paint(" ").on(Color::DarkGreen)
);
println!("Yellow : \t {}", terminal.paint(" ").on(Color::Yellow));
println!(
"Dark Yellow : \t {}",
terminal.paint(" ").on(Color::DarkYellow)
);
println!("Blue : \t\t {}", terminal.paint(" ").on(Color::Blue));
println!(
"Dark Blue : \t {}",
terminal.paint(" ").on(Color::DarkBlue)
);
println!("Magenta : \t {}", terminal.paint(" ").on(Color::Magenta));
println!(
"Dark Magenta : \t {}",
terminal.paint(" ").on(Color::DarkMagenta)
);
println!("Cyan : \t\t {}", terminal.paint(" ").on(Color::Cyan));
println!(
"Dark Cyan : \t {}",
terminal.paint(" ").on(Color::DarkCyan)
);
println!("Grey : \t\t {}", terminal.paint(" ").on(Color::Grey));
println!("White : \t {}", terminal.paint(" ").on(Color::White));
#[cfg(unix)]
println!(
"RGB (10,10,10): \t {}",
terminal.paint(" ").on(Color::Rgb {
r: 10,
g: 10,
b: 10
})
);
#[cfg(unix)]
println!(
"RGB (10,10,10): \t {}",
terminal.paint(" ").on(Color::AnsiValue(50))
);
}
/// Print font with all available attributes. Note that this can only be used at unix systems and that some are not supported widely | demonstration..
#[cfg(unix)]
pub fn print_font_with_attributes() {
let context = Context::new();
let terminal = terminal::terminal(&context);
println!("{}", terminal.paint("Normal text"));
println!("{}", terminal.paint("Bold text").bold());
println!("{}", terminal.paint("Italic text").italic());
println!("{}", terminal.paint("Slow blinking text").slow_blink());
println!("{}", terminal.paint("Rapid blinking text").rapid_blink());
println!("{}", terminal.paint("Hidden text").hidden());
println!("{}", terminal.paint("Underlined text").underlined());
println!("{}", terminal.paint("Reversed color").reverse());
println!("{}", terminal.paint("Dim text color").dim());
println!("{}", terminal.paint("Crossed out font").crossed_out());
}
/// Print all supported rgb colors | demonstration.
#[cfg(unix)]
pub fn print_supported_colors() {
let context = Context::new();
let terminal = terminal::terminal(&context);
let count = crossterm::style::color(&context)
.get_available_color_count()
.unwrap();
for i in 0..count {
println!(
"{}",
terminal
.paint(format!("Color: {}", i))
.with(Color::AnsiValue(i as u8))
);
}
}

View File

@ -1,67 +0,0 @@
extern crate crossterm;
use crossterm::Crossterm;
/// use the `Crossterm` to get an instance to the cursor module | demonstration.
pub fn use_crossterm_cursor()
{
let crossterm = Crossterm::new();
let mut cursor = crossterm.cursor();
cursor.goto(5,5).print("test");
}
use crossterm::style::Color;
/// use the `Crossterm` to get an instance to the color module | demonstration.
pub fn use_crossterm_color()
{
let crossterm = Crossterm::new();
let mut color = crossterm.color();
color.set_bg(Color::Red);
color.set_fg(Color::Green);
}
use crossterm::terminal::ClearType;
/// use the `Crossterm` to get an instance to the terminal module | demonstration.
pub fn use_crossterm_terminal()
{
let crossterm = Crossterm::new();
let mut terminal = crossterm.terminal();
terminal.clear(ClearType::All);
terminal.set_size(40,40);
}
/// paint text with colors using `Crossterm` | demonstration.
pub fn use_crossterm_paint()
{
let crossterm = Crossterm::new();
crossterm.paint("Black on BLUE").with(Color::Black).on(Color::Blue);
}
/// write text to terminal using `Crossterm` | demonstration.
pub fn use_crossterm_write()
{
let crossterm = Crossterm::new();
crossterm.write("some text \nsome text on new line");
}
/// Switch to alternate screen using the `Context` of `Crossterm` | demonstration.
pub fn create_alternate_screen_from_crossterm()
{
use crossterm::screen::*;
use std::convert::From;
let crossterm = Crossterm::new();
{
// move into alternate screen
let alternate_screen = AlternateScreen::from(crossterm.context());
// this will move the cursor and print `some text` on the alternate screen.
crossterm.cursor().goto(10, 10).print("Some text");
} // <- alternate screen ends here an will be switched back to main screen.
// print "Some other text" on the mainscreen at x: 0, y: 10
crossterm.cursor().goto(0,10).print("Some other text");
}

View File

@ -1,141 +0,0 @@
//!
//! Examples of actions that could be performed with te cursor.
//!
extern crate crossterm;
use self::crossterm::cursor::{cursor, TerminalCursor};
use self::crossterm::Context;
/// Set the cursor to position X: 10, Y: 5 in the terminal.
pub fn goto() {
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);
}
/// get the cursor position
pub fn pos() {
let context = Context::new();
// Get the cursor
let mut cursor = cursor(&context);
// get the cursor position.
let (x, y) = cursor.pos();
}
/// Move the cursor 3 up | demonstration.
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
cursor.move_up(10);
}
/// Move the cursor 3 to the right | demonstration.
pub fn move_right() {
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
cursor.move_right(3);
}
/// Move the cursor 3 down | demonstration.
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
cursor.move_down(3);
}
/// Move the cursor 3 to the left | demonstration.
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
cursor.move_left(3);
}
/// Print character at X: 10 Y: 5 | demonstration.
pub fn print() {
let context = Context::new();
// To print an some displayable content on an certain position.
// Get the cursor
let mut cursor = cursor(&context);
// 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 much 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.
*/
cursor.goto(10, 5).print("@");
}
/// Save and reset cursor position | demonstration..
pub fn safe_and_reset_position() {
let context = Context::new();
let mut cursor = cursor(&context);
// Goto X: 5 Y: 5
cursor.goto(5, 5);
// Safe cursor position: X: 5 Y: 5
cursor.save_position();
// Goto X: 5 Y: 20
cursor.goto(5, 20);
// Print at X: 5 Y: 20.
println!("Yea!");
// Reset back to X: 5 Y: 5.
cursor.reset_position();
// Print Back at X: 5 Y: 5.
println!("Back");
println!()
}
/// Hide cursor display | demonstration.
pub fn hide_cursor() {
let context = Context::new();
let cursor = cursor(&context);
cursor.hide();
}
/// Show cursor display | demonstration.
pub fn show_cursor() {
let context = Context::new();
let cursor = cursor(&context);
cursor.show();
}
/// Show cursor display, only works on certain terminals.| demonstration
pub fn blink_cursor() {
let context = Context::new();
let cursor = cursor(&context);
cursor.blink(false);
cursor.blink(false);
}

View File

@ -1,8 +0,0 @@
This folder will contain some examples of how to use this crate in an real live environment.
If you have created a game or something feel free to upload it, would be a great help for other people and me to make this crate better!
The programs are:
- First depth search:
This is an search algorithm implemented visually. This program uses the following functionalities: cursor movement, coloring, alternate screen and terminal clearing.

View File

@ -1,11 +0,0 @@
[package]
name = "first_depth_search"
version = "0.1.0"
authors = ["TimonPost <timonpost@hotmail.nl>"]
[dependencies]
rand = "0.4.2"
[dependencies.crossterm]
path = "../../../../"
branch = "development"

View File

@ -1,155 +0,0 @@
//! Implementation of the first depth search algorithm
use super::variables::{Direction, Position};
use super::messages::END_MESSAGE;
use super::map::Map;
use crossterm::style::Color;
use crossterm::Crossterm;
use super::rand;
use super::rand::distributions::{IndependentSample, Range};
use std::io::{stdout, Write};
use std::{thread, time};
pub struct FirstDepthSearch<'crossterm>
{
direction: Direction,
map: Map,
stack: Vec<Position>,
root_pos: Position,
is_terminated: bool,
crossterm: &'crossterm Crossterm
}
impl<'crossterm> FirstDepthSearch<'crossterm>
{
pub fn new(map: Map, start_pos: Position, crossterm: &'crossterm Crossterm) -> FirstDepthSearch<'crossterm>
{
FirstDepthSearch
{
direction: Direction::Up,
map: map,
stack: Vec::new(),
root_pos: start_pos,
is_terminated: false,
crossterm: crossterm,
}
}
pub fn start(&mut self)
{
self.is_terminated = false;
// push first position on the stack
self.stack.push(self.root_pos);
let mut cursor = self.crossterm.cursor();
cursor.hide();
// loop until there are now items left in the stack.
loop {
if self.stack.len() == 0
{
break;
}
self.choose_random_neighbor();
if self.is_terminated
{
break;
}
self.update_position();
let cell = self.crossterm.paint(" ").on(Color::Blue);
let pos = self.root_pos.clone();
let x = pos.x as u16;
let y = pos.y as u16;
cursor.goto(x,y).print(cell);
::std::io::stdout().flush();
thread::sleep(time::Duration::from_millis(2));
}
}
/// With this function we are choosing an random neighbor that we havent visited yet.
fn choose_random_neighbor(&mut self)
{
let mut available_directions: Vec<Direction> = Vec::with_capacity(4);
// check every direction if the direction is not visited we can add it to the list.
// note that if the y or x is 0 that we don't want to subtract because we get an subtract overflow.
if self.root_pos.y != 0 && !self.map.is_cell_visited(self.root_pos.x, self.root_pos.y - 1)
{
available_directions.push(Direction::Up)
}
if !&self.map.is_cell_visited(self.root_pos.x, self.root_pos.y + 1)
{
available_directions.push(Direction::Down)
}
if self.root_pos.x != 0 && !self.map.is_cell_visited(self.root_pos.x - 1, self.root_pos.y)
{
available_directions.push(Direction::Left)
}
if !&self.map.is_cell_visited(self.root_pos.x + 1, self.root_pos.y)
{
available_directions.push(Direction::Right)
}
let directions_count = available_directions.len();
// if there are no directions left we need to backtrack until we find directions to go to.
if directions_count != 0
{
let step = Range::new(0, directions_count);
let mut rng = rand::thread_rng();
let choice = step.ind_sample(&mut rng);
// set the current direction to the new random generated direction.
self.direction = available_directions[choice];
}
else {
self.find_first_possible_direction();
}
}
/// Find direction to go to if there is no direction pop the current position of the stack for back tracking to the previous position.
fn find_first_possible_direction(&mut self)
{
// if there are no elements left in the stack that means we have visited all cell and we van terminate the program.
if let Some(previous_cell) = &self.stack.pop()
{
// update root pos to previous cell and continue searching for new neighbours
self.root_pos = *previous_cell;
self.choose_random_neighbor();
}
else {
self.is_terminated = true;
}
}
/// update the root position to the new direction we went in
fn update_position(&mut self)
{
match self.direction
{
Direction::Up => self.root_pos.y -= 1,
Direction::Down => self.root_pos.y += 1,
Direction::Left => self.root_pos.x -= 1,
Direction::Right => self.root_pos.x += 1,
_ => panic!()
};
self.map.set_visited(self.root_pos.x, self.root_pos.y);
self.stack.push(self.root_pos);
}
}

View File

@ -1,90 +0,0 @@
extern crate rand;
extern crate crossterm;
mod map;
mod algorithm;
mod messages;
mod variables;
use crossterm::Crossterm;
use crossterm::terminal::ClearType;
use crossterm::style::Color;
use crossterm::screen;
use self::variables::{Size, Position };
use self::messages::WELCOME_MESSAGE;
use std::iter::Iterator;
use std::{thread, time};
fn main()
{
run();
}
/// run the program
pub fn run()
{
// // create new Crossterm instance.
// let mut crossterm = Crossterm::new();
//
// print_welcome_screen(&crossterm);
//
// start_algorithm(&mut crossterm);
//
// print_end_screen(&crossterm);
}
fn start_algorithm(crossterm: &mut Crossterm)
{
// we first want to switch to alternate screen. On the alternate screen we are going to run or firstdepthsearch algorithm
let alternate_screen = screen::AlternateScreen::from(crossterm.context());
// setup the map size and the position to start searching for a path.
let map_size = Size::new(100,40);
let start_pos = Position::new(10,10);
// create and render the map. Or map border is going to have an █ look and inside the map is just a space.
let mut map = map::Map::new(map_size, '█', ' ');
map.render_map(crossterm);
// create the algorithm and start the
let mut algorithm = algorithm::FirstDepthSearch::new(map, start_pos, &crossterm);
algorithm.start();
}
fn print_end_screen(crossterm: &Crossterm)
{
}
fn print_welcome_screen(crossterm: &Crossterm)
{
// create the handle for the cursor and terminal.
let mut cursor = crossterm.cursor();
let mut terminal = crossterm.terminal();
// clear the screen and print the welcome message.
terminal.clear(ClearType::All);
cursor.goto(0,0);
terminal.write(WELCOME_MESSAGE.join("\n"));
cursor.hide();
cursor.goto(0,10);
terminal.write(
"The first depth search algorithm will start in: Seconds"
);
// print some progress example.
for i in (1..5).rev() {
// print the current counter at the line of `Seconds to Go: {counter}`
cursor
.goto(48, 10)
.print(terminal.paint(format!("{}", i)).with(Color::Red).on(Color::Blue));
// 1 second delay
thread::sleep(time::Duration::from_secs(1));
}
}

View File

@ -1,75 +0,0 @@
use super::variables::{Cell, Position, Size };
use crossterm::terminal::terminal;
use crossterm::cursor::cursor;
use crossterm::Crossterm;
use crossterm::style::{ObjectStyle, StyledObject, Color};
use crossterm::Context;
use std::rc::Rc;
use std::fmt::Display;
pub struct Map
{
pub map: Vec<Vec<Cell>>,
pub size: Size,
}
impl Map
{
pub fn new(map_size: Size, wall_cell_char: char, map_cell_char: char) -> Map
{
let mut map: Vec<Vec<Cell>> = Vec::new();
// initialize the map shown on the screen. Each cell of terminal should have a value that could be changed by the algorithm
// create n rows with n cells.
for y in 0..map_size.height
{
let mut row: Vec<Cell> = Vec::new();
for x in 0..map_size.width
{
if (y == 0 || y == map_size.height - 1) || (x == 0 || x == map_size.width - 1)
{
row.push(Cell::new(Position::new(x, y), Color::Black, wall_cell_char, true));
} else {
row.push(Cell::new(Position::new(x, y), Color::Black, map_cell_char, false));
}
}
map.push(row);
}
Map { map: map, size: Size::new(map_size.width, map_size.height)}
}
// render the map on the screen.
pub fn render_map(&mut self, crossterm: &mut Crossterm)
{
let mut cursor = crossterm.cursor();
for row in self.map.iter_mut()
{
for column in row.iter_mut()
{
// we only have to render the walls
if (column.position.y == 0 || column.position.y == self.size.height - 1) || (column.position.x == 0 || column.position.x == self.size.width - 1)
{
let cell_style = crossterm.paint(column.look).on(column.color);
cursor.goto(column.position.x as u16, column.position.y as u16)
.print(cell_style);
}
}
}
}
// check if position in the map at the given coords is visted.
pub fn is_cell_visited(&self, x: usize, y: usize) -> bool
{
self.map[y][x].visited
}
// change an position in the map to visited.
pub fn set_visited(&mut self, x: usize, y: usize)
{
self.map[y][x].visited = true;
}
}

View File

@ -1,25 +0,0 @@
use super::variables::Position;
pub const WELCOME_MESSAGE: [&str; 6] =
[
"__ __ .__ __ ",
"/ \\ / \\ ____ | | | | ______ _____ ____ ",
"\\ \\/\\/ // __ \\| | | |/ / _ \\ / \\_/ __ \\ ",
" \\ /\\ ___/| |_| < <_> ) Y Y \\ ___/ ",
" \\__/\\ / \\___ >____/__|_ \\____/|__|_| /\\___ > ",
" \\/ \\/ \\/ \\/ \\/ "
];
pub const END_MESSAGE: [&str; 5] =
[
"-----------------------",
" ",
" No routes (DONE) ",
" ",
"-----------------------",
];
pub fn print_stack_count(position: Position)
{
}

View File

@ -1,4 +0,0 @@
mod map;
mod messages;
mod variables;
mod algorithm;

View File

@ -1,63 +0,0 @@
extern crate crossterm;
use self::crossterm::terminal::{terminal, ClearType};
use self::crossterm::style::{Color, StyledObject, ObjectStyle };
use self::crossterm::Context;
use std::fmt::Debug;
use std::fmt;
#[derive(Copy, Clone,Debug)]
pub enum Direction
{
Up = 0,
Down = 1,
Left = 2,
Right = 3
}
#[derive(Copy, Clone, Debug)]
pub struct Position
{
pub x: usize,
pub y: usize
}
impl Position
{
pub fn new(x: usize, y: usize) -> Position
{
Position { x, y }
}
}
#[derive(Copy, Clone)]
pub struct Size
{
pub width: usize,
pub height: usize
}
impl Size
{
pub fn new(width: usize, height: usize) -> Size
{
Size {width,height}
}
}
pub struct Cell
{
pub position: Position,
pub color: Color,
pub look: char,
pub visited: bool
}
impl Cell
{
pub fn new(position: Position, color: Color, look: char, visited: bool) -> Cell
{
Cell { position, color, look, visited }
}
}

View File

@ -1,81 +0,0 @@
extern crate crossterm;
use crossterm::style::Color;
use crossterm::cursor::cursor;
use crossterm::screen::AlternateScreen;
use crossterm::terminal::{self, ClearType};
use crossterm::Context;
use std::io::{stdout, Write};
use std::rc::Rc;
use std::{thread, time};
fn print_wait_screen(context: Rc<Context>) {
let mut terminal = terminal::terminal(&context);
terminal.clear(ClearType::All);
let mut cursor = cursor(&context);
cursor.goto(0, 0);
cursor.hide();
terminal.write(
"Welcome to the wait screen.\n\
Please wait a few seconds until we arrive back at the main screen.\n\
Progress: ",
);
// print some progress example.
for i in 1..5 {
// print the current counter at the line of `Seconds to Go: {counter}`
cursor
.goto(10, 2)
.print(terminal.paint(format!("{} of the 5 items processed", i)).with(Color::Red).on(Color::Blue));
// 1 second delay
thread::sleep(time::Duration::from_secs(1));
}
stdout().flush();
}
/// print wait screen on alternate screen, then swich back.
pub fn print_wait_screen_on_alternate_window(context: Rc<Context>) {
// create scope. If this scope ends the screen will be switched back to mainscreen.
// because `AlternateScreen` switches back to main screen when switching back.
{
// create new alternate screen instance and switch to the alternate screen.
let mut screen = AlternateScreen::from(context.clone());
write!(screen, "test");
println!();
// Print the wait screen.
print_wait_screen(context.clone());
}
}
/// some stress test switch from and to alternate screen.
pub fn switch_between_main_and_alternate_screen() {
let context = Context::new();
let mut cursor = cursor(&context);
{
// create new alternate screen instance and switch to the alternate screen.
let mut screen = AlternateScreen::from(context.clone());
cursor.goto(0, 0);
write!(screen, "we are at the alternate screen!");
screen.flush();
thread::sleep(time::Duration::from_secs(3));
screen.to_main();
write!(screen, "we are at the main screen!");
screen.flush();
thread::sleep(time::Duration::from_secs(3));
screen.to_alternate();
write!(screen, "we are at the alternate screen!");
screen.flush();
thread::sleep(time::Duration::from_secs(3));
}
println!("Whe are back at the main screen");
}

View File

@ -1,8 +0,0 @@
/// Examples of actions that could be performed on the alternatescreen.
pub mod alternate_screen;
/// Examples of actions that could be performed on the terminal.
pub mod terminal;
// Raw screen
pub mod raw_mode;

View File

@ -1,56 +0,0 @@
extern crate crossterm;
use crossterm::cursor::cursor;
use crossterm::screen::AlternateScreen;
use crossterm::terminal::{self, ClearType};
use crossterm::Context;
use std::io::{stdout, Write};
use std::rc::Rc;
use std::{thread, time};
use crossterm::raw::IntoRawMode;
// raw screen is not working correctly currently
fn print_wait_screen(context: Rc<Context>) {
terminal::terminal(&context).clear(ClearType::All);
let mut cursor = cursor(&context);
cursor.goto(0, 0).print("Welcome to the wait screen.");
cursor
.goto(0, 1)
.print("Please wait a few seconds until we arrive back at the main screen.");
cursor.goto(0, 2).print("Progress: ");
// print some progress example.
for i in 1..5 {
// print the current counter at the line of `Seconds to Go: {counter}`
cursor
.goto(10, 2)
.print(format!("{} of the 5 items processed", i));
// 1 second delay
thread::sleep(time::Duration::from_secs(1));
}
}
pub fn print_wait_screen_on_alternate_window() {
let context = Context::new();
// create scope. If this scope ends the screen will be switched back to mainscreen.
// because `AlternateScreen` switches back to main screen when going out of scope.
{
// create new alternate screen instance this call is also switching the screen to alternate screen.
// then convert the output of the program to raw mode.
// then print the wait screen on the alternate screen in raw mode.
let mut screen = AlternateScreen::from(context.clone());
let raw_screen = screen.into_raw_mode(context.clone());
// Print the wait screen.
print_wait_screen(context.clone());
screen.flush();
}
println!("Whe are back at the main screen");
}

View File

@ -1,160 +0,0 @@
//!
//! Terminal Examples
//!
extern crate crossterm;
use crossterm::cursor;
use crossterm::terminal::{terminal, ClearType};
use crossterm::Context;
fn print_test_data() {
for i in 0..100 {
println!("Test data to test terminal: {}", i);
}
}
/// Clear all lines in terminal | demonstration
pub fn clear_all_lines() {
let context = Context::new();
// Get terminal
let mut terminal = terminal(&context);
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() {
let context = Context::new();
// Get terminal
let mut terminal = terminal(&context);
print_test_data();
// Set terminal cursor position (see example for more info).
cursor::cursor(&context).goto(4, 8);
// 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() {
let context = Context::new();
// Get terminal
let mut terminal = terminal(&context);
print_test_data();
// Set terminal cursor position (see example for more info).
cursor::cursor(&context).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() {
let context = Context::new();
// Get terminal
let mut terminal = terminal(&context);
print_test_data();
// Set terminal cursor position (see example for more info).
cursor::cursor(&context).goto(4, 4);
// Clear current line cells.
terminal.clear(ClearType::CurrentLine);
}
/// Clear all lines from cursor position X:4, Y:7 up | demonstration
pub fn clear_until_new_line() {
let context = Context::new();
// Get terminal
let mut terminal = terminal(&context);
print_test_data();
// Set terminal cursor position (see example for more info).
cursor::cursor(&context).goto(4, 20);
// Clear all the cells until next line.
terminal.clear(ClearType::UntilNewLine);
}
/// Print the the current terminal size | demonstration.
pub fn print_terminal_size() {
let context = Context::new();
// Get terminal
let mut terminal = terminal(&context);
// Get terminal size
let terminal_size = terminal.terminal_size();
// Print results
print!("X: {}, y: {}", terminal_size.0, terminal_size.1);
}
/// Set the terminal size to width 10, height: 10 | demonstration.
pub fn set_terminal_size() {
let context = Context::new();
let mut terminal = terminal(&context);
terminal.set_size(10, 10);
}
/// Scroll down 10 lines | demonstration.
pub fn scroll_down() {
let context = Context::new();
print_test_data();
// Get terminal
let mut terminal = terminal(&context);
// Scroll down 10 lines.
terminal.scroll_down(10);
}
/// Scroll down 10 lines | demonstration.
pub fn scroll_up() {
let context = Context::new();
print_test_data();
// Get terminal
let mut terminal = terminal(&context);
// Scroll up 10 lines.
terminal.scroll_up(5);
}
/// Resize the terminal to X: 10, Y: 10 | demonstration.
pub fn resize_terminal() {
let context = Context::new();
// Get terminal
let mut terminal = terminal(&context);
// Get terminal size
terminal.set_size(10, 10);
}
/// exit the current proccess.
pub fn exit() {
let context = Context::new();
// Get terminal
let mut terminal = terminal(&context);
// Get terminal size
terminal.exit();
}

76
examples/duplex.rs Normal file
View File

@ -0,0 +1,76 @@
//! This bin folder can be used to try the examples out located in the examples directory.
//!
//! All you need to do is:
//!
//! - Download the crossterm source code.
//! - Add this in the Cargo.toml file:
//! ``` [[bin]]
//! name = "example_bin"
//! path = "./examples/bin.rs"
//! ```
//!
//! - Run program with: `cargo run`
extern crate crossterm;
use crossterm::style::Color;
use crossterm::Crossterm;
use crossterm::terminal::ClearType;
use std::thread::sleep;
use std::sync::{Arc,Mutex};
use std::io::Read;
use std::time::Duration;
// mod terminal;
// mod color;
// mod cursor;
// mod crossterm_type;
// mod input;
//use input::keyboard::{async_input, input as stdin};
use std::thread;
fn main() {
let mut terminal = Arc::new(Mutex::new(Crossterm::new()));
let input = terminal.lock().unwrap().input().read_async();
terminal.lock().unwrap().enable_raw_mode();
let mut input_buf = Arc::new(Mutex::new(String::new()));
let mut key_buf = [0 as u8; 32];
thread::spawn(move || {
loop {
swap_write(&mut terminal.lock().unwrap(), "random program output",&input_buf.lock().unwrap());
sleep(Duration::from_millis(100));
}
});
loop {
let mut term = terminal.lock().unwrap();
let (term_width, term_height) = term.terminal().terminal_size();
if let Ok(count) = input.read(&mut key_buf) {
for idx in 0..count {
let b = key_buf.get(idx).unwrap();
if *b == 3 {
std::process::exit(0); // Ctrl+C = exit immediate
} else if *b == 13 {
// The return key was pressed.
let mut input_buf_tmp = &mut input_buf.lock().unwrap();
input_buf.lock().unwrap().clear();
swap_write(&mut term, "", &input_buf_tmp);
} else {
let mut input_buf_tmp = &mut input_buf.lock().unwrap();
input_buf_tmp.push(*b as char);
swap_write(&mut term, "", &input_buf_tmp);
}
}
}
}
}
pub fn swap_write(terminal: &mut Crossterm, msg: &str, input_buf: &String) {
let (term_width, term_height) = terminal.terminal().terminal_size();
terminal.cursor().goto(0, term_height);
terminal.terminal().clear(ClearType::CurrentLine);
terminal
.terminal()
.write(format!("{}\n\r>{}", msg, input_buf));
}

View File

@ -12,8 +12,8 @@
//! - Run program with: `cargo run`
extern crate crossterm;
use crossterm::Crossterm;
use crossterm::style::Color;
use crossterm::Crossterm;
// mod terminal;
// mod color;

View File

@ -11,29 +11,25 @@ pub mod unix_command;
#[cfg(target_os = "windows")]
pub mod win_commands;
/// This trait provides a way to execute some state changing commands.
pub trait IStateCommand {
fn execute(&mut self) -> Result<()>;
fn undo(&mut self) -> Result<()>;
}
pub trait IEnableAnsiCommand
{
pub trait IEnableAnsiCommand {
fn enable(&mut self) -> bool;
fn disable(&mut self) -> bool;
}
/// This trait provides an interface for switching to alternate screen and back.
pub trait IAlternateScreenCommand
{
fn enable(&self,screen_manager: &mut ScreenManager) -> Result<()>;
/*pub trait IAlternateScreenCommand: Send{
fn enable(&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: Send{
fn enable(&mut self) -> Result<()>;
fn disable(&mut self) -> Result<()>;
}
}*/

View File

@ -7,9 +7,9 @@ use std::io::Result;
/// This command is used for switching to alternate screen and back to main screen.
pub struct ToAlternateScreenCommand;
impl ToAlternateScreenCommand {
impl ToAlternateScreenCommand {
pub fn new() -> ToAlternateScreenCommand {
return ToAlternateScreenCommand {};
return ToAlternateScreenCommand;
}
}

View File

@ -1,12 +1,12 @@
//! This module contains the commands that can be used for unix systems.
use super::{IStateCommand, IRawScreenCommand};
use super::{IRawScreenCommand, IStateCommand};
use kernel::unix_kernel::terminal;
use termios::{tcsetattr, Termios, CREAD, ECHO, ICANON, TCSAFLUSH};
const FD_STDIN: ::std::os::unix::io::RawFd = 1;
use std::io::{Result,Error, ErrorKind};
use std::io::{Error, ErrorKind, Result};
/// This command is used for switching to NoncanonicalMode.
#[derive(Copy, Clone)]
@ -14,7 +14,7 @@ pub struct NoncanonicalModeCommand;
impl NoncanonicalModeCommand {
pub fn new() -> NoncanonicalModeCommand {
NoncanonicalModeCommand { }
NoncanonicalModeCommand {}
}
}
@ -28,7 +28,10 @@ impl IStateCommand for NoncanonicalModeCommand {
noncan.c_lflag &= !CREAD;
tcsetattr(FD_STDIN, TCSAFLUSH, &noncan)?;
} else {
return Err(Error::new(ErrorKind::Other,"Could not set console mode when enabling raw mode"))
return Err(Error::new(
ErrorKind::Other,
"Could not set console mode when enabling raw mode",
));
}
Ok(())
}
@ -43,40 +46,51 @@ impl IStateCommand for NoncanonicalModeCommand {
tcsetattr(FD_STDIN, TCSAFLUSH, &noncan)?;
} else {
return Err(Error::new(ErrorKind::Other,"Could not set console mode when enabling raw mode"))
return Err(Error::new(
ErrorKind::Other,
"Could not set console mode when enabling raw mode",
));
}
Ok(())
}
}
/// This command is used for enabling and disabling raw mode for the terminal.
pub struct EnableRawModeCommand {
pub struct RawModeCommand {
original_mode: Result<Termios>,
}
impl EnableRawModeCommand {
pub fn new() -> EnableRawModeCommand {
return EnableRawModeCommand { original_mode: terminal::get_terminal_mode(), }
impl RawModeCommand {
pub fn new() -> Self {
RawModeCommand {
original_mode: terminal::get_terminal_mode(),
}
}
}
impl IRawScreenCommand for EnableRawModeCommand {
fn enable(&mut self) -> Result<()> {
/// Enables raw mode.
pub fn enable(&mut self) -> Result<()> {
if let Ok(original_mode) = self.original_mode {
let mut new_mode = original_mode;
terminal::make_raw(&mut new_mode);
terminal::set_terminal_mode(&new_mode);
} else {
return Err(Error::new(ErrorKind::Other,"Could not set console mode when enabling raw mode"))
return Err(Error::new(
ErrorKind::Other,
"Could not set console mode when enabling raw mode",
));
}
Ok(())
}
fn disable(&mut self) -> Result<()> {
/// Disables raw mode.
pub fn disable(&mut self) -> Result<()> {
if let Ok(ref original_mode) = self.original_mode {
let result = terminal::set_terminal_mode(&original_mode)?;
} else {
return Err(Error::new(ErrorKind::Other,"Could not set console mode when enabling raw mode"))
return Err(Error::new(
ErrorKind::Other,
"Could not set console mode when enabling raw mode",
));
}
Ok(())
}

View File

@ -1,6 +1,6 @@
//! This module contains the commands that can be used for windows systems.
use super::{ ScreenManager, IEnableAnsiCommand, IAlternateScreenCommand, IRawScreenCommand};
use super::{IAlternateScreenCommand, IEnableAnsiCommand, IRawScreenCommand, ScreenManager};
use kernel::windows_kernel::{ansi_support, csbi, handle, kernel};
use std::mem;
@ -8,7 +8,7 @@ use winapi::shared::minwindef::DWORD;
use winapi::um::wincon;
use winapi::um::wincon::{CHAR_INFO, COORD, ENABLE_VIRTUAL_TERMINAL_PROCESSING, SMALL_RECT};
use std::io::{Result, ErrorKind, Error };
use std::io::{Error, ErrorKind, Result};
/// This command is used for enabling and disabling ANSI code support for windows systems,
/// For more info check: https://docs.microsoft.com/en-us/windows/console/console-virtual-terminal-sequences.
@ -70,53 +70,65 @@ impl IEnableAnsiCommand for EnableAnsiCommand {
/// This command is used for enabling and disabling raw mode for windows systems.
/// For more info check: https://docs.microsoft.com/en-us/windows/console/high-level-console-modes.
#[derive(Clone, Copy)]
pub struct EnableRawModeCommand {
pub struct RawModeCommand {
mask: DWORD,
}
impl EnableRawModeCommand {
pub fn new() -> EnableRawModeCommand {
impl RawModeCommand {
pub fn new() -> Self {
use self::wincon::{ENABLE_ECHO_INPUT, ENABLE_LINE_INPUT, ENABLE_PROCESSED_INPUT};
EnableRawModeCommand {
RawModeCommand {
mask: ENABLE_LINE_INPUT | ENABLE_PROCESSED_INPUT | ENABLE_ECHO_INPUT,
}
}
}
impl IRawScreenCommand for EnableRawModeCommand {
fn enable(&mut self) -> Result<()> {
/// Enables raw mode.
pub fn enable(&mut self) -> Result<()> {
let input_handle = handle::get_input_handle()?;
let mut dw_mode: DWORD = 0;
if !kernel::get_console_mode(&input_handle, &mut dw_mode) {
return Err(Error::new(ErrorKind::Other,"Could not get console mode when enabling raw mode"))
return Err(Error::new(
ErrorKind::Other,
"Could not get console mode when enabling raw mode",
));
}
let new_mode = dw_mode & !self.mask;
if !kernel::set_console_mode(&input_handle, new_mode) {
return Err(Error::new(ErrorKind::Other,"Could not set console mode when enabling raw mode"))
return Err(Error::new(
ErrorKind::Other,
"Could not set console mode when enabling raw mode",
));
}
return Ok(())
Ok(())
}
fn disable(&mut self) -> Result<()> {
/// Disables raw mode.
pub fn disable(&mut self) -> Result<()> {
let output_handle = handle::get_input_handle()?;
let mut dw_mode: DWORD = 0;
if !kernel::get_console_mode(&output_handle, &mut dw_mode) {
return Err(Error::new(ErrorKind::Other,"Could not get console mode when disabling raw mode"))
return Err(Error::new(
ErrorKind::Other,
"Could not get console mode when disabling raw mode",
));
}
let new_mode = dw_mode | self.mask;
if !kernel::set_console_mode(&output_handle, new_mode) {
return Err(Error::new(ErrorKind::Other,"Could not set console mode when disabling raw mode"))
return Err(Error::new(
ErrorKind::Other,
"Could not set console mode when disabling raw mode",
));
}
return Ok(())
return Ok(());
}
}
@ -125,13 +137,13 @@ impl IRawScreenCommand for EnableRawModeCommand {
pub struct ToAlternateScreenCommand;
impl ToAlternateScreenCommand {
pub fn new() -> ToAlternateScreenCommand{
pub fn new() -> ToAlternateScreenCommand {
return ToAlternateScreenCommand {};
}
}
impl IAlternateScreenCommand for ToAlternateScreenCommand {
fn enable(&self, screen_manager: &mut ScreenManager) -> Result<()>{
fn enable(&self, screen_manager: &mut ScreenManager) -> Result<()> {
use super::super::super::manager::WinApiScreenManager;
let handle = handle::get_output_handle()?;
@ -145,25 +157,25 @@ impl IAlternateScreenCommand for ToAlternateScreenCommand {
match screen_manager
.as_any_mut()
.downcast_mut::<WinApiScreenManager>()
{
Some(b) => b.set_alternate_handle(new_handle),
None => return Err(Error::new(ErrorKind::Other,"Invalid cast exception")),
};
{
Some(b) => b.set_alternate_handle(new_handle),
None => return Err(Error::new(ErrorKind::Other, "Invalid cast exception")),
};
let b: &mut WinApiScreenManager = match screen_manager
.as_any_mut()
.downcast_mut::<WinApiScreenManager>()
{
Some(b) => b,
None => return Err(Error::new(ErrorKind::Other,"Invalid cast exception")),
};
{
Some(b) => b,
None => return Err(Error::new(ErrorKind::Other, "Invalid cast exception")),
};
b.set_alternate_handle(new_handle);
Ok(())
}
fn disable(&self, screen_manager: &mut ScreenManager) -> Result<()>{
fn disable(&self, screen_manager: &mut ScreenManager) -> Result<()> {
let handle = handle::get_output_handle()?;
csbi::set_active_screen_buffer(handle);

View File

@ -1,104 +1,92 @@
use super::commands::{IRawScreenCommand, IAlternateScreenCommand};
use super::commands::{IAlternateScreenCommand, IRawScreenCommand};
use super::screen::RawScreen;
use super::screen::AlternateScreen;
use super::screen::RawScreen;
use super::super::manager;
use super::super::cursor;
use super::super::input;
use super::super::terminal;
use super::super::manager;
use super::super::style;
use super::super::terminal;
use std::fmt::{Display};
use std::fmt::Display;
use std::io::Write;
use std::io::Result;
pub struct Crossterm {
pub active_screen: manager::ScreenManager,
raw_terminal: Option<Box<IRawScreenCommand>>,
raw_terminal: Option<RawScreenCommand>,
// Would be cool to figure out a way to have multiple screens instead of just only the main and alternate screen.
// For windows this would be easy but for unix I have no idea.
alternate_screen: Option<Box<IAlternateScreenCommand>>
alternate_screen: Option<AlternateScreenCommand>,
}
impl<'crossterm> Crossterm
{
pub fn new() -> Crossterm
{
Crossterm
{
active_screen: manager::ScreenManager::new(),
impl<'a> Crossterm {
pub fn new() -> Crossterm {
Crossterm {
active_screen: manager::ScreenManager::new(),
raw_terminal: None,
alternate_screen: None,
}
}
pub fn enable_raw_mode(&mut self) -> Result<()> {
match self.raw_terminal
{
None => {
self.raw_terminal = Some(RawScreen::new());
return self.enable_raw_mode();
},
Some(ref mut raw_terminal) => {
raw_terminal.enable()?;
self.active_screen.set_is_raw_screen(true);
},
match self.raw_terminal {
None => {
self.raw_terminal = Some(RawScreen::new());
return self.enable_raw_mode();
}
return Ok(())
Some(ref mut raw_terminal) => {
raw_terminal.enable()?;
self.active_screen.set_is_raw_screen(true);
}
}
Ok(())
}
pub fn disable_raw_mode(&mut self) -> Result<()>
{
match self.raw_terminal
{
None => {
self.raw_terminal = Some(RawScreen::new());
return self.disable_raw_mode();
},
Some(ref mut raw_terminal) => {
raw_terminal.disable()?;
self.active_screen.set_is_raw_screen(false);
},
pub fn disable_raw_mode(&mut self) -> Result<()> {
match self.raw_terminal {
None => {
self.raw_terminal = Some(RawScreen::new());
return self.disable_raw_mode();
}
return Ok(())
Some(ref mut raw_terminal) => {
raw_terminal.disable()?;
self.active_screen.set_is_raw_screen(false);
}
}
Ok(())
}
pub fn to_alternate_screen(&mut self) -> Result<()>
{
match self.alternate_screen
{
None => {
self.alternate_screen = Some(AlternateScreen::new());
return self.to_alternate_screen();
},
Some(ref mut alternate_screen) => {
alternate_screen.enable(&mut self.active_screen)?;
self.active_screen.set_is_alternate_screen(true);
},
pub fn to_alternate_screen(&mut self) -> Result<()> {
match self.alternate_screen {
None => {
self.alternate_screen = Some(AlternateScreen::new());
return self.to_alternate_screen();
}
Some(ref mut alternate_screen) => {
alternate_screen.enable(&mut self.active_screen)?;
self.active_screen.set_is_alternate_screen(true);
}
}
return Ok(())
return Ok(());
}
pub fn to_main_screen(&mut self) -> Result<()>
{
match self.alternate_screen
{
None => {
self.alternate_screen = Some(AlternateScreen::new());
return self.to_main_screen();
},
Some(ref mut alternate_screen) => {
alternate_screen.disable(&mut self.active_screen)?;
self.active_screen.set_is_alternate_screen(false);
},
pub fn to_main_screen(&mut self) -> Result<()> {
match self.alternate_screen {
None => {
self.alternate_screen = Some(AlternateScreen::new());
return self.to_main_screen();
}
Some(ref mut alternate_screen) => {
alternate_screen.disable(&mut self.active_screen)?;
self.active_screen.set_is_alternate_screen(false);
}
}
return Ok(())
return Ok(());
}
pub fn cursor(&self) -> cursor::TerminalCursor {
@ -106,15 +94,15 @@ impl<'crossterm> Crossterm
}
pub fn input(&self) -> input::TerminalInput {
return input::TerminalInput::new(&self.active_screen)
return input::TerminalInput::new(&self.active_screen);
}
pub fn terminal(&self) -> terminal::Terminal {
return terminal::Terminal::new(&self.active_screen)
return terminal::Terminal::new(&self.active_screen);
}
pub fn color(&self) -> style::TerminalColor {
return style::TerminalColor::new(&self.active_screen)
return style::TerminalColor::new(&self.active_screen);
}
// Wraps an displayable object so it can be formatted with colors and attributes.
@ -129,8 +117,7 @@ impl<'crossterm> Crossterm
}
}
impl Write for Crossterm
{
impl Write for Crossterm {
fn write(&mut self, buf: &[u8]) -> Result<usize> {
self.active_screen.write_buf(buf)
}
@ -140,19 +127,13 @@ impl Write for Crossterm
}
}
impl Drop for Crossterm
{
impl Drop for Crossterm {
fn drop(&mut self) {
if let Some(ref mut screen) = self.alternate_screen
{
if let Some(ref mut screen) = self.alternate_screen {
screen.disable(&mut self.active_screen);
}
if let Some(ref mut raw_terminal) = self.raw_terminal
{
if let Some(ref mut raw_terminal) = self.raw_terminal {
raw_terminal.disable();
}
}
}

View File

@ -3,10 +3,10 @@
use super::ScreenManager;
#[cfg(windows)]
use kernel::windows_kernel::terminal::{exit, terminal_size, buffer_size};
use kernel::windows_kernel::terminal::{buffer_size, exit, terminal_size};
#[cfg(windows)]
use kernel::windows_kernel::cursor::{pos};
use kernel::windows_kernel::cursor::pos;
#[cfg(unix)]
use kernel::unix_kernel::terminal::{exit, pos, terminal_size};

View File

@ -1,14 +1,13 @@
//! This module contains some code that can be used for all module in this library.
#[macro_use]
pub mod macros;
pub mod commands;
pub mod screen;
pub mod functions;
pub mod screen;
pub mod traits;
mod crossterm;
pub use self::crossterm::Crossterm;
use super::manager::ScreenManager;
use super::manager::ScreenManager;

View File

@ -22,8 +22,8 @@
//! Todo: example
//!
use super::{functions, ScreenManager};
use super::commands;
use super::{functions, ScreenManager};
use std::convert::From;
use std::io::{self, Write};
@ -45,4 +45,3 @@ impl AlternateScreen {
command
}
}

View File

@ -1,9 +1,9 @@
//! This module provides some modules to work with the terminal screen. Like raw and alternate screen.
mod raw;
mod alternate;
mod raw;
use super::{ScreenManager, functions, commands};
use super::{commands, functions, ScreenManager};
pub use self::alternate::AlternateScreen;
pub use self::raw::RawScreen;
pub use self::alternate::AlternateScreen;

View File

@ -18,8 +18,8 @@ use common::commands::unix_command::EnableRawModeCommand;
#[cfg(windows)]
use common::commands::win_commands::EnableRawModeCommand;
use super::{functions, ScreenManager};
use super::commands;
use super::{functions, ScreenManager};
use std::io::{self, Write};
@ -36,4 +36,4 @@ impl RawScreen {
///// Trait withs contains a method for switching into raw mode.
//pub trait IntoRawMode: Write + Sized {
// fn into_raw_mode(&self, context: Rc<Context>) -> io::Result<RawTerminal>;
//}
//}

View File

@ -1,18 +1,17 @@
//! This module contains all `unix` specific terminal related logic.
use self::libc::{c_int, c_ushort, ioctl, STDOUT_FILENO, TIOCGWINSZ};
use common::commands::unix_command::{EnableRawModeCommand, NoncanonicalModeCommand};
use libc;
pub use libc::termios;
use self::libc::{c_int, c_ushort, ioctl, STDOUT_FILENO, TIOCGWINSZ};
use common::commands::unix_command::{NoncanonicalModeCommand, EnableRawModeCommand};
use std::io::Error;
use std::os::unix::io::AsRawFd;
use std::{fs, io, mem};
use termios::{cfmakeraw, tcsetattr, Termios, TCSADRAIN};
use std::io::ErrorKind;
use std::io::Read;
use std::time::{SystemTime, Duration};
use std::os::unix::io::AsRawFd;
use std::time::{Duration, SystemTime};
use std::{fs, io, mem};
use termios::{cfmakeraw, tcsetattr, Termios, TCSADRAIN};
use Crossterm;
@ -41,7 +40,6 @@ pub fn terminal_size() -> (u16, u16) {
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.
(us.cols - 1, us.rows - 1)
} else {
(0, 0)
}
@ -67,9 +65,8 @@ pub fn pos() -> (u16, u16) {
// Either consume all data up to R or wait for a timeout.
while buf[0] != delimiter && now.elapsed().unwrap() < timeout {
if let Ok(c) = stdin.read(&mut buf){
if c >= 0
{
if let Ok(c) = stdin.read(&mut buf) {
if c >= 0 {
read_chars.push(buf[0]);
}
}
@ -87,14 +84,8 @@ pub fn pos() -> (u16, u16) {
let coords: String = read_str.chars().skip(beg + 1).collect();
let mut nums = coords.split(';');
let cy = nums.next()
.unwrap()
.parse::<u16>()
.unwrap();
let cx = nums.next()
.unwrap()
.parse::<u16>()
.unwrap();
let cy = nums.next().unwrap().parse::<u16>().unwrap();
let cx = nums.next().unwrap().parse::<u16>().unwrap();
(cx, cy)
}

View File

@ -7,13 +7,12 @@ static mut IS_ANSI_ON_WINDOWS_ENABLED: Option<bool> = None;
static mut DOES_WINDOWS_SUPPORT_ANSI: Option<bool> = None;
static ENABLE_ANSI: Once = ONCE_INIT;
use common::commands::win_commands::{EnableAnsiCommand};
use common::commands::win_commands::EnableAnsiCommand;
use common::commands::IEnableAnsiCommand;
/// Try enable `ANSI escape codes` and return the result.
pub fn try_enable_ansi_support() -> bool {
ENABLE_ANSI.call_once(|| {
let mut command = EnableAnsiCommand::new();
let success = command.enable();

View File

@ -60,10 +60,7 @@ pub fn get_csbi_by_handle(handle: &HANDLE) -> Result<CONSOLE_SCREEN_BUFFER_INFO>
}
/// Set the console screen buffer size
pub fn set_console_screen_buffer_size(
size: COORD,
screen_manager: &ScreenManager,
) -> bool {
pub fn set_console_screen_buffer_size(size: COORD, screen_manager: &ScreenManager) -> bool {
let handle = handle::get_current_handle(screen_manager).unwrap();
unsafe {

View File

@ -35,17 +35,18 @@ pub fn save_cursor_pos(screen_manager: &ScreenManager) {
/// get the current cursor position.
pub fn pos(screen_manager: &ScreenManager) -> (u16, u16) {
let handle = handle::get_current_handle(screen_manager).unwrap();
if let Ok(csbi) = csbi::get_csbi_by_handle(&handle) {
( csbi.dwCursorPosition.X as u16, csbi.dwCursorPosition.Y as u16 )
(
csbi.dwCursorPosition.X as u16,
csbi.dwCursorPosition.Y as u16,
)
} else {
(0, 0)
}
}
/// Set the cursor position to the given x and y. Note that this is 0 based.
pub fn set_console_cursor_position(x: i16, y: i16, screen_manager: &ScreenManager) {
if x < 0 || x >= <i16>::max_value() {

View File

@ -1,7 +1,7 @@
//! This module contains some logic for working with the console handle.
use winapi::um::processenv::GetStdHandle;
use winapi::um::handleapi::INVALID_HANDLE_VALUE;
use winapi::um::processenv::GetStdHandle;
use winapi::um::winbase::{STD_INPUT_HANDLE, STD_OUTPUT_HANDLE};
use winapi::um::winnt::HANDLE;
@ -15,7 +15,7 @@ pub fn get_current_handle(screen_manager: &ScreenManager) -> Result<HANDLE> {
let handle: Result<HANDLE>;
let winapi_screen_manager: &WinApiScreenManager = match screen_manager
let winapi_screen_manager: &WinApiScreenManager = match screen_manager
.as_any()
.downcast_ref::<WinApiScreenManager>()
{

View File

@ -1,14 +1,13 @@
//! This module contains some basic winapi calls.
use winapi::um::consoleapi::{GetConsoleMode, SetConsoleMode};
use winapi::um::winnt::HANDLE;
use winapi::um::wincon::{
SetConsoleTextAttribute, SetConsoleWindowInfo, GetLargestConsoleWindowSize,
COORD, SMALL_RECT
GetLargestConsoleWindowSize, SetConsoleTextAttribute, SetConsoleWindowInfo, COORD, SMALL_RECT,
};
use winapi::um::winnt::HANDLE;
use super::{handle, Empty};
use super::super::super::manager::ScreenManager;
use super::{handle, Empty};
use std::io::{ErrorKind, Result};
@ -43,11 +42,7 @@ pub fn set_console_text_attribute(value: u16, screen_manager: &ScreenManager) ->
}
/// Change console info.
pub fn set_console_info(
absolute: bool,
rect: &SMALL_RECT,
screen_manager: &ScreenManager,
) -> bool {
pub fn set_console_info(absolute: bool, rect: &SMALL_RECT, screen_manager: &ScreenManager) -> bool {
let handle = handle::get_current_handle(screen_manager).unwrap();
let absolute = match absolute {

View File

@ -1,16 +1,16 @@
//! This module contains the `windows` (unsafe) logic.
pub mod ansi_support;
pub mod csbi;
pub mod cursor;
pub mod handle;
pub mod kernel;
pub mod terminal;
pub mod writing;
pub mod csbi;
pub mod handle;
use winapi::um::wincon::{CONSOLE_SCREEN_BUFFER_INFO, COORD, SMALL_RECT};
use common::traits::Empty;
use super::super::manager::ScreenManager;
use common::traits::Empty;
use winapi::um::wincon::{CONSOLE_SCREEN_BUFFER_INFO, COORD, SMALL_RECT};
impl Empty for COORD {
fn empty() -> COORD {

View File

@ -4,7 +4,6 @@ use super::{csbi, handle, ScreenManager};
/// Get the terminal size
pub fn terminal_size() -> (u16, u16) {
let handle = handle::get_output_handle().unwrap();
if let Ok(csbi) = csbi::get_csbi_by_handle(&handle) {
@ -18,14 +17,10 @@ pub fn terminal_size() -> (u16, u16) {
}
pub fn buffer_size(screen_manager: &ScreenManager) -> (u16, u16) {
let handle = handle::get_output_handle().unwrap();
if let Ok(csbi) = csbi::get_csbi_by_handle(&handle) {
(
(csbi.dwSize.X) as u16,
(csbi.dwSize.Y) as u16,
)
((csbi.dwSize.X) as u16, (csbi.dwSize.Y) as u16)
} else {
return (0, 0);
}

View File

@ -9,7 +9,7 @@ use winapi::um::wincon::{
};
use winapi::um::winnt::HANDLE;
use super::{ScreenManager, csbi, handle, kernel};
use super::{csbi, handle, kernel, ScreenManager};
use std::io::{self, ErrorKind, Result};
use std::str;

View File

@ -10,11 +10,11 @@ mod kernel;
mod modules;
pub use common::screen;
pub use modules::style;
pub use modules::cursor;
pub use modules::manager;
pub use modules::terminal;
pub use modules::input;
pub use modules::manager;
pub use modules::style;
pub use modules::terminal;
pub use common::Crossterm;

View File

@ -2,14 +2,14 @@
//! This module is used for windows 10 terminals and unix terminals by default.
//! Note that the cursor position is 0 based. This means that we start counting at 0 when setting the cursor position ect.
use super::{ScreenManager, functions, ITerminalCursor};
use super::{functions, ITerminalCursor, ScreenManager};
/// This struct is an ansi implementation for cursor related actions.
pub struct AnsiCursor;
impl AnsiCursor {
pub fn new() -> Box<AnsiCursor> {
Box::from(AnsiCursor { })
Box::from(AnsiCursor {})
}
}

View File

@ -5,8 +5,8 @@
use super::*;
use std::io::Write;
use std::fmt::Display;
use std::io::Write;
/// Struct that stores an specific platform implementation for cursor related actions.
///
@ -42,10 +42,9 @@ impl<'cursor> TerminalCursor<'cursor> {
/// Create new cursor instance whereon cursor related actions can be performed.
pub fn new(screen_manager: &'cursor ScreenManager) -> TerminalCursor<'cursor> {
#[cfg(target_os = "windows")]
let cursor = functions::get_module::<Box<ITerminalCursor>>(
WinApiCursor::new(),
AnsiCursor::new(),
).unwrap();
let cursor =
functions::get_module::<Box<ITerminalCursor>>(WinApiCursor::new(), AnsiCursor::new())
.unwrap();
#[cfg(not(target_os = "windows"))]
let cursor = AnsiCursor::new() as Box<ITerminalCursor>;

View File

@ -3,16 +3,16 @@
mod cursor;
mod ansi_cursor;
#[cfg(target_os = "windows")]
mod winapi_cursor;
mod ansi_cursor;
use self::ansi_cursor::AnsiCursor;
#[cfg(target_os = "windows")]
use self::winapi_cursor::WinApiCursor;
use self::ansi_cursor::AnsiCursor;
pub use self::cursor::{cursor, TerminalCursor};
use super::{ScreenManager, functions};
use super::{functions, ScreenManager};
///! This trait defines the actions that can be preformed with the terminal cursor.
///! This trait can be implemented so that an concrete implementation of the ITerminalCursor can forfill

View File

@ -12,7 +12,7 @@ pub struct WinApiCursor;
impl WinApiCursor {
pub fn new() -> Box<WinApiCursor> {
Box::from(WinApiCursor { })
Box::from(WinApiCursor {})
}
}

View File

@ -25,11 +25,10 @@ use super::*;
/// ```
pub struct TerminalInput<'terminal> {
terminal_input: Box<ITerminalInput>,
screen_manager: &'terminal ScreenManager
screen_manager: &'terminal ScreenManager,
}
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> {
#[cfg(target_os = "windows")]
@ -40,7 +39,7 @@ impl<'terminal> TerminalInput<'terminal> {
TerminalInput {
terminal_input: input,
screen_manager: screen_manager
screen_manager: screen_manager,
}
}
@ -76,34 +75,34 @@ impl<'terminal> TerminalInput<'terminal> {
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));
/// }
///
/// ```
/// 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 {
self.terminal_input.read_async(&self.screen_manager)
}
@ -144,11 +143,12 @@ impl<'terminal> TerminalInput<'terminal> {
/// }
/// ```
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 {
return TerminalInput::new(screen_manager)
return TerminalInput::new(screen_manager);
}

View File

@ -8,15 +8,15 @@ mod unix_input;
#[cfg(target_os = "windows")]
mod windows_input;
#[cfg(target_os = "windows")]
use self::windows_input::WindowsInput;
#[cfg(not(target_os = "windows"))]
use self::unix_input::UnixInput;
#[cfg(target_os = "windows")]
use self::windows_input::WindowsInput;
pub use self::input::{input, TerminalInput};
use super::ScreenManager;
use std::io::{Read, self};
use std::io::{self, Read};
use std::sync::mpsc;
/// This trait defines the actions that can be preformed with the terminal color.

View File

@ -5,8 +5,8 @@ use std::io::{self, Read, Write};
use std::sync::mpsc;
use std::thread;
use super::{AsyncReader, ITerminalInput, ScreenManager};
use kernel::unix_kernel::terminal::{get_tty, read_char};
use super::{ScreenManager, AsyncReader, ITerminalInput};
pub struct UnixInput;
@ -32,9 +32,11 @@ impl ITerminalInput for UnixInput {
fn read_async(&self, screen_manger: &ScreenManager) -> AsyncReader {
let (send, recv) = mpsc::channel();
thread::spawn(move || for i in get_tty().unwrap().bytes() {
if send.send(i).is_err() {
return;
thread::spawn(move || {
for i in get_tty().unwrap().bytes() {
if send.send(i).is_err() {
return;
}
}
});
@ -44,16 +46,21 @@ impl ITerminalInput for UnixInput {
fn read_until_async(&self, delimiter: u8, screen_manger: &ScreenManager) -> AsyncReader {
let (send, recv) = mpsc::channel();
thread::spawn(move || for i in get_tty().unwrap().bytes() {
thread::spawn(move || {
for i in get_tty().unwrap().bytes() {
match i {
Ok(byte) => {
let end_of_stream = &byte == &delimiter;
let send_error = send.send(Ok(byte)).is_err();
match i {
Ok(byte) => {
let end_of_stream = &byte == &delimiter;
let send_error = send.send(Ok(byte)).is_err();
if end_of_stream || send_error { return; }
},
Err(_) => { return; }
if end_of_stream || send_error {
return;
}
}
Err(_) => {
return;
}
}
}
});

View File

@ -1,7 +1,7 @@
//! This is an WINDOWS specific implementation for input related action.
use std::char;
use std::io::{self,Write};
use std::io::{self, Write};
use std::sync::mpsc;
use std::thread;
@ -19,14 +19,20 @@ impl WindowsInput {
}
impl ITerminalInput for WindowsInput {
fn read_line(&self,screen_manger: &ScreenManager) -> io::Result<String> {
fn read_line(&self, screen_manger: &ScreenManager) -> io::Result<String> {
let mut chars: Vec<char> = Vec::new();
loop {
let is_raw_screen = screen_manger.is_raw_screen();
// _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()
}
};
// if 0 or 0xe0 we need to listen again because the next key will be an special key
if pressed_char != 0 || pressed_char != 0xe0 {
@ -37,8 +43,6 @@ impl ITerminalInput for WindowsInput {
} else {
chars.push(c);
}
}
None => panic!("Some error needs to be returned"),
};
@ -52,7 +56,13 @@ impl ITerminalInput for WindowsInput {
let is_raw_screen = screen_manger.is_raw_screen();
// _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()
}
};
// we could return error but maybe option to keep listening until valid character is inputted.
if pressed_char == 0 || pressed_char == 0xe0 {
@ -73,7 +83,7 @@ impl ITerminalInput for WindowsInput {
}
}
fn read_async(&self,screen_manger: &ScreenManager) -> AsyncReader {
fn read_async(&self, screen_manger: &ScreenManager) -> AsyncReader {
let (tx, rx) = mpsc::channel();
let is_raw_screen = screen_manger.is_raw_screen();
@ -81,7 +91,13 @@ impl ITerminalInput for WindowsInput {
thread::spawn(move || {
loop {
// _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()
}
};
// we could return error but maybe option to keep listening until valid character is inputted.
if pressed_char == 0 || pressed_char == 0xe0 {
@ -99,7 +115,7 @@ impl ITerminalInput for WindowsInput {
AsyncReader { recv: rx }
}
fn read_until_async(&self, delimiter: u8,screen_manger: &ScreenManager) -> AsyncReader {
fn read_until_async(&self, delimiter: u8, screen_manger: &ScreenManager) -> AsyncReader {
let (tx, rx) = mpsc::channel();
let is_raw_screen = screen_manger.is_raw_screen();
@ -107,7 +123,13 @@ impl ITerminalInput for WindowsInput {
thread::spawn(move || {
loop {
// _getwch is without echo and _getwche is with echo
let pressed_char = unsafe { if is_raw_screen { _getwch() } else { _getwche() } } as u8;
let pressed_char = unsafe {
if is_raw_screen {
_getwch()
} else {
_getwche()
}
} as u8;
let end_of_stream = (pressed_char == delimiter);

View File

@ -5,20 +5,20 @@
use super::IScreenManager;
use std::any::Any;
use std::cell::RefCell;
use std::io::{self, Read, Write};
use std::cell::RefCell ;
use std::str::from_utf8;
/// This struct is an ANSI escape code implementation for screen related actions.
pub struct AnsiScreenManager {
is_alternate_screen: bool,
is_raw_screen: bool,
output: RefCell<Box<Write>>
output: RefCell<Box<Write>>,
}
impl IScreenManager for AnsiScreenManager {
fn set_is_raw_screen(&mut self, value: bool) {
self.is_raw_screen = value;
self.is_raw_screen = value;
}
fn set_is_alternate_screen(&mut self, value: bool) {

View File

@ -29,7 +29,7 @@ use winapi::um::winnt::HANDLE;
/// Struct that stores an specific platform implementation for screen related actions.
pub struct ScreenManager {
screen_manager: Box<IScreenManager>,
screen_manager: Box<IScreenManager + Send>,
}
impl ScreenManager {
@ -44,9 +44,7 @@ impl ScreenManager {
#[cfg(not(target_os = "windows"))]
let screen_manager = Box::from(AnsiScreenManager::new()) as Box<IScreenManager>;
ScreenManager {
screen_manager,
}
ScreenManager { screen_manager }
}
/// Set whether screen is raw screen.
@ -75,8 +73,7 @@ impl ScreenManager {
}
/// Flush the current screen.
pub fn flush(&self) -> io::Result<()>
{
pub fn flush(&self) -> io::Result<()> {
self.screen_manager.flush()
}

View File

@ -20,13 +20,13 @@
mod manager;
mod ansi_manager;
#[cfg(target_os = "windows")]
mod win_manager;
mod ansi_manager;
pub use self::ansi_manager::AnsiScreenManager;
#[cfg(target_os = "windows")]
pub use self::win_manager::WinApiScreenManager;
pub use self::ansi_manager::AnsiScreenManager;
pub use self::manager::ScreenManager;
use super::functions;

View File

@ -1,10 +1,10 @@
pub mod cursor;
pub mod terminal;
pub mod input;
pub mod manager;
pub mod style;
pub mod terminal;
pub use super::manager::ScreenManager;
use super::common::functions;
use super::common::commands;
use super::common::traits;
use super::common::functions;
use super::common::traits;
pub use super::manager::ScreenManager;

View File

@ -1,25 +1,30 @@
//! This is an ANSI specific implementation for styling related action.
//! This module is used for windows 10 terminals and unix terminals by default.
use super::{ITerminalColor, Color, ScreenManager, ColorType};
use super::{Color, ColorType, ITerminalColor, ScreenManager};
/// This struct is an ANSI escape code implementation for color related actions.
pub struct AnsiColor;
impl AnsiColor {
pub fn new() -> AnsiColor {
AnsiColor { }
AnsiColor {}
}
}
impl ITerminalColor for AnsiColor {
fn set_fg(&self, fg_color: Color, screen_manager: &ScreenManager) {
screen_manager.write_string(format!(csi!("{}m"), self.color_value(fg_color, ColorType::Foreground)));
screen_manager.write_string(format!(
csi!("{}m"),
self.color_value(fg_color, ColorType::Foreground)
));
}
fn set_bg(&self, bg_color: Color, screen_manager: &ScreenManager) {
screen_manager.write_string(format!(csi!("{}m"), self.color_value(bg_color, ColorType::Background))
);
screen_manager.write_string(format!(
csi!("{}m"),
self.color_value(bg_color, ColorType::Background)
));
}
fn reset(&self, screen_manager: &ScreenManager) {

View File

@ -25,10 +25,10 @@ use std::io;
/// ```
pub struct TerminalColor<'terminal> {
color: Box<ITerminalColor>,
screen_manager: &'terminal ScreenManager
screen_manager: &'terminal ScreenManager,
}
impl<'terminal> TerminalColor<'terminal> {
impl<'terminal> TerminalColor<'terminal> {
/// Create new instance whereon color related actions can be performed.
pub fn new(screen_manager: &'terminal ScreenManager) -> TerminalColor<'terminal> {
#[cfg(target_os = "windows")]
@ -42,7 +42,7 @@ impl<'terminal> TerminalColor<'terminal> {
TerminalColor {
color,
screen_manager
screen_manager,
}
}
@ -117,5 +117,5 @@ impl<'terminal> TerminalColor<'terminal> {
/// Get an Terminal Color implementation whereon color related actions can be performed.
pub fn color(screen_manager: &ScreenManager) -> TerminalColor {
TerminalColor::new(screen_manager)
TerminalColor::new(screen_manager)
}

View File

@ -4,21 +4,21 @@ pub mod color;
pub mod objectstyle;
pub mod styledobject;
mod ansi_color;
#[cfg(target_os = "windows")]
mod winapi_color;
mod ansi_color;
use self::ansi_color::AnsiColor;
#[cfg(target_os = "windows")]
use self::winapi_color::WinApiColor;
use self::ansi_color::AnsiColor;
use std::convert::From;
use std::str::FromStr;
pub use self::color::TerminalColor;
pub use self::styledobject::StyledObject;
pub use self::objectstyle::ObjectStyle;
use super::{ScreenManager, functions};
pub use self::styledobject::StyledObject;
use super::{functions, ScreenManager};
/// 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

View File

@ -1,6 +1,6 @@
//! This module contains the `object style` that can be applied to an `styled object`.
use super::{ScreenManager, Color, StyledObject};
use super::{Color, ScreenManager, StyledObject};
use std::fmt::Display;
@ -30,7 +30,11 @@ impl Default for ObjectStyle {
impl ObjectStyle {
/// 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 ScreenManager,
) -> StyledObject<'style, D> {
StyledObject {
object_style: self.clone(),
screen_manager: screen_manager,

View File

@ -1,6 +1,6 @@
//! This module contains the logic to style an object that contains some state witch can be styled.
use super::{ScreenManager, ObjectStyle, Color};
use super::{Color, ObjectStyle, ScreenManager};
use std::fmt::{self, Display};
use std::io::Write;
@ -18,7 +18,7 @@ pub struct StyledObject<'terminal, D: Display> {
pub screen_manager: &'terminal ScreenManager,
}
impl<'terminal,D: Display> StyledObject<'terminal,D> {
impl<'terminal, D: Display> StyledObject<'terminal, D> {
/// Set the foreground of the styled object to the passed `Color`
///
/// #Example
@ -39,7 +39,7 @@ impl<'terminal,D: Display> StyledObject<'terminal,D> {
/// println!("{}", paint("I am colored green").with(Color::Green));
///
/// ```
pub fn with(mut self, foreground_color: Color) -> StyledObject<'terminal,D> {
pub fn with(mut self, foreground_color: Color) -> StyledObject<'terminal, D> {
self.object_style = self.object_style.fg(foreground_color);
self
}
@ -64,7 +64,7 @@ impl<'terminal,D: Display> StyledObject<'terminal,D> {
/// println!("{}", paint("I am colored green").on(Color::Green))
///
/// ```
pub fn on(mut self, background_color: Color) -> StyledObject<'terminal,D> {
pub fn on(mut self, background_color: Color) -> StyledObject<'terminal, D> {
self.object_style = self.object_style.bg(background_color);
self
}
@ -82,7 +82,7 @@ impl<'terminal,D: Display> StyledObject<'terminal,D> {
///
/// ```
#[cfg(unix)]
pub fn attr(mut self, attr: Attribute) -> StyledObject<'terminal,D> {
pub fn attr(mut self, attr: Attribute) -> StyledObject<'terminal, D> {
&self.object_style.add_attr(attr);
self
}
@ -90,60 +90,60 @@ impl<'terminal,D: Display> StyledObject<'terminal,D> {
/// Increase the font intensity.
#[cfg(unix)]
#[inline(always)]
pub fn bold(self) -> StyledObject<'terminal,D> {
pub fn bold(self) -> StyledObject<'terminal, D> {
self.attr(Attribute::Bold)
}
/// Faint (decreased intensity) (Not widely supported).
#[cfg(unix)]
#[inline(always)]
pub fn dim(self) -> StyledObject<'terminal,D> {
pub fn dim(self) -> StyledObject<'terminal, D> {
self.attr(Attribute::Dim)
}
/// Make the font italic (Not widely supported; Sometimes treated as inverse).
#[cfg(unix)]
#[inline(always)]
pub fn italic(self) -> StyledObject<'terminal,D> {
pub fn italic(self) -> StyledObject<'terminal, D> {
self.attr(Attribute::Italic)
}
/// Underline font.
#[cfg(unix)]
#[inline(always)]
pub fn underlined(self) -> StyledObject<'terminal,D> {
pub fn underlined(self) -> StyledObject<'terminal, D> {
self.attr(Attribute::Underlined)
}
/// Slow Blink (less than 150 per minute; not widely supported).
#[cfg(unix)]
#[inline(always)]
pub fn slow_blink(self) -> StyledObject<'terminal,D> {
pub fn slow_blink(self) -> StyledObject<'terminal, D> {
self.attr(Attribute::SlowBlink)
}
/// Rapid Blink (MS-DOS ANSI.SYS; 150+ per minute; not widely supported).
#[cfg(unix)]
#[inline(always)]
pub fn rapid_blink(self) -> StyledObject<'terminal,D> {
pub fn rapid_blink(self) -> StyledObject<'terminal, D> {
self.attr(Attribute::RapidBlink)
}
/// Swap foreground and background colors.
#[cfg(unix)]
#[inline(always)]
pub fn reverse(self) -> StyledObject<'terminal,D> {
pub fn reverse(self) -> StyledObject<'terminal, D> {
self.attr(Attribute::Reverse)
}
/// Hide text (Not widely supported).
#[cfg(unix)]
#[inline(always)]
pub fn hidden(self) -> StyledObject<'terminal,D> {
pub fn hidden(self) -> StyledObject<'terminal, D> {
self.attr(Attribute::Hidden)
}
/// Characters legible, but marked for deletion. Not widely supported.
#[cfg(unix)]
#[inline(always)]
pub fn crossed_out(self) -> StyledObject<'terminal,D> {
pub fn crossed_out(self) -> StyledObject<'terminal, D> {
self.attr(Attribute::CrossedOut)
}
}
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> {
let mut colored_terminal = super::super::super::style::color::color(self.screen_manager);
let mut reset = true;
@ -160,7 +160,8 @@ impl<'terminal, D: Display> Display for StyledObject<'terminal,D> {
#[cfg(unix)]
for attr in self.object_style.attrs.iter() {
self.screen_manager.write_string(format!(csi!("{}m"), *attr as i16));
self.screen_manager
.write_string(format!(csi!("{}m"), *attr as i16));
reset = true;
}

View File

@ -2,7 +2,7 @@
//! This module is used for windows 10 terminals and unix terminals by default.
use super::super::cursor::cursor;
use super::{ClearType, ITerminal, ScreenManager, functions};
use super::{functions, ClearType, ITerminal, ScreenManager};
/// This struct is an ansi escape code implementation for terminal related actions.
pub struct AnsiTerminal;

View File

@ -2,16 +2,16 @@
pub mod terminal;
mod ansi_terminal;
#[cfg(target_os = "windows")]
mod winapi_terminal;
mod ansi_terminal;
use self::ansi_terminal::AnsiTerminal;
#[cfg(target_os = "windows")]
use self::winapi_terminal::WinApiTerminal;
use self::ansi_terminal::AnsiTerminal;
pub use self::terminal::Terminal;
use super::{ ScreenManager, functions };
use super::{functions, ScreenManager};
/// Enum that specifies a way of clearing.
pub enum ClearType {
@ -38,7 +38,7 @@ pub trait ITerminal {
/// Scroll `n` lines up in the current terminal.
fn scroll_up(&self, count: i16, screen_manager: &ScreenManager);
/// Scroll `n` lines down in the current terminal.
fn scroll_down(&self, count: i16,screen_manager: &ScreenManager);
fn scroll_down(&self, count: i16, screen_manager: &ScreenManager);
/// Resize terminal to the given width and height.
fn set_size(&self, width: i16, height: i16, screen_manager: &ScreenManager);
/// Close the current terminal

View File

@ -41,7 +41,7 @@ impl<'terminal> Terminal<'terminal> {
Terminal {
terminal,
screen_manager: screen_manager
screen_manager: screen_manager,
}
}
@ -105,7 +105,7 @@ impl<'terminal> Terminal<'terminal> {
///
/// ```
pub fn scroll_up(&self, count: i16) {
self.terminal.scroll_up(count,&self.screen_manager);
self.terminal.scroll_up(count, &self.screen_manager);
}
/// Scroll `n` lines up in the current terminal.
@ -114,7 +114,7 @@ impl<'terminal> Terminal<'terminal> {
///
/// ```rust
///
/// let crossterm = Crossterm::new();
/// let crossterm = Crossterm::new();
/// let term = crossterm.terminal();
///
/// // scroll down by 5 lines
@ -122,7 +122,7 @@ impl<'terminal> Terminal<'terminal> {
///
/// ```
pub fn scroll_down(&self, count: i16) {
self.terminal.scroll_down(count,&self.screen_manager);
self.terminal.scroll_down(count, &self.screen_manager);
}
/// Set the terminal size. Note that not all terminals can be set to a very small scale.
@ -139,7 +139,7 @@ impl<'terminal> Terminal<'terminal> {
///
/// ```
pub fn set_size(&self, width: i16, height: i16) {
self.terminal.set_size(width, height,&self.screen_manager);
self.terminal.set_size(width, height, &self.screen_manager);
}
/// Exit the current process.

View File

@ -3,8 +3,8 @@
//!
//! 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::super::super::cursor::cursor;
use super::{functions, ClearType, ITerminal, ScreenManager};
use kernel::windows_kernel::{csbi, kernel, terminal, writing};
use winapi::um::wincon::{CONSOLE_SCREEN_BUFFER_INFO, COORD, SMALL_RECT};
@ -13,7 +13,7 @@ pub struct WinApiTerminal;
impl WinApiTerminal {
pub fn new() -> WinApiTerminal {
WinApiTerminal { }
WinApiTerminal {}
}
}
@ -23,7 +23,9 @@ impl ITerminal for WinApiTerminal {
let pos = cursor(screen_manager).pos();
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::FromCursorUp => clear_before_cursor(pos, csbi, screen_manager),
ClearType::CurrentLine => clear_current_line(pos, csbi, screen_manager),
@ -46,8 +48,7 @@ impl ITerminal for WinApiTerminal {
srct_window.Top -= count; // move top down
srct_window.Bottom = count; // move bottom down
let success =
kernel::set_console_info(false, &mut srct_window, &screen_manager);
let success = kernel::set_console_info(false, &mut srct_window, &screen_manager);
if success {
panic!("Something went wrong when scrolling down");
}
@ -67,8 +68,7 @@ impl ITerminal for WinApiTerminal {
srct_window.Top += count; // move top down
srct_window.Bottom += count; // move bottom down
let success =
kernel::set_console_info(true, &mut srct_window, &screen_manager);
let success = kernel::set_console_info(true, &mut srct_window, &screen_manager);
if success {
panic!("Something went wrong when scrolling down");
}
@ -250,7 +250,11 @@ pub fn clear_current_line(
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,
) {
let (x, y) = pos;
// location where to start clearing