Putted Screen
behind an Option
. Now when you call the functions: color, cursor, terminal, input you won't need to provide a Screen
anymore.
When you want to work with the 'alternate screen' you can call the following functions: terminal::from_screen etc. Which will give you an instance to the back of the module you are calling it in. So instead of: let color = color(Screen::default()); let cursor = cursor(Screen::default()); let input = input(Screen::default()); let terminal = terminal(Screen::default()); You can do: let color = color(); let cursor = cursor(); let input = input(); let terminal = terminal();
This commit is contained in:
parent
3dfa98cba3
commit
b717d306c3
@ -1,3 +1,8 @@
|
|||||||
|
# Changes crossterm 0.5.0
|
||||||
|
- Implemented Display for styled object.
|
||||||
|
- Removed `Screen` from the following functions: `crossterm::cursor(), crossterm::color(), crossterm::terminal()`, you won't need to care about `Screen` unless you are working with alternate or raw screen.
|
||||||
|
- more to come ...
|
||||||
|
|
||||||
# Changes crossterm to 0.4.3
|
# Changes crossterm to 0.4.3
|
||||||
- Fixed bug [issue 41](https://github.com/TimonPost/crossterm/issues/41)
|
- Fixed bug [issue 41](https://github.com/TimonPost/crossterm/issues/41)
|
||||||
|
|
||||||
|
@ -8,125 +8,111 @@ use self::crossterm::{terminal, Screen};
|
|||||||
|
|
||||||
/// print some red font | demonstration.
|
/// print some red font | demonstration.
|
||||||
pub fn paint_foreground() {
|
pub fn paint_foreground() {
|
||||||
|
// Create a styled object.
|
||||||
|
|
||||||
let screen = Screen::default();
|
|
||||||
// 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.
|
|
||||||
// Call the method `with()` on the object given by `style()` and pass in any Color from the Color enum.
|
// Call the method `with()` on the object given by `style()` and pass in any Color from the Color enum.
|
||||||
let mut styledobject = style("Red foreground").with(Color::Red);
|
let mut styledobject = style("Red foreground").with(Color::Red);
|
||||||
|
|
||||||
// Print the object to the given screen and.
|
// Print the object to the given screen and.
|
||||||
styledobject.paint(&screen);
|
println!("Colored text: {}", styledobject);
|
||||||
|
|
||||||
style("Some colored text").with(Color::Blue).on(Color::Black).paint(&screen);
|
// Or print inline
|
||||||
|
println!("Colored text: {}", style("Red foreground").with(Color::Blue));
|
||||||
// Crossterm provides method chaining for coloring so that the above points can be inlined.
|
|
||||||
style(format!("Red foreground color : \t {}", "■")).with(Color::Red).paint(&screen);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// print some font on red background | demonstration.
|
/// print some font on red background | demonstration.
|
||||||
pub fn paint_background() {
|
pub fn paint_background() {
|
||||||
let screen = Screen::default();
|
// Create a styled object.
|
||||||
// Pass an string to the `paint()` method with you want to paint.
|
// Call the method `with()` on the object given by `style()` and pass in any Color from the Color enum.
|
||||||
// This will give you an object back wits can be styled and displayed.
|
let mut styledobject = style("Red foreground").on(Color::Red);
|
||||||
// Call the method `on()` on the object given by `style()` and pass in any Color from the Color enum.
|
|
||||||
let mut styledobject = style("Red background color").on(Color::Red);
|
|
||||||
|
|
||||||
// Print the object to the given screen and.
|
// Print the object to the given screen and.
|
||||||
styledobject.paint(&screen);
|
println!("Colored text: {}", styledobject);
|
||||||
|
|
||||||
// Crossterm provides method chaining for coloring so that the above points can be inlined.
|
// Or print inline
|
||||||
style(format!("Red background color : \t {}", "■")).with(Color::Red).paint(&screen);
|
println!("Colored text: {}", style("Red foreground").on(Color::Blue));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Print all available foreground colors | demonstration.
|
/// Print all available foreground colors | demonstration.
|
||||||
pub fn print_all_foreground_colors() {
|
pub fn print_all_foreground_colors() {
|
||||||
let screen = Screen::default();
|
println!("{}", style(format!("Black : \t\t {} \n", "■")).with(Color::Black));
|
||||||
|
println!("{}", style(format!("Red : \t\t {} \n", "■")).with(Color::Red));
|
||||||
style(format!("Black : \t\t {} \n", "■")).with(Color::Black).paint(&screen);
|
println!("{}", style(format!("Cyan : \t\t {} \n", "■")).with(Color::Cyan));
|
||||||
style(format!("Red : \t\t {} \n", "■")).with(Color::Red).paint(&screen);
|
println!("{}", style(format!("DarkCyan : \t {} \n", "■")).with(Color::DarkCyan));
|
||||||
style(format!("Cyan : \t\t {} \n", "■")).with(Color::Cyan).paint(&screen);
|
println!("{}", style(format!("DarkRed : \t {} \n", "■")).with(Color::DarkRed));
|
||||||
style(format!("DarkCyan : \t {} \n", "■")).with(Color::DarkCyan).paint(&screen);
|
println!("{}", style(format!("Green : \t {} \n", "■")).with(Color::Green));
|
||||||
style(format!("DarkRed : \t {} \n", "■")).with(Color::DarkRed).paint(&screen);
|
println!("{}", style(format!("DarkGreen : \t {} \n", "■")).with(Color::DarkGreen));
|
||||||
style(format!("Green : \t {} \n", "■")).with(Color::Green).paint(&screen);
|
println!("{}", style(format!("Blue : \t\t {} \n", "■")).with(Color::Blue));
|
||||||
style(format!("DarkGreen : \t {} \n", "■")).with(Color::DarkGreen).paint(&screen);
|
println!("{}", style(format!("DarkBlue : \t {} \n", "■")).with(Color::DarkBlue));
|
||||||
style(format!("Blue : \t\t {} \n", "■")).with(Color::Blue).paint(&screen);
|
println!("{}", style(format!("Magenta : \t {} \n", "■")).with(Color::Magenta));
|
||||||
style(format!("DarkBlue : \t {} \n", "■")).with(Color::DarkBlue).paint(&screen);
|
println!("{}", style(format!("DarkMagenta : \t {} \n", "■")).with(Color::DarkMagenta));
|
||||||
style(format!("Magenta : \t {} \n", "■")).with(Color::Magenta).paint(&screen);
|
println!("{}", style(format!("Yellow : \t {} \n", "■")).with(Color::Yellow));
|
||||||
style(format!("DarkMagenta : \t {} \n", "■")).with(Color::DarkMagenta).paint(&screen);
|
println!("{}", style(format!("DarkYellow : \t {} \n", "■")).with(Color::DarkYellow));
|
||||||
style(format!("Yellow : \t {} \n", "■")).with(Color::Yellow).paint(&screen);
|
println!("{}", style(format!("Grey : \t\t {} \n", "■")).with(Color::Grey));
|
||||||
style(format!("DarkYellow : \t {} \n", "■")).with(Color::DarkYellow).paint(&screen);
|
println!("{}", style(format!("White : \t {} \n", "■")).with(Color::White));
|
||||||
style(format!("Grey : \t\t {} \n", "■")).with(Color::Grey).paint(&screen);
|
|
||||||
style(format!("White : \t {} \n", "■")).with(Color::White).paint(&screen);
|
|
||||||
|
|
||||||
#[cfg(unix)]
|
#[cfg(unix)]
|
||||||
style("RGB color (10,10,10) ").with(Color::Rgb {
|
println!("{}", style("RGB color (10,10,10) ").with(Color::Rgb {
|
||||||
r: 10,
|
r: 10,
|
||||||
g: 10,
|
g: 10,
|
||||||
b: 10
|
b: 10
|
||||||
}).paint(&screen);
|
}));
|
||||||
|
|
||||||
#[cfg(unix)]
|
#[cfg(unix)]
|
||||||
style("RGB color (10,10,10) ").with(Color::AnsiValue(50)).paint(&screen);
|
println!("{}",style("RGB color (10,10,10) ")).with(Color::AnsiValue(50));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Print all available foreground colors | demonstration.
|
/// Print all available foreground colors | demonstration.
|
||||||
pub fn print_all_background_colors() {
|
pub fn print_all_background_colors() {
|
||||||
let screen = Screen::default();
|
println!("{}", style(format!("Black : \t {} \n", "■")).on(Color::Black));
|
||||||
|
println!("{}", style(format!("Red : \t\t {} \n", "■")).on(Color::Red));
|
||||||
style(format!("Black : \t {} \n", "■")).on(Color::Black).paint(&screen);
|
println!("{}", style(format!("Cyan : \t\t {} \n", "■")).on(Color::Cyan));
|
||||||
style(format!("Red : \t\t {} \n", "■")).on(Color::Red).paint(&screen);
|
println!("{}", style(format!("DarkCyan : \t {} \n", "■")).on(Color::DarkCyan));
|
||||||
style(format!("Cyan : \t\t {} \n", "■")).on(Color::Cyan).paint(&screen);
|
println!("{}", style(format!("DarkRed : \t {} \n", "■")).on(Color::DarkRed));
|
||||||
style(format!("DarkCyan : \t {} \n", "■")).on(Color::DarkCyan).paint(&screen);
|
println!("{}", style(format!("Green : \t {} \n", "■")).on(Color::Green));
|
||||||
style(format!("DarkRed : \t {} \n", "■")).on(Color::DarkRed).paint(&screen);
|
println!("{}", style(format!("DarkGreen : \t {} \n", "■")).on(Color::DarkGreen));
|
||||||
style(format!("Green : \t {} \n", "■")).on(Color::Green).paint(&screen);
|
println!("{}", style(format!("Blue : \t\t {} \n", "■")).on(Color::Blue));
|
||||||
style(format!("DarkGreen : \t {} \n", "■")).on(Color::DarkGreen).paint(&screen);
|
println!("{}", style(format!("DarkBlue : \t {} \n", "■")).on(Color::DarkBlue));
|
||||||
style(format!("Blue : \t\t {} \n", "■")).on(Color::Blue).paint(&screen);
|
println!("{}", style(format!("Magenta : \t {} \n", "■")).on(Color::Magenta));
|
||||||
style(format!("DarkBlue : \t {} \n", "■")).on(Color::DarkBlue).paint(&screen);
|
println!("{}", style(format!("DarkMagenta : \t {} \n", "■")).on(Color::DarkMagenta));
|
||||||
style(format!("Magenta : \t {} \n", "■")).on(Color::Magenta).paint(&screen);
|
println!("{}", style(format!("Yellow : \t {} \n", "■")).on(Color::Yellow));
|
||||||
style(format!("DarkMagenta : \t {} \n", "■")).on(Color::DarkMagenta).paint(&screen);
|
println!("{}", style(format!("DarkYellow : \t {} \n", "■")).on(Color::DarkYellow));
|
||||||
style(format!("Yellow : \t {} \n", "■")).on(Color::Yellow).paint(&screen);
|
println!("{}", style(format!("Grey : \t\t {} \n", "■")).on(Color::Grey));
|
||||||
style(format!("DarkYellow : \t {} \n", "■")).on(Color::DarkYellow).paint(&screen);
|
println!("{}", style(format!("White : \t {} \n", "■")).on(Color::White));
|
||||||
style(format!("Grey : \t\t {} \n", "■")).on(Color::Grey).paint(&screen);
|
|
||||||
style(format!("White : \t {} \n", "■")).on(Color::White).paint(&screen);
|
|
||||||
|
|
||||||
#[cfg(unix)]
|
#[cfg(unix)]
|
||||||
style("RGB color (10,10,10) ").on(Color::Rgb {
|
println!("{}", style("RGB color (10,10,10) ").on(Color::Rgb {
|
||||||
r: 10,
|
r: 10,
|
||||||
g: 10,
|
g: 10,
|
||||||
b: 10
|
b: 10
|
||||||
}).paint(&screen);
|
}));
|
||||||
|
|
||||||
#[cfg(unix)]
|
#[cfg(unix)]
|
||||||
style("RGB color (10,10,10) ").on(Color::AnsiValue(50)).paint(&screen);
|
println!("{}",style("RGB color (10,10,10) ").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..
|
/// 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)]
|
#[cfg(unix)]
|
||||||
pub fn print_font_with_attributes() {
|
pub fn print_font_with_attributes() {
|
||||||
let screen = Screen::default();
|
println!("{}",style("Normal text"));
|
||||||
style("Normal text").paint(&screen);
|
println!("{}",style("Bold text").bold());
|
||||||
style("Bold text").bold().paint(&screen);
|
println!("{}",style("Italic text").italic());
|
||||||
style("Italic text").italic().paint(&screen);
|
println!("{}",style("Slow blinking text").slow_blink());
|
||||||
style("Slow blinking text").slow_blink().paint(&screen);
|
println!("{}",style("Rapid blinking text").rapid_blink());
|
||||||
style("Rapid blinking text").rapid_blink().paint(&screen);
|
println!("{}",style("Hidden text").hidden());
|
||||||
style("Hidden text").hidden().paint(&screen);
|
println!("{}",style("Underlined text").underlined());
|
||||||
style("Underlined text").underlined().paint(&screen);
|
println!("{}",style("Reversed text").reverse());
|
||||||
style("Reversed text").reverse().paint(&screen);
|
println!("{}",style("Dim text").dim());
|
||||||
style("Dim text").dim().paint(&screen);
|
println!("{}",style("Crossed out font").crossed_out());
|
||||||
style("Crossed out font").crossed_out().paint(&screen);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Print all supported RGB colors | demonstration.
|
/// Print all supported RGB colors | demonstration.
|
||||||
#[cfg(unix)]
|
#[cfg(unix)]
|
||||||
pub fn print_supported_colors() {
|
pub fn print_supported_colors() {
|
||||||
let screen = Screen::default();
|
let count = color()
|
||||||
let count = color(&screen)
|
|
||||||
.get_available_color_count()
|
.get_available_color_count()
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
for i in 0..count {
|
for i in 0..count {
|
||||||
style(format!("White : \t {}", i)).on(Color::AnsiValue(i as u8)).paint(&screen);
|
println!("{}", style(format!("White : \t {}", i)).on(Color::AnsiValue(i as u8)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -9,8 +9,7 @@ use self::crossterm::Screen;
|
|||||||
/// Set the cursor to position X: 10, Y: 5 in the terminal.
|
/// Set the cursor to position X: 10, Y: 5 in the terminal.
|
||||||
pub fn goto() {
|
pub fn goto() {
|
||||||
// Get the cursor
|
// Get the cursor
|
||||||
let screen = Screen::default();
|
let mut cursor = cursor();
|
||||||
let mut cursor = cursor(&screen);
|
|
||||||
// Set the cursor to position X: 10, Y: 5 in the terminal
|
// Set the cursor to position X: 10, Y: 5 in the terminal
|
||||||
cursor.goto(10, 5);
|
cursor.goto(10, 5);
|
||||||
}
|
}
|
||||||
@ -18,8 +17,7 @@ pub fn goto() {
|
|||||||
/// get the cursor position
|
/// get the cursor position
|
||||||
pub fn pos() {
|
pub fn pos() {
|
||||||
// Get the cursor
|
// Get the cursor
|
||||||
let screen = Screen::default();
|
let mut cursor = cursor();
|
||||||
let mut cursor = cursor(&screen);
|
|
||||||
// get the cursor position.
|
// get the cursor position.
|
||||||
let (x, y) = cursor.pos();
|
let (x, y) = cursor.pos();
|
||||||
}
|
}
|
||||||
@ -27,8 +25,7 @@ pub fn pos() {
|
|||||||
/// Move the cursor 3 up | demonstration.
|
/// Move the cursor 3 up | demonstration.
|
||||||
pub fn move_up() {
|
pub fn move_up() {
|
||||||
// Get the cursor
|
// Get the cursor
|
||||||
let screen = Screen::default();
|
let mut cursor = cursor();
|
||||||
let mut cursor = cursor(&screen);
|
|
||||||
|
|
||||||
// Move the cursor to position 3 times to the up in the terminal
|
// Move the cursor to position 3 times to the up in the terminal
|
||||||
cursor.move_up(10);
|
cursor.move_up(10);
|
||||||
@ -36,24 +33,21 @@ pub fn move_up() {
|
|||||||
|
|
||||||
/// Move the cursor 3 to the right | demonstration.
|
/// Move the cursor 3 to the right | demonstration.
|
||||||
pub fn move_right() {
|
pub fn move_right() {
|
||||||
let screen = Screen::default();
|
let mut cursor = cursor();
|
||||||
let mut cursor = cursor(&screen);
|
|
||||||
// Move the cursor to position 3 times to the right in the terminal
|
// Move the cursor to position 3 times to the right in the terminal
|
||||||
cursor.move_right(3);
|
cursor.move_right(3);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Move the cursor 3 down | demonstration.
|
/// Move the cursor 3 down | demonstration.
|
||||||
pub fn move_down() {
|
pub fn move_down() {
|
||||||
let screen = Screen::default();
|
let mut cursor = cursor();
|
||||||
let mut cursor = cursor(&screen);
|
|
||||||
// Move the cursor to position 3 times to the down in the terminal
|
// Move the cursor to position 3 times to the down in the terminal
|
||||||
cursor.move_down(3);
|
cursor.move_down(3);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Move the cursor 3 to the left | demonstration.
|
/// Move the cursor 3 to the left | demonstration.
|
||||||
pub fn move_left() {
|
pub fn move_left() {
|
||||||
let screen = Screen::default();
|
let mut cursor = cursor();
|
||||||
let mut cursor = cursor(&screen);
|
|
||||||
|
|
||||||
// Move the cursor to position 3 times to the left in the terminal
|
// Move the cursor to position 3 times to the left in the terminal
|
||||||
cursor.move_left(3);
|
cursor.move_left(3);
|
||||||
@ -87,8 +81,7 @@ pub fn move_left() {
|
|||||||
|
|
||||||
/// Save and reset cursor position | demonstration..
|
/// Save and reset cursor position | demonstration..
|
||||||
pub fn safe_and_reset_position() {
|
pub fn safe_and_reset_position() {
|
||||||
let screen = Screen::default();
|
let mut cursor = cursor();
|
||||||
let mut cursor = cursor(&screen);
|
|
||||||
|
|
||||||
// Goto X: 5 Y: 5
|
// Goto X: 5 Y: 5
|
||||||
cursor.goto(5, 5);
|
cursor.goto(5, 5);
|
||||||
@ -108,22 +101,19 @@ pub fn safe_and_reset_position() {
|
|||||||
|
|
||||||
/// Hide cursor display | demonstration.
|
/// Hide cursor display | demonstration.
|
||||||
pub fn hide_cursor() {
|
pub fn hide_cursor() {
|
||||||
let screen = Screen::default();
|
let mut cursor = cursor();
|
||||||
let mut cursor = cursor(&screen);
|
|
||||||
cursor.hide();
|
cursor.hide();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Show cursor display | demonstration.
|
/// Show cursor display | demonstration.
|
||||||
pub fn show_cursor() {
|
pub fn show_cursor() {
|
||||||
let screen = Screen::default();
|
let mut cursor = cursor();
|
||||||
let mut cursor = cursor(&screen);
|
|
||||||
cursor.show();
|
cursor.show();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Show cursor display, only works on certain terminals.| demonstration
|
/// Show cursor display, only works on certain terminals.| demonstration
|
||||||
pub fn blink_cursor() {
|
pub fn blink_cursor() {
|
||||||
let screen = Screen::default();
|
let mut cursor = cursor();
|
||||||
let mut cursor = cursor(&screen);
|
|
||||||
cursor.blink(false);
|
cursor.blink(false);
|
||||||
cursor.blink(false);
|
cursor.blink(false);
|
||||||
}
|
}
|
||||||
|
@ -9,7 +9,7 @@
|
|||||||
extern crate crossterm;
|
extern crate crossterm;
|
||||||
|
|
||||||
// modules that could be test
|
// modules that could be test
|
||||||
//mod terminal;
|
mod terminal;
|
||||||
mod color;
|
mod color;
|
||||||
mod cursor;
|
mod cursor;
|
||||||
mod some_types;
|
mod some_types;
|
||||||
|
@ -11,8 +11,7 @@ use std::time::Duration;
|
|||||||
/// this will capture the input until the given key.
|
/// this will capture the input until the given key.
|
||||||
pub fn read_async_until() {
|
pub fn read_async_until() {
|
||||||
// create raw screen
|
// create raw screen
|
||||||
let screen = Screen::default();
|
let crossterm = Crossterm::new();
|
||||||
let crossterm = Crossterm::new(&screen);
|
|
||||||
|
|
||||||
// init some modules we use for this demo
|
// init some modules we use for this demo
|
||||||
let input = crossterm.input();
|
let input = crossterm.input();
|
||||||
@ -44,8 +43,7 @@ pub fn read_async_until() {
|
|||||||
|
|
||||||
/// this will read pressed characters async until `x` is typed.
|
/// this will read pressed characters async until `x` is typed.
|
||||||
pub fn read_async() {
|
pub fn read_async() {
|
||||||
let screen = Screen::default();
|
let input = input();
|
||||||
let input = input(&screen);
|
|
||||||
|
|
||||||
let mut stdin = input.read_async().bytes();
|
let mut stdin = input.read_async().bytes();
|
||||||
|
|
||||||
@ -65,7 +63,7 @@ pub fn read_async() {
|
|||||||
|
|
||||||
pub fn read_async_demo() {
|
pub fn read_async_demo() {
|
||||||
let screen = Screen::new(true);
|
let screen = Screen::new(true);
|
||||||
let crossterm = Crossterm::new(&screen);
|
let crossterm = Crossterm::from_screen(&screen);
|
||||||
|
|
||||||
// init some modules we use for this demo
|
// init some modules we use for this demo
|
||||||
let input = crossterm.input();
|
let input = crossterm.input();
|
||||||
@ -104,7 +102,7 @@ pub fn async_reading_on_alternate_screen() {
|
|||||||
// switch to alternate screen
|
// switch to alternate screen
|
||||||
if let Ok(alternate) = screen.enable_alternate_modes(true)
|
if let Ok(alternate) = screen.enable_alternate_modes(true)
|
||||||
{
|
{
|
||||||
let crossterm = Crossterm::new(&alternate.screen);
|
let crossterm = Crossterm::from_screen(&alternate.screen);
|
||||||
// init some modules we use for this demo
|
// init some modules we use for this demo
|
||||||
let input = crossterm.input();
|
let input = crossterm.input();
|
||||||
let terminal = crossterm.terminal();
|
let terminal = crossterm.terminal();
|
||||||
|
@ -4,8 +4,7 @@ use self::crossterm::input::input;
|
|||||||
use self::crossterm::Screen;
|
use self::crossterm::Screen;
|
||||||
|
|
||||||
pub fn read_char() {
|
pub fn read_char() {
|
||||||
let screen = Screen::default();
|
let input = input();
|
||||||
let input = input(&screen);
|
|
||||||
|
|
||||||
match input.read_char() {
|
match input.read_char() {
|
||||||
Ok(s) => println!("char typed: {}", s),
|
Ok(s) => println!("char typed: {}", s),
|
||||||
@ -14,8 +13,7 @@ pub fn read_char() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn read_line() {
|
pub fn read_line() {
|
||||||
let screen = Screen::default();
|
let input = input();
|
||||||
let input = input(&screen);
|
|
||||||
|
|
||||||
match input.read_line() {
|
match input.read_line() {
|
||||||
Ok(s) => println!("string typed: {}", s),
|
Ok(s) => println!("string typed: {}", s),
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
extern crate crossterm;
|
extern crate crossterm;
|
||||||
|
|
||||||
use crossterm::{Screen, Crossterm};
|
use crossterm::{Screen, Crossterm};
|
||||||
use crossterm::terminal::{terminal,Terminal, ClearType};
|
use crossterm::terminal::{from_screen,Terminal, ClearType};
|
||||||
use crossterm::cursor::{TerminalCursor, cursor};
|
use crossterm::cursor::{TerminalCursor, cursor};
|
||||||
use crossterm::input::input;
|
use crossterm::input::input;
|
||||||
use std::sync::{Arc,Mutex};
|
use std::sync::{Arc,Mutex};
|
||||||
@ -12,7 +12,7 @@ fn main() {
|
|||||||
use crossterm::color;
|
use crossterm::color;
|
||||||
|
|
||||||
let screen = Screen::new(true);
|
let screen = Screen::new(true);
|
||||||
let crossterm = Crossterm::new(&screen);
|
let crossterm = Crossterm::from_screen(&screen);
|
||||||
let cursor = crossterm.cursor();
|
let cursor = crossterm.cursor();
|
||||||
cursor.hide();
|
cursor.hide();
|
||||||
|
|
||||||
@ -23,7 +23,7 @@ fn main() {
|
|||||||
let mut count = 0;
|
let mut count = 0;
|
||||||
|
|
||||||
thread::spawn(move || {
|
thread::spawn(move || {
|
||||||
let input = input(&screen);
|
let input = input();
|
||||||
let mut stdin = input.read_async().bytes();
|
let mut stdin = input.read_async().bytes();
|
||||||
|
|
||||||
loop
|
loop
|
||||||
@ -60,7 +60,7 @@ fn log(input_buf: Arc<Mutex<String>>, screen: &Screen) -> Vec<thread::JoinHandle
|
|||||||
{
|
{
|
||||||
let mut threads = Vec::with_capacity(10);
|
let mut threads = Vec::with_capacity(10);
|
||||||
|
|
||||||
let (_, term_height) = terminal(&screen).terminal_size();
|
let (_, term_height) = from_screen(screen).terminal_size();
|
||||||
|
|
||||||
for i in 0..1
|
for i in 0..1
|
||||||
{
|
{
|
||||||
|
@ -44,7 +44,7 @@ impl<'screen> FirstDepthSearch<'screen>
|
|||||||
// push first position on the stack
|
// push first position on the stack
|
||||||
self.stack.push(self.root_pos);
|
self.stack.push(self.root_pos);
|
||||||
|
|
||||||
let crossterm = Crossterm::new(&self.screen);
|
let crossterm = Crossterm::from_screen(&self.screen);
|
||||||
let mut cursor = crossterm.cursor();
|
let mut cursor = crossterm.cursor();
|
||||||
cursor.hide();
|
cursor.hide();
|
||||||
|
|
||||||
@ -75,7 +75,7 @@ impl<'screen> FirstDepthSearch<'screen>
|
|||||||
cell.paint(&self.screen);
|
cell.paint(&self.screen);
|
||||||
self.screen.stdout.flush();
|
self.screen.stdout.flush();
|
||||||
|
|
||||||
thread::sleep(time::Duration::from_millis(2));
|
thread::sleep(time::Duration::from_millis(1));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -55,7 +55,7 @@ fn print_welcome_screen()
|
|||||||
{
|
{
|
||||||
let mut screen = Screen::new(true);
|
let mut screen = Screen::new(true);
|
||||||
|
|
||||||
let crossterm = Crossterm::new(&screen);
|
let crossterm = Crossterm::from_screen(&screen);
|
||||||
|
|
||||||
// create the handle for the cursor and terminal.
|
// create the handle for the cursor and terminal.
|
||||||
let terminal = crossterm.terminal();
|
let terminal = crossterm.terminal();
|
||||||
|
@ -41,8 +41,7 @@ impl Map
|
|||||||
// render the map on the screen.
|
// render the map on the screen.
|
||||||
pub fn render_map(&mut self, screen: &Screen)
|
pub fn render_map(&mut self, screen: &Screen)
|
||||||
{
|
{
|
||||||
let crossterm = Crossterm::new(&screen);
|
let crossterm = Crossterm::from_screen(screen);
|
||||||
let mut cursor = crossterm.cursor();
|
|
||||||
|
|
||||||
for row in self.map.iter_mut()
|
for row in self.map.iter_mut()
|
||||||
{
|
{
|
||||||
@ -52,7 +51,7 @@ impl Map
|
|||||||
if (column.position.y == 0 || column.position.y == self.size.height - 1) || (column.position.x == 0 || column.position.x == self.size.width - 1)
|
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.style(column.look).on(column.color);
|
let cell_style = crossterm.style(column.look).on(column.color);
|
||||||
cursor.goto(column.position.x as u16, column.position.y as u16);
|
cursor().goto(column.position.x as u16, column.position.y as u16);
|
||||||
cell_style.paint(&screen);
|
cell_style.paint(&screen);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -27,7 +27,7 @@ fn main() {
|
|||||||
|
|
||||||
{
|
{
|
||||||
let mut screen = Screen::new(true);
|
let mut screen = Screen::new(true);
|
||||||
let crossterm = Crossterm::new(&screen);
|
let crossterm = Crossterm::from_screen(&screen);
|
||||||
|
|
||||||
let cursor = crossterm.cursor();
|
let cursor = crossterm.cursor();
|
||||||
let mut input = crossterm.input();
|
let mut input = crossterm.input();
|
||||||
@ -86,7 +86,7 @@ fn main() {
|
|||||||
|
|
||||||
fn title_screen() -> Size
|
fn title_screen() -> Size
|
||||||
{
|
{
|
||||||
let crossterm = Crossterm::new(&Screen::default());
|
let crossterm = Crossterm::new();
|
||||||
|
|
||||||
let cursor = crossterm.cursor();
|
let cursor = crossterm.cursor();
|
||||||
let terminal = crossterm.terminal().clear(ClearType::All);
|
let terminal = crossterm.terminal().clear(ClearType::All);
|
||||||
@ -110,7 +110,7 @@ fn title_screen() -> Size
|
|||||||
|
|
||||||
fn print_game_stats(map_size: Size, snake_lenght: usize, food_aten: usize, screen: &mut Screen)
|
fn print_game_stats(map_size: Size, snake_lenght: usize, food_aten: usize, screen: &mut Screen)
|
||||||
{
|
{
|
||||||
let crossterm = Crossterm::new(&Screen::default());
|
let crossterm = Crossterm::new();
|
||||||
|
|
||||||
let cursor = crossterm.cursor();
|
let cursor = crossterm.cursor();
|
||||||
let terminal = crossterm.terminal().clear(ClearType::All);
|
let terminal = crossterm.terminal().clear(ClearType::All);
|
||||||
@ -124,7 +124,7 @@ fn print_game_stats(map_size: Size, snake_lenght: usize, food_aten: usize, scree
|
|||||||
|
|
||||||
fn game_over_screen()
|
fn game_over_screen()
|
||||||
{
|
{
|
||||||
let crossterm = Crossterm::new(&Screen::default());
|
let crossterm = Crossterm::new();
|
||||||
|
|
||||||
let cursor = crossterm.cursor();
|
let cursor = crossterm.cursor();
|
||||||
let terminal = crossterm.terminal();
|
let terminal = crossterm.terminal();
|
||||||
|
@ -2,7 +2,7 @@ use super::variables::{Position, Size, Direction };
|
|||||||
use super::snake::Snake;
|
use super::snake::Snake;
|
||||||
|
|
||||||
use crossterm::{Crossterm, Screen};
|
use crossterm::{Crossterm, Screen};
|
||||||
use crossterm::cursor::cursor;
|
use crossterm::cursor::from_screen;
|
||||||
use crossterm::style::{ObjectStyle, StyledObject, Color, style};
|
use crossterm::style::{ObjectStyle, StyledObject, Color, style};
|
||||||
|
|
||||||
use rand::distributions::{IndependentSample, Range};
|
use rand::distributions::{IndependentSample, Range};
|
||||||
@ -30,7 +30,7 @@ impl Map
|
|||||||
// render the map on the screen.
|
// render the map on the screen.
|
||||||
pub fn render_map(&mut self, screen: &Screen, free_positions: &mut HashMap<String, Position>)
|
pub fn render_map(&mut self, screen: &Screen, free_positions: &mut HashMap<String, Position>)
|
||||||
{
|
{
|
||||||
let crossterm = Crossterm::new(screen);
|
let crossterm = Crossterm::from_screen(screen);
|
||||||
let mut cursor = crossterm.cursor();
|
let mut cursor = crossterm.cursor();
|
||||||
let mut terminal = crossterm.terminal();
|
let mut terminal = crossterm.terminal();
|
||||||
|
|
||||||
@ -73,7 +73,7 @@ impl Map
|
|||||||
|
|
||||||
fn draw_food(&self, screen: &Screen)
|
fn draw_food(&self, screen: &Screen)
|
||||||
{
|
{
|
||||||
cursor(screen).goto(self.foot_pos.x as u16, self.foot_pos.y as u16);
|
from_screen(screen).goto(self.foot_pos.x as u16, self.foot_pos.y as u16);
|
||||||
style("$").with(Color::Green).paint(screen);
|
style("$").with(Color::Green).paint(screen);
|
||||||
screen.stdout.flush();
|
screen.stdout.flush();
|
||||||
}
|
}
|
||||||
|
@ -33,7 +33,7 @@ impl Snake
|
|||||||
|
|
||||||
pub fn move_snake(&mut self, direction: &Direction, screen: &Screen, free_positions: &mut HashMap<String, Position> )
|
pub fn move_snake(&mut self, direction: &Direction, screen: &Screen, free_positions: &mut HashMap<String, Position> )
|
||||||
{
|
{
|
||||||
let crossterm = Crossterm::new(screen);
|
let crossterm = Crossterm::from_screen(screen);
|
||||||
let cursor = crossterm.cursor();
|
let cursor = crossterm.cursor();
|
||||||
let terminal = crossterm.terminal();
|
let terminal = crossterm.terminal();
|
||||||
|
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
extern crate crossterm;
|
extern crate crossterm;
|
||||||
|
|
||||||
use self::crossterm::terminal::{terminal, ClearType};
|
use self::crossterm::terminal::{self, ClearType};
|
||||||
use self::crossterm::style::{Color, StyledObject, ObjectStyle, style };
|
use self::crossterm::style::{Color, StyledObject, ObjectStyle, style };
|
||||||
use self::crossterm::cursor::cursor;
|
use self::crossterm::cursor;
|
||||||
use self::crossterm::Screen;
|
use self::crossterm::Screen;
|
||||||
|
|
||||||
use std::fmt::Debug;
|
use std::fmt::Debug;
|
||||||
@ -33,15 +33,15 @@ impl Position
|
|||||||
|
|
||||||
pub fn draw(&self, val: &str, screen: &Screen)
|
pub fn draw(&self, val: &str, screen: &Screen)
|
||||||
{
|
{
|
||||||
cursor(screen).goto(self.x as u16, self.y as u16);
|
cursor::from_screen(screen).goto(self.x as u16, self.y as u16);
|
||||||
style(val).with(Color::Red).paint(&screen);
|
style(val).with(Color::Red).paint(&screen);
|
||||||
screen.stdout.flush();
|
screen.stdout.flush();
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn remove(&self, screen: &Screen)
|
pub fn remove(&self, screen: &Screen)
|
||||||
{
|
{
|
||||||
cursor(screen).goto(self.x as u16, self.y as u16);
|
cursor::from_screen(screen).goto(self.x as u16, self.y as u16);
|
||||||
terminal(&screen).write(" ");
|
terminal::from_screen(&screen).write(" ");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4,12 +4,10 @@ use crossterm::{Crossterm, Screen};
|
|||||||
use crossterm::style::Color;
|
use crossterm::style::Color;
|
||||||
|
|
||||||
/// use the `Crossterm` to get an instance to the cursor module | demonstration.
|
/// use the `Crossterm` to get an instance to the cursor module | demonstration.
|
||||||
pub fn use_crossterm_cursor()
|
pub fn crossterm()
|
||||||
{
|
{
|
||||||
let screen = Screen::default();
|
|
||||||
|
|
||||||
// Create the crossterm type to access different modules.
|
// Create the crossterm type to access different modules.
|
||||||
let crossterm = Crossterm::new(&screen);
|
let crossterm = Crossterm::new();
|
||||||
|
|
||||||
// pass a reference to the current screen.
|
// pass a reference to the current screen.
|
||||||
let cursor = crossterm.cursor();
|
let cursor = crossterm.cursor();
|
||||||
|
@ -8,7 +8,7 @@ use std::io::{stdout, Write};
|
|||||||
use std::{thread, time};
|
use std::{thread, time};
|
||||||
|
|
||||||
fn print_wait_screen(screen: &Screen) {
|
fn print_wait_screen(screen: &Screen) {
|
||||||
let crossterm = Crossterm::new(screen);
|
let crossterm = Crossterm::from_screen(screen);
|
||||||
let terminal = crossterm.terminal();
|
let terminal = crossterm.terminal();
|
||||||
let cursor = crossterm.cursor();
|
let cursor = crossterm.cursor();
|
||||||
|
|
||||||
|
@ -8,7 +8,7 @@ use std::io::{stdout, Write};
|
|||||||
use std::{thread, time};
|
use std::{thread, time};
|
||||||
|
|
||||||
fn print_wait_screen(screen: &mut Screen) {
|
fn print_wait_screen(screen: &mut Screen) {
|
||||||
let crossterm = Crossterm::new(screen);
|
let crossterm = Crossterm::from_screen(screen);
|
||||||
let terminal = crossterm.terminal();
|
let terminal = crossterm.terminal();
|
||||||
let cursor = crossterm.cursor();
|
let cursor = crossterm.cursor();
|
||||||
|
|
||||||
|
@ -5,8 +5,7 @@
|
|||||||
extern crate crossterm;
|
extern crate crossterm;
|
||||||
|
|
||||||
use crossterm::terminal::{ClearType, terminal};
|
use crossterm::terminal::{ClearType, terminal};
|
||||||
use crossterm::{Crossterm, Screen};
|
use crossterm::cursor;
|
||||||
|
|
||||||
fn print_test_data() {
|
fn print_test_data() {
|
||||||
for i in 0..100 {
|
for i in 0..100 {
|
||||||
println!("Test data to test terminal: {}", i);
|
println!("Test data to test terminal: {}", i);
|
||||||
@ -15,8 +14,7 @@ fn print_test_data() {
|
|||||||
|
|
||||||
/// Clear all lines in terminal | demonstration
|
/// Clear all lines in terminal | demonstration
|
||||||
pub fn clear_all_lines() {
|
pub fn clear_all_lines() {
|
||||||
let crossterm = Crossterm::new(&Screen::default());
|
let mut terminal = terminal();
|
||||||
let mut terminal = crossterm.terminal();
|
|
||||||
|
|
||||||
print_test_data();
|
print_test_data();
|
||||||
|
|
||||||
@ -26,13 +24,12 @@ pub fn clear_all_lines() {
|
|||||||
|
|
||||||
/// Clear all lines from cursor position X:4, Y:4 down | demonstration
|
/// Clear all lines from cursor position X:4, Y:4 down | demonstration
|
||||||
pub fn clear_from_cursor_down() {
|
pub fn clear_from_cursor_down() {
|
||||||
let crossterm = Crossterm::new(&Screen::default());
|
let mut terminal = terminal();
|
||||||
let mut terminal = crossterm.terminal();
|
|
||||||
|
|
||||||
print_test_data();
|
print_test_data();
|
||||||
|
|
||||||
// Set terminal cursor position (see example for more info).
|
// Set terminal cursor position (see example for more info).
|
||||||
crossterm.cursor().goto(4, 8);
|
cursor().goto(4, 8);
|
||||||
|
|
||||||
// Clear all cells from current cursor position down.
|
// Clear all cells from current cursor position down.
|
||||||
terminal.clear(ClearType::FromCursorDown);
|
terminal.clear(ClearType::FromCursorDown);
|
||||||
@ -40,13 +37,12 @@ pub fn clear_from_cursor_down() {
|
|||||||
|
|
||||||
/// Clear all lines from cursor position X:4, Y:4 up | demonstration
|
/// Clear all lines from cursor position X:4, Y:4 up | demonstration
|
||||||
pub fn clear_from_cursor_up() {
|
pub fn clear_from_cursor_up() {
|
||||||
let crossterm = Crossterm::new(&Screen::default());
|
let mut terminal = terminal();
|
||||||
let mut terminal = crossterm.terminal();
|
|
||||||
|
|
||||||
print_test_data();
|
print_test_data();
|
||||||
|
|
||||||
// Set terminal cursor position (see example for more info).
|
// Set terminal cursor position (see example for more info).
|
||||||
crossterm.cursor().goto(4, 4);
|
cursor().goto(4, 4);
|
||||||
|
|
||||||
// Clear all cells from current cursor position down.
|
// Clear all cells from current cursor position down.
|
||||||
terminal.clear(ClearType::FromCursorUp);
|
terminal.clear(ClearType::FromCursorUp);
|
||||||
@ -54,13 +50,12 @@ pub fn clear_from_cursor_up() {
|
|||||||
|
|
||||||
/// Clear all lines from cursor position X:4, Y:4 up | demonstration
|
/// Clear all lines from cursor position X:4, Y:4 up | demonstration
|
||||||
pub fn clear_current_line() {
|
pub fn clear_current_line() {
|
||||||
let crossterm = Crossterm::new(&Screen::default());
|
let mut terminal = terminal();
|
||||||
let mut terminal = crossterm.terminal();
|
|
||||||
|
|
||||||
print_test_data();
|
print_test_data();
|
||||||
|
|
||||||
// Set terminal cursor position (see example for more info).
|
// Set terminal cursor position (see example for more info).
|
||||||
crossterm.cursor().goto(4, 4);
|
cursor().goto(4, 4);
|
||||||
|
|
||||||
// Clear current line cells.
|
// Clear current line cells.
|
||||||
terminal.clear(ClearType::CurrentLine);
|
terminal.clear(ClearType::CurrentLine);
|
||||||
@ -68,13 +63,12 @@ pub fn clear_current_line() {
|
|||||||
|
|
||||||
/// Clear all lines from cursor position X:4, Y:7 up | demonstration
|
/// Clear all lines from cursor position X:4, Y:7 up | demonstration
|
||||||
pub fn clear_until_new_line() {
|
pub fn clear_until_new_line() {
|
||||||
let crossterm = Crossterm::new(&Screen::default());
|
let mut terminal = terminal();
|
||||||
let mut terminal = crossterm.terminal();
|
|
||||||
|
|
||||||
print_test_data();
|
print_test_data();
|
||||||
|
|
||||||
// Set terminal cursor position (see example for more info).
|
// Set terminal cursor position (see example for more info).
|
||||||
crossterm.cursor().goto(4, 20);
|
cursor().goto(4, 20);
|
||||||
|
|
||||||
// Clear all the cells until next line.
|
// Clear all the cells until next line.
|
||||||
terminal.clear(ClearType::UntilNewLine);
|
terminal.clear(ClearType::UntilNewLine);
|
||||||
@ -82,8 +76,7 @@ pub fn clear_until_new_line() {
|
|||||||
|
|
||||||
/// Print the the current terminal size | demonstration.
|
/// Print the the current terminal size | demonstration.
|
||||||
pub fn print_terminal_size() {
|
pub fn print_terminal_size() {
|
||||||
let screen = Screen::default();
|
let mut terminal = terminal();
|
||||||
let mut terminal = terminal(&screen);
|
|
||||||
|
|
||||||
// Get terminal size
|
// Get terminal size
|
||||||
let (width, height) = terminal.terminal_size();
|
let (width, height) = terminal.terminal_size();
|
||||||
@ -94,16 +87,16 @@ pub fn print_terminal_size() {
|
|||||||
|
|
||||||
/// Set the terminal size to width 10, height: 10 | demonstration.
|
/// Set the terminal size to width 10, height: 10 | demonstration.
|
||||||
pub fn set_terminal_size() {
|
pub fn set_terminal_size() {
|
||||||
let screen = Screen::default();
|
|
||||||
let mut terminal = terminal(&screen);
|
let mut terminal = terminal();
|
||||||
|
|
||||||
terminal.set_size(10, 10);
|
terminal.set_size(10, 10);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Scroll down 10 lines | demonstration.
|
/// Scroll down 10 lines | demonstration.
|
||||||
pub fn scroll_down() {
|
pub fn scroll_down() {
|
||||||
let screen = Screen::default();
|
|
||||||
let mut terminal = terminal(&screen);
|
let mut terminal = terminal();
|
||||||
|
|
||||||
print_test_data();
|
print_test_data();
|
||||||
|
|
||||||
@ -113,8 +106,8 @@ pub fn scroll_down() {
|
|||||||
|
|
||||||
/// Scroll down 10 lines | demonstration.
|
/// Scroll down 10 lines | demonstration.
|
||||||
pub fn scroll_up() {
|
pub fn scroll_up() {
|
||||||
let screen = Screen::default();
|
|
||||||
let mut terminal = terminal(&screen);
|
let mut terminal = terminal();
|
||||||
|
|
||||||
print_test_data();
|
print_test_data();
|
||||||
|
|
||||||
@ -124,8 +117,8 @@ pub fn scroll_up() {
|
|||||||
|
|
||||||
/// Resize the terminal to X: 10, Y: 10 | demonstration.
|
/// Resize the terminal to X: 10, Y: 10 | demonstration.
|
||||||
pub fn resize_terminal() {
|
pub fn resize_terminal() {
|
||||||
let screen = Screen::default();
|
|
||||||
let mut terminal = terminal(&screen);
|
let mut terminal = terminal();
|
||||||
|
|
||||||
// Get terminal size
|
// Get terminal size
|
||||||
terminal.set_size(10, 10);
|
terminal.set_size(10, 10);
|
||||||
@ -133,7 +126,7 @@ pub fn resize_terminal() {
|
|||||||
|
|
||||||
/// exit the current proccess.
|
/// exit the current proccess.
|
||||||
pub fn exit() {
|
pub fn exit() {
|
||||||
let screen = Screen::default();
|
|
||||||
let mut terminal = terminal(&screen);
|
let mut terminal = terminal();
|
||||||
terminal.exit();
|
terminal.exit();
|
||||||
}
|
}
|
||||||
|
@ -36,88 +36,101 @@ use std::sync::Arc;
|
|||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
pub struct Crossterm {
|
pub struct Crossterm {
|
||||||
stdout: Arc<TerminalOutput>
|
stdout: Option<Arc<TerminalOutput>>
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'crossterm> Crossterm {
|
impl<'crossterm> Crossterm {
|
||||||
/// Create a new instance of `Crossterm`
|
/// Create a new instance of `Crossterm`
|
||||||
pub fn new(screen: &Screen) -> Crossterm {
|
pub fn new() -> Crossterm {
|
||||||
Crossterm { stdout: screen.stdout.clone() }
|
Crossterm { stdout: None }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Create a new instance of `Crossterm`
|
||||||
|
pub fn from_screen(screen: &Screen) -> Crossterm {
|
||||||
|
Crossterm { stdout: Some(screen.stdout.clone()) }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get an `TerminalCursor` implementation whereon cursor related actions can be performed.
|
/// Get an `TerminalCursor` implementation whereon cursor related actions can be performed.
|
||||||
///
|
///
|
||||||
/// ```rust
|
/// ```rust
|
||||||
/// extern crate crossterm;
|
/// extern crate crossterm;
|
||||||
/// use crossterm::{Crossterm, Screen};
|
/// use crossterm::Crossterm;
|
||||||
///
|
///
|
||||||
/// let crossterm = Crossterm::new(&Screen::default());
|
/// let crossterm = Crossterm::new();
|
||||||
/// let cursor = crossterm.cursor();
|
/// let cursor = crossterm.cursor();
|
||||||
/// ```
|
/// ```
|
||||||
pub fn cursor(&self) -> cursor::TerminalCursor {
|
pub fn cursor(&self) -> cursor::TerminalCursor {
|
||||||
cursor::TerminalCursor::new(&self.stdout)
|
match &self.stdout {
|
||||||
|
None => { cursor::TerminalCursor::new()},
|
||||||
|
Some(stdout) => { cursor::TerminalCursor::on_screen(&stdout) },
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get an `TerminalInput` implementation whereon terminal related actions can be performed.
|
/// Get an `TerminalInput` implementation whereon terminal related actions can be performed.
|
||||||
///
|
///
|
||||||
/// ```rust
|
/// ```rust
|
||||||
/// extern crate crossterm;
|
/// extern crate crossterm;
|
||||||
/// use crossterm::{Crossterm, Screen};
|
/// use crossterm::Crossterm;
|
||||||
/// use crossterm::terminal;
|
|
||||||
///
|
///
|
||||||
/// let crossterm = Crossterm::new(&Screen::default());
|
/// let crossterm = Crossterm::new();
|
||||||
/// let input = crossterm.input();
|
/// let input = crossterm.input();
|
||||||
/// ```
|
/// ```
|
||||||
pub fn input(&self) -> input::TerminalInput {
|
pub fn input(&self) -> input::TerminalInput {
|
||||||
return input::TerminalInput::new(&self.stdout);
|
match &self.stdout {
|
||||||
|
None => input::TerminalInput::new(),
|
||||||
|
Some(stdout) => input::TerminalInput::on_screen(&stdout),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get an `Terminal` implementation whereon terminal related actions can be performed.
|
/// Get an `Terminal` implementation whereon terminal related actions can be performed.
|
||||||
///
|
///
|
||||||
/// ```rust
|
/// ```rust
|
||||||
/// extern crate crossterm;
|
/// extern crate crossterm;
|
||||||
/// use crossterm::{Crossterm, Screen};
|
/// use crossterm::Crossterm;
|
||||||
///
|
///
|
||||||
/// let crossterm = Crossterm::new(&Screen::default());
|
/// let crossterm = Crossterm::new();
|
||||||
/// let mut terminal = crossterm.terminal();
|
/// let mut terminal = crossterm.terminal();
|
||||||
/// ```
|
/// ```
|
||||||
pub fn terminal(&self) -> terminal::Terminal {
|
pub fn terminal(&self) -> terminal::Terminal {
|
||||||
return terminal::Terminal::new(&self.stdout);
|
match &self.stdout {
|
||||||
|
None => terminal::Terminal::new(),
|
||||||
|
Some(stdout) => terminal::Terminal::on_screen(&stdout),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get an `TerminalColor` implementation whereon color related actions can be performed.
|
/// Get an `TerminalColor` implementation whereon color related actions can be performed.
|
||||||
///
|
///
|
||||||
/// ```rust
|
/// ```rust
|
||||||
/// extern crate crossterm;
|
/// extern crate crossterm;
|
||||||
/// use crossterm::{Crossterm, Screen};
|
/// use crossterm::Crossterm;
|
||||||
///
|
///
|
||||||
/// let crossterm = Crossterm::new(&Screen::default());
|
/// let crossterm = Crossterm::new();
|
||||||
/// let mut terminal = crossterm.terminal();
|
/// let mut terminal = crossterm.color();
|
||||||
/// ```
|
/// ```
|
||||||
pub fn color(&self) -> style::TerminalColor {
|
pub fn color(&self) -> style::TerminalColor {
|
||||||
return style::TerminalColor::new(&self.stdout);
|
match &self.stdout {
|
||||||
|
None => style::TerminalColor::new(),
|
||||||
|
Some(stdout) => style::TerminalColor::on_screen(&stdout),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// This could be used to style an `Displayable` type with colors and attributes.
|
/// This could be used to style an `Displayable` type with colors and attributes.
|
||||||
///
|
///
|
||||||
/// ```rust
|
/// ```rust
|
||||||
/// extern crate crossterm;
|
/// extern crate crossterm;
|
||||||
/// use crossterm::{Crossterm, Screen};
|
/// use crossterm::Crossterm;
|
||||||
///
|
///
|
||||||
/// let crossterm = Crossterm::new(&Screen::default());
|
/// let crossterm = Crossterm::new();
|
||||||
///
|
///
|
||||||
/// // get an styled object which could be painted to the terminal.
|
/// // get an styled object which could be painted to the terminal.
|
||||||
/// let styled_object = crossterm.style("Some Blue colored text on black background")
|
/// let styled_object = crossterm.style("Some Blue colored text on black background")
|
||||||
/// .with(Color::Blue)
|
/// .with(Color::Blue)
|
||||||
/// .on(Color::Black);
|
/// .on(Color::Black);
|
||||||
///
|
///
|
||||||
/// // create an default screen.
|
|
||||||
/// let screen = Screen::default();
|
|
||||||
///
|
|
||||||
/// // print the styled font * times to the current screen.
|
/// // print the styled font * times to the current screen.
|
||||||
/// for i in 1..10
|
/// for i in 1..10
|
||||||
/// {
|
/// {
|
||||||
/// styled_object.paint(&screen);
|
/// println!("{}", styled_object);
|
||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
pub fn style<D>(&self, val: D) -> style::StyledObject<D>
|
pub fn style<D>(&self, val: D) -> style::StyledObject<D>
|
||||||
@ -130,6 +143,13 @@ impl<'crossterm> Crossterm {
|
|||||||
impl From<Arc<TerminalOutput>> for Crossterm
|
impl From<Arc<TerminalOutput>> for Crossterm
|
||||||
{
|
{
|
||||||
fn from(stdout: Arc<TerminalOutput>) -> Self {
|
fn from(stdout: Arc<TerminalOutput>) -> Self {
|
||||||
Crossterm { stdout: stdout }
|
Crossterm { stdout: Some(stdout) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<Screen> for Crossterm
|
||||||
|
{
|
||||||
|
fn from(screen: Screen) -> Self {
|
||||||
|
Crossterm { stdout: Some(screen.stdout.clone()) }
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
use super::TerminalOutput;
|
use super::TerminalOutput;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
use std::io::{self, Write};
|
||||||
|
|
||||||
#[cfg(windows)]
|
#[cfg(windows)]
|
||||||
use kernel::windows_kernel::ansi_support::{try_enable_ansi_support, windows_supportable};
|
use kernel::windows_kernel::ansi_support::{try_enable_ansi_support, windows_supportable};
|
||||||
@ -21,7 +22,7 @@ pub fn get_terminal_size() -> (u16, u16) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Get the cursor position based on the current platform.
|
/// Get the cursor position based on the current platform.
|
||||||
pub fn get_cursor_position(_stdout: &Arc<TerminalOutput>) -> (u16, u16) {
|
pub fn get_cursor_position() -> (u16, u16) {
|
||||||
#[cfg(unix)]
|
#[cfg(unix)]
|
||||||
return pos().expect("Valide position");
|
return pos().expect("Valide position");
|
||||||
// return pos().unwrap_or_else(|x| { return (0,0) });
|
// return pos().unwrap_or_else(|x| { return (0,0) });
|
||||||
@ -60,3 +61,17 @@ pub fn get_module<T>(winapi_impl: T, unix_impl: T) -> Option<T> {
|
|||||||
|
|
||||||
term
|
term
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn write(stdout: &Option<&Arc<TerminalOutput>>, string: String) {
|
||||||
|
match stdout {
|
||||||
|
None => { print!("{}", string.as_str()); io::stdout().flush(); },
|
||||||
|
Some(output) => { output.write_string(string); },
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn write_str(stdout: &Option<&Arc<TerminalOutput>>, string: &str) {
|
||||||
|
match stdout {
|
||||||
|
None => { print!("{}", string); io::stdout().flush(); },
|
||||||
|
Some(output) => { output.write_str(string); },
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -13,6 +13,8 @@ use std::convert::From;
|
|||||||
|
|
||||||
/// With this type you will be able to switch to alternate screen and back to main screen.
|
/// With this type you will be able to switch to alternate screen and back to main screen.
|
||||||
/// Check also the Screen type for swishing to alternate mode.
|
/// Check also the Screen type for swishing to alternate mode.
|
||||||
|
///
|
||||||
|
/// Although this type is available for you to use I would recommend using `Screen` instead.
|
||||||
pub struct AlternateScreen
|
pub struct AlternateScreen
|
||||||
{
|
{
|
||||||
command: Box<IAlternateScreenCommand + Sync + Send>,
|
command: Box<IAlternateScreenCommand + Sync + Send>,
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
//! This module provides some modules to work with the terminal screen. Like raw and alternate screen.
|
//! This module provides some modules to work with the terminal screen.
|
||||||
|
//! Like allowing you to switch between raw and alternate screen.
|
||||||
|
|
||||||
mod alternate;
|
mod alternate;
|
||||||
mod raw;
|
mod raw;
|
||||||
|
@ -21,6 +21,9 @@ use std::io;
|
|||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
/// A wrapper for the raw terminal state. Which can be used to write to.
|
/// A wrapper for the raw terminal state. Which can be used to write to.
|
||||||
|
///
|
||||||
|
/// Although this type is available for you to use I would recommend using `Screen` instead.
|
||||||
|
/// Note that when you want to use input and rawmode you should use `Screen`.
|
||||||
pub struct RawScreen;
|
pub struct RawScreen;
|
||||||
|
|
||||||
impl RawScreen {
|
impl RawScreen {
|
||||||
|
@ -4,14 +4,12 @@ use TerminalOutput;
|
|||||||
use std::io::Write;
|
use std::io::Write;
|
||||||
use std::io::Result;
|
use std::io::Result;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
use std::sync::atomic::AtomicBool;
|
||||||
|
|
||||||
/// This type represents an screen.
|
/// This type represents an screen which could be in normal, raw and alternate modes.
|
||||||
/// This screen has an stdout which is used by the program to write to or to execute commands with.
|
|
||||||
///
|
///
|
||||||
/// You have to make sure that you pass the correct `Screen` to the modules `cursor, terminal, color, input, style`.
|
/// Lets talk about the different modes a bit:
|
||||||
/// Most of the time you just have one screen so you could get an instance of that screen with: `Screen::default()`.
|
|
||||||
///
|
///
|
||||||
/// The screen can be in two modes at first:
|
|
||||||
/// - Alternate modes:
|
/// - Alternate modes:
|
||||||
///
|
///
|
||||||
/// *Nix style applications often utilize an alternate screen buffer, so that they can modify the entire contents of the buffer, without affecting the application that started them.
|
/// *Nix style applications often utilize an alternate screen buffer, so that they can modify the entire contents of the buffer, without affecting the application that started them.
|
||||||
@ -31,31 +29,34 @@ use std::sync::Arc;
|
|||||||
/// - Escape characters
|
/// - Escape characters
|
||||||
/// Note that in raw modes `\n` `\r` will move to the new line but the cursor will be at the same position as before on the new line therefor use `\n\r` to start at the new line at the first cell.
|
/// Note that in raw modes `\n` `\r` will move to the new line but the cursor will be at the same position as before on the new line therefor use `\n\r` to start at the new line at the first cell.
|
||||||
///
|
///
|
||||||
/// Also this screen has an buffer where you can write to. When you want to write the buffer to the screen you could flush the screen.
|
/// You have to make sure that you pass the correct `Screen` to the modules `cursor, terminal, color, input, style`.
|
||||||
|
/// If you switch to alternate screen modes you will get some `Screen` handle back. This `Screen` handle represents the alternate screen.
|
||||||
|
/// Once you want to do coloring or such you need to pass the `Screen` handle the library so that it could be used for coloring on the right screen.
|
||||||
///
|
///
|
||||||
|
/// # Example
|
||||||
/// ```rust
|
/// ```rust
|
||||||
/// // create default screen.
|
/// // create default screen (not raw).
|
||||||
/// let screen = Screen::default();
|
/// let screen = Screen::default();
|
||||||
|
///
|
||||||
/// // create raw screen.
|
/// // create raw screen.
|
||||||
/// let mut screen = Screen::new(true);
|
/// let mut screen = Screen::new(true);
|
||||||
///
|
///
|
||||||
/// // write some text to the internal buffer of this type.
|
/// // create a `Screen` with raw modes disabled.
|
||||||
/// screen.write(b"Some text");
|
|
||||||
/// screen.write(b"Some more text");
|
|
||||||
/// screen.write(b"Some more text");
|
|
||||||
///
|
|
||||||
/// // write the above text by flushing the internal buffer of this type.
|
|
||||||
/// screen.flush();
|
|
||||||
///
|
|
||||||
/// let screen = Screen::new(false);
|
/// let screen = Screen::new(false);
|
||||||
///
|
///
|
||||||
/// // create raw alternate screen from normal screen.
|
/// // create 'raw alternate screen' from normal screen.
|
||||||
/// if let Ok(alternate_screen) = screen.enable_alternate_modes(true)
|
/// if let Ok(alternate_screen) = screen.enable_alternate_modes(true)
|
||||||
/// {
|
/// {
|
||||||
/// let crossterm = Crossterm::new(&alternate_screen.screen);
|
/// // 'alternate screen' is an instance which you should use when you want your actions like: coloring and cursor movement happening at the alternate screen.
|
||||||
///
|
/// // For that you can use `Crossterm::from_screen(alternate.screen)` so that all modules like: cursor, input, terminal will be executed on alternate screen.
|
||||||
/// // make sure to pass in the screen of the AlternateScreen.
|
/// let crossterm = Crossterm::from_screen(&alternate_screen.screen);
|
||||||
/// crossterm.cursor();
|
/// crossterm.cursor();
|
||||||
|
/// crossterm.terminal();
|
||||||
|
///
|
||||||
|
/// // If you want access modules directly without the `Crossterm` type. You should do the following:
|
||||||
|
/// let cursor = crossterm::cursor::from_screen(&alternate_screen.screen);
|
||||||
|
/// let terminal = crossterm::terminal::from_screen(&alternate_screen.screen);
|
||||||
|
/// let input = crossterm::input::from_screen(&alternate_screen.screen);
|
||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
///
|
///
|
||||||
@ -98,9 +99,18 @@ impl Screen
|
|||||||
return Ok(alternate_screen);
|
return Ok(alternate_screen);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Write buffer to an internal buffer. When you want to write the buffer to screen use `flush()`.
|
/// Write buffer to an internal buffer. When you want to write the buffer to screen use `flush_buf()`.
|
||||||
///
|
///
|
||||||
/// This function is useful if you want to build up some output and when you are ready you could flush the output to the screen.
|
/// This function is useful if you want to build up some output and when you are ready you could flush the output to the screen.
|
||||||
|
///
|
||||||
|
/// # Example
|
||||||
|
/// ```
|
||||||
|
/// // write some text to the internal buffer of this type. Note that this will not be printed until you call `flush_buf`
|
||||||
|
/// let screen = Screen::default();
|
||||||
|
/// screen.write_buf(b"Some text");
|
||||||
|
/// screen.write_buf(b"Some more text");
|
||||||
|
/// screen.write_buf(b"Some more text");
|
||||||
|
/// ```
|
||||||
pub fn write_buf(&mut self, buf: &[u8]) -> Result<usize> {
|
pub fn write_buf(&mut self, buf: &[u8]) -> Result<usize> {
|
||||||
self.buffer.write(buf)?;
|
self.buffer.write(buf)?;
|
||||||
Ok(buf.len())
|
Ok(buf.len())
|
||||||
|
@ -3,63 +3,65 @@
|
|||||||
//! Note that the cursor position is 0 based. This means that we start counting at 0 when setting the cursor position ect.
|
//! Note that the cursor position is 0 based. This means that we start counting at 0 when setting the cursor position ect.
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
|
use std::io::Write;
|
||||||
|
|
||||||
|
|
||||||
/// This struct is an ansi implementation for cursor related actions.
|
/// This struct is an ansi implementation for cursor related actions.
|
||||||
pub struct AnsiCursor;
|
pub struct AnsiCursor { }
|
||||||
|
|
||||||
impl AnsiCursor {
|
impl AnsiCursor
|
||||||
|
{
|
||||||
pub fn new() -> Box<AnsiCursor> {
|
pub fn new() -> Box<AnsiCursor> {
|
||||||
Box::from(AnsiCursor {})
|
Box::from(AnsiCursor { })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ITerminalCursor for AnsiCursor {
|
impl ITerminalCursor for AnsiCursor {
|
||||||
fn goto(&self, x: u16, y: u16, stdout: &Arc<TerminalOutput>) {
|
fn goto(&self, x: u16, y: u16, stdout: &Option<&Arc<TerminalOutput>>) {
|
||||||
stdout.write_string(format!(csi!("{};{}H"), y + 1, x + 1));
|
functions::write(stdout, format!(csi!("{};{}H"), y + 1, x + 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
fn pos(&self, stdout: &Arc<TerminalOutput>) -> (u16, u16) {
|
fn pos(&self) -> (u16, u16) {
|
||||||
functions::get_cursor_position(stdout)
|
functions::get_cursor_position()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn move_up(&self, count: u16, stdout: &Arc<TerminalOutput>) {
|
fn move_up(&self, count: u16, stdout: &Option<&Arc<TerminalOutput>>) {
|
||||||
stdout.write_string(format!(csi!("{}A"), count));
|
functions::write(stdout, format!(csi!("{}A"), count));
|
||||||
}
|
}
|
||||||
|
|
||||||
fn move_right(&self, count: u16, stdout: &Arc<TerminalOutput>) {
|
fn move_right(&self, count: u16, stdout: &Option<&Arc<TerminalOutput>>) {
|
||||||
stdout.write_string(format!(csi!("{}C"), count));
|
functions::write(stdout, format!(csi!("{}C"), count));
|
||||||
}
|
}
|
||||||
|
|
||||||
fn move_down(&self, count: u16, stdout: &Arc<TerminalOutput>) {
|
fn move_down(&self, count: u16, stdout: &Option<&Arc<TerminalOutput>>) {
|
||||||
stdout.write_string(format!(csi!("{}B"), count));
|
functions::write(stdout, format!(csi!("{}B"), count));
|
||||||
}
|
}
|
||||||
|
|
||||||
fn move_left(&self, count: u16, stdout: &Arc<TerminalOutput>) {
|
fn move_left(&self, count: u16, stdout: &Option<&Arc<TerminalOutput>>) {
|
||||||
stdout.write_string(format!(csi!("{}D"), count));
|
functions::write(stdout, format!(csi!("{}D"), count));
|
||||||
}
|
}
|
||||||
|
|
||||||
fn save_position(&self, stdout: &Arc<TerminalOutput>) {
|
fn save_position(&self, stdout: &Option<&Arc<TerminalOutput>>) {
|
||||||
stdout.write_str(csi!("s"));
|
functions::write_str(stdout, csi!("s"));
|
||||||
}
|
}
|
||||||
|
|
||||||
fn reset_position(&self, stdout: &Arc<TerminalOutput>) {
|
fn reset_position(&self, stdout: &Option<&Arc<TerminalOutput>>) {
|
||||||
stdout.write_str(csi!("u"));
|
functions::write_str(stdout, csi!("u"));
|
||||||
}
|
}
|
||||||
|
|
||||||
fn hide(&self, stdout: &Arc<TerminalOutput>) {
|
fn hide(&self, stdout: &Option<&Arc<TerminalOutput>>) {
|
||||||
stdout.write_str(csi!("?25l"));
|
functions::write_str(stdout, csi!("?25l"));
|
||||||
}
|
}
|
||||||
|
|
||||||
fn show(&self, stdout: &Arc<TerminalOutput>) {
|
fn show(&self, stdout: &Option<&Arc<TerminalOutput>>) {
|
||||||
stdout.write_str(csi!("?25h"));
|
functions::write_str(stdout, csi!("?25h"));
|
||||||
}
|
}
|
||||||
|
|
||||||
fn blink(&self, blink: bool, stdout: &Arc<TerminalOutput>) {
|
fn blink(&self, blink: bool, stdout: &Option<&Arc<TerminalOutput>>) {
|
||||||
if blink {
|
if blink {
|
||||||
stdout.write_str(csi!("?12h"));
|
functions::write_str(stdout, csi!("?12h"));
|
||||||
} else {
|
} else {
|
||||||
stdout.write_str(csi!("?12l"));
|
functions::write_str(stdout, csi!("?12l"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -15,8 +15,7 @@ use Screen;
|
|||||||
/// use self::crossterm::cursor;
|
/// use self::crossterm::cursor;
|
||||||
/// use self::crossterm::Screen;
|
/// use self::crossterm::Screen;
|
||||||
///
|
///
|
||||||
/// let screen = Screen::default();
|
/// let mut cursor = cursor();
|
||||||
/// let mut cursor = cursor(&screen);
|
|
||||||
///
|
///
|
||||||
/// // Get cursor and goto pos X: 5, Y: 10
|
/// // Get cursor and goto pos X: 5, Y: 10
|
||||||
/// cursor.goto(5,10);
|
/// cursor.goto(5,10);
|
||||||
@ -26,14 +25,17 @@ use Screen;
|
|||||||
/// cursor.blink(true);
|
/// cursor.blink(true);
|
||||||
/// cursor.move_left(2);
|
/// cursor.move_left(2);
|
||||||
/// ```
|
/// ```
|
||||||
|
///
|
||||||
|
/// When you want to use 'cursor' on 'alternate screen' use the `Screen` type instead and pass it to the `cursor::from_screen()` function.
|
||||||
|
/// By doing that cursor actions will be performed on the alternate screen.
|
||||||
pub struct TerminalCursor<'stdout> {
|
pub struct TerminalCursor<'stdout> {
|
||||||
screen: &'stdout Arc<TerminalOutput>,
|
|
||||||
terminal_cursor: Box<ITerminalCursor + Sync + Send>,
|
terminal_cursor: Box<ITerminalCursor + Sync + Send>,
|
||||||
|
stdout: Option<&'stdout Arc<TerminalOutput>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'stdout> TerminalCursor<'stdout> {
|
impl<'stdout> TerminalCursor <'stdout>{
|
||||||
/// Create new cursor instance whereon cursor related actions can be performed.
|
/// Create new cursor instance whereon cursor related actions can be performed.
|
||||||
pub fn new(screen: &'stdout Arc<TerminalOutput>) -> TerminalCursor<'stdout> {
|
pub fn new() -> TerminalCursor<'stdout> {
|
||||||
#[cfg(target_os = "windows")]
|
#[cfg(target_os = "windows")]
|
||||||
let cursor =
|
let cursor =
|
||||||
functions::get_module::<Box<ITerminalCursor + Sync + Send>>(WinApiCursor::new(), AnsiCursor::new())
|
functions::get_module::<Box<ITerminalCursor + Sync + Send>>(WinApiCursor::new(), AnsiCursor::new())
|
||||||
@ -44,90 +46,99 @@ impl<'stdout> TerminalCursor<'stdout> {
|
|||||||
|
|
||||||
TerminalCursor {
|
TerminalCursor {
|
||||||
terminal_cursor: cursor,
|
terminal_cursor: cursor,
|
||||||
screen: screen,
|
stdout: None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn on_screen(stdout: &'stdout Arc<TerminalOutput>) -> TerminalCursor<'stdout> {
|
||||||
|
#[cfg(target_os = "windows")]
|
||||||
|
let cursor =
|
||||||
|
functions::get_module::<Box<ITerminalCursor + Sync + Send>>(WinApiCursor::new(), AnsiCursor::new())
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
#[cfg(not(target_os = "windows"))]
|
||||||
|
let cursor = AnsiCursor::new() as Box<ITerminalCursor + Sync + Send>;
|
||||||
|
|
||||||
|
TerminalCursor {
|
||||||
|
terminal_cursor: cursor,
|
||||||
|
stdout: Some(stdout),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Goto some position (x,y) in the terminal.
|
/// Goto some position (x,y) in the terminal.
|
||||||
///
|
///
|
||||||
/// ```rust
|
/// ```rust
|
||||||
/// let screen = Screen::default();
|
/// let cursor = cursor();
|
||||||
/// let cursor = cursor(&screen);
|
|
||||||
///
|
///
|
||||||
/// // change the cursor to position, x: 4 and y: 5
|
/// // change the cursor to position, x: 4 and y: 5
|
||||||
/// cursor.goto(4,5);
|
/// cursor.goto(4,5);
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
pub fn goto(&self, x: u16, y: u16) {
|
pub fn goto(&self, x: u16, y: u16) {
|
||||||
self.terminal_cursor.goto(x, y, &self.screen);
|
self.terminal_cursor.goto(x, y, &self.stdout);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get current cursor position (x,y) in the terminal.
|
/// Get current cursor position (x,y) in the terminal.
|
||||||
///
|
///
|
||||||
/// ```rust
|
/// ```rust
|
||||||
/// let screen = Screen::default();
|
/// let cursor = cursor();
|
||||||
/// let cursor = cursor(&screen);
|
|
||||||
///
|
///
|
||||||
/// // get the current cursor pos
|
/// // get the current cursor pos
|
||||||
/// let (x,y) = cursor.pos();
|
/// let (x,y) = cursor.pos();
|
||||||
/// ```
|
/// ```
|
||||||
pub fn pos(&self) -> (u16, u16) {
|
pub fn pos(&self) -> (u16, u16) {
|
||||||
self.terminal_cursor.pos(&self.screen)
|
self.terminal_cursor.pos()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Move the current cursor position `n` times up.
|
/// Move the current cursor position `n` times up.
|
||||||
///
|
///
|
||||||
/// ```rust
|
/// ```rust
|
||||||
/// let screen = Screen::default();
|
/// let cursor = cursor();
|
||||||
/// let cursor = cursor(&screen);
|
|
||||||
///
|
///
|
||||||
/// // Move the cursor to position 3 times to the up in the terminal
|
/// // Move the cursor to position 3 times to the up in the terminal
|
||||||
/// cursor.move_up(3);
|
/// cursor.move_up(3);
|
||||||
/// ```
|
/// ```
|
||||||
pub fn move_up(&mut self, count: u16) -> &mut TerminalCursor<'stdout> {
|
pub fn move_up(&mut self, count: u16) -> &mut TerminalCursor<'stdout> {
|
||||||
self.terminal_cursor.move_up(count, &self.screen);
|
self.terminal_cursor.move_up(count, &self.stdout);
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Move the current cursor position `n` times right.
|
/// Move the current cursor position `n` times right.
|
||||||
///
|
///
|
||||||
/// ```rust
|
/// ```rust
|
||||||
/// let screen = Screen::default();
|
/// let cursor = cursor();
|
||||||
/// let cursor = cursor(&screen);
|
|
||||||
///
|
///
|
||||||
/// // Move the cursor to position 3 times to the right in the terminal
|
/// // Move the cursor to position 3 times to the right in the terminal
|
||||||
/// cursor.move_right(3);
|
/// cursor.move_right(3);
|
||||||
/// ```
|
/// ```
|
||||||
pub fn move_right(&mut self, count: u16) -> &mut TerminalCursor<'stdout> {
|
pub fn move_right(&mut self, count: u16) -> &mut TerminalCursor<'stdout> {
|
||||||
self.terminal_cursor.move_right(count, &self.screen);
|
self.terminal_cursor.move_right(count, &self.stdout);
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Move the current cursor position `n` times down.
|
/// Move the current cursor position `n` times down.
|
||||||
///
|
///
|
||||||
/// ```rust
|
/// ```rust
|
||||||
/// let screen = Screen::default();
|
/// let cursor = cursor();
|
||||||
/// let cursor = cursor(&screen);
|
|
||||||
///
|
///
|
||||||
/// // Move the cursor to position 3 times to the down in the terminal
|
/// // Move the cursor to position 3 times to the down in the terminal
|
||||||
/// cursor.move_down(3);
|
/// cursor.move_down(3);
|
||||||
/// ```
|
/// ```
|
||||||
pub fn move_down(&mut self, count: u16) -> &mut TerminalCursor<'stdout> {
|
pub fn move_down(&mut self, count: u16) -> &mut TerminalCursor<'stdout> {
|
||||||
self.terminal_cursor.move_down(count, &self.screen);
|
self.terminal_cursor.move_down(count, &self.stdout);
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Move the current cursor position `n` times left.
|
/// Move the current cursor position `n` times left.
|
||||||
///
|
///
|
||||||
/// ```rust
|
/// ```rust
|
||||||
/// let screen = Screen::default();
|
/// let cursor = cursor();
|
||||||
/// let cursor = cursor(&screen);
|
|
||||||
///
|
///
|
||||||
/// // Move the cursor to position 3 times to the left in the terminal
|
/// // Move the cursor to position 3 times to the left in the terminal
|
||||||
/// cursor.move_left(3);
|
/// cursor.move_left(3);
|
||||||
/// ```
|
/// ```
|
||||||
pub fn move_left(&mut self, count: u16) -> &mut TerminalCursor<'stdout> {
|
pub fn move_left(&mut self, count: u16) -> &mut TerminalCursor<'stdout> {
|
||||||
self.terminal_cursor.move_left(count, &self.screen);
|
self.terminal_cursor.move_left(count, &self.stdout);
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -136,13 +147,12 @@ impl<'stdout> TerminalCursor<'stdout> {
|
|||||||
/// Note that this position is stored program based not per instance of the `Cursor` struct.
|
/// Note that this position is stored program based not per instance of the `Cursor` struct.
|
||||||
///
|
///
|
||||||
/// ```rust
|
/// ```rust
|
||||||
/// let screen = Screen::default();
|
/// let cursor = cursor();
|
||||||
/// let cursor = cursor(&screen);
|
|
||||||
///
|
///
|
||||||
/// cursor.safe_position();
|
/// cursor.safe_position();
|
||||||
/// ```
|
/// ```
|
||||||
pub fn save_position(&self) {
|
pub fn save_position(&self) {
|
||||||
self.terminal_cursor.save_position(&self.screen);
|
self.terminal_cursor.save_position(&self.stdout);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return to saved cursor position
|
/// Return to saved cursor position
|
||||||
@ -150,36 +160,34 @@ impl<'stdout> TerminalCursor<'stdout> {
|
|||||||
/// Note that this method reset to the position set by `save_position()` and that this position is stored program based not per instance of the `Cursor` struct.
|
/// Note that this method reset to the position set by `save_position()` and that this position is stored program based not per instance of the `Cursor` struct.
|
||||||
///
|
///
|
||||||
/// ```rust
|
/// ```rust
|
||||||
/// let screen = Screen::default();
|
/// let cursor = cursor();
|
||||||
/// let cursor = cursor(&screen);
|
|
||||||
///
|
///
|
||||||
/// cursor.reset_position();
|
/// cursor.reset_position();
|
||||||
/// ```
|
/// ```
|
||||||
pub fn reset_position(&self) {
|
pub fn reset_position(&self) {
|
||||||
self.terminal_cursor.reset_position(&self.screen);
|
self.terminal_cursor.reset_position(&self.stdout);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Hide de cursor in the console.
|
/// Hide de cursor in the console.
|
||||||
///
|
///
|
||||||
/// ```rust
|
/// ```rust
|
||||||
/// let cursor = cursor(&Screen::default());
|
/// let cursor = cursor();
|
||||||
/// cursor.hide();
|
/// cursor.hide();
|
||||||
/// ```
|
/// ```
|
||||||
pub fn hide(&self) {
|
pub fn hide(&self) {
|
||||||
self.terminal_cursor.hide(&self.screen);
|
self.terminal_cursor.hide(&self.stdout);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Show the cursor in the console.
|
/// Show the cursor in the console.
|
||||||
///
|
///
|
||||||
/// ```rust
|
/// ```rust
|
||||||
///
|
///
|
||||||
/// let screen = Screen::default();
|
/// let cursor = cursor();
|
||||||
/// let cursor = cursor(&screen);
|
|
||||||
/// cursor.show();
|
/// cursor.show();
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
pub fn show(&self) {
|
pub fn show(&self) {
|
||||||
self.terminal_cursor.show(&self.screen);
|
self.terminal_cursor.show(&self.stdout);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Enable or disable blinking of the terminal.
|
/// Enable or disable blinking of the terminal.
|
||||||
@ -187,18 +195,22 @@ impl<'stdout> TerminalCursor<'stdout> {
|
|||||||
/// Not all terminals are supporting this functionality. Windows versions lower than windows 10 also are not supporting this version.
|
/// Not all terminals are supporting this functionality. Windows versions lower than windows 10 also are not supporting this version.
|
||||||
///
|
///
|
||||||
/// ```rust
|
/// ```rust
|
||||||
/// let screen = Screen::default();
|
/// let cursor = cursor();
|
||||||
/// let cursor = cursor(&screen);
|
|
||||||
/// cursor.blink(true);
|
/// cursor.blink(true);
|
||||||
/// cursor.blink(false);
|
/// cursor.blink(false);
|
||||||
/// ```
|
/// ```
|
||||||
pub fn blink(&self, blink: bool) {
|
pub fn blink(&self, blink: bool) {
|
||||||
self.terminal_cursor.blink(blink, &self.screen);
|
self.terminal_cursor.blink(blink, &self.stdout);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get an TerminalCursor implementation whereon cursor related actions can be performed.
|
/// Get an TerminalCursor implementation whereon cursor related actions can be performed.
|
||||||
/// Pass the reference to any screen you want this type to perform actions on.
|
pub fn cursor() -> TerminalCursor<'static> {
|
||||||
pub fn cursor<'stdout>(stdout: &'stdout Screen) -> TerminalCursor<'stdout> {
|
TerminalCursor::new()
|
||||||
TerminalCursor::new(&stdout.stdout)
|
}
|
||||||
|
|
||||||
|
/// Get an TerminalCursor implementation whereon cursor related actions can be performed.
|
||||||
|
/// Pass the reference to any screen you want this type to perform actions on.
|
||||||
|
pub fn from_screen<'stdout>(screen: &'stdout Screen) -> TerminalCursor<'stdout> {
|
||||||
|
TerminalCursor::on_screen(&screen.stdout)
|
||||||
}
|
}
|
||||||
|
@ -14,7 +14,7 @@ use self::ansi_cursor::AnsiCursor;
|
|||||||
#[cfg(target_os = "windows")]
|
#[cfg(target_os = "windows")]
|
||||||
use self::winapi_cursor::WinApiCursor;
|
use self::winapi_cursor::WinApiCursor;
|
||||||
|
|
||||||
pub use self::cursor::{cursor, TerminalCursor};
|
pub use self::cursor::{cursor, from_screen, TerminalCursor};
|
||||||
|
|
||||||
use super::functions;
|
use super::functions;
|
||||||
use TerminalOutput;
|
use TerminalOutput;
|
||||||
@ -30,25 +30,25 @@ use std::sync::Arc;
|
|||||||
///! so that cursor related actions can be preformed on both unix and windows systems.
|
///! so that cursor related actions can be preformed on both unix and windows systems.
|
||||||
trait ITerminalCursor : Sync + Send {
|
trait ITerminalCursor : Sync + Send {
|
||||||
/// Goto some location (x,y) in the context.
|
/// Goto some location (x,y) in the context.
|
||||||
fn goto(&self, x: u16, y: u16, stdout: &Arc<TerminalOutput>);
|
fn goto(&self, x: u16, y: u16, stdout: &Option<&Arc<TerminalOutput>>);
|
||||||
/// Get the location (x,y) of the current cusror in the context
|
/// Get the location (x,y) of the current cusror in the context
|
||||||
fn pos(&self, stdout: &Arc<TerminalOutput>) -> (u16, u16);
|
fn pos(&self) -> (u16, u16);
|
||||||
/// Move cursor n times up
|
/// Move cursor n times up
|
||||||
fn move_up(&self, count: u16, stdout: &Arc<TerminalOutput>);
|
fn move_up(&self, count: u16,stdout: &Option<&Arc<TerminalOutput>>);
|
||||||
/// Move the cursor `n` times to the right.
|
/// Move the cursor `n` times to the right.
|
||||||
fn move_right(&self, count: u16, stdout: &Arc<TerminalOutput>);
|
fn move_right(&self, count: u16,stdout: &Option<&Arc<TerminalOutput>>);
|
||||||
/// Move the cursor `n` times down.
|
/// Move the cursor `n` times down.
|
||||||
fn move_down(&self, count: u16, stdout: &Arc<TerminalOutput>);
|
fn move_down(&self, count: u16,stdout: &Option<&Arc<TerminalOutput>>);
|
||||||
/// Move the cursor `n` times left.
|
/// Move the cursor `n` times left.
|
||||||
fn move_left(&self, count: u16, stdout: &Arc<TerminalOutput>);
|
fn move_left(&self, count: u16,stdout: &Option<&Arc<TerminalOutput>>);
|
||||||
/// Save cursor position so that its saved position can be recalled later. Note that this position is stored program based not per instance of the cursor struct.
|
/// Save cursor position so that its saved position can be recalled later. Note that this position is stored program based not per instance of the cursor struct.
|
||||||
fn save_position(&self, stdout: &Arc<TerminalOutput>);
|
fn save_position(&self,stdout: &Option<&Arc<TerminalOutput>>);
|
||||||
/// Return to saved cursor position
|
/// Return to saved cursor position
|
||||||
fn reset_position(&self, stdout: &Arc<TerminalOutput>);
|
fn reset_position(&self,stdout: &Option<&Arc<TerminalOutput>>);
|
||||||
/// Hide the terminal cursor.
|
/// Hide the terminal cursor.
|
||||||
fn hide(&self, stdout: &Arc<TerminalOutput>);
|
fn hide(&self,stdout: &Option<&Arc<TerminalOutput>>);
|
||||||
/// Show the terminal cursor
|
/// Show the terminal cursor
|
||||||
fn show(&self, stdout: &Arc<TerminalOutput>);
|
fn show(&self,stdout: &Option<&Arc<TerminalOutput>>);
|
||||||
/// Enable or disable the blinking of the cursor.
|
/// Enable or disable the blinking of the cursor.
|
||||||
fn blink(&self, blink: bool, stdout: &Arc<TerminalOutput>);
|
fn blink(&self, blink: bool,stdout: &Option<&Arc<TerminalOutput>>);
|
||||||
}
|
}
|
||||||
|
@ -14,10 +14,11 @@ mod winapi_tests {
|
|||||||
fn goto_winapi()
|
fn goto_winapi()
|
||||||
{
|
{
|
||||||
let screen = Screen::default();
|
let screen = Screen::default();
|
||||||
|
let stdout = Some(&screen.stdout);
|
||||||
let cursor = WinApiCursor::new();
|
let cursor = WinApiCursor::new();
|
||||||
|
|
||||||
cursor.goto(5, 5, &screen.stdout);
|
cursor.goto(5, 5,&stdout);
|
||||||
let (x, y) = cursor.pos(&screen.stdout);
|
let (x, y) = cursor.pos();
|
||||||
|
|
||||||
assert_eq!(x, 5);
|
assert_eq!(x, 5);
|
||||||
assert_eq!(y, 5);
|
assert_eq!(y, 5);
|
||||||
@ -27,14 +28,15 @@ mod winapi_tests {
|
|||||||
fn reset_safe_winapi()
|
fn reset_safe_winapi()
|
||||||
{
|
{
|
||||||
let screen = Screen::default();
|
let screen = Screen::default();
|
||||||
|
let stdout = Some(&screen.stdout);
|
||||||
let cursor = WinApiCursor::new();
|
let cursor = WinApiCursor::new();
|
||||||
let (x, y) = cursor.pos(&screen.stdout);
|
let (x, y) = cursor.pos();
|
||||||
|
|
||||||
cursor.save_position(&screen.stdout);
|
cursor.save_position(&stdout);
|
||||||
cursor.goto(5, 5, &screen.stdout);
|
cursor.goto(5, 5,&stdout);
|
||||||
cursor.reset_position(&screen.stdout);
|
cursor.reset_position(&stdout);
|
||||||
|
|
||||||
let (x_saved, y_saved) = cursor.pos(&screen.stdout);
|
let (x_saved, y_saved) = cursor.pos();
|
||||||
|
|
||||||
assert_eq!(x, x_saved);
|
assert_eq!(x, x_saved);
|
||||||
assert_eq!(y, y_saved);
|
assert_eq!(y, y_saved);
|
||||||
@ -47,14 +49,15 @@ fn reset_safe_ansi()
|
|||||||
{
|
{
|
||||||
if try_enable_ansi() {
|
if try_enable_ansi() {
|
||||||
let screen = Screen::default();
|
let screen = Screen::default();
|
||||||
|
let stdout = Some(&screen.stdout);
|
||||||
let cursor = AnsiCursor::new();
|
let cursor = AnsiCursor::new();
|
||||||
let (x, y) = cursor.pos(&screen.stdout);
|
let (x, y) = cursor.pos();
|
||||||
|
|
||||||
cursor.save_position(&screen.stdout);
|
cursor.save_position(&stdout);
|
||||||
cursor.goto(5, 5,&screen.stdout);
|
cursor.goto(5, 5,&stdout);
|
||||||
cursor.reset_position(&screen.stdout);
|
cursor.reset_position(&stdout);
|
||||||
|
|
||||||
let (x_saved, y_saved) = cursor.pos(&screen.stdout);
|
let (x_saved, y_saved) = cursor.pos();
|
||||||
|
|
||||||
assert_eq!(x, x_saved);
|
assert_eq!(x, x_saved);
|
||||||
assert_eq!(y, y_saved);
|
assert_eq!(y, y_saved);
|
||||||
@ -66,10 +69,11 @@ fn goto_ansi()
|
|||||||
{
|
{
|
||||||
if try_enable_ansi() {
|
if try_enable_ansi() {
|
||||||
let screen = Screen::default();
|
let screen = Screen::default();
|
||||||
|
let stdout = Some(&screen.stdout);
|
||||||
let cursor = AnsiCursor::new();
|
let cursor = AnsiCursor::new();
|
||||||
|
|
||||||
cursor.goto(5, 5, &screen.stdout);
|
cursor.goto(5, 5,&stdout);
|
||||||
let (x, y) = cursor.pos(&screen.stdout);
|
let (x, y) = cursor.pos();
|
||||||
|
|
||||||
assert_eq!(x, 5);
|
assert_eq!(x, 5);
|
||||||
assert_eq!(y, 5);
|
assert_eq!(y, 5);
|
||||||
|
@ -16,48 +16,49 @@ impl WinApiCursor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl ITerminalCursor for WinApiCursor {
|
impl ITerminalCursor for WinApiCursor {
|
||||||
fn goto(&self, x: u16, y: u16, stdout: &Arc<TerminalOutput>) {
|
fn goto(&self, x: u16, y: u16,_stdout: &Option<&Arc<TerminalOutput>>) {
|
||||||
cursor::set_console_cursor_position(x as i16, y as i16);
|
cursor::set_console_cursor_position(x as i16, y as i16);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn pos(&self, stdout: &Arc<TerminalOutput>) -> (u16, u16) {
|
fn pos(&self) -> (u16, u16) {
|
||||||
cursor::pos()
|
cursor::pos()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn move_up(&self, count: u16, stdout: &Arc<TerminalOutput>) {
|
fn move_up(&self, count: u16,_stdout: &Option<&Arc<TerminalOutput>>) {
|
||||||
let (xpos, ypos) = self.pos(stdout);
|
let (xpos, ypos) = self.pos();
|
||||||
self.goto(xpos, ypos - count, stdout);
|
self.goto(xpos, ypos - count, _stdout);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn move_right(&self, count: u16, stdout: &Arc<TerminalOutput>) {
|
fn move_right(&self, count: u16,_stdout: &Option<&Arc<TerminalOutput>>) {
|
||||||
let (xpos, ypos) = self.pos(stdout);
|
let (xpos, ypos) = self.pos();
|
||||||
self.goto(xpos + count, ypos, stdout);
|
self.goto(xpos + count, ypos, _stdout);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn move_down(&self, count: u16, stdout: &Arc<TerminalOutput>) {
|
fn move_down(&self, count: u16,_stdout: &Option<&Arc<TerminalOutput>>) {
|
||||||
let (xpos, ypos) = self.pos(stdout);
|
let (xpos, ypos) = self.pos();
|
||||||
self.goto(xpos, ypos + count, stdout);
|
self.goto(xpos, ypos + count, _stdout);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn move_left(&self, count: u16, stdout: &Arc<TerminalOutput>) {
|
fn move_left(&self, count: u16,_stdout: &Option<&Arc<TerminalOutput>>) {
|
||||||
let (xpos, ypos) = self.pos(stdout);
|
let (xpos, ypos) = self.pos();
|
||||||
self.goto(xpos - count, ypos, stdout);
|
self.goto(xpos - count, ypos, _stdout);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn save_position(&self, stdout: &Arc<TerminalOutput>) {
|
fn save_position(&self,_stdout: &Option<&Arc<TerminalOutput>>) {
|
||||||
cursor::save_cursor_pos();
|
cursor::save_cursor_pos();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn reset_position(&self, stdout: &Arc<TerminalOutput>) {
|
fn reset_position(&self,_stdout: &Option<&Arc<TerminalOutput>>) {
|
||||||
cursor::reset_to_saved_position();
|
cursor::reset_to_saved_position();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn hide(&self, stdout: &Arc<TerminalOutput>) {
|
fn hide(&self,_stdout: &Option<&Arc<TerminalOutput>>) {
|
||||||
cursor::cursor_visibility(false);
|
cursor::cursor_visibility(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn show(&self, stdout: &Arc<TerminalOutput>) {
|
fn show(&self,_stdout: &Option<&Arc<TerminalOutput>>) {
|
||||||
cursor::cursor_visibility(true);
|
cursor::cursor_visibility(true);
|
||||||
}
|
}
|
||||||
fn blink(&self, blink: bool, stdout: &Arc<TerminalOutput>) {}
|
|
||||||
|
fn blink(&self, blink: bool,_stdout: &Option<&Arc<TerminalOutput>>) {}
|
||||||
}
|
}
|
||||||
|
@ -13,20 +13,26 @@ use Screen;
|
|||||||
/// use self::crossterm::Screen;
|
/// use self::crossterm::Screen;
|
||||||
/// use self::crossterm::input;
|
/// use self::crossterm::input;
|
||||||
///
|
///
|
||||||
/// let screen = Screen::default();
|
/// let input = input();
|
||||||
/// let input = input(&screen);
|
|
||||||
/// let result = input.read_line();
|
/// let result = input.read_line();
|
||||||
/// let pressed_char = input.read_char();
|
/// let pressed_char = input.read_char();
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
|
///
|
||||||
|
/// **!! Take note when using input with raw mode you should use the `Screen` type. !!**
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// let screen = Screen::new(true);
|
||||||
|
/// let input = crossterm::input::from_screen(&screen);///
|
||||||
|
/// ```
|
||||||
pub struct TerminalInput<'stdout> {
|
pub struct TerminalInput<'stdout> {
|
||||||
terminal_input: Box<ITerminalInput + Sync + Send>,
|
terminal_input: Box<ITerminalInput + Sync + Send>,
|
||||||
stdout: &'stdout Arc<TerminalOutput>,
|
stdout: Option<&'stdout Arc<TerminalOutput>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'stdout> TerminalInput<'stdout> {
|
impl<'stdout> TerminalInput<'stdout> {
|
||||||
/// Create new instance of TerminalInput whereon input related actions could be preformed.
|
/// Create new instance of TerminalInput whereon input related actions could be preformed.
|
||||||
pub fn new(stdout: &'stdout Arc<TerminalOutput>) -> TerminalInput<'stdout> {
|
pub fn new() -> TerminalInput<'stdout> {
|
||||||
#[cfg(target_os = "windows")]
|
#[cfg(target_os = "windows")]
|
||||||
let input = Box::from(WindowsInput::new());
|
let input = Box::from(WindowsInput::new());
|
||||||
|
|
||||||
@ -35,15 +41,28 @@ impl<'stdout> TerminalInput<'stdout> {
|
|||||||
|
|
||||||
TerminalInput {
|
TerminalInput {
|
||||||
terminal_input: input,
|
terminal_input: input,
|
||||||
stdout: stdout,
|
stdout: None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Create new instance of TerminalInput whereon input related actions could be preformed.
|
||||||
|
pub fn on_screen(stdout: &'stdout Arc<TerminalOutput>) -> TerminalInput<'stdout> {
|
||||||
|
#[cfg(target_os = "windows")]
|
||||||
|
let input = Box::from(WindowsInput::new());
|
||||||
|
|
||||||
|
#[cfg(not(target_os = "windows"))]
|
||||||
|
let input = Box::from(UnixInput::new());
|
||||||
|
|
||||||
|
TerminalInput {
|
||||||
|
terminal_input: input,
|
||||||
|
stdout: Some(stdout),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Read one line from the user input.
|
/// Read one line from the user input.
|
||||||
///
|
///
|
||||||
/// ```rust
|
/// ```rust
|
||||||
/// let screen = Screen::default();
|
/// let input = input();
|
||||||
/// let input = input(&screen);
|
|
||||||
/// match input.read_line() {
|
/// match input.read_line() {
|
||||||
/// Ok(s) => println!("string typed: {}", s),
|
/// Ok(s) => println!("string typed: {}", s),
|
||||||
/// Err(e) => println!("error: {}", e),
|
/// Err(e) => println!("error: {}", e),
|
||||||
@ -56,8 +75,7 @@ impl<'stdout> TerminalInput<'stdout> {
|
|||||||
/// Read one character from the user input
|
/// Read one character from the user input
|
||||||
///
|
///
|
||||||
/// ```rust
|
/// ```rust
|
||||||
/// let screen = Screen::default();
|
/// let input = input();
|
||||||
/// let input = input(&screen);
|
|
||||||
///
|
///
|
||||||
/// match input.read_char() {
|
/// match input.read_char() {
|
||||||
/// Ok(c) => println!("character pressed: {}", c),
|
/// Ok(c) => println!("character pressed: {}", c),
|
||||||
@ -71,12 +89,12 @@ impl<'stdout> TerminalInput<'stdout> {
|
|||||||
/// Read the input asynchronously from the user.
|
/// Read the input asynchronously from the user.
|
||||||
///
|
///
|
||||||
/// This call will not block the current thread.
|
/// This call will not block the current thread.
|
||||||
// Under the hood a thread is fired which will read input on unix systems from TTY and on windows systems with '_getwch' and '_getwche'
|
/// Under the hood a thread is fired which will read input on unix systems from TTY and on windows systems with '_getwch' and '_getwche'
|
||||||
///
|
///
|
||||||
/// ```rust
|
/// ```rust
|
||||||
/// // we need to enable raw mode otherwise the characters will be outputted by default before we are able to read them.
|
/// // we need to enable raw mode otherwise the characters will be outputted by default before we are able to read them.
|
||||||
/// let screen = Screen::new(true);
|
/// let screen = Screen::new(true);
|
||||||
/// let input = input(&screen);
|
/// let input = crossterm::input::from_screen(&screen);
|
||||||
///
|
///
|
||||||
/// let mut stdin = input.read_async().bytes();
|
/// let mut stdin = input.read_async().bytes();
|
||||||
///
|
///
|
||||||
@ -108,12 +126,12 @@ impl<'stdout> TerminalInput<'stdout> {
|
|||||||
/// // we need to enable raw mode otherwise the characters will be outputted by default before we are able to read them.
|
/// // we need to enable raw mode otherwise the characters will be outputted by default before we are able to read them.
|
||||||
/// let screen = Screen::new(true);
|
/// let screen = Screen::new(true);
|
||||||
///
|
///
|
||||||
/// let crossterm = Crossterm::new(&screen);
|
/// // create an instance of `Crossterm` which will preform the actions on the raw screen.
|
||||||
|
/// let crossterm = Crossterm::from_screen(&screen);
|
||||||
/// let input = crossterm.input();
|
/// let input = crossterm.input();
|
||||||
/// let terminal = crossterm.terminal();
|
/// let terminal = crossterm.terminal();
|
||||||
/// let mut cursor = crossterm.cursor();
|
/// let mut cursor = crossterm.cursor();
|
||||||
///
|
///
|
||||||
///
|
|
||||||
/// let mut stdin = input.read_until_async(b'\r').bytes();
|
/// let mut stdin = input.read_until_async(b'\r').bytes();
|
||||||
///
|
///
|
||||||
/// for i in 0..100 {
|
/// for i in 0..100 {
|
||||||
@ -143,7 +161,12 @@ impl<'stdout> TerminalInput<'stdout> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Get an Terminal Input implementation whereon input related actions can be performed.
|
/// Get an Terminal Input implementation whereon input related actions can be performed.
|
||||||
/// Pass the reference to any screen you want this type to perform actions on.
|
pub fn input<'stdout>() -> TerminalInput<'stdout> {
|
||||||
pub fn input<'stdout>(stdout: &'stdout Screen) -> TerminalInput<'stdout> {
|
return TerminalInput::new();
|
||||||
return TerminalInput::new(&stdout.stdout);
|
}
|
||||||
|
|
||||||
|
/// Get an Terminal Input implementation whereon input related actions can be performed.
|
||||||
|
/// Pass the reference to any screen you want this type to perform actions on.
|
||||||
|
pub fn from_screen<'stdout>(screen: &'stdout Screen) -> TerminalInput<'stdout> {
|
||||||
|
TerminalInput::on_screen(&screen.stdout)
|
||||||
}
|
}
|
||||||
|
@ -30,13 +30,13 @@ use TerminalOutput;
|
|||||||
/// Unix is using the tty and windows is using libc C functions to read the input.
|
/// Unix is using the tty and windows is using libc C functions to read the input.
|
||||||
trait ITerminalInput {
|
trait ITerminalInput {
|
||||||
/// Read one line from the user input
|
/// Read one line from the user input
|
||||||
fn read_line(&self, screen_manger: &Arc<TerminalOutput>) -> io::Result<String>;
|
fn read_line(&self, stdout: &Option<&Arc<TerminalOutput>>) -> io::Result<String>;
|
||||||
/// Read one character from the user input
|
/// Read one character from the user input
|
||||||
fn read_char(&self, screen_manger: &Arc<TerminalOutput>) -> io::Result<char>;
|
fn read_char(&self, stdout: &Option<&Arc<TerminalOutput>>) -> io::Result<char>;
|
||||||
/// Read the input asynchronously from the user.
|
/// Read the input asynchronously from the user.
|
||||||
fn read_async(&self, screen_manger: &Arc<TerminalOutput>) -> AsyncReader;
|
fn read_async(&self, stdout: &Option<&Arc<TerminalOutput>>) -> AsyncReader;
|
||||||
/// Read the input asynchronously until a certain character is hit.
|
/// Read the input asynchronously until a certain character is hit.
|
||||||
fn read_until_async(&self, delimiter: u8, screen_manger: &Arc<TerminalOutput>) -> AsyncReader;
|
fn read_until_async(&self, delimiter: u8, stdout: &Option<&Arc<TerminalOutput>>) -> AsyncReader;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// This is a wrapper for reading from the input asynchronously.
|
/// This is a wrapper for reading from the input asynchronously.
|
||||||
|
@ -15,7 +15,7 @@ impl UnixInput {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl ITerminalInput for UnixInput {
|
impl ITerminalInput for UnixInput {
|
||||||
fn read_line(&self, _screen_manger: &Arc<TerminalOutput>) -> io::Result<String> {
|
fn read_line(&self, __stdout: &Option<&Arc<TerminalOutput>>) -> io::Result<String> {
|
||||||
let mut rv = String::new();
|
let mut rv = String::new();
|
||||||
io::stdin().read_line(&mut rv)?;
|
io::stdin().read_line(&mut rv)?;
|
||||||
let len = rv.trim_right_matches(&['\r', '\n'][..]).len();
|
let len = rv.trim_right_matches(&['\r', '\n'][..]).len();
|
||||||
@ -23,11 +23,11 @@ impl ITerminalInput for UnixInput {
|
|||||||
Ok(rv)
|
Ok(rv)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn read_char(&self, _screen_manger: &Arc<TerminalOutput>) -> io::Result<char> {
|
fn read_char(&self, __stdout: &Option<&Arc<TerminalOutput>>) -> io::Result<char> {
|
||||||
read_char()
|
read_char()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn read_async(&self, _screen_manger: &Arc<TerminalOutput>) -> AsyncReader {
|
fn read_async(&self, __stdout: &Option<&Arc<TerminalOutput>>) -> AsyncReader {
|
||||||
let (send, recv) = mpsc::channel();
|
let (send, recv) = mpsc::channel();
|
||||||
|
|
||||||
thread::spawn(move || {
|
thread::spawn(move || {
|
||||||
@ -41,7 +41,7 @@ impl ITerminalInput for UnixInput {
|
|||||||
AsyncReader { recv: recv }
|
AsyncReader { recv: recv }
|
||||||
}
|
}
|
||||||
|
|
||||||
fn read_until_async(&self, delimiter: u8, _screen_manger: &Arc<TerminalOutput>) -> AsyncReader {
|
fn read_until_async(&self, delimiter: u8, __stdout: &Option<&Arc<TerminalOutput>>) -> AsyncReader {
|
||||||
let (send, recv) = mpsc::channel();
|
let (send, recv) = mpsc::channel();
|
||||||
|
|
||||||
thread::spawn(move || {
|
thread::spawn(move || {
|
||||||
|
@ -16,11 +16,14 @@ impl WindowsInput {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl ITerminalInput for WindowsInput {
|
impl ITerminalInput for WindowsInput {
|
||||||
fn read_line(&self, screen_manger: &Arc<TerminalOutput>) -> io::Result<String> {
|
fn read_line(&self, stdout: &Option<&Arc<TerminalOutput>>) -> io::Result<String> {
|
||||||
let mut chars: Vec<char> = Vec::new();
|
let mut chars: Vec<char> = Vec::new();
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
let is_raw_screen = screen_manger.is_in_raw_mode;
|
let is_raw_screen = match stdout {
|
||||||
|
Some(output) => output.is_in_raw_mode,
|
||||||
|
None => false
|
||||||
|
};
|
||||||
|
|
||||||
// _getwch is without echo and _getwche is with echo
|
// _getwch is without echo and _getwche is with echo
|
||||||
let pressed_char = unsafe {
|
let pressed_char = unsafe {
|
||||||
@ -49,8 +52,11 @@ impl ITerminalInput for WindowsInput {
|
|||||||
return Ok(chars.into_iter().collect());
|
return Ok(chars.into_iter().collect());
|
||||||
}
|
}
|
||||||
|
|
||||||
fn read_char(&self, screen_manger: &Arc<TerminalOutput>) -> io::Result<char> {
|
fn read_char(&self, stdout: &Option<&Arc<TerminalOutput>>) -> io::Result<char> {
|
||||||
let is_raw_screen = screen_manger.is_in_raw_mode;
|
let is_raw_screen = match stdout {
|
||||||
|
Some(output) => output.is_in_raw_mode,
|
||||||
|
None => false
|
||||||
|
};
|
||||||
|
|
||||||
// _getwch is without echo and _getwche is with echo
|
// _getwch is without echo and _getwche is with echo
|
||||||
let pressed_char = unsafe {
|
let pressed_char = unsafe {
|
||||||
@ -80,10 +86,13 @@ impl ITerminalInput for WindowsInput {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn read_async(&self, screen_manger: &Arc<TerminalOutput>) -> AsyncReader {
|
fn read_async(&self, stdout: &Option<&Arc<TerminalOutput>>) -> AsyncReader {
|
||||||
let (tx, rx) = mpsc::channel();
|
let (tx, rx) = mpsc::channel();
|
||||||
|
|
||||||
let is_raw_screen = screen_manger.is_in_raw_mode;
|
let is_raw_screen = match stdout {
|
||||||
|
Some(output) => output.is_in_raw_mode,
|
||||||
|
None => false
|
||||||
|
};
|
||||||
|
|
||||||
thread::spawn(move || {
|
thread::spawn(move || {
|
||||||
loop {
|
loop {
|
||||||
@ -108,10 +117,13 @@ impl ITerminalInput for WindowsInput {
|
|||||||
AsyncReader { recv: rx }
|
AsyncReader { recv: rx }
|
||||||
}
|
}
|
||||||
|
|
||||||
fn read_until_async(&self, delimiter: u8, screen_manger: &Arc<TerminalOutput>) -> AsyncReader {
|
fn read_until_async(&self, delimiter: u8, stdout: &Option<&Arc<TerminalOutput>>) -> AsyncReader {
|
||||||
let (tx, rx) = mpsc::channel();
|
let (tx, rx) = mpsc::channel();
|
||||||
|
|
||||||
let is_raw_screen = screen_manger.is_in_raw_mode;
|
let is_raw_screen = match stdout {
|
||||||
|
Some(output) => output.is_in_raw_mode,
|
||||||
|
None => false
|
||||||
|
};
|
||||||
|
|
||||||
thread::spawn(move || {
|
thread::spawn(move || {
|
||||||
loop {
|
loop {
|
||||||
|
@ -22,6 +22,7 @@ use super::*;
|
|||||||
|
|
||||||
use std::any::Any;
|
use std::any::Any;
|
||||||
use std::default::Default;
|
use std::default::Default;
|
||||||
|
use std::io::Write;
|
||||||
use screen::RawScreen;
|
use screen::RawScreen;
|
||||||
|
|
||||||
/// Struct that is an handle to an terminal screen.
|
/// Struct that is an handle to an terminal screen.
|
||||||
@ -69,6 +70,16 @@ impl TerminalOutput {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Write for TerminalOutput {
|
||||||
|
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
|
||||||
|
self.write_buf(buf)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn flush(&mut self) -> io::Result<()> {
|
||||||
|
self.flush()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Default for TerminalOutput
|
impl Default for TerminalOutput
|
||||||
{
|
{
|
||||||
/// Get the default handle to the current screen.
|
/// Get the default handle to the current screen.
|
||||||
|
@ -15,7 +15,7 @@ impl WinApiOutput
|
|||||||
{
|
{
|
||||||
pub fn new() -> WinApiOutput
|
pub fn new() -> WinApiOutput
|
||||||
{
|
{
|
||||||
WinApiOutput {}
|
WinApiOutput
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -13,22 +13,22 @@ impl AnsiColor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl ITerminalColor for AnsiColor {
|
impl ITerminalColor for AnsiColor {
|
||||||
fn set_fg(&self, fg_color: Color, stdout: &Arc<TerminalOutput>) {
|
fn set_fg(&self, fg_color: Color, stdout: &Option<&Arc<TerminalOutput>>) {
|
||||||
stdout.write_string(format!(
|
functions::write(stdout,format!(
|
||||||
csi!("{}m"),
|
csi!("{}m"),
|
||||||
self.color_value(fg_color, ColorType::Foreground)
|
self.color_value(fg_color, ColorType::Foreground)
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_bg(&self, bg_color: Color, stdout: &Arc<TerminalOutput>) {
|
fn set_bg(&self, bg_color: Color, stdout: &Option<&Arc<TerminalOutput>>) {
|
||||||
stdout.write_string(format!(
|
functions::write(stdout,format!(
|
||||||
csi!("{}m"),
|
csi!("{}m"),
|
||||||
self.color_value(bg_color, ColorType::Background)
|
self.color_value(bg_color, ColorType::Background)
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
fn reset(&self, stdout: &Arc<TerminalOutput>) {
|
fn reset(&self, stdout: &Option<&Arc<TerminalOutput>>) {
|
||||||
stdout.write_str(csi!("0m"));
|
functions::write_str(stdout, csi!("0m"));
|
||||||
}
|
}
|
||||||
|
|
||||||
fn color_value(&self, color: Color, color_type: ColorType) -> String {
|
fn color_value(&self, color: Color, color_type: ColorType) -> String {
|
||||||
|
@ -13,11 +13,9 @@ use Screen;
|
|||||||
///
|
///
|
||||||
///
|
///
|
||||||
/// ```rust
|
/// ```rust
|
||||||
/// use crossterm::{Screen}
|
|
||||||
/// use crossterm::style::color;
|
/// use crossterm::style::color;
|
||||||
///
|
///
|
||||||
/// let screen = Screen::default();
|
/// let colored_terminal = color();
|
||||||
/// let colored_terminal = color(&screen);
|
|
||||||
///
|
///
|
||||||
/// // set foreground color
|
/// // set foreground color
|
||||||
/// colored_terminal.set_fg(Color::Red);
|
/// colored_terminal.set_fg(Color::Red);
|
||||||
@ -25,15 +23,18 @@ use Screen;
|
|||||||
/// colored_terminal.set_bg(Color::Red);
|
/// colored_terminal.set_bg(Color::Red);
|
||||||
/// // reset color to default
|
/// // reset color to default
|
||||||
/// colored_terminal.reset();
|
/// colored_terminal.reset();
|
||||||
|
///
|
||||||
|
/// When you want to use 'color' on 'alternate screen' use the `Screen` type instead and pass it to the `color::from_screen()` function.
|
||||||
|
/// By doing that styling actions will be performed on the alternate screen.
|
||||||
/// ```
|
/// ```
|
||||||
pub struct TerminalColor<'stdout> {
|
pub struct TerminalColor<'stdout> {
|
||||||
color: Box<ITerminalColor + Sync + Send>,
|
color: Box<ITerminalColor + Sync + Send>,
|
||||||
stdout: &'stdout Arc<TerminalOutput>,
|
stdout: Option<&'stdout Arc<TerminalOutput>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'stdout> TerminalColor<'stdout> {
|
impl<'stdout> TerminalColor<'stdout> {
|
||||||
/// Create new instance whereon color related actions can be performed.
|
/// Create new instance whereon color related actions can be performed.
|
||||||
pub fn new(stdout: &'stdout Arc<TerminalOutput>) -> TerminalColor<'stdout> {
|
pub fn new() -> TerminalColor<'stdout> {
|
||||||
#[cfg(target_os = "windows")]
|
#[cfg(target_os = "windows")]
|
||||||
let color = functions::get_module::<Box<ITerminalColor + Sync + Send>>(
|
let color = functions::get_module::<Box<ITerminalColor + Sync + Send>>(
|
||||||
Box::from(WinApiColor::new()),
|
Box::from(WinApiColor::new()),
|
||||||
@ -45,21 +46,36 @@ impl<'stdout> TerminalColor<'stdout> {
|
|||||||
|
|
||||||
TerminalColor {
|
TerminalColor {
|
||||||
color,
|
color,
|
||||||
stdout: stdout,
|
stdout: None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Create new instance of `TerminalInput` whereon input related actions could be preformed.
|
||||||
|
pub fn on_screen(stdout: &'stdout Arc<TerminalOutput>) -> TerminalColor<'stdout> {
|
||||||
|
#[cfg(target_os = "windows")]
|
||||||
|
let color = functions::get_module::<Box<ITerminalColor + Sync + Send>>(
|
||||||
|
Box::from(WinApiColor::new()),
|
||||||
|
Box::from(AnsiColor::new()),
|
||||||
|
).unwrap();
|
||||||
|
|
||||||
|
#[cfg(not(target_os = "windows"))]
|
||||||
|
let color = Box::from(AnsiColor::new()) as Box<ITerminalColor + Sync + Send>;
|
||||||
|
|
||||||
|
TerminalColor {
|
||||||
|
color,
|
||||||
|
stdout: Some(stdout)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Set the foreground color to the given color.
|
/// Set the foreground color to the given color.
|
||||||
///
|
///
|
||||||
/// ```rust
|
/// ```rust
|
||||||
/// let screen = Screen::default();
|
/// let colored_terminal = color();
|
||||||
/// let colored_terminal = color(&screen);
|
|
||||||
///
|
///
|
||||||
/// // Set foreground color of the font
|
/// // Set foreground color of the font
|
||||||
/// colored_terminal.set_fg(Color::Red);
|
/// colored_terminal.set_fg(Color::Red);
|
||||||
/// // crossterm provides to set the background from &str or String
|
/// // crossterm provides to set the background from &str or String
|
||||||
/// colored_terminal.set_fg(Color::from("Red"));
|
/// colored_terminal.set_fg(Color::from("Red"));
|
||||||
///
|
|
||||||
/// ```
|
/// ```
|
||||||
pub fn set_fg(&self, color: Color) {
|
pub fn set_fg(&self, color: Color) {
|
||||||
self.color.set_fg(color, &self.stdout);
|
self.color.set_fg(color, &self.stdout);
|
||||||
@ -68,14 +84,12 @@ impl<'stdout> TerminalColor<'stdout> {
|
|||||||
/// Set the background color to the given color.
|
/// Set the background color to the given color.
|
||||||
///
|
///
|
||||||
/// ```rust
|
/// ```rust
|
||||||
/// let screen = Screen::default();
|
/// let colored_terminal = color();
|
||||||
/// let colored_terminal = color(&screen);
|
|
||||||
///
|
///
|
||||||
/// // Set background color of the font
|
/// // Set background color of the font
|
||||||
/// colored_terminal.set_bg(Color::Red);
|
/// colored_terminal.set_bg(Color::Red);
|
||||||
/// // crossterm provides to set the background from &str or String
|
/// // crossterm provides to set the background from &str or String
|
||||||
/// colored_terminal.set_bg(Color::from("Red"));
|
/// colored_terminal.set_bg(Color::from("Red"));
|
||||||
///
|
|
||||||
/// ```
|
/// ```
|
||||||
pub fn set_bg(&self, color: Color) {
|
pub fn set_bg(&self, color: Color) {
|
||||||
self.color.set_bg(color, &self.stdout);
|
self.color.set_bg(color, &self.stdout);
|
||||||
@ -84,8 +98,7 @@ impl<'stdout> TerminalColor<'stdout> {
|
|||||||
/// Reset the terminal colors and attributes to default.
|
/// Reset the terminal colors and attributes to default.
|
||||||
///
|
///
|
||||||
/// ```rust
|
/// ```rust
|
||||||
/// let screen = Screen::default();
|
/// let colored_terminal = color();
|
||||||
/// let colored_terminal = color(&screen);
|
|
||||||
/// colored_terminal.reset();
|
/// colored_terminal.reset();
|
||||||
/// ```
|
/// ```
|
||||||
pub fn reset(&self) {
|
pub fn reset(&self) {
|
||||||
@ -111,6 +124,13 @@ impl<'stdout> TerminalColor<'stdout> {
|
|||||||
|
|
||||||
/// Get an Terminal Color implementation whereon color related actions can be performed.
|
/// Get an Terminal Color implementation whereon color related actions can be performed.
|
||||||
/// Pass the reference to any screen you want this type to perform actions on.
|
/// Pass the reference to any screen you want this type to perform actions on.
|
||||||
pub fn color<'stdout>(screen: &'stdout Screen) -> TerminalColor<'stdout> {
|
pub fn color<'stdout>() -> TerminalColor<'stdout> {
|
||||||
TerminalColor::new(&screen.stdout)
|
TerminalColor::new()
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// Get an Terminal Color implementation whereon color related actions can be performed.
|
||||||
|
/// Pass the reference to any screen you want this type to perform actions on.
|
||||||
|
pub fn from_screen<'stdout>(screen: &'stdout Screen) -> TerminalColor<'stdout> {
|
||||||
|
TerminalColor::on_screen(&screen.stdout)
|
||||||
}
|
}
|
||||||
|
@ -17,7 +17,7 @@ use std::str::FromStr;
|
|||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use std::fmt::Display;
|
use std::fmt::Display;
|
||||||
|
|
||||||
pub use self::color::{TerminalColor, color};
|
pub use self::color::{TerminalColor, color, from_screen};
|
||||||
pub use self::objectstyle::ObjectStyle;
|
pub use self::objectstyle::ObjectStyle;
|
||||||
pub use self::styledobject::StyledObject;
|
pub use self::styledobject::StyledObject;
|
||||||
pub use self::styledobject::DisplayableObject;
|
pub use self::styledobject::DisplayableObject;
|
||||||
@ -35,31 +35,32 @@ use TerminalOutput;
|
|||||||
/// so that color related actions can be preformed on both unix and windows systems.
|
/// so that color related actions can be preformed on both unix and windows systems.
|
||||||
trait ITerminalColor {
|
trait ITerminalColor {
|
||||||
/// Set the foreground color to the given color.
|
/// Set the foreground color to the given color.
|
||||||
fn set_fg(&self, fg_color: Color, stdout: &Arc<TerminalOutput>);
|
fn set_fg(&self, fg_color: Color, stdout: &Option<&Arc<TerminalOutput>>);
|
||||||
/// Set the background color to the given color.
|
/// Set the background color to the given color.
|
||||||
fn set_bg(&self, fg_color: Color, stdout: &Arc<TerminalOutput>);
|
fn set_bg(&self, fg_color: Color, stdout: &Option<&Arc<TerminalOutput>>);
|
||||||
/// Reset the terminal color to default.
|
/// Reset the terminal color to default.
|
||||||
fn reset(&self, stdout: &Arc<TerminalOutput>);
|
fn reset(&self, stdout: &Option<&Arc<TerminalOutput>>);
|
||||||
/// Gets an value that represents an color from the given `Color` and `ColorType`.
|
/// Gets an value that represents an color from the given `Color` and `ColorType`.
|
||||||
fn color_value(&self, color: Color, color_type: ColorType) -> String;
|
fn color_value(&self, color: Color, color_type: ColorType) -> String;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// This could be used to style an Displayable with colors and attributes.
|
/// This could be used to style an `Displayable` type with colors and attributes.
|
||||||
///
|
///
|
||||||
/// ```rust
|
/// ```rust
|
||||||
|
/// extern crate crossterm;
|
||||||
|
/// use crossterm::Crossterm;
|
||||||
///
|
///
|
||||||
/// use crossterm::Screen;
|
/// let crossterm = Crossterm::new();
|
||||||
///
|
///
|
||||||
/// // get an styled object which could be painted to the terminal.
|
/// // get an styled object which could be painted to the terminal.
|
||||||
/// let styled_object = style("Some Blue colored text on black background").with(Color::Blue).on(Color::Black);
|
/// let styled_object = crossterm.style("Some Blue colored text on black background")
|
||||||
///
|
/// .with(Color::Blue)
|
||||||
/// // create an default screen.
|
/// .on(Color::Black);
|
||||||
/// let screen = Screen::default();
|
|
||||||
///
|
///
|
||||||
/// // print the styled font * times to the current screen.
|
/// // print the styled font * times to the current screen.
|
||||||
/// for i in 1..10
|
/// for i in 1..10
|
||||||
/// {
|
/// {
|
||||||
/// styled_object.paint(&screen);
|
/// println!("{}", styled_object);
|
||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
pub fn style<'a,D: 'a>(val: D) -> StyledObject<D>
|
pub fn style<'a,D: 'a>(val: D) -> StyledObject<D>
|
||||||
|
@ -1,9 +1,10 @@
|
|||||||
//! This module contains the logic to style an object that contains some state witch can be styled.
|
//! This module contains the logic to style an object that contains some state witch can be styled.
|
||||||
|
|
||||||
use super::{Color, ObjectStyle};
|
use super::{color, from_screen, Color, ObjectStyle};
|
||||||
use Screen;
|
use Screen;
|
||||||
|
|
||||||
use std::fmt::Display;
|
use std::fmt::{self, Display, Formatter};
|
||||||
|
use std::io::Write;
|
||||||
|
|
||||||
#[cfg(unix)]
|
#[cfg(unix)]
|
||||||
use super::Attribute;
|
use super::Attribute;
|
||||||
@ -15,32 +16,29 @@ pub struct StyledObject<D: Display> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, D: Display + 'a> StyledObject<D> {
|
impl<'a, D: Display + 'a> StyledObject<D> {
|
||||||
/// Set the foreground of the styled object to the passed `Color`
|
/// Set the foreground of the styled object to the passed `Color`.
|
||||||
///
|
///
|
||||||
/// ```rust
|
/// ```rust
|
||||||
/// use self::crossterm::style::{style,Color};
|
/// use self::crossterm::style::{style,Color};
|
||||||
///
|
///
|
||||||
/// // create an styled object with the foreground color red.
|
/// // create an styled object with the foreground color red.
|
||||||
/// let styledobject = style("Some colored text").with(Color::Blue);
|
/// let styledobject = style("Some colored text").with(Color::Red);
|
||||||
/// // create an styled object with the foreground color blue.
|
/// // create an styled object with the foreground color blue.
|
||||||
/// let styledobject1 = style("Some colored text").with(Color::Blue);
|
/// let styledobject1 = style("Some colored text").with(Color::Blue);
|
||||||
///
|
///
|
||||||
/// let screen = Screen::default();
|
|
||||||
///
|
|
||||||
/// // print the styledobject to see the result
|
/// // print the styledobject to see the result
|
||||||
/// styledobject.paint(&screen);
|
/// println!("{}", styledobject);
|
||||||
/// styledobject1.paint(&screen);
|
/// println!("{}", styledobject1);
|
||||||
///
|
///
|
||||||
/// // print an styled object directly.
|
/// // print an styled object directly.
|
||||||
/// style("Some colored text").with(Color::Blue).paint(&screen);
|
/// println!("{}", style("Some colored text").on(Color::Blue));
|
||||||
///
|
|
||||||
/// ```
|
/// ```
|
||||||
pub fn with(mut self, foreground_color: Color) -> StyledObject<D> {
|
pub fn with(mut self, foreground_color: Color) -> StyledObject<D> {
|
||||||
self.object_style = self.object_style.fg(foreground_color);
|
self.object_style = self.object_style.fg(foreground_color);
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Set the background of the styled object to the passed `Color`
|
/// Set the background of the styled object to the passed `Color`.
|
||||||
///
|
///
|
||||||
/// #Example
|
/// #Example
|
||||||
///
|
///
|
||||||
@ -48,26 +46,23 @@ impl<'a, D: Display + 'a> StyledObject<D> {
|
|||||||
/// use self::crossterm::style::{style,Color};
|
/// use self::crossterm::style::{style,Color};
|
||||||
///
|
///
|
||||||
/// // create an styled object with the background color red.
|
/// // create an styled object with the background color red.
|
||||||
/// let styledobject = style("Some colored text").on(Color::Blue);
|
/// let styledobject = style("Some colored text").on(Color::Red);
|
||||||
/// // create an styled object with the foreground color blue.
|
/// // create an styled object with the foreground color blue.
|
||||||
/// let styledobject1 = style("Some colored text").on(Color::Blue);
|
/// let styledobject1 = style("Some colored text").on(Color::Blue);
|
||||||
///
|
///
|
||||||
/// let screen = Screen::default();
|
|
||||||
///
|
|
||||||
/// // print the styledobject to see the result
|
/// // print the styledobject to see the result
|
||||||
/// styledobject.paint(&screen);
|
/// println!("{}", styledobject);
|
||||||
/// styledobject1.paint(&screen);
|
/// println!("{}", styledobject1);
|
||||||
///
|
///
|
||||||
/// // print an styled object directly.
|
/// // print an styled object directly.
|
||||||
/// style("Some colored text").on(Color::Blue).paint(&screen);
|
/// println!("{}", style("Some colored text").on(Color::Blue));
|
||||||
///
|
|
||||||
/// ```
|
/// ```
|
||||||
pub fn on(mut self, background_color: Color) -> StyledObject<D> {
|
pub fn on(mut self, background_color: Color) -> StyledObject<D> {
|
||||||
self.object_style = self.object_style.bg(background_color);
|
self.object_style = self.object_style.bg(background_color);
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Set the attribute of an styled object to the passed `Attribute`
|
/// Set the attribute of an styled object to the passed `Attribute`.
|
||||||
///
|
///
|
||||||
/// #Example
|
/// #Example
|
||||||
///
|
///
|
||||||
@ -75,7 +70,7 @@ impl<'a, D: Display + 'a> StyledObject<D> {
|
|||||||
/// extern crate crossterm;
|
/// extern crate crossterm;
|
||||||
/// use self::crossterm::style::{style,Attribute};
|
/// use self::crossterm::style::{style,Attribute};
|
||||||
///
|
///
|
||||||
/// style("Some colored text").attr(Attribute::Bold).paint(&screen);
|
/// println!("{}", style("Some bold text").attr(Attribute::Bold);
|
||||||
/// ```
|
/// ```
|
||||||
#[cfg(unix)]
|
#[cfg(unix)]
|
||||||
pub fn attr(mut self, attr: Attribute) -> StyledObject<D> {
|
pub fn attr(mut self, attr: Attribute) -> StyledObject<D> {
|
||||||
@ -138,7 +133,7 @@ impl<'a, D: Display + 'a> StyledObject<D> {
|
|||||||
self.attr(Attribute::CrossedOut)
|
self.attr(Attribute::CrossedOut)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// This could be used to paint the styled object on the screen. Pass a reference to the screen whereon you want to perform the painting.
|
/// This could be used to paint the styled object onto the given screen. You have to pass a reference to the screen whereon you want to perform the painting.
|
||||||
///
|
///
|
||||||
/// ``` rust
|
/// ``` rust
|
||||||
/// style("Some colored text")
|
/// style("Some colored text")
|
||||||
@ -146,9 +141,12 @@ impl<'a, D: Display + 'a> StyledObject<D> {
|
|||||||
/// .on(Color::Black)
|
/// .on(Color::Black)
|
||||||
/// .paint(&screen);
|
/// .paint(&screen);
|
||||||
/// ```
|
/// ```
|
||||||
|
///
|
||||||
|
/// You should take not that `StyledObject` implements `Display`. You don't need to call paint unless you are on alternate screen.
|
||||||
|
/// Checkout `into_displayable()` for more information about this.
|
||||||
pub fn paint(&self, screen: &Screen)
|
pub fn paint(&self, screen: &Screen)
|
||||||
{
|
{
|
||||||
let colored_terminal = ::color(&screen);
|
let colored_terminal = from_screen(&screen);
|
||||||
let mut reset = true;
|
let mut reset = true;
|
||||||
|
|
||||||
if let Some(bg) = self.object_style.bg_color {
|
if let Some(bg) = self.object_style.bg_color {
|
||||||
@ -178,13 +176,19 @@ impl<'a, D: Display + 'a> StyledObject<D> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// this converts an styled object into an `DisplayableObject` witch implements: `Display` and could be used inside the write function of the standard library's.
|
/// This converts an styled object into an `DisplayableObject` witch implements: `Display` and could be used inside the write function of the standard library.
|
||||||
|
///
|
||||||
|
/// _StyledObject already implements `Display` right?_
|
||||||
|
///
|
||||||
|
/// This is true, however there are some complex issues why this won't work on alternate screen.
|
||||||
|
/// That is the reason why this functions exists.
|
||||||
|
/// You could just pass in the 'screen' from your alternate screen to this method and your `StyledObject` will be printed to the alternate screen just fine.
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// let screen = Screen::default();
|
/// let screen = Screen::default(); /* represents the alternate screen */
|
||||||
// let styled_object = style("test").with(Color::Yellow);
|
/// let styled_object = style("test").with(Color::Yellow);
|
||||||
// let display_object = styled_object.into_displayable(&screen);
|
/// let display_object = styled_object.into_displayable(&screen);
|
||||||
// println!("Colored text: {}. Default color", display_object);
|
/// println!("Colored text: {}. Default color", display_object);
|
||||||
/// ```
|
/// ```
|
||||||
pub fn into_displayable(self, screen: &'a Screen) -> DisplayableObject<'a, D>
|
pub fn into_displayable(self, screen: &'a Screen) -> DisplayableObject<'a, D>
|
||||||
{
|
{
|
||||||
@ -192,13 +196,37 @@ impl<'a, D: Display + 'a> StyledObject<D> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
use std::fmt::{Formatter, Error};
|
impl<D: Display> Display for StyledObject<D> {
|
||||||
|
fn fmt(&self, f: &mut Formatter) -> Result<(), fmt::Error> {
|
||||||
|
let mut colored_terminal = color();
|
||||||
|
let mut reset = true;
|
||||||
|
|
||||||
/// This is a wrapper for a styled object so that the styled object could be printed with the standard write functions in rust.
|
if let Some(bg) = self.object_style.bg_color {
|
||||||
|
colored_terminal.set_bg(bg);
|
||||||
|
reset = true;
|
||||||
|
}
|
||||||
|
if let Some(fg) = self.object_style.fg_color {
|
||||||
|
colored_terminal.set_fg(fg);
|
||||||
|
reset = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt::Display::fmt(&self.content, f)?;
|
||||||
|
std::io::stdout().flush().expect("Flush stdout failed");
|
||||||
|
|
||||||
|
if reset {
|
||||||
|
colored_terminal.reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// This is a wrapper for a styled object on alternate screen so that the styled object could be printed on the alternate screen with the standard write functions in rust.
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// write! ("some normal text, {} <- some colored text", DisplayableObject::new(&screen, styled_object));
|
/// write! ("some normal text, {} <- some colored text", DisplayableObject::new(&screen, styled_object));
|
||||||
/// println! ("some normal text, {} <- some colored text", DisplayableObject::new(&screen, styled_object))
|
/// println! ("some normal text, {} <- some colored text", DisplayableObject::new(&screen, styled_object));
|
||||||
/// ```
|
/// ```
|
||||||
pub struct DisplayableObject<'a, D:Display + 'a>
|
pub struct DisplayableObject<'a, D:Display + 'a>
|
||||||
{
|
{
|
||||||
@ -216,7 +244,7 @@ impl <'a, D: Display + 'a> DisplayableObject<'a, D>
|
|||||||
|
|
||||||
impl<'a, D: Display + 'a> Display for DisplayableObject<'a, D>
|
impl<'a, D: Display + 'a> Display for DisplayableObject<'a, D>
|
||||||
{
|
{
|
||||||
fn fmt(&self, _f: &mut Formatter) -> Result<(), Error> {
|
fn fmt(&self, _f: &mut Formatter) -> Result<(), fmt::Error> {
|
||||||
self.styled_object.paint(&self.screen);
|
self.styled_object.paint(&self.screen);
|
||||||
return Ok(())
|
return Ok(())
|
||||||
}
|
}
|
||||||
|
@ -20,7 +20,7 @@ impl WinApiColor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl ITerminalColor for WinApiColor {
|
impl ITerminalColor for WinApiColor {
|
||||||
fn set_fg(&self, fg_color: Color, stdout: &Arc<TerminalOutput>) {
|
fn set_fg(&self, fg_color: Color, _stdout: &Option<&Arc<TerminalOutput>>) {
|
||||||
let color_value = &self.color_value(fg_color, ColorType::Foreground);
|
let color_value = &self.color_value(fg_color, ColorType::Foreground);
|
||||||
|
|
||||||
let csbi = csbi::get_csbi().unwrap();
|
let csbi = csbi::get_csbi().unwrap();
|
||||||
@ -41,7 +41,7 @@ impl ITerminalColor for WinApiColor {
|
|||||||
kernel::set_console_text_attribute(color);
|
kernel::set_console_text_attribute(color);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_bg(&self, bg_color: Color, stdout: &Arc<TerminalOutput>) {
|
fn set_bg(&self, bg_color: Color, _stdout: &Option<&Arc<TerminalOutput>>) {
|
||||||
let color_value = &self.color_value(bg_color, ColorType::Background);
|
let color_value = &self.color_value(bg_color, ColorType::Background);
|
||||||
|
|
||||||
let (csbi, handle) = csbi::get_csbi_and_handle().unwrap();
|
let (csbi, handle) = csbi::get_csbi_and_handle().unwrap();
|
||||||
@ -62,7 +62,7 @@ impl ITerminalColor for WinApiColor {
|
|||||||
kernel::set_console_text_attribute(color);
|
kernel::set_console_text_attribute(color);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn reset(&self, stdout: &Arc<TerminalOutput>) {
|
fn reset(&self, _stdout: &Option<&Arc<TerminalOutput>>) {
|
||||||
kernel::set_console_text_attribute(self.original_color);
|
kernel::set_console_text_attribute(self.original_color);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -15,47 +15,49 @@ impl AnsiTerminal {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl ITerminal for AnsiTerminal {
|
impl ITerminal for AnsiTerminal {
|
||||||
fn clear(&self, clear_type: ClearType, stdout: &Arc<TerminalOutput>) {
|
fn clear(&self, clear_type: ClearType, stdout: &Option<&Arc<TerminalOutput>>) {
|
||||||
match clear_type {
|
match clear_type {
|
||||||
ClearType::All => {
|
ClearType::All => {
|
||||||
stdout.write_str(csi!("2J"));
|
functions::write_str(&stdout,csi!("2J"));
|
||||||
TerminalCursor::new(stdout).goto(0,0);
|
TerminalCursor::new().goto(0,0);
|
||||||
}
|
}
|
||||||
ClearType::FromCursorDown => {
|
ClearType::FromCursorDown => {
|
||||||
stdout.write_str(csi!("J"));
|
functions::write_str(&stdout,csi!("J"));
|
||||||
}
|
}
|
||||||
ClearType::FromCursorUp => {
|
ClearType::FromCursorUp => {
|
||||||
stdout.write_str(csi!("1J"));
|
functions::write_str(&stdout,csi!("1J"));
|
||||||
}
|
}
|
||||||
ClearType::CurrentLine => {
|
ClearType::CurrentLine => {
|
||||||
stdout.write_str(csi!("2K"));
|
functions::write_str(&stdout,csi!("2K"));
|
||||||
}
|
}
|
||||||
ClearType::UntilNewLine => {
|
ClearType::UntilNewLine => {
|
||||||
stdout.write_str(csi!("K"));
|
functions::write_str(&stdout,csi!("K"));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
fn terminal_size(&self, _stdout: &Arc<TerminalOutput>) -> (u16, u16) {
|
fn terminal_size(&self, _stdout: &Option<&Arc<TerminalOutput>>) -> (u16, u16) {
|
||||||
functions::get_terminal_size()
|
functions::get_terminal_size()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn scroll_up(&self, count: i16, stdout: &Arc<TerminalOutput>) {
|
fn scroll_up(&self, count: i16, stdout: &Option<&Arc<TerminalOutput>>) {
|
||||||
stdout.write_string(format!(csi!("{}S"), count));
|
functions::write(&stdout,format!(csi!("{}S"), count));
|
||||||
}
|
}
|
||||||
|
|
||||||
fn scroll_down(&self, count: i16, stdout: &Arc<TerminalOutput>) {
|
fn scroll_down(&self, count: i16, stdout: &Option<&Arc<TerminalOutput>>) {
|
||||||
stdout.write_string(format!(csi!("{}T"), count));
|
functions::write(&stdout,format!(csi!("{}T"), count));
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_size(&self, width: i16, height: i16, stdout: &Arc<TerminalOutput>) {
|
fn set_size(&self, width: i16, height: i16, stdout: &Option<&Arc<TerminalOutput>>) {
|
||||||
stdout.write_string(format!(csi!("8;{};{}t"), height, width));
|
functions::write(&stdout,format!(csi!("8;{};{}t"), height, width));
|
||||||
}
|
}
|
||||||
|
|
||||||
fn exit(&self,stdout: &Arc<TerminalOutput>) {
|
fn exit(&self,stdout: &Option<&Arc<TerminalOutput>>) {
|
||||||
|
if let Some(output) = stdout {
|
||||||
// drop the screen with the current stdout. This will make sure when in raw mode this will be disabled first.
|
// drop the screen with the current stdout. This will make sure when in raw mode this will be disabled first.
|
||||||
let screen = Screen::from(stdout.clone());
|
let screen = Screen::from(output.to_owned().clone());
|
||||||
drop(screen);
|
drop(screen);
|
||||||
functions::exit_terminal();
|
functions::exit_terminal();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -13,7 +13,7 @@ use self::ansi_terminal::AnsiTerminal;
|
|||||||
#[cfg(target_os = "windows")]
|
#[cfg(target_os = "windows")]
|
||||||
use self::winapi_terminal::WinApiTerminal;
|
use self::winapi_terminal::WinApiTerminal;
|
||||||
|
|
||||||
pub use self::terminal::{terminal, Terminal};
|
pub use self::terminal::{terminal, from_screen, Terminal};
|
||||||
|
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use super::functions;
|
use super::functions;
|
||||||
@ -38,15 +38,15 @@ pub enum ClearType {
|
|||||||
/// so that color related actions can be preformed on both unix and windows systems.
|
/// so that color related actions can be preformed on both unix and windows systems.
|
||||||
trait ITerminal {
|
trait ITerminal {
|
||||||
/// Clear the current cursor by specifying the clear type
|
/// Clear the current cursor by specifying the clear type
|
||||||
fn clear(&self, clear_type: ClearType, stdout: &Arc<TerminalOutput>);
|
fn clear(&self, clear_type: ClearType, stdout: &Option<&Arc<TerminalOutput>>);
|
||||||
/// Get the terminal size (x,y)
|
/// Get the terminal size (x,y)
|
||||||
fn terminal_size(&self, stdout: &Arc<TerminalOutput>) -> (u16, u16);
|
fn terminal_size(&self, stdout: &Option<&Arc<TerminalOutput>>) -> (u16, u16);
|
||||||
/// Scroll `n` lines up in the current terminal.
|
/// Scroll `n` lines up in the current terminal.
|
||||||
fn scroll_up(&self, count: i16, stdout: &Arc<TerminalOutput>);
|
fn scroll_up(&self, count: i16, stdout: &Option<&Arc<TerminalOutput>>);
|
||||||
/// Scroll `n` lines down in the current terminal.
|
/// Scroll `n` lines down in the current terminal.
|
||||||
fn scroll_down(&self, count: i16, stdout: &Arc<TerminalOutput>);
|
fn scroll_down(&self, count: i16, stdout: &Option<&Arc<TerminalOutput>>);
|
||||||
/// Resize terminal to the given width and height.
|
/// Resize terminal to the given width and height.
|
||||||
fn set_size(&self, width: i16, height: i16, stdout: &Arc<TerminalOutput>);
|
fn set_size(&self, width: i16, height: i16, stdout: &Option<&Arc<TerminalOutput>>);
|
||||||
/// Close the current terminal
|
/// Close the current terminal
|
||||||
fn exit(&self,stdout: &Arc<TerminalOutput>);
|
fn exit(&self,stdout: &Option<&Arc<TerminalOutput>>);
|
||||||
}
|
}
|
||||||
|
@ -12,22 +12,23 @@ use std::fmt;
|
|||||||
/// ```rust
|
/// ```rust
|
||||||
/// use crossterm::terminal;
|
/// use crossterm::terminal;
|
||||||
///
|
///
|
||||||
/// let screen = Screen::default();
|
/// let term = terminal();
|
||||||
/// let term = terminal(&screen);
|
|
||||||
///
|
///
|
||||||
/// term.scroll_down(5);
|
/// term.scroll_down(5);
|
||||||
/// term.scroll_up(4);
|
/// term.scroll_up(4);
|
||||||
/// let (with, height) = term.terminal_size();
|
/// let (with, height) = term.terminal_size();
|
||||||
///
|
///
|
||||||
|
/// When you want to use 'terminal' actions on 'alternate screen' use the `Screen` type instead, and pass it to the `terminal::from_screen()` function.
|
||||||
|
/// By doing that terminal actions will be performed on the alternate screen.
|
||||||
/// ```
|
/// ```
|
||||||
pub struct Terminal<'stdout> {
|
pub struct Terminal<'stdout> {
|
||||||
terminal: Box<ITerminal + Sync + Send>,
|
terminal: Box<ITerminal + Sync + Send>,
|
||||||
screen: &'stdout Arc<TerminalOutput>,
|
screen: Option<&'stdout Arc<TerminalOutput>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'stdout> Terminal<'stdout> {
|
impl<'stdout> Terminal<'stdout> {
|
||||||
/// Create new terminal instance whereon terminal related actions can be performed.
|
/// Create new terminal instance whereon terminal related actions can be performed.
|
||||||
pub fn new(screen: &'stdout Arc<TerminalOutput>) -> Terminal<'stdout> {
|
pub fn new() -> Terminal<'stdout> {
|
||||||
#[cfg(target_os = "windows")]
|
#[cfg(target_os = "windows")]
|
||||||
let terminal = functions::get_module::<Box<ITerminal + Sync + Send>>(
|
let terminal = functions::get_module::<Box<ITerminal + Sync + Send>>(
|
||||||
Box::new(WinApiTerminal::new()),
|
Box::new(WinApiTerminal::new()),
|
||||||
@ -39,15 +40,31 @@ impl<'stdout> Terminal<'stdout> {
|
|||||||
|
|
||||||
Terminal {
|
Terminal {
|
||||||
terminal,
|
terminal,
|
||||||
screen: screen,
|
screen: None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Create new instance of TerminalInput whereon input related actions could be preformed.
|
||||||
|
pub fn on_screen(stdout: &'stdout Arc<TerminalOutput>) -> Terminal<'stdout> {
|
||||||
|
#[cfg(target_os = "windows")]
|
||||||
|
let terminal = functions::get_module::<Box<ITerminal + Sync + Send>>(
|
||||||
|
Box::new(WinApiTerminal::new()),
|
||||||
|
Box::new(AnsiTerminal::new()),
|
||||||
|
).unwrap();
|
||||||
|
|
||||||
|
#[cfg(not(target_os = "windows"))]
|
||||||
|
let terminal = Box::from(AnsiTerminal::new()) as Box<ITerminal + Sync + Send>;
|
||||||
|
|
||||||
|
Terminal {
|
||||||
|
terminal,
|
||||||
|
screen: Some(stdout),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Clear the current cursor by specifying the clear type.
|
/// Clear the current cursor by specifying the clear type.
|
||||||
///
|
///
|
||||||
/// ```rust
|
/// ```rust
|
||||||
/// let screen = Screen::default();
|
/// let mut term = terminal();
|
||||||
/// let mut term = terminal(&screen);
|
|
||||||
///
|
///
|
||||||
/// // clear all cells in terminal.
|
/// // clear all cells in terminal.
|
||||||
/// term.clear(terminal::ClearType::All);
|
/// term.clear(terminal::ClearType::All);
|
||||||
@ -67,12 +84,10 @@ impl<'stdout> Terminal<'stdout> {
|
|||||||
/// Get the terminal size (x,y).
|
/// Get the terminal size (x,y).
|
||||||
///
|
///
|
||||||
/// ```rust
|
/// ```rust
|
||||||
/// let screen = Screen::default();
|
/// let mut term = terminal();
|
||||||
/// let mut term = terminal(&screen);
|
|
||||||
///
|
///
|
||||||
/// let size = term.terminal_size();
|
/// let size = term.terminal_size();
|
||||||
/// println!("{:?}", size);
|
/// println!("{:?}", size);
|
||||||
///
|
|
||||||
/// ```
|
/// ```
|
||||||
pub fn terminal_size(&self) -> (u16, u16) {
|
pub fn terminal_size(&self) -> (u16, u16) {
|
||||||
return self.terminal.terminal_size(&self.screen);
|
return self.terminal.terminal_size(&self.screen);
|
||||||
@ -81,12 +96,10 @@ impl<'stdout> Terminal<'stdout> {
|
|||||||
/// Scroll `n` lines up in the current terminal.
|
/// Scroll `n` lines up in the current terminal.
|
||||||
///
|
///
|
||||||
/// ```rust
|
/// ```rust
|
||||||
/// let screen = Screen::default();
|
/// let mut term = terminal();
|
||||||
/// let mut term = terminal(&screen);
|
|
||||||
///
|
///
|
||||||
/// // scroll up by 5 lines
|
/// // scroll up by 5 lines
|
||||||
/// let size = term.scroll_up(5);
|
/// let size = term.scroll_up(5);
|
||||||
///
|
|
||||||
/// ```
|
/// ```
|
||||||
pub fn scroll_up(&self, count: i16) {
|
pub fn scroll_up(&self, count: i16) {
|
||||||
self.terminal.scroll_up(count, &self.screen);
|
self.terminal.scroll_up(count, &self.screen);
|
||||||
@ -95,12 +108,10 @@ impl<'stdout> Terminal<'stdout> {
|
|||||||
/// Scroll `n` lines up in the current terminal.
|
/// Scroll `n` lines up in the current terminal.
|
||||||
///
|
///
|
||||||
/// ```rust
|
/// ```rust
|
||||||
/// let screen = Screen::default();
|
/// let mut term = terminal();
|
||||||
/// let mut term = terminal(&screen);
|
|
||||||
///
|
///
|
||||||
/// // scroll down by 5 lines
|
/// // scroll down by 5 lines
|
||||||
/// let size = term.scroll_down(5);
|
/// let size = term.scroll_down(5);
|
||||||
///
|
|
||||||
/// ```
|
/// ```
|
||||||
pub fn scroll_down(&self, count: i16) {
|
pub fn scroll_down(&self, count: i16) {
|
||||||
self.terminal.scroll_down(count, &self.screen);
|
self.terminal.scroll_down(count, &self.screen);
|
||||||
@ -109,12 +120,10 @@ impl<'stdout> Terminal<'stdout> {
|
|||||||
/// Set the terminal size. Note that not all terminals can be set to a very small scale.
|
/// Set the terminal size. Note that not all terminals can be set to a very small scale.
|
||||||
///
|
///
|
||||||
/// ```rust
|
/// ```rust
|
||||||
/// let screen = Screen::default();
|
/// let mut term = terminal();
|
||||||
/// let mut term = terminal(&screen);
|
|
||||||
///
|
///
|
||||||
/// // Set of the size to X: 10 and Y: 10
|
/// // Set of the size to X: 10 and Y: 10
|
||||||
/// let size = term.set_size(10,10);
|
/// let size = term.set_size(10,10);
|
||||||
///
|
|
||||||
/// ```
|
/// ```
|
||||||
pub fn set_size(&self, width: i16, height: i16) {
|
pub fn set_size(&self, width: i16, height: i16) {
|
||||||
self.terminal.set_size(width, height, &self.screen);
|
self.terminal.set_size(width, height, &self.screen);
|
||||||
@ -123,11 +132,9 @@ impl<'stdout> Terminal<'stdout> {
|
|||||||
/// Exit the current process.
|
/// Exit the current process.
|
||||||
///
|
///
|
||||||
/// ```rust
|
/// ```rust
|
||||||
/// let screen = Screen::default();
|
/// let mut term = terminal();
|
||||||
/// let mut term = terminal(&screen);
|
|
||||||
///
|
///
|
||||||
/// let size = term.exit();
|
/// let size = term.exit();
|
||||||
///
|
|
||||||
/// ```
|
/// ```
|
||||||
pub fn exit(&self) {
|
pub fn exit(&self) {
|
||||||
self.terminal.exit(&self.screen);
|
self.terminal.exit(&self.screen);
|
||||||
@ -136,22 +143,26 @@ impl<'stdout> Terminal<'stdout> {
|
|||||||
/// Write any displayable content to the current terminal screen.
|
/// Write any displayable content to the current terminal screen.
|
||||||
///
|
///
|
||||||
/// ```rust
|
/// ```rust
|
||||||
/// let screen = Screen::default();
|
/// let mut term = terminal();
|
||||||
/// let mut term = terminal(&screen);
|
|
||||||
///
|
///
|
||||||
/// let size = term.write("Some text \n Some text on new line");
|
/// let size = term.write("Some text \n Some text on new line");
|
||||||
///
|
|
||||||
/// ```
|
/// ```
|
||||||
pub fn write<D: fmt::Display>(&self, value: D) {
|
pub fn write<D: fmt::Display>(&self, value: D) {
|
||||||
use std::fmt::Write;
|
use std::fmt::Write;
|
||||||
let mut string = String::new();
|
let mut string = String::new();
|
||||||
write!(string, "{}", value).unwrap();
|
write!(string, "{}", value).unwrap();
|
||||||
self.screen.write_string(string);
|
functions::write(&self.screen, string);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get an terminal implementation whereon terminal related actions could performed.
|
/// Get an terminal implementation whereon terminal related actions could performed.
|
||||||
/// Pass the reference to any screen you want this type to perform actions on.
|
/// Pass the reference to any screen you want this type to perform actions on.
|
||||||
pub fn terminal<'stdout>(screen: &'stdout Screen) -> Terminal<'stdout> {
|
pub fn terminal<'stdout>() -> Terminal<'stdout> {
|
||||||
Terminal::new(&screen.stdout)
|
Terminal::new()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get an Terminal Color implementation whereon color related actions can be performed.
|
||||||
|
/// Pass the reference to any screen you want this type to perform actions on.
|
||||||
|
pub fn from_screen(screen: &Screen) -> Terminal {
|
||||||
|
Terminal::on_screen(&screen.stdout)
|
||||||
}
|
}
|
||||||
|
@ -14,11 +14,12 @@ mod winapi_tests {
|
|||||||
fn resize_winapi()
|
fn resize_winapi()
|
||||||
{
|
{
|
||||||
let screen = Screen::default();
|
let screen = Screen::default();
|
||||||
|
let stdout = Some(&screen.stdout);
|
||||||
let terminal = WinApiTerminal::new();
|
let terminal = WinApiTerminal::new();
|
||||||
|
|
||||||
terminal.set_size(10, 10, &screen.stdout);
|
terminal.set_size(10, 10, &stdout);
|
||||||
|
|
||||||
let (x, y) = terminal.terminal_size(&screen.stdout);
|
let (x, y) = terminal.terminal_size(&stdout);
|
||||||
|
|
||||||
assert_eq!(x, 10);
|
assert_eq!(x, 10);
|
||||||
assert_eq!(y, 10);
|
assert_eq!(y, 10);
|
||||||
@ -32,14 +33,15 @@ fn resize_ansi()
|
|||||||
use std::{thread, time};
|
use std::{thread, time};
|
||||||
if try_enable_ansi() {
|
if try_enable_ansi() {
|
||||||
let screen = Screen::default();
|
let screen = Screen::default();
|
||||||
|
let stdout = Some(&screen.stdout);
|
||||||
let terminal = AnsiTerminal::new();
|
let terminal = AnsiTerminal::new();
|
||||||
|
|
||||||
terminal.set_size(50,50, &screen.stdout);
|
terminal.set_size(50,50, &stdout);
|
||||||
|
|
||||||
// see issue: https://github.com/eminence/terminal-size/issues/11
|
// see issue: https://github.com/eminence/terminal-size/issues/11
|
||||||
thread::sleep(time::Duration::from_millis(30));
|
thread::sleep(time::Duration::from_millis(30));
|
||||||
|
|
||||||
let (x, y) = terminal.terminal_size(&screen.stdout);
|
let (x, y) = terminal.terminal_size(&stdout);
|
||||||
|
|
||||||
assert_eq!(x, 50);
|
assert_eq!(x, 50);
|
||||||
assert_eq!(y, 50);
|
assert_eq!(y, 50);
|
||||||
|
@ -19,9 +19,9 @@ impl WinApiTerminal {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl ITerminal for WinApiTerminal {
|
impl ITerminal for WinApiTerminal {
|
||||||
fn clear(&self, clear_type: ClearType, stdout: &Arc<TerminalOutput>) {
|
fn clear(&self, clear_type: ClearType, stdout: &Option<&Arc<TerminalOutput>>) {
|
||||||
let csbi = csbi::get_csbi().unwrap();
|
let csbi = csbi::get_csbi().unwrap();
|
||||||
let pos = TerminalCursor::new(stdout).pos();
|
let pos = TerminalCursor::new().pos();
|
||||||
|
|
||||||
match clear_type {
|
match clear_type {
|
||||||
ClearType::All => {
|
ClearType::All => {
|
||||||
@ -34,11 +34,11 @@ impl ITerminal for WinApiTerminal {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
fn terminal_size(&self, stdout: &Arc<TerminalOutput>) -> (u16, u16) {
|
fn terminal_size(&self, stdout: &Option<&Arc<TerminalOutput>>) -> (u16, u16) {
|
||||||
terminal::terminal_size()
|
terminal::terminal_size()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn scroll_up(&self, count: i16, stdout: &Arc<TerminalOutput>) {
|
fn scroll_up(&self, count: i16, stdout: &Option<&Arc<TerminalOutput>>) {
|
||||||
let csbi = csbi::get_csbi().unwrap();
|
let csbi = csbi::get_csbi().unwrap();
|
||||||
|
|
||||||
// Set srctWindow to the current window size and location.
|
// Set srctWindow to the current window size and location.
|
||||||
@ -56,7 +56,7 @@ impl ITerminal for WinApiTerminal {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn scroll_down(&self, count: i16, stdout: &Arc<TerminalOutput>) {
|
fn scroll_down(&self, count: i16, stdout: &Option<&Arc<TerminalOutput>>) {
|
||||||
let csbi = csbi::get_csbi().unwrap();
|
let csbi = csbi::get_csbi().unwrap();
|
||||||
// Set srctWindow to the current window size and location.
|
// Set srctWindow to the current window size and location.
|
||||||
let mut srct_window = csbi.srWindow;
|
let mut srct_window = csbi.srWindow;
|
||||||
@ -74,7 +74,7 @@ impl ITerminal for WinApiTerminal {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Set the current terminal size
|
/// Set the current terminal size
|
||||||
fn set_size(&self, width: i16, height: i16, stdout: &Arc<TerminalOutput>) {
|
fn set_size(&self, width: i16, height: i16, stdout: &Option<&Arc<TerminalOutput>>) {
|
||||||
if width <= 0 {
|
if width <= 0 {
|
||||||
panic!("Cannot set the terminal width lower than 1");
|
panic!("Cannot set the terminal width lower than 1");
|
||||||
}
|
}
|
||||||
@ -150,18 +150,21 @@ impl ITerminal for WinApiTerminal {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn exit(&self, stdout: &Arc<TerminalOutput>) {
|
fn exit(&self, stdout: &Option<&Arc<TerminalOutput>>) {
|
||||||
|
if let Some(output) = stdout
|
||||||
|
{
|
||||||
// drop the screen with the current stdout. This will make sure when in raw mode this will be disabled first.
|
// drop the screen with the current stdout. This will make sure when in raw mode this will be disabled first.
|
||||||
let mut screen = Screen::from(stdout.clone());
|
let mut screen = Screen::from(output.to_owned().clone());
|
||||||
drop(screen);
|
drop(screen);
|
||||||
functions::exit_terminal();
|
functions::exit_terminal();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn clear_after_cursor(
|
pub fn clear_after_cursor(
|
||||||
pos: (u16, u16),
|
pos: (u16, u16),
|
||||||
csbi: CONSOLE_SCREEN_BUFFER_INFO,
|
csbi: CONSOLE_SCREEN_BUFFER_INFO,
|
||||||
stdout: &Arc<TerminalOutput>,
|
stdout: &Option<&Arc<TerminalOutput>>,
|
||||||
) {
|
) {
|
||||||
let (mut x, mut y) = pos;
|
let (mut x, mut y) = pos;
|
||||||
|
|
||||||
@ -185,7 +188,7 @@ pub fn clear_after_cursor(
|
|||||||
pub fn clear_before_cursor(
|
pub fn clear_before_cursor(
|
||||||
pos: (u16, u16),
|
pos: (u16, u16),
|
||||||
csbi: CONSOLE_SCREEN_BUFFER_INFO,
|
csbi: CONSOLE_SCREEN_BUFFER_INFO,
|
||||||
stdout: &Arc<TerminalOutput>,
|
stdout: &Option<&Arc<TerminalOutput>>,
|
||||||
) {
|
) {
|
||||||
let (xpos, ypos) = pos;
|
let (xpos, ypos) = pos;
|
||||||
|
|
||||||
@ -205,7 +208,7 @@ pub fn clear_before_cursor(
|
|||||||
clear(start_location, cells_to_write);
|
clear(start_location, cells_to_write);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn clear_entire_screen(csbi: CONSOLE_SCREEN_BUFFER_INFO, stdout: &Arc<TerminalOutput>) {
|
pub fn clear_entire_screen(csbi: CONSOLE_SCREEN_BUFFER_INFO, stdout: &Option<&Arc<TerminalOutput>>) {
|
||||||
// position x at start
|
// position x at start
|
||||||
let x = 0;
|
let x = 0;
|
||||||
// position y at start
|
// position y at start
|
||||||
@ -222,14 +225,22 @@ pub fn clear_entire_screen(csbi: CONSOLE_SCREEN_BUFFER_INFO, stdout: &Arc<Termin
|
|||||||
|
|
||||||
clear(start_location, cells_to_write);
|
clear(start_location, cells_to_write);
|
||||||
|
|
||||||
|
match stdout {
|
||||||
|
Some(ref output) => {
|
||||||
// put the cursor back at (0, 0)
|
// put the cursor back at (0, 0)
|
||||||
TerminalCursor::new(stdout).goto(0, 0);
|
TerminalCursor::on_screen(output).goto(0, 0);
|
||||||
|
}
|
||||||
|
None => {
|
||||||
|
// put the cursor back at (0, 0)
|
||||||
|
TerminalCursor::new().goto(0, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn clear_current_line(
|
pub fn clear_current_line(
|
||||||
pos: (u16, u16),
|
pos: (u16, u16),
|
||||||
csbi: CONSOLE_SCREEN_BUFFER_INFO,
|
csbi: CONSOLE_SCREEN_BUFFER_INFO,
|
||||||
stdout: &Arc<TerminalOutput>,
|
stdout: &Option<&Arc<TerminalOutput>>,
|
||||||
) {
|
) {
|
||||||
// position x at start
|
// position x at start
|
||||||
let x = 0;
|
let x = 0;
|
||||||
@ -248,13 +259,22 @@ pub fn clear_current_line(
|
|||||||
clear(start_location, cells_to_write);
|
clear(start_location, cells_to_write);
|
||||||
|
|
||||||
// put the cursor back at 1 cell on current row
|
// put the cursor back at 1 cell on current row
|
||||||
TerminalCursor::new(stdout).goto(0, y);
|
match stdout {
|
||||||
|
Some(ref output) => {
|
||||||
|
// put the cursor back at (0, 0)
|
||||||
|
TerminalCursor::on_screen(output).goto(0, y);
|
||||||
|
}
|
||||||
|
None => {
|
||||||
|
// put the cursor back at (0, 0)
|
||||||
|
TerminalCursor::new().goto(0, y);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn clear_until_line(
|
pub fn clear_until_line(
|
||||||
pos: (u16, u16),
|
pos: (u16, u16),
|
||||||
csbi: CONSOLE_SCREEN_BUFFER_INFO,
|
csbi: CONSOLE_SCREEN_BUFFER_INFO,
|
||||||
stdout: &Arc<TerminalOutput>,
|
stdout: &Option<&Arc<TerminalOutput>>,
|
||||||
) {
|
) {
|
||||||
let (x, y) = pos;
|
let (x, y) = pos;
|
||||||
|
|
||||||
@ -269,7 +289,16 @@ pub fn clear_until_line(
|
|||||||
clear(start_location, cells_to_write);
|
clear(start_location, cells_to_write);
|
||||||
|
|
||||||
// put the cursor back at original cursor position
|
// put the cursor back at original cursor position
|
||||||
TerminalCursor::new(stdout).goto(x, y);
|
match stdout {
|
||||||
|
Some(ref output) => {
|
||||||
|
// put the cursor back at (0, 0)
|
||||||
|
TerminalCursor::on_screen(output).goto(x, y);
|
||||||
|
}
|
||||||
|
None => {
|
||||||
|
// put the cursor back at (0, 0)
|
||||||
|
TerminalCursor::new().goto(x, y);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn clear(start_loaction: COORD, cells_to_write: u32) {
|
fn clear(start_loaction: COORD, cells_to_write: u32) {
|
||||||
|
Loading…
Reference in New Issue
Block a user