refactored code comments fixed examples and invalid comments. Also added documentation
This commit is contained in:
parent
48a429a396
commit
2a40d10ae9
File diff suppressed because it is too large
Load Diff
@ -14,14 +14,23 @@
|
|||||||
extern crate crossterm;
|
extern crate crossterm;
|
||||||
|
|
||||||
mod terminal;
|
mod terminal;
|
||||||
|
mod cursor;
|
||||||
|
mod color;
|
||||||
|
|
||||||
use terminal::alternate_screen;
|
use terminal::alternate_screen;
|
||||||
use terminal::raw_mode;
|
use terminal::raw_mode;
|
||||||
|
use terminal::terminal as term;
|
||||||
|
|
||||||
use crossterm::cursor;
|
use self::crossterm::Context;
|
||||||
|
use self::crossterm::terminal::ClearType;
|
||||||
|
use crossterm::raw;
|
||||||
|
use crossterm::screen;
|
||||||
|
use crossterm::raw::IntoRawMode;
|
||||||
|
use std::io::Write;
|
||||||
|
use std::{time, thread};
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
|
// alternate_screen::switch_between_main_and_alternate_screen();
|
||||||
|
let context = Context::new();
|
||||||
raw_mode::print_wait_screen_on_alternate_window();
|
raw_mode::print_wait_screen_on_alternate_window();
|
||||||
}
|
}
|
@ -5,43 +5,54 @@
|
|||||||
extern crate crossterm;
|
extern crate crossterm;
|
||||||
|
|
||||||
use self::crossterm::style::{ Color };
|
use self::crossterm::style::{ Color };
|
||||||
|
use self::crossterm::terminal;
|
||||||
|
use self::crossterm::Context;
|
||||||
|
|
||||||
/// print some red font | demonstration.
|
/// print some red font | demonstration.
|
||||||
pub fn paint_foreground()
|
pub fn paint_foreground()
|
||||||
{
|
{
|
||||||
|
let context = Context::new();
|
||||||
|
let terminal = terminal::terminal(&context);
|
||||||
|
|
||||||
// Pass an string to the `paint()` method with you want to paint.
|
// 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.
|
// This will give you an object back wits can be styled and displayed.
|
||||||
let mut styledobject = paint("Red font");
|
let mut styledobject = terminal.paint("Red font");
|
||||||
// Call the method `with()` on the object given by `paint()` and pass in any Color from the Color enum.
|
// Call the method `with()` on the object given by `paint()` and pass in any Color from the Color enum.
|
||||||
styledobject = styledobject.with(Color::Red);
|
styledobject = styledobject.with(Color::Red);
|
||||||
// Print the object to the console and see the result.
|
// Print the object to the console and see the result.
|
||||||
println!("{}", styledobject);
|
println!("{}", styledobject);
|
||||||
|
|
||||||
// Crossterm provides method chaining so that the above points can be inlined.
|
// Crossterm provides method chaining so that the above points can be inlined.
|
||||||
println!("{}", paint("Red font").with(Color::Red));
|
println!("{}", terminal.paint("Red font").with(Color::Red));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// print some font on red background | demonstration.
|
/// print some font on red background | demonstration.
|
||||||
pub fn paint_background()
|
pub fn paint_background()
|
||||||
{
|
{
|
||||||
|
let context = Context::new();
|
||||||
|
let terminal = terminal::terminal(&context);
|
||||||
|
|
||||||
// Pass an string to the `paint()` method with you want to paint.
|
// 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.
|
// This will give you an object back wits can be styled and displayed.
|
||||||
let mut styledobject = paint("Red background color");
|
let mut styledobject = terminal.paint("Red background color");
|
||||||
// Call the method `on()` on the object given by `paint()` and pass in an Color from the Color enum.
|
// Call the method `on()` on the object given by `paint()` and pass in an Color from the Color enum.
|
||||||
styledobject = styledobject.on(Color::Red);
|
styledobject = styledobject.on(Color::Red);
|
||||||
// Print the object to the console and check see the result
|
// Print the object to the console and check see the result
|
||||||
println!("{}", styledobject);
|
println!("{}", styledobject);
|
||||||
|
|
||||||
// Crossterm provides method chaining so that the above points can be inlined.
|
// Crossterm provides method chaining so that the above points can be inlined.
|
||||||
println!("{}", paint("Red background color").on(Color::Red));
|
println!("{}", terminal.paint("Red background color").on(Color::Red));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// print font with fore- background color | demonstration.
|
/// print font with fore- background color | demonstration.
|
||||||
pub fn paint_foreground_and_background()
|
pub fn paint_foreground_and_background()
|
||||||
{
|
{
|
||||||
|
let context = Context::new();
|
||||||
|
let terminal = terminal::terminal(&context);
|
||||||
|
|
||||||
// Pass an string to the `paint()` method with you want to paint.
|
// 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.
|
// This will give you an object back wits can be styled and displayed.
|
||||||
let mut styledobject = paint("Red font on blue background color");
|
let mut styledobject = terminal.paint("Red font on blue background color");
|
||||||
/* Foreground color:
|
/* Foreground color:
|
||||||
Call the method `with()` on the object given by `paint()`
|
Call the method `with()` on the object given by `paint()`
|
||||||
Pass in an Color from the Color enum.
|
Pass in an Color from the Color enum.
|
||||||
@ -56,77 +67,89 @@ pub fn paint_foreground_and_background()
|
|||||||
println!("{}", styledobject);
|
println!("{}", styledobject);
|
||||||
|
|
||||||
// Crossterm provides method chaining so that the above points can be inlined.
|
// Crossterm provides method chaining so that the above points can be inlined.
|
||||||
println!("{}", paint("Red font on blue background color").with(Color::Red).on(Color::Blue));
|
println!("{}", terminal.paint("Red font on blue background color").with(Color::Red).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()
|
||||||
{
|
{
|
||||||
println!("Black : \t {}", paint("■").with(Color::Black));
|
let context = Context::new();
|
||||||
println!("Red : \t\t {}", paint("■").with(Color::Red));
|
let terminal = terminal::terminal(&context);
|
||||||
println!("Dark Red: \t {}", paint("■").with(Color::DarkRed));
|
|
||||||
println!("Green : \t {}", paint("■").with(Color::Green));
|
println!("Black : \t {}", terminal.paint("■").with(Color::Black));
|
||||||
println!("Dark Green : \t {}", paint("■").with(Color::DarkGreen));
|
println!("Red : \t\t {}", terminal.paint("■").with(Color::Red));
|
||||||
println!("Yellow : \t {}", paint("■").with(Color::Yellow));
|
println!("Dark Red: \t {}", terminal.paint("■").with(Color::DarkRed));
|
||||||
println!("Dark Yellow : \t {}", paint("■").with(Color::DarkYellow));
|
println!("Green : \t {}", terminal.paint("■").with(Color::Green));
|
||||||
println!("Blue : \t\t {}", paint("■").with(Color::Blue));
|
println!("Dark Green : \t {}", terminal.paint("■").with(Color::DarkGreen));
|
||||||
println!("Dark Blue : \t {}", paint("■").with(Color::DarkBlue));
|
println!("Yellow : \t {}", terminal.paint("■").with(Color::Yellow));
|
||||||
println!("Magenta : \t {}", paint("■").with(Color::Magenta));
|
println!("Dark Yellow : \t {}", terminal.paint("■").with(Color::DarkYellow));
|
||||||
println!("Dark Magenta : \t {}", paint("■").with(Color::DarkMagenta));
|
println!("Blue : \t\t {}", terminal.paint("■").with(Color::Blue));
|
||||||
println!("Cyan : \t\t {}", paint("■").with(Color::Cyan));
|
println!("Dark Blue : \t {}", terminal.paint("■").with(Color::DarkBlue));
|
||||||
println!("Dark Cyan : \t {}", paint("■").with(Color::DarkCyan));
|
println!("Magenta : \t {}", terminal.paint("■").with(Color::Magenta));
|
||||||
println!("Grey : \t\t {}", paint("■").with(Color::Grey));
|
println!("Dark Magenta : \t {}", terminal.paint("■").with(Color::DarkMagenta));
|
||||||
println!("White : \t {}", paint("■").with(Color::White));
|
println!("Cyan : \t\t {}", terminal.paint("■").with(Color::Cyan));
|
||||||
|
println!("Dark Cyan : \t {}", terminal.paint("■").with(Color::DarkCyan));
|
||||||
|
println!("Grey : \t\t {}", terminal.paint("■").with(Color::Grey));
|
||||||
|
println!("White : \t {}", terminal.paint("■").with(Color::White));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Print all available foreground colors | demonstration.
|
/// Print all available foreground colors | demonstration.
|
||||||
pub fn print_all_background_colors()
|
pub fn print_all_background_colors()
|
||||||
{
|
{
|
||||||
println!("Black : \t {}", paint(" ").on(Color::Black));
|
let context = Context::new();
|
||||||
println!("Red : \t\t {}", paint(" ").on(Color::Red));
|
let terminal = terminal::terminal(&context);
|
||||||
println!("Dark Red: \t {}", paint(" ").on(Color::DarkRed));
|
|
||||||
println!("Green : \t {}", paint(" ").on(Color::Green));
|
println!("Black : \t {}", terminal.paint(" ").on(Color::Black));
|
||||||
println!("Dark Green : \t {}", paint(" ").on(Color::DarkGreen));
|
println!("Red : \t\t {}", terminal.paint(" ").on(Color::Red));
|
||||||
println!("Yellow : \t {}", paint(" ").on(Color::Yellow));
|
println!("Dark Red: \t {}", terminal.paint(" ").on(Color::DarkRed));
|
||||||
println!("Dark Yellow : \t {}", paint(" ").on(Color::DarkYellow));
|
println!("Green : \t {}", terminal.paint(" ").on(Color::Green));
|
||||||
println!("Blue : \t\t {}", paint(" ").on(Color::Blue));
|
println!("Dark Green : \t {}", terminal.paint(" ").on(Color::DarkGreen));
|
||||||
println!("Dark Blue : \t {}", paint(" ").on(Color::DarkBlue));
|
println!("Yellow : \t {}", terminal.paint(" ").on(Color::Yellow));
|
||||||
println!("Magenta : \t {}", paint(" ").on(Color::Magenta));
|
println!("Dark Yellow : \t {}", terminal.paint(" ").on(Color::DarkYellow));
|
||||||
println!("Dark Magenta : \t {}", paint(" ").on(Color::DarkMagenta));
|
println!("Blue : \t\t {}", terminal.paint(" ").on(Color::Blue));
|
||||||
println!("Cyan : \t\t {}", paint(" ").on(Color::Cyan));
|
println!("Dark Blue : \t {}", terminal.paint(" ").on(Color::DarkBlue));
|
||||||
println!("Dark Cyan : \t {}", paint(" ").on(Color::DarkCyan));
|
println!("Magenta : \t {}", terminal.paint(" ").on(Color::Magenta));
|
||||||
println!("Grey : \t\t {}", paint(" ").on(Color::Grey));
|
println!("Dark Magenta : \t {}", terminal.paint(" ").on(Color::DarkMagenta));
|
||||||
println!("White : \t {}", paint(" ").on(Color::White));
|
println!("Cyan : \t\t {}", terminal.paint(" ").on(Color::Cyan));
|
||||||
|
println!("Dark Cyan : \t {}", terminal.paint(" ").on(Color::DarkCyan));
|
||||||
|
println!("Grey : \t\t {}", terminal.paint(" ").on(Color::Grey));
|
||||||
|
println!("White : \t {}", terminal.paint(" ").on(Color::White));
|
||||||
#[cfg(unix)]
|
#[cfg(unix)]
|
||||||
println!("RGB (10,10,10): \t {}", paint(" ").on(Color::Rgb {r: 10, g: 10, b: 10}));
|
println!("RGB (10,10,10): \t {}", terminal.paint(" ").on(Color::Rgb {r: 10, g: 10, b: 10}));
|
||||||
#[cfg(unix)]
|
#[cfg(unix)]
|
||||||
println!("RGB (10,10,10): \t {}", paint(" ").on(Color::AnsiValue(50)));
|
println!("RGB (10,10,10): \t {}", terminal.paint(" ").on(Color::AnsiValue(50)));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Print font with all available attributes. Note that this can only be used at unix systems and that some are not supported widely | demonstration..
|
/// 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()
|
||||||
{
|
{
|
||||||
println!("{}", paint("Normal text"));
|
let context = Context::new();
|
||||||
println!("{}", paint("Bold text").bold());
|
let terminal = terminal::terminal(&context);
|
||||||
println!("{}", paint("Italic text").italic());
|
|
||||||
println!("{}", paint("Slow blinking text").slow_blink());
|
println!("{}", terminal.paint("Normal text"));
|
||||||
println!("{}", paint("Rapid blinking text").rapid_blink());
|
println!("{}", terminal.paint("Bold text").bold());
|
||||||
println!("{}", paint("Hidden text").hidden());
|
println!("{}", terminal.paint("Italic text").italic());
|
||||||
println!("{}", paint("Underlined text").underlined());
|
println!("{}", terminal.paint("Slow blinking text").slow_blink());
|
||||||
println!("{}", paint("Reversed color").reverse());
|
println!("{}", terminal.paint("Rapid blinking text").rapid_blink());
|
||||||
println!("{}", paint("Dim text color").dim());
|
println!("{}", terminal.paint("Hidden text").hidden());
|
||||||
println!("{}", paint("Crossed out font").crossed_out());
|
println!("{}", terminal.paint("Underlined text").underlined());
|
||||||
|
println!("{}", terminal.paint("Reversed color").reverse());
|
||||||
|
println!("{}", terminal.paint("Dim text color").dim());
|
||||||
|
println!("{}", terminal.paint("Crossed out font").crossed_out());
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Print all supported rgb colors | demonstration.
|
/// Print all supported rgb colors | demonstration.
|
||||||
#[cfg(unix)]
|
#[cfg(unix)]
|
||||||
pub fn print_supported_colors()
|
pub fn print_supported_colors()
|
||||||
{
|
{
|
||||||
let count = crossterm::style::color().get_available_color_count().unwrap();
|
let context = Context::new();
|
||||||
|
let terminal = terminal::terminal(&context);
|
||||||
|
|
||||||
|
let count = crossterm::style::color(context.screen_manager.clone()).get_available_color_count().unwrap();
|
||||||
|
|
||||||
for i in 0..count
|
for i in 0..count
|
||||||
{
|
{
|
||||||
println!("{}", paint(format!("Color: {}",i)).with(Color::AnsiValue(i as u8)));
|
println!("{}", terminal.paint(format!("Color: {}",i)).with(Color::AnsiValue(i as u8)));
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -3,23 +3,38 @@
|
|||||||
//!
|
//!
|
||||||
|
|
||||||
extern crate crossterm;
|
extern crate crossterm;
|
||||||
|
|
||||||
use self::crossterm::cursor::{cursor, TerminalCursor};
|
use self::crossterm::cursor::{cursor, TerminalCursor};
|
||||||
|
use self::crossterm::Context;
|
||||||
|
|
||||||
/// 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()
|
||||||
{
|
{
|
||||||
|
let context = Context::new();
|
||||||
|
|
||||||
// Get the cursor
|
// Get the cursor
|
||||||
let mut cursor = cursor();
|
let mut cursor = cursor(&context);
|
||||||
// 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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// get the cursor position
|
||||||
|
pub fn pos()
|
||||||
|
{
|
||||||
|
let context = Context::new();
|
||||||
|
|
||||||
|
// Get the cursor
|
||||||
|
let mut cursor = cursor(&context);
|
||||||
|
// get the cursor position.
|
||||||
|
let (x,y) = cursor.pos();
|
||||||
|
}
|
||||||
|
|
||||||
/// Move the cursor 3 up | demonstration.
|
/// Move the cursor 3 up | demonstration.
|
||||||
pub fn move_up()
|
pub fn move_up()
|
||||||
{
|
{
|
||||||
|
let context = Context::new();
|
||||||
|
|
||||||
// Get the cursor
|
// Get the cursor
|
||||||
let mut cursor = cursor();
|
let mut cursor = cursor(&context);
|
||||||
// Move the cursor to position 3 times to the up in the terminal
|
// Move the cursor to position 3 times to the up in the terminal
|
||||||
cursor.move_up(3);
|
cursor.move_up(3);
|
||||||
}
|
}
|
||||||
@ -27,8 +42,10 @@ 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 context = Context::new();
|
||||||
|
|
||||||
// Get the cursor
|
// Get the cursor
|
||||||
let mut cursor = cursor();
|
let mut cursor = cursor(&context);
|
||||||
// Move the cursor to position 3 times to the right in the terminal
|
// Move the cursor to position 3 times to the right in the terminal
|
||||||
cursor.move_right(3);
|
cursor.move_right(3);
|
||||||
}
|
}
|
||||||
@ -36,8 +53,10 @@ pub fn move_right()
|
|||||||
/// Move the cursor 3 down | demonstration.
|
/// Move the cursor 3 down | demonstration.
|
||||||
pub fn move_down()
|
pub fn move_down()
|
||||||
{
|
{
|
||||||
|
let context = Context::new();
|
||||||
|
|
||||||
// Get the cursor
|
// Get the cursor
|
||||||
let mut cursor = cursor();
|
let mut cursor = cursor(&context);
|
||||||
// Move the cursor to position 3 times to the down in the terminal
|
// Move the cursor to position 3 times to the down in the terminal
|
||||||
cursor.move_down(3);
|
cursor.move_down(3);
|
||||||
}
|
}
|
||||||
@ -45,8 +64,10 @@ pub fn move_down()
|
|||||||
/// 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 context = Context::new();
|
||||||
|
|
||||||
// Get the cursor
|
// Get the cursor
|
||||||
let mut cursor = cursor();
|
let mut cursor = cursor(&context);
|
||||||
// Move the cursor to position 3 times to the left in the terminal
|
// Move the cursor to position 3 times to the left in the terminal
|
||||||
cursor.move_left(3);
|
cursor.move_left(3);
|
||||||
}
|
}
|
||||||
@ -54,10 +75,12 @@ pub fn move_left()
|
|||||||
/// Print character at X: 10 Y: 5 | demonstration.
|
/// Print character at X: 10 Y: 5 | demonstration.
|
||||||
pub fn print()
|
pub fn print()
|
||||||
{
|
{
|
||||||
|
let context = Context::new();
|
||||||
|
|
||||||
// To print an some displayable content on an certain position.
|
// To print an some displayable content on an certain position.
|
||||||
|
|
||||||
// Get the cursor
|
// Get the cursor
|
||||||
let mut cursor = cursor();
|
let mut cursor = cursor(&context);
|
||||||
// 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);
|
||||||
// Print the @ symbol at position X: 10, Y: 5 in the terminal
|
// Print the @ symbol at position X: 10, Y: 5 in the terminal
|
||||||
@ -79,7 +102,9 @@ pub fn print()
|
|||||||
/// 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 mut cursor = cursor();
|
let context = Context::new();
|
||||||
|
|
||||||
|
let mut cursor = cursor(&context);
|
||||||
|
|
||||||
// Goto X: 5 Y: 5
|
// Goto X: 5 Y: 5
|
||||||
cursor.goto(5,5);
|
cursor.goto(5,5);
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
extern crate crossterm;
|
extern crate crossterm;
|
||||||
|
|
||||||
use crossterm::Terminal;
|
use crossterm::Context;
|
||||||
use crossterm::screen::AlternateScreen;
|
use crossterm::screen::AlternateScreen;
|
||||||
use crossterm::cursor::cursor;
|
use crossterm::cursor::cursor;
|
||||||
use crossterm::terminal::{self, ClearType};
|
use crossterm::terminal::{self, ClearType};
|
||||||
@ -8,7 +8,7 @@ use crossterm::terminal::{self, ClearType};
|
|||||||
use std::io::{Write, stdout};
|
use std::io::{Write, stdout};
|
||||||
use std::{time, thread};
|
use std::{time, thread};
|
||||||
|
|
||||||
fn print_wait_screen(terminal: &Terminal)
|
fn print_wait_screen(terminal: &Context)
|
||||||
{
|
{
|
||||||
terminal::terminal(&terminal).clear(ClearType::All);
|
terminal::terminal(&terminal).clear(ClearType::All);
|
||||||
|
|
||||||
@ -39,16 +39,16 @@ fn print_wait_screen(terminal: &Terminal)
|
|||||||
|
|
||||||
pub fn print_wait_screen_on_alternate_window()
|
pub fn print_wait_screen_on_alternate_window()
|
||||||
{
|
{
|
||||||
let terminal = Terminal::new();
|
let context = Context::new();
|
||||||
|
|
||||||
// create scope. If this scope ends the screen will be switched back to mainscreen.
|
// create scope. If this scope ends the screen will be switched back to mainscreen.
|
||||||
// because `AlternateScreen` switches back to main screen when switching back.
|
// because `AlternateScreen` switches back to main screen when switching back.
|
||||||
{
|
{
|
||||||
// create new alternate screen instance and switch to the alternate screen.
|
// create new alternate screen instance and switch to the alternate screen.
|
||||||
let mut screen = AlternateScreen::from(&terminal);
|
let mut screen = AlternateScreen::from(&context);
|
||||||
|
|
||||||
// Print the wait screen.
|
// Print the wait screen.
|
||||||
print_wait_screen(&terminal);
|
print_wait_screen(&context);
|
||||||
}
|
}
|
||||||
|
|
||||||
println!("Whe are back at the main screen");
|
println!("Whe are back at the main screen");
|
||||||
@ -56,12 +56,12 @@ pub fn print_wait_screen_on_alternate_window()
|
|||||||
|
|
||||||
pub fn switch_between_main_and_alternate_screen()
|
pub fn switch_between_main_and_alternate_screen()
|
||||||
{
|
{
|
||||||
let terminal = Terminal::new();
|
let context = Context::new();
|
||||||
let mut cursor = cursor(&terminal);
|
let mut cursor = cursor(&context);
|
||||||
|
|
||||||
{
|
{
|
||||||
// create new alternate screen instance and switch to the alternate screen.
|
// create new alternate screen instance and switch to the alternate screen.
|
||||||
let mut screen = AlternateScreen::from(&terminal);
|
let mut screen = AlternateScreen::from(&context);
|
||||||
cursor.goto(0,0);
|
cursor.goto(0,0);
|
||||||
write!(screen, "we are at the alternate screen!");
|
write!(screen, "we are at the alternate screen!");
|
||||||
screen.flush();
|
screen.flush();
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
extern crate crossterm;
|
extern crate crossterm;
|
||||||
|
|
||||||
use crossterm::Terminal;
|
use crossterm::Context;
|
||||||
use crossterm::screen::AlternateScreen;
|
use crossterm::screen::AlternateScreen;
|
||||||
use crossterm::cursor::cursor;
|
use crossterm::cursor::cursor;
|
||||||
use crossterm::terminal::{self, ClearType};
|
use crossterm::terminal::{self, ClearType};
|
||||||
@ -11,23 +11,14 @@ use std::{time, thread};
|
|||||||
use crossterm::raw::IntoRawMode;
|
use crossterm::raw::IntoRawMode;
|
||||||
|
|
||||||
// raw screen is not working correctly currently
|
// raw screen is not working correctly currently
|
||||||
fn print_wait_screen(terminal: &Terminal)
|
fn print_wait_screen(context: &Context)
|
||||||
{
|
{
|
||||||
terminal::terminal(&terminal).clear(ClearType::All);
|
terminal::terminal(&context).clear(ClearType::All);
|
||||||
|
|
||||||
let mut cursor = cursor(&terminal);
|
let mut cursor = cursor(&context);
|
||||||
cursor.goto(0,0);
|
cursor.goto(0,0).print("Welcome to the wait screen.");
|
||||||
|
cursor.goto(0,1).print("Please wait a few seconds until we arrive back at the main screen.");
|
||||||
{
|
cursor.goto(0,2).print("Progress: ");
|
||||||
let mut screen_manager = terminal.screen_manager.lock().unwrap();
|
|
||||||
{
|
|
||||||
write!(screen_manager.stdout(),
|
|
||||||
"Welcome to the wait screen.\n\
|
|
||||||
Please wait a few seconds until we arrive back at the main screen.\n\
|
|
||||||
Progress: "
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// print some progress example.
|
// print some progress example.
|
||||||
for i in 1..5
|
for i in 1..5
|
||||||
@ -42,18 +33,21 @@ fn print_wait_screen(terminal: &Terminal)
|
|||||||
|
|
||||||
pub fn print_wait_screen_on_alternate_window()
|
pub fn print_wait_screen_on_alternate_window()
|
||||||
{
|
{
|
||||||
let terminal = Terminal::new();
|
let context = Context::new();
|
||||||
|
|
||||||
// create scope. If this scope ends the screen will be switched back to mainscreen.
|
// create scope. If this scope ends the screen will be switched back to mainscreen.
|
||||||
// because `AlternateScreen` switches back to main screen when switching back.
|
// because `AlternateScreen` switches back to main screen when going out of scope.
|
||||||
{
|
{
|
||||||
let a = stdout().into_raw_mode(&terminal);
|
// create new alternate screen instance this call is also switching the screen to alternate screen.
|
||||||
|
// then convert the output of the program to raw mode.
|
||||||
|
// then print the wait screen on the alternate screen in raw mode.
|
||||||
|
let mut screen = AlternateScreen::from(&context);
|
||||||
|
let alternate_screen = screen.into_raw_mode(&context);
|
||||||
|
|
||||||
thread::sleep(time::Duration::from_secs(3));
|
// Print the wait screen.
|
||||||
|
print_wait_screen(&context);
|
||||||
|
|
||||||
|
screen.flush();
|
||||||
// // Print the wait screen.
|
|
||||||
// print_wait_screen(&terminal);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
println!("Whe are back at the main screen");
|
println!("Whe are back at the main screen");
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
|
|
||||||
extern crate crossterm;
|
extern crate crossterm;
|
||||||
|
|
||||||
use crossterm::Terminal;
|
use crossterm::Context;
|
||||||
use crossterm::terminal::{ ClearType, terminal };
|
use crossterm::terminal::{ ClearType, terminal };
|
||||||
use crossterm::cursor;
|
use crossterm::cursor;
|
||||||
|
|
||||||
@ -18,10 +18,10 @@ 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 term = Terminal::new();
|
let context = Context::new();
|
||||||
|
|
||||||
// Get terminal
|
// Get terminal
|
||||||
let mut terminal = terminal(&term);
|
let mut terminal = terminal(&context);
|
||||||
|
|
||||||
print_test_data();
|
print_test_data();
|
||||||
|
|
||||||
@ -32,15 +32,15 @@ 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 term = Terminal::new();
|
let context = Context::new();
|
||||||
|
|
||||||
// Get terminal
|
// Get terminal
|
||||||
let mut terminal = terminal(&term);
|
let mut terminal = terminal(&context);
|
||||||
|
|
||||||
print_test_data();
|
print_test_data();
|
||||||
|
|
||||||
// Set terminal cursor position (see example for more info).
|
// Set terminal cursor position (see example for more info).
|
||||||
cursor::cursor(&term).goto(4,8);
|
cursor::cursor(&context).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);
|
||||||
@ -49,15 +49,15 @@ 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 term = Terminal::new();
|
let context = Context::new();
|
||||||
|
|
||||||
// Get terminal
|
// Get terminal
|
||||||
let mut terminal = terminal(&term);
|
let mut terminal = terminal(&context);
|
||||||
|
|
||||||
print_test_data();
|
print_test_data();
|
||||||
|
|
||||||
// Set terminal cursor position (see example for more info).
|
// Set terminal cursor position (see example for more info).
|
||||||
cursor::cursor(&term).goto(4,4);
|
cursor::cursor(&context).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);
|
||||||
@ -66,15 +66,15 @@ 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 term = Terminal::new();
|
let context = Context::new();
|
||||||
|
|
||||||
// Get terminal
|
// Get terminal
|
||||||
let mut terminal = terminal(&term);
|
let mut terminal = terminal(&context);
|
||||||
|
|
||||||
print_test_data();
|
print_test_data();
|
||||||
|
|
||||||
// Set terminal cursor position (see example for more info).
|
// Set terminal cursor position (see example for more info).
|
||||||
cursor::cursor(&term).goto(4,4);
|
cursor::cursor(&context).goto(4,4);
|
||||||
|
|
||||||
// Clear current line cells.
|
// Clear current line cells.
|
||||||
terminal.clear(ClearType::CurrentLine);
|
terminal.clear(ClearType::CurrentLine);
|
||||||
@ -83,15 +83,15 @@ 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 term = Terminal::new();
|
let context = Context::new();
|
||||||
|
|
||||||
// Get terminal
|
// Get terminal
|
||||||
let mut terminal = terminal(&term);
|
let mut terminal = terminal(&context);
|
||||||
|
|
||||||
print_test_data();
|
print_test_data();
|
||||||
|
|
||||||
// Set terminal cursor position (see example for more info).
|
// Set terminal cursor position (see example for more info).
|
||||||
cursor::cursor(&term).goto(4,20);
|
cursor::cursor(&context).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);
|
||||||
@ -100,10 +100,10 @@ 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 term = Terminal::new();
|
let context = Context::new();
|
||||||
|
|
||||||
// Get terminal
|
// Get terminal
|
||||||
let mut terminal = terminal(&term);
|
let mut terminal = terminal(&context);
|
||||||
// Get terminal size
|
// Get terminal size
|
||||||
let terminal_size = terminal.terminal_size();
|
let terminal_size = terminal.terminal_size();
|
||||||
// Print results
|
// Print results
|
||||||
@ -113,9 +113,9 @@ 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 term = Terminal::new();
|
let context = Context::new();
|
||||||
|
|
||||||
let mut terminal = terminal(&term);
|
let mut terminal = terminal(&context);
|
||||||
|
|
||||||
terminal.set_size(10,10);
|
terminal.set_size(10,10);
|
||||||
}
|
}
|
||||||
@ -123,11 +123,11 @@ pub fn set_terminal_size()
|
|||||||
/// Scroll down 10 lines | demonstration.
|
/// Scroll down 10 lines | demonstration.
|
||||||
pub fn scroll_down()
|
pub fn scroll_down()
|
||||||
{
|
{
|
||||||
let term = Terminal::new();
|
let context = Context::new();
|
||||||
|
|
||||||
print_test_data();
|
print_test_data();
|
||||||
// Get terminal
|
// Get terminal
|
||||||
let mut terminal = terminal(&term);
|
let mut terminal = terminal(&context);
|
||||||
// Scroll down 10 lines.
|
// Scroll down 10 lines.
|
||||||
terminal.scroll_down(10);
|
terminal.scroll_down(10);
|
||||||
}
|
}
|
||||||
@ -135,12 +135,12 @@ pub fn scroll_down()
|
|||||||
/// Scroll down 10 lines | demonstration.
|
/// Scroll down 10 lines | demonstration.
|
||||||
pub fn scroll_up()
|
pub fn scroll_up()
|
||||||
{
|
{
|
||||||
let term = Terminal::new();
|
let context = Context::new();
|
||||||
|
|
||||||
print_test_data();
|
print_test_data();
|
||||||
|
|
||||||
// Get terminal
|
// Get terminal
|
||||||
let mut terminal = terminal(&term);
|
let mut terminal = terminal(&context);
|
||||||
// Scroll up 10 lines.
|
// Scroll up 10 lines.
|
||||||
terminal.scroll_up(10);
|
terminal.scroll_up(10);
|
||||||
}
|
}
|
||||||
@ -148,10 +148,10 @@ 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 term = Terminal::new();
|
let context = Context::new();
|
||||||
|
|
||||||
// Get terminal
|
// Get terminal
|
||||||
let mut terminal = terminal(&term);
|
let mut terminal = terminal(&context);
|
||||||
// Get terminal size
|
// Get terminal size
|
||||||
terminal.set_size(10,10);
|
terminal.set_size(10,10);
|
||||||
}
|
}
|
||||||
|
@ -1,75 +1,73 @@
|
|||||||
//! This is an ANSI specific implementation for cursor related action.
|
//! This is an ANSI specific implementation for cursor related action.
|
||||||
//! This module is used for windows 10 terminals and unix terminals by default.
|
//! This module is used for windows 10 terminals and unix terminals by default.
|
||||||
|
//! Note that the cursor position is 0 based. This means that we start counting at 0 when setting the cursor position ect.
|
||||||
|
|
||||||
use Terminal ;
|
use Context;
|
||||||
use shared::functions;
|
use shared::functions;
|
||||||
use super::ITerminalCursor;
|
use super::ITerminalCursor;
|
||||||
|
|
||||||
|
|
||||||
/// 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<'output> AnsiCursor {
|
impl AnsiCursor {
|
||||||
pub fn new() -> Box<AnsiCursor> {
|
pub fn new() -> Box<AnsiCursor> {
|
||||||
Box::from(AnsiCursor {})
|
Box::from(AnsiCursor {})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'term> ITerminalCursor for AnsiCursor {
|
impl ITerminalCursor for AnsiCursor {
|
||||||
|
|
||||||
fn goto(&self, x: u16, y: u16, terminal: &Terminal)
|
fn goto(&self, x: u16, y: u16, context: &Context)
|
||||||
{
|
{
|
||||||
// ANSI codes are one-based. I want 0 based so we just need to increment and x,y.
|
let mut screen = context.screen_manager.lock().unwrap();
|
||||||
let mut screen = terminal.screen_manager.lock().unwrap();
|
|
||||||
{
|
{
|
||||||
screen.write_ansi(format!(csi!("{};{}H"), y + 1, x +1));
|
screen.write_ansi(format!(csi!("{};{}H"), y + 1, x +1));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn pos(&self, terminal: &Terminal) -> (u16, u16) {
|
fn pos(&self, context: &Context) -> (u16, u16) {
|
||||||
functions::get_cursor_position(&terminal)
|
functions::get_cursor_position(&context)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn move_up(&self, count: u16, terminal: &Terminal) {
|
fn move_up(&self, count: u16, context: &Context) {
|
||||||
let mut screen = terminal.screen_manager.lock().unwrap();
|
let mut screen = context.screen_manager.lock().unwrap();
|
||||||
{
|
{
|
||||||
screen.write_ansi(format!(csi!("{}A"), count));
|
screen.write_ansi(format!(csi!("{}A"), count));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn move_right(&self, count: u16, terminal: &Terminal) {
|
fn move_right(&self, count: u16, context: &Context) {
|
||||||
let mut screen = terminal.screen_manager.lock().unwrap();
|
let mut screen = context.screen_manager.lock().unwrap();
|
||||||
{
|
{
|
||||||
screen.write_ansi(format!(csi!("{}C"), count));
|
screen.write_ansi(format!(csi!("{}C"), count));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn move_down(&self, count: u16, terminal: &Terminal) {
|
fn move_down(&self, count: u16, context: &Context) {
|
||||||
let mut screen = terminal.screen_manager.lock().unwrap();
|
let mut screen = context.screen_manager.lock().unwrap();
|
||||||
{
|
{
|
||||||
screen.write_ansi(format!(csi!("{}B"), count));
|
screen.write_ansi(format!(csi!("{}B"), count));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn move_left(&self, count: u16, terminal: &Terminal) {
|
fn move_left(&self, count: u16, context: &Context) {
|
||||||
let mut screen = terminal.screen_manager.lock().unwrap();
|
let mut screen = context.screen_manager.lock().unwrap();
|
||||||
{
|
{
|
||||||
screen.write_ansi(format!(csi!("{}D"), count));
|
screen.write_ansi(format!(csi!("{}D"), count));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn save_position(&mut self, terminal: &Terminal)
|
fn save_position(&mut self, context: &Context)
|
||||||
{
|
{
|
||||||
let mut screen = terminal.screen_manager.lock().unwrap();
|
let mut screen = context.screen_manager.lock().unwrap();
|
||||||
{
|
{
|
||||||
screen.write_ansi_str(csi!("s"));
|
screen.write_ansi_str(csi!("s"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn reset_position(&self, terminal: &Terminal)
|
fn reset_position(&self, context: &Context)
|
||||||
{
|
{
|
||||||
let mut screen = terminal.screen_manager.lock().unwrap();
|
let mut screen = context.screen_manager.lock().unwrap();
|
||||||
{
|
{
|
||||||
screen.write_ansi_str(csi!("u"));
|
screen.write_ansi_str(csi!("u"));
|
||||||
}
|
}
|
||||||
|
@ -1,31 +1,31 @@
|
|||||||
//! With this module you can perform actions that are cursor related.
|
//! With this module you can perform actions that are cursor related.
|
||||||
//! Like changing and displaying the position of the cursor in terminal.
|
//! Like changing and display the position of the cursor in terminal.
|
||||||
//!
|
//!
|
||||||
//! Note that positions of the cursor are 0 -based witch means that the coordinates starts counting from 0
|
//! Note that positions of the cursor are 0 -based witch means that the coordinates (cells) starts counting from 0
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
use Terminal;
|
use Context;
|
||||||
|
|
||||||
use std::fmt::Display;
|
use std::fmt::Display;
|
||||||
use std::io::Write;
|
use std::io::Write;
|
||||||
|
|
||||||
/// Struct that stores an specific platform implementation for cursor related actions.
|
/// Struct that stores an specific platform implementation for cursor related actions.
|
||||||
pub struct TerminalCursor<'term> {
|
pub struct TerminalCursor<'context> {
|
||||||
terminal: &'term Terminal,
|
context: &'context Context,
|
||||||
terminal_cursor: Option<Box<ITerminalCursor>>,
|
terminal_cursor: Option<Box<ITerminalCursor>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl <'term> TerminalCursor<'term>
|
impl <'context> TerminalCursor<'context>
|
||||||
{
|
{
|
||||||
/// 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(terminal: &'term Terminal) -> TerminalCursor<'term> {
|
pub fn new(context: &'context Context) -> TerminalCursor<'context> {
|
||||||
#[cfg(target_os = "windows")]
|
#[cfg(target_os = "windows")]
|
||||||
let cursor = functions::get_module::<Box<ITerminalCursor>>(WinApiCursor::new(), AnsiCursor::new());
|
let cursor = functions::get_module::<Box<ITerminalCursor>>(WinApiCursor::new(), AnsiCursor::new());
|
||||||
|
|
||||||
#[cfg(not(target_os = "windows"))]
|
#[cfg(not(target_os = "windows"))]
|
||||||
let cursor = Some(AnsiCursor::new() as Box<ITerminalCursor>);
|
let cursor = Some(AnsiCursor::new() as Box<ITerminalCursor>);
|
||||||
|
|
||||||
TerminalCursor { terminal_cursor: cursor , terminal: terminal}
|
TerminalCursor { terminal_cursor: cursor , context}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Goto some position (x,y) in the terminal.
|
/// Goto some position (x,y) in the terminal.
|
||||||
@ -35,15 +35,23 @@ impl <'term> TerminalCursor<'term>
|
|||||||
/// ```rust
|
/// ```rust
|
||||||
///
|
///
|
||||||
/// extern crate crossterm;
|
/// extern crate crossterm;
|
||||||
///
|
/// use self::crossterm::Context;
|
||||||
/// use self::crossterm::cursor;
|
/// use self::crossterm::cursor;
|
||||||
///
|
///
|
||||||
/// cursor::cursor().goto(10,10);
|
// pub fn goto()
|
||||||
|
// {
|
||||||
|
// let context = Context::new();
|
||||||
|
//
|
||||||
|
// // Get the cursor
|
||||||
|
// let mut cursor = cursor(&context);
|
||||||
|
// // Set the cursor to position X: 10, Y: 5 in the terminal
|
||||||
|
// cursor.goto(10,5);
|
||||||
|
// }
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
pub fn goto(&mut self, x: u16, y: u16) -> &mut TerminalCursor<'term> {
|
pub fn goto(&mut self, x: u16, y: u16) -> &mut TerminalCursor<'context> {
|
||||||
if let Some(ref terminal_cursor) = self.terminal_cursor {
|
if let Some(ref terminal_cursor) = self.terminal_cursor {
|
||||||
terminal_cursor.goto(x, y, &self.terminal);
|
terminal_cursor.goto(x, y, &self.context);
|
||||||
}
|
}
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
@ -55,16 +63,23 @@ impl <'term> TerminalCursor<'term>
|
|||||||
/// ```rust
|
/// ```rust
|
||||||
///
|
///
|
||||||
/// extern crate crossterm;
|
/// extern crate crossterm;
|
||||||
///
|
/// use self::crossterm::Context;
|
||||||
/// use self::crossterm::cursor;
|
/// use self::crossterm::cursor;
|
||||||
///
|
///
|
||||||
/// let pos = cursor::cursor().pos();
|
/// pub fn pos()
|
||||||
/// println!("{:?}", pos);
|
/// {
|
||||||
|
/// let context = Context::new();
|
||||||
|
///
|
||||||
|
/// // Get the cursor
|
||||||
|
/// let mut cursor = cursor(&context);
|
||||||
|
/// // get the cursor position.
|
||||||
|
/// let (x,y) = cursor.pos();
|
||||||
|
/// }
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
pub fn pos(&mut self) -> (u16, u16) {
|
pub fn pos(&mut self) -> (u16, u16) {
|
||||||
if let Some(ref terminal_cursor) = self.terminal_cursor {
|
if let Some(ref terminal_cursor) = self.terminal_cursor {
|
||||||
terminal_cursor.pos(&self.terminal)
|
terminal_cursor.pos(&self.context)
|
||||||
} else {
|
} else {
|
||||||
(0, 0)
|
(0, 0)
|
||||||
}
|
}
|
||||||
@ -77,19 +92,23 @@ impl <'term> TerminalCursor<'term>
|
|||||||
/// ```rust
|
/// ```rust
|
||||||
///
|
///
|
||||||
/// extern crate crossterm;
|
/// extern crate crossterm;
|
||||||
///
|
/// use self::crossterm::Context;
|
||||||
/// use self::crossterm::cursor;
|
/// use self::crossterm::cursor;
|
||||||
///
|
///
|
||||||
/// // Move 1 time up
|
/// pub fn move_up()
|
||||||
/// cursor::cursor().move_up(1);
|
/// {
|
||||||
|
/// let context = Context::new();
|
||||||
///
|
///
|
||||||
/// // Move 2 times up
|
/// // Get the cursor
|
||||||
/// cursor::cursor().move_up(2);
|
/// let mut cursor = cursor(&context);
|
||||||
|
/// // Move the cursor to position 3 times to the up in the terminal
|
||||||
|
/// cursor.move_up(3);
|
||||||
|
/// }
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
pub fn move_up(&mut self, count: u16) -> &mut TerminalCursor<'term> {
|
pub fn move_up(&mut self, count: u16) -> &mut TerminalCursor<'context> {
|
||||||
if let Some(ref terminal_cursor) = self.terminal_cursor {
|
if let Some(ref terminal_cursor) = self.terminal_cursor {
|
||||||
terminal_cursor.move_up(count, &self.terminal);
|
terminal_cursor.move_up(count, &self.context);
|
||||||
}
|
}
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
@ -99,22 +118,23 @@ impl <'term> TerminalCursor<'term>
|
|||||||
/// #Example
|
/// #Example
|
||||||
///
|
///
|
||||||
/// ```rust
|
/// ```rust
|
||||||
///
|
|
||||||
/// extern crate crossterm;
|
/// extern crate crossterm;
|
||||||
///
|
/// use self::crossterm::Context;
|
||||||
/// use self::crossterm::cursor;
|
/// use self::crossterm::cursor;
|
||||||
///
|
///
|
||||||
///
|
// pub fn move_right()
|
||||||
/// // move 1 time right
|
// {
|
||||||
/// cursor::cursor().move_right(1);
|
// let context = Context::new();
|
||||||
///
|
//
|
||||||
/// // move 2 times right
|
// // Get the cursor
|
||||||
/// cursor::cursor().move_right(2);
|
// let mut cursor = cursor(&context);
|
||||||
///
|
// // Move the cursor to position 3 times to the right in the terminal
|
||||||
|
// cursor.move_right(3);
|
||||||
|
// }
|
||||||
/// ```
|
/// ```
|
||||||
pub fn move_right(&mut self, count: u16) -> &mut TerminalCursor<'term> {
|
pub fn move_right(&mut self, count: u16) -> &mut TerminalCursor<'context> {
|
||||||
if let Some(ref terminal_cursor) = self.terminal_cursor {
|
if let Some(ref terminal_cursor) = self.terminal_cursor {
|
||||||
terminal_cursor.move_right(count, &self.terminal);
|
terminal_cursor.move_right(count, &self.context);
|
||||||
}
|
}
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
@ -126,19 +146,23 @@ impl <'term> TerminalCursor<'term>
|
|||||||
/// ```rust
|
/// ```rust
|
||||||
///
|
///
|
||||||
/// extern crate crossterm;
|
/// extern crate crossterm;
|
||||||
///
|
/// use self::crossterm::Context;
|
||||||
/// use self::crossterm::cursor;
|
/// use self::crossterm::cursor;
|
||||||
///
|
///
|
||||||
/// // move 1 time down
|
/// pub fn move_down()
|
||||||
/// cursor::cursor().move_down(1);
|
/// {
|
||||||
|
/// let context = Context::new();
|
||||||
///
|
///
|
||||||
/// // move 2 times down
|
/// // Get the cursor
|
||||||
/// cursor::cursor().move_down(2);
|
/// let mut cursor = cursor(&context);
|
||||||
|
/// // Move the cursor to position 3 times to the down in the terminal
|
||||||
|
/// cursor.move_down(3);
|
||||||
|
/// }
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
pub fn move_down(&mut self, count: u16) -> &mut TerminalCursor<'term> {
|
pub fn move_down(&mut self, count: u16) -> &mut TerminalCursor<'context> {
|
||||||
if let Some(ref terminal_cursor) = self.terminal_cursor {
|
if let Some(ref terminal_cursor) = self.terminal_cursor {
|
||||||
terminal_cursor.move_down(count, &self.terminal);
|
terminal_cursor.move_down(count, &self.context);
|
||||||
}
|
}
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
@ -150,19 +174,23 @@ impl <'term> TerminalCursor<'term>
|
|||||||
/// ```rust
|
/// ```rust
|
||||||
///
|
///
|
||||||
/// extern crate crossterm;
|
/// extern crate crossterm;
|
||||||
///
|
/// use self::crossterm::Context;
|
||||||
/// use self::crossterm::cursor;
|
/// use self::crossterm::cursor;
|
||||||
///
|
///
|
||||||
/// // move 1 time left
|
/// pub fn move_left()
|
||||||
/// cursor::cursor().move_left(1);
|
/// {
|
||||||
|
/// let context = Context::new();
|
||||||
///
|
///
|
||||||
/// // move 2 time left
|
/// // Get the cursor
|
||||||
/// cursor::cursor().move_left(2);
|
/// let mut cursor = cursor(&context);
|
||||||
|
/// // Move the cursor to position 3 times to the left in the terminal
|
||||||
|
/// cursor.move_left(3);
|
||||||
|
/// }
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
pub fn move_left(&mut self, count: u16) -> &mut TerminalCursor<'term> {
|
pub fn move_left(&mut self, count: u16) -> &mut TerminalCursor<'context> {
|
||||||
if let Some(ref terminal_cursor) = self.terminal_cursor {
|
if let Some(ref terminal_cursor) = self.terminal_cursor {
|
||||||
terminal_cursor.move_left(count, &self.terminal);
|
terminal_cursor.move_left(count, &self.context);
|
||||||
}
|
}
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
@ -184,23 +212,27 @@ impl <'term> TerminalCursor<'term>
|
|||||||
///
|
///
|
||||||
/// extern crate crossterm;
|
/// extern crate crossterm;
|
||||||
///
|
///
|
||||||
|
/// use self::crossterm::Context;
|
||||||
/// use self::crossterm::cursor;
|
/// use self::crossterm::cursor;
|
||||||
|
///
|
||||||
/// use std;
|
/// use std;
|
||||||
/// use std::io::Write;
|
/// use std::io::Write;
|
||||||
///
|
///
|
||||||
|
/// let context = Context::new();
|
||||||
|
///
|
||||||
/// // of course we can just do this.
|
/// // of course we can just do this.
|
||||||
/// cursor::cursor().goto(10,10);
|
/// cursor::cursor(&context).goto(10,10);
|
||||||
/// print!("@");
|
/// print!("@");
|
||||||
/// std::io::stdout().flush();
|
/// std::io::stdout().flush();
|
||||||
///
|
///
|
||||||
/// // but now we can chain the methods so it looks cleaner and it automatically flushes the buffer.
|
/// // but now we can chain the methods so it looks cleaner and it automatically flushes the buffer.
|
||||||
/// cursor::cursor()
|
/// cursor::cursor(&context)
|
||||||
/// .goto(10,10)
|
/// .goto(10,10)
|
||||||
/// .print("@");
|
/// .print("@");
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
pub fn print<D: Display>(&mut self, value: D) -> &mut TerminalCursor<'term> {
|
pub fn print<D: Display>(&mut self, value: D) -> &mut TerminalCursor<'context> {
|
||||||
let mut screen = self.terminal.screen_manager.lock().unwrap();
|
let mut screen = self.context.screen_manager.lock().unwrap();
|
||||||
{
|
{
|
||||||
write!(screen.stdout(), "{}", value);
|
write!(screen.stdout(), "{}", value);
|
||||||
// rust is line buffered so we need to flush the buffer in order to print it at the current cursor position.
|
// rust is line buffered so we need to flush the buffer in order to print it at the current cursor position.
|
||||||
@ -218,16 +250,17 @@ impl <'term> TerminalCursor<'term>
|
|||||||
/// ```rust
|
/// ```rust
|
||||||
///
|
///
|
||||||
/// extern crate crossterm;
|
/// extern crate crossterm;
|
||||||
///
|
/// use self::crossterm::Context;
|
||||||
/// use self::crossterm::cursor;
|
/// use self::crossterm::cursor;
|
||||||
///
|
///
|
||||||
/// cursor::cursor().safe_position();
|
/// let context = Context::new();
|
||||||
|
/// cursor::cursor(&context).safe_position();
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
pub fn save_position(&mut self)
|
pub fn save_position(&mut self)
|
||||||
{
|
{
|
||||||
if let Some(ref mut terminal_cursor) = self.terminal_cursor {
|
if let Some(ref mut terminal_cursor) = self.terminal_cursor {
|
||||||
terminal_cursor.save_position(&self.terminal);
|
terminal_cursor.save_position(&self.context);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -240,40 +273,43 @@ impl <'term> TerminalCursor<'term>
|
|||||||
/// ```rust
|
/// ```rust
|
||||||
///
|
///
|
||||||
/// extern crate crossterm;
|
/// extern crate crossterm;
|
||||||
///
|
|
||||||
/// use self::crossterm::cursor::cursor;
|
/// use self::crossterm::cursor::cursor;
|
||||||
|
/// use self::crossterm::Context;
|
||||||
///
|
///
|
||||||
/// cursor().reset_position();
|
/// let context = Context::new();
|
||||||
|
/// cursor(&context).reset_position();
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
pub fn reset_position(&mut self)
|
pub fn reset_position(&mut self)
|
||||||
{
|
{
|
||||||
if let Some(ref terminal_cursor) = self.terminal_cursor {
|
if let Some(ref terminal_cursor) = self.terminal_cursor {
|
||||||
terminal_cursor.reset_position(&self.terminal);
|
terminal_cursor.reset_position(&self.context);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get an TerminalCursor implementation whereon cursor related actions can be performed.
|
/// Get an TerminalCursor implementation whereon cursor related actions can be performed.
|
||||||
///
|
///
|
||||||
/// Check `/examples/cursor` in the libary for more spesific examples.
|
/// Check `/examples/version/cursor` in the libary for more spesific examples.
|
||||||
///
|
///
|
||||||
/// #Example
|
/// #Example
|
||||||
///
|
///
|
||||||
/// ```rust
|
/// ```rust
|
||||||
///
|
///
|
||||||
/// extern crate crossterm;
|
/// extern crate crossterm;
|
||||||
///
|
/// use self::crossterm::Context;
|
||||||
/// use self::crossterm::cursor;
|
/// use self::crossterm::cursor;
|
||||||
///
|
///
|
||||||
|
/// let context = Context::new();
|
||||||
|
///
|
||||||
/// // Get cursor and goto pos X: 5, Y: 10
|
/// // Get cursor and goto pos X: 5, Y: 10
|
||||||
/// let mut cursor = cursor::cursor();
|
/// let mut cursor = cursor::cursor(&context);
|
||||||
/// cursor.goto(5,10);
|
/// cursor.goto(5,10);
|
||||||
///
|
///
|
||||||
/// //Or you can do it in one line.
|
/// //Or you can do it in one line.
|
||||||
/// cursor::cursor().goto(5,10);
|
/// cursor::cursor(&context).goto(5,10);
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
pub fn cursor<'term>(terminal: &'term Terminal) -> Box<TerminalCursor<'term>> {
|
pub fn cursor<'context>(context: &'context Context) -> Box<TerminalCursor<'context>> {
|
||||||
Box::from(TerminalCursor::new(&terminal))
|
Box::from(TerminalCursor::new(&context))
|
||||||
}
|
}
|
||||||
|
@ -9,6 +9,7 @@
|
|||||||
//!
|
//!
|
||||||
|
|
||||||
pub mod cursor;
|
pub mod cursor;
|
||||||
|
|
||||||
#[cfg(target_os = "windows")]
|
#[cfg(target_os = "windows")]
|
||||||
mod winapi_cursor;
|
mod winapi_cursor;
|
||||||
mod ansi_cursor;
|
mod ansi_cursor;
|
||||||
@ -17,7 +18,7 @@ mod ansi_cursor;
|
|||||||
use self::winapi_cursor::WinApiCursor;
|
use self::winapi_cursor::WinApiCursor;
|
||||||
use self::ansi_cursor::AnsiCursor;
|
use self::ansi_cursor::AnsiCursor;
|
||||||
|
|
||||||
use Terminal;
|
use Context;
|
||||||
pub use self::cursor::{ cursor, TerminalCursor };
|
pub use self::cursor::{ cursor, TerminalCursor };
|
||||||
|
|
||||||
///! This trait defines the actions that can be preformed with the terminal cursor.
|
///! This trait defines the actions that can be preformed with the terminal cursor.
|
||||||
@ -29,20 +30,20 @@ pub use self::cursor::{ cursor, TerminalCursor };
|
|||||||
///! This trait is implemented for `WINAPI` (Windows specific) and `ANSI` (Unix specific),
|
///! This trait is implemented for `WINAPI` (Windows specific) and `ANSI` (Unix specific),
|
||||||
///! so that cursor related actions can be preformed on both unix and windows systems.
|
///! so that cursor related actions can be preformed on both unix and windows systems.
|
||||||
pub trait ITerminalCursor {
|
pub trait ITerminalCursor {
|
||||||
/// Goto some location (x,y) in the terminal.
|
/// Goto some location (x,y) in the context.
|
||||||
fn goto(&self, x: u16, y: u16, terminal: &Terminal);
|
fn goto(&self, x: u16, y: u16, context: &Context);
|
||||||
/// Get the location (x,y) of the current cusror in the terminal
|
/// Get the location (x,y) of the current cusror in the context
|
||||||
fn pos(&self, terminal: &Terminal) -> (u16, u16);
|
fn pos(&self, context: &Context) -> (u16, u16);
|
||||||
/// Move cursor n times up
|
/// Move cursor n times up
|
||||||
fn move_up(&self, count: u16, terminal: &Terminal);
|
fn move_up(&self, count: u16, context: &Context);
|
||||||
/// Move the cursor `n` times to the right.
|
/// Move the cursor `n` times to the right.
|
||||||
fn move_right(&self, count: u16, terminal: &Terminal);
|
fn move_right(&self, count: u16, context: &Context);
|
||||||
/// Move the cursor `n` times down.
|
/// Move the cursor `n` times down.
|
||||||
fn move_down(&self, count: u16, terminal: &Terminal);
|
fn move_down(&self, count: u16, context: &Context);
|
||||||
/// Move the cursor `n` times left.
|
/// Move the cursor `n` times left.
|
||||||
fn move_left(&self, count: u16, terminal: &Terminal);
|
fn move_left(&self, count: u16, context: &Context);
|
||||||
/// Save cursor position for recall 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(&mut self, terminal: &Terminal);
|
fn save_position(&mut self, context: &Context);
|
||||||
/// Return to saved cursor position
|
/// Return to saved cursor position
|
||||||
fn reset_position(&self, terminal: &Terminal);
|
fn reset_position(&self, context: &Context);
|
||||||
}
|
}
|
@ -1,58 +1,56 @@
|
|||||||
//! This is an WINAPI specific implementation for cursor related action.
|
//! This is an WINAPI specific implementation for cursor related action.
|
||||||
//! This module is used for windows terminals that do not support ANSI escape codes.
|
//! This module is used for windows terminals that do not support ANSI escape codes.
|
||||||
|
//! Note that the cursor position is 0 based. This means that we start counting at 0 when setting the cursor position ect.
|
||||||
|
|
||||||
use {Terminal, Construct};
|
use Context;
|
||||||
use super::ITerminalCursor;
|
use super::ITerminalCursor;
|
||||||
use kernel::windows_kernel::{kernel, cursor};
|
use kernel::windows_kernel::{kernel, cursor};
|
||||||
|
|
||||||
/// This struct is an windows implementation for cursor related actions.
|
/// This struct is an windows implementation for cursor related actions.
|
||||||
pub struct WinApiCursor;
|
pub struct WinApiCursor;
|
||||||
|
|
||||||
impl Construct for WinApiCursor {
|
impl WinApiCursor {
|
||||||
fn new() -> Box<WinApiCursor> {
|
pub fn new() -> Box<WinApiCursor> {
|
||||||
Box::from(WinApiCursor { })
|
Box::from(WinApiCursor { })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ITerminalCursor for WinApiCursor {
|
impl ITerminalCursor for WinApiCursor {
|
||||||
|
|
||||||
fn goto(&self, x: u16, y: u16, terminal: &Terminal) {
|
fn goto(&self, x: u16, y: u16, context: &Context) {
|
||||||
kernel::set_console_cursor_position(x as i16, y as i16);
|
kernel::set_console_cursor_position(x as i16, y as i16);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn pos(&self, terminal: &Terminal) -> (u16, u16) {
|
fn pos(&self, context: &Context) -> (u16, u16) {
|
||||||
cursor::pos()
|
cursor::pos()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn move_up(&self, count: u16, terminal: &Terminal) {
|
fn move_up(&self, count: u16, context: &Context) {
|
||||||
let (xpos,ypos) = self.pos();
|
let (xpos,ypos) = self.pos();
|
||||||
self.goto(xpos, ypos - count);
|
self.goto(xpos, ypos - count);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn move_right(&self, count: u16, terminal: &Terminal) {
|
fn move_right(&self, count: u16, context: &Context) {
|
||||||
let (xpos,ypos) = self.pos();
|
let (xpos,ypos) = self.pos();
|
||||||
|
|
||||||
self.goto(xpos + count, ypos);
|
self.goto(xpos + count, ypos);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn move_down(&self, count: u16, terminal: &Terminal) {
|
fn move_down(&self, count: u16, context: &Context) {
|
||||||
let (xpos,ypos) = self.pos();
|
let (xpos,ypos) = self.pos();
|
||||||
|
|
||||||
self.goto(xpos, ypos + count);
|
self.goto(xpos, ypos + count);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn move_left(&self, count: u16, terminal: &Terminal) {
|
fn move_left(&self, count: u16, context: &Context) {
|
||||||
let (xpos,ypos) = self.pos();
|
let (xpos,ypos) = self.pos();
|
||||||
|
|
||||||
self.goto(xpos - count, ypos);
|
self.goto(xpos - count, ypos);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn save_position(&mut self, terminal: &Terminal)
|
fn save_position(&mut self, context: &Context)
|
||||||
{
|
{
|
||||||
cursor::save_cursor_pos();
|
cursor::save_cursor_pos();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn reset_position(&self, terminal: &Terminal)
|
fn reset_position(&self, context: &Context)
|
||||||
{
|
{
|
||||||
cursor::reset_to_saved_position();
|
cursor::reset_to_saved_position();
|
||||||
}
|
}
|
||||||
|
@ -1,13 +1,14 @@
|
|||||||
//! This module contains all `unix` specific terminal related logic.
|
//! This module contains all `unix` specific terminal related logic.
|
||||||
|
|
||||||
use { libc, Context, Terminal };
|
use {libc, StateManager, Context, CommandManager};
|
||||||
use termios::Termios;
|
use termios::Termios;
|
||||||
pub use self::libc::{termios};
|
pub use self::libc::{termios};
|
||||||
use self::libc::{STDOUT_FILENO, TIOCGWINSZ, c_ushort, ioctl, c_int};
|
use self::libc::{STDOUT_FILENO, TIOCGWINSZ, c_ushort, ioctl, c_int};
|
||||||
use state::commands::{ NoncanonicalModeCommand, IContextCommand} ;
|
use state::commands::{ NoncanonicalModeCommand, IStateCommand} ;
|
||||||
|
|
||||||
use std::io::Error;
|
use std::io::Error;
|
||||||
use std::{ io, mem };
|
use std::{ io, mem };
|
||||||
|
use std::rc::Rc;
|
||||||
|
|
||||||
/// A representation of the size of the current terminal.
|
/// A representation of the size of the current terminal.
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
@ -40,16 +41,15 @@ pub fn terminal_size() -> (u16,u16) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Get the current cursor position.
|
/// Get the current cursor position.
|
||||||
pub fn pos(terminal: &Terminal) -> (u16,u16)
|
pub fn pos(terminal: &Context) -> (u16, u16)
|
||||||
{
|
{
|
||||||
use std::io::{ Write,Read };
|
use std::io::{ Write,Read };
|
||||||
|
|
||||||
|
let mut command_id = NoncanonicalModeCommand::new(&terminal.state_manager);
|
||||||
|
|
||||||
let mut command = NoncanonicalModeCommand::new(&terminal.context);
|
CommandManager::execute(terminal, command_id);
|
||||||
command.0.execute(&terminal);
|
|
||||||
|
|
||||||
// This code is original written by term_cursor credits to them.
|
// This code is original written by term_cursor credits to them.
|
||||||
|
|
||||||
use std::io;
|
use std::io;
|
||||||
let mut std = io::stdout();
|
let mut std = io::stdout();
|
||||||
// Write command
|
// Write command
|
||||||
@ -97,10 +97,8 @@ pub fn pos(terminal: &Terminal) -> (u16,u16)
|
|||||||
// Expect `R`
|
// Expect `R`
|
||||||
let res = if c == 'R' { (cols as u16, rows as u16) } else { return (0, 0) };
|
let res = if c == 'R' { (cols as u16, rows as u16) } else { return (0, 0) };
|
||||||
|
|
||||||
let mut context = terminal.context.lock().unwrap();
|
CommandManager::undo(terminal, command_id);
|
||||||
{
|
|
||||||
context.undo_state(command.1, terminal);
|
|
||||||
}
|
|
||||||
res
|
res
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
//! This module handles the enabling `ANSI escape codes` for windows terminals.
|
//! This module handles the enabling `ANSI escape codes` for windows terminals.
|
||||||
|
|
||||||
use Context;
|
use StateManager;
|
||||||
use state::commands::ICommand;
|
use state::commands::ICommand;
|
||||||
|
|
||||||
static mut HAS_BEEN_TRYED_TO_ENABLE: bool = false;
|
static mut HAS_BEEN_TRYED_TO_ENABLE: bool = false;
|
||||||
|
@ -23,6 +23,7 @@ pub fn save_cursor_pos()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// get the current cursor position.
|
||||||
pub fn pos() -> (u16,u16)
|
pub fn pos() -> (u16,u16)
|
||||||
{
|
{
|
||||||
let csbi = kernel::get_console_screen_buffer_info();
|
let csbi = kernel::get_console_screen_buffer_info();
|
||||||
|
@ -1,78 +0,0 @@
|
|||||||
use winapi::um::winnt::HANDLE;
|
|
||||||
use std::mem::zeroed;
|
|
||||||
use winapi::um::processenv::{GetStdHandle};
|
|
||||||
use winapi::um::winbase::{STD_OUTPUT_HANDLE, STD_INPUT_HANDLE };
|
|
||||||
|
|
||||||
static mut ALTERNATEHANDLE: Option<HANDLE> = None;
|
|
||||||
static mut CONSOLE_OUTPUT_HANDLE: Option<HANDLE> = None;
|
|
||||||
static mut CONSOLE_INPUT_HANDLE: Option<HANDLE> = None;
|
|
||||||
|
|
||||||
|
|
||||||
pub fn register_new_alternate_handle(handle: Handle) -> HANDLE
|
|
||||||
{
|
|
||||||
unsafe
|
|
||||||
{
|
|
||||||
ALTERNATEHANDLE = handle;
|
|
||||||
}
|
|
||||||
|
|
||||||
ALTERNATEHANDLE.unwrap();
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn clear_alternate_screen()
|
|
||||||
{
|
|
||||||
unsafe
|
|
||||||
{
|
|
||||||
ALTERNATEHANDLE = None;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Get the std_output_handle of the console
|
|
||||||
pub fn get_output_handle() -> HANDLE {
|
|
||||||
unsafe {
|
|
||||||
if let Some(alternate_handle) = ALTERNATEHANDLE
|
|
||||||
{
|
|
||||||
alternate_handle
|
|
||||||
}
|
|
||||||
else if let Some(handle) = CONSOLE_OUTPUT_HANDLE {
|
|
||||||
handle
|
|
||||||
} else {
|
|
||||||
let handle = GetStdHandle(STD_OUTPUT_HANDLE);
|
|
||||||
|
|
||||||
if !is_valid_handle(&handle)
|
|
||||||
{
|
|
||||||
panic!("Cannot get output handle")
|
|
||||||
}
|
|
||||||
|
|
||||||
CONSOLE_OUTPUT_HANDLE = Some(handle);
|
|
||||||
handle
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Get the std_input_handle of the console
|
|
||||||
pub fn get_input_handle() -> HANDLE {
|
|
||||||
unsafe {
|
|
||||||
if let Some(handle) = CONSOLE_INPUT_HANDLE {
|
|
||||||
handle
|
|
||||||
} else {
|
|
||||||
let handle = GetStdHandle(STD_INPUT_HANDLE);
|
|
||||||
|
|
||||||
if !is_valid_handle(&handle)
|
|
||||||
{
|
|
||||||
panic!("Cannot get input handle")
|
|
||||||
}
|
|
||||||
|
|
||||||
CONSOLE_INPUT_HANDLE = Some(handle);
|
|
||||||
handle
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Checks if the console handle is an invalid handle value.
|
|
||||||
pub fn is_valid_handle(handle: &HANDLE) -> bool {
|
|
||||||
if *handle == INVALID_HANDLE_VALUE {
|
|
||||||
false
|
|
||||||
} else {
|
|
||||||
true
|
|
||||||
}
|
|
||||||
}
|
|
@ -58,7 +58,7 @@ pub fn get_input_handle() -> HANDLE {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Checks if the console handle is an invalid handle value.
|
/// Checks if the console handle is an invalid handle value.
|
||||||
pub fn is_valid_handle(handle: &HANDLE) -> bool {
|
fn is_valid_handle(handle: &HANDLE) -> bool {
|
||||||
if *handle == INVALID_HANDLE_VALUE {
|
if *handle == INVALID_HANDLE_VALUE {
|
||||||
false
|
false
|
||||||
} else {
|
} else {
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
//! This module contains the `windows` specific (unsafe) logic.
|
//! This module contains the `windows` specific logic.
|
||||||
|
|
||||||
pub mod kernel;
|
pub mod kernel;
|
||||||
pub mod cursor;
|
pub mod cursor;
|
||||||
|
11
src/lib.rs
11
src/lib.rs
@ -14,12 +14,11 @@ pub mod terminal;
|
|||||||
pub mod manager;
|
pub mod manager;
|
||||||
|
|
||||||
pub use shared::{screen, raw};
|
pub use shared::{screen, raw};
|
||||||
|
pub use state::context::Context;
|
||||||
|
|
||||||
use shared::traits::{Construct};
|
use state::command_manager::CommandManager;
|
||||||
pub use state::{ Context };
|
use state::state_manager::StateManager;
|
||||||
pub use manager::manager::{ ScreenManager };
|
use manager::ScreenManager;
|
||||||
pub use shared::terminal::Terminal;
|
|
||||||
|
|
||||||
|
|
||||||
#[cfg(windows)]
|
#[cfg(windows)]
|
||||||
extern crate winapi;
|
extern crate winapi;
|
||||||
@ -27,5 +26,3 @@ extern crate winapi;
|
|||||||
extern crate libc;
|
extern crate libc;
|
||||||
#[cfg(unix)]
|
#[cfg(unix)]
|
||||||
extern crate termios;
|
extern crate termios;
|
||||||
|
|
||||||
extern crate rand;
|
|
@ -1,3 +1,7 @@
|
|||||||
|
//! This is an ANSI specific implementation for the screen manager
|
||||||
|
//! This module is used for windows 10 terminals and unix terminals by default.
|
||||||
|
//! This module uses the stdout to write to the console.
|
||||||
|
|
||||||
use std::io::{self, Write};
|
use std::io::{self, Write};
|
||||||
|
|
||||||
use super::IScreenManager;
|
use super::IScreenManager;
|
||||||
@ -24,24 +28,12 @@ impl<Output :Write> IScreenManager<Output> for AnsiScreenManager<Output>
|
|||||||
{
|
{
|
||||||
write!(self.output, "{}", string);
|
write!(self.output, "{}", string);
|
||||||
self.flush();
|
self.flush();
|
||||||
// println!("test");
|
|
||||||
// match self.is_alternate_screen
|
|
||||||
// {
|
|
||||||
// true => ,
|
|
||||||
// false => write!(io::stdout(), "{}", string),
|
|
||||||
// };
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn write_ansi_str(&mut self, string: &str)
|
fn write_ansi_str(&mut self, string: &str)
|
||||||
{
|
{
|
||||||
write!(self.output, "{}", string);
|
write!(self.output, "{}", string);
|
||||||
self.flush();
|
self.flush();
|
||||||
// println!("test");
|
|
||||||
// match self.is_alternate_screen
|
|
||||||
// {
|
|
||||||
// true => write!(self.output, "{}", string),
|
|
||||||
// false => write!(io::stdout(), "{}", string),
|
|
||||||
// };
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,8 +1,12 @@
|
|||||||
use std::io::Write;
|
//! This module provides an interface for working with the sceen. With that I mean that you can get or wirte to the handle of the current screen. stdout.
|
||||||
|
//! Because crossterm can work with alternate screen, we need a place that holds the handle to the current screen. And this module provides this place.
|
||||||
|
|
||||||
use super::IScreenManager;
|
use super::IScreenManager;
|
||||||
use super::ansi_manager::AnsiScreenManager;
|
use super::ansi_manager::AnsiScreenManager;
|
||||||
|
|
||||||
|
use std::io::Write;
|
||||||
|
|
||||||
|
/// Struct that stores an specific platform implementation for screen related actions.
|
||||||
pub struct ScreenManager
|
pub struct ScreenManager
|
||||||
{
|
{
|
||||||
screen_manager: Box<IScreenManager<Box<Write>>>
|
screen_manager: Box<IScreenManager<Box<Write>>>
|
||||||
@ -10,6 +14,7 @@ pub struct ScreenManager
|
|||||||
|
|
||||||
impl ScreenManager
|
impl ScreenManager
|
||||||
{
|
{
|
||||||
|
/// Create new screen manager instance whereon screen related actions can be performed.
|
||||||
pub fn new() -> ScreenManager {
|
pub fn new() -> ScreenManager {
|
||||||
// #[cfg(target_os = "windows")]
|
// #[cfg(target_os = "windows")]
|
||||||
// let cursor = functions::get_module::<Box<ITerminalCursor>>(WinApiCursor::new(), AnsiCursor::new());
|
// let cursor = functions::get_module::<Box<ITerminalCursor>>(WinApiCursor::new(), AnsiCursor::new());
|
||||||
@ -22,6 +27,7 @@ impl ScreenManager
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Get the stdout of the current screen
|
||||||
pub fn stdout(&mut self) -> &mut Box<Write>
|
pub fn stdout(&mut self) -> &mut Box<Write>
|
||||||
{
|
{
|
||||||
self.screen_manager.stdout()
|
self.screen_manager.stdout()
|
||||||
@ -32,11 +38,13 @@ impl ScreenManager
|
|||||||
self.screen_manager.toggle_is_alternate_screen(is_alternate_screen);
|
self.screen_manager.toggle_is_alternate_screen(is_alternate_screen);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Write an ANSI code as String.
|
||||||
pub fn write_ansi(&mut self, string: String)
|
pub fn write_ansi(&mut self, string: String)
|
||||||
{
|
{
|
||||||
self.screen_manager.write_ansi(string);
|
self.screen_manager.write_ansi(string);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Write an ANSI code as &str
|
||||||
pub fn write_ansi_str(&mut self, string: &str)
|
pub fn write_ansi_str(&mut self, string: &str)
|
||||||
{
|
{
|
||||||
self.screen_manager.write_ansi_str(string);
|
self.screen_manager.write_ansi_str(string);
|
||||||
|
@ -1,3 +1,6 @@
|
|||||||
|
//! This module provides one place to work with the screen.
|
||||||
|
//! For example whe can write to the console true this module.
|
||||||
|
|
||||||
pub mod manager;
|
pub mod manager;
|
||||||
|
|
||||||
#[cfg(target_os = "windows")]
|
#[cfg(target_os = "windows")]
|
||||||
@ -12,8 +15,11 @@ pub use self::manager::{ ScreenManager };
|
|||||||
|
|
||||||
pub trait IScreenManager<Output>
|
pub trait IScreenManager<Output>
|
||||||
{
|
{
|
||||||
|
/// get the stdout of the screen. This can be used to write to the
|
||||||
fn stdout(&mut self) -> &mut Output;
|
fn stdout(&mut self) -> &mut Output;
|
||||||
fn toggle_is_alternate_screen(&mut self, is_alternate_screen: bool);
|
fn toggle_is_alternate_screen(&mut self, is_alternate_screen: bool);
|
||||||
|
/// Write ansi code as String to the current stdout.
|
||||||
fn write_ansi(&mut self, string: String);
|
fn write_ansi(&mut self, string: String);
|
||||||
|
/// Write a &str to the current stdout.
|
||||||
fn write_ansi_str(&mut self, string: &str);
|
fn write_ansi_str(&mut self, string: &str);
|
||||||
}
|
}
|
@ -1,6 +1,6 @@
|
|||||||
//! Some actions need to preformed platform independently since they can not be solved `ANSI escape codes`.
|
//! Some actions need to preformed platform independently since they can not be solved `ANSI escape codes`.
|
||||||
|
|
||||||
use Terminal;
|
use Context;
|
||||||
|
|
||||||
#[cfg(windows)]
|
#[cfg(windows)]
|
||||||
use kernel::windows_kernel::terminal::terminal_size;
|
use kernel::windows_kernel::terminal::terminal_size;
|
||||||
@ -20,7 +20,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(screen: &Terminal) -> (u16,u16)
|
pub fn get_cursor_position(screen: &Context) -> (u16, u16)
|
||||||
{
|
{
|
||||||
#[cfg(unix)]
|
#[cfg(unix)]
|
||||||
return pos(&screen);
|
return pos(&screen);
|
||||||
|
@ -4,6 +4,5 @@
|
|||||||
pub mod macros;
|
pub mod macros;
|
||||||
pub mod traits;
|
pub mod traits;
|
||||||
pub mod functions;
|
pub mod functions;
|
||||||
pub mod terminal;
|
|
||||||
pub mod screen;
|
pub mod screen;
|
||||||
pub mod raw;
|
pub mod raw;
|
@ -24,49 +24,34 @@ use super::super::state::commands::unix_command::EnableRawModeCommand;
|
|||||||
#[cfg(windows)]
|
#[cfg(windows)]
|
||||||
use state::commands::win_commands::EnableRawModeCommand;
|
use state::commands::win_commands::EnableRawModeCommand;
|
||||||
|
|
||||||
use { Terminal };
|
use {Context, CommandManager };
|
||||||
use state::commands::IContextCommand;
|
use state::commands::IStateCommand;
|
||||||
|
|
||||||
use std::io::{ self, Write};
|
use std::io::{ self, Write};
|
||||||
|
use std::rc::Rc;
|
||||||
|
|
||||||
/// 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.
|
||||||
pub struct RawTerminal<'a>
|
pub struct RawTerminal<'a>
|
||||||
{
|
{
|
||||||
terminal : &'a Terminal,
|
terminal : &'a Context,
|
||||||
command_id: u16,
|
command_id: u16,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Trait withs contains a method for switching into raw mode.
|
/// Trait withs contains a method for switching into raw mode.
|
||||||
pub trait IntoRawMode<'a>: Write + Sized
|
pub trait IntoRawMode<'a>: Write + Sized
|
||||||
{
|
{
|
||||||
fn into_raw_mode(&self, terminal: &'a Terminal) -> io::Result<RawTerminal<'a>>;
|
fn into_raw_mode(&self, terminal: &'a Context) -> io::Result<RawTerminal<'a>>;
|
||||||
}
|
}
|
||||||
|
|
||||||
//impl<'a> IntoRawMode<'a> for RawTerminal<'a>
|
|
||||||
//{
|
|
||||||
// /// Switch to raw mode.
|
|
||||||
// ///
|
|
||||||
// /// Raw mode means that input (stdin) won't be printed it will instead have to be written manually by
|
|
||||||
// /// the program. The input isn't canonicalised or line buffered (that is, you can
|
|
||||||
// /// read from input(stdin) one byte of a time).
|
|
||||||
// fn into_raw_mode(self, terminal: &'a Terminal) -> io::Result<RawTerminal>
|
|
||||||
// {
|
|
||||||
// let (mut command, command_id) = EnableRawModeCommand::new(&terminal.context);
|
|
||||||
// let success = command.execute(&terminal);
|
|
||||||
//
|
|
||||||
// if success
|
|
||||||
// {
|
|
||||||
// Ok(RawTerminal { terminal: terminal, command_id: command_id})
|
|
||||||
//
|
|
||||||
// }else { panic!("cannot move into raw mode") }
|
|
||||||
// }
|
|
||||||
//}
|
|
||||||
|
|
||||||
impl <'a, W: Write> IntoRawMode<'a> for W
|
impl <'a, W: Write> IntoRawMode<'a> for W
|
||||||
{
|
{
|
||||||
fn into_raw_mode(&self, terminal: &'a Terminal) -> io::Result<RawTerminal<'a>> {
|
/// Raw mode means that input (stdin) won't be printed it will instead have to be written manually by
|
||||||
let (mut command, command_id) = EnableRawModeCommand::new(&terminal.context);
|
/// the program. The input isn't canonicalised or line buffered (that is, you can
|
||||||
let success = command.execute(&terminal);
|
/// read from input(stdin) one byte of a time).
|
||||||
|
fn into_raw_mode(&self, terminal: &'a Context) -> io::Result<RawTerminal<'a>> {
|
||||||
|
let command_id = EnableRawModeCommand::new(&terminal.state_manager);
|
||||||
|
|
||||||
|
let success = CommandManager::execute(terminal, command_id);
|
||||||
|
|
||||||
if success
|
if success
|
||||||
{
|
{
|
||||||
@ -96,9 +81,6 @@ impl <'a> Drop for RawTerminal<'a>
|
|||||||
{
|
{
|
||||||
fn drop(&mut self)
|
fn drop(&mut self)
|
||||||
{
|
{
|
||||||
let mut context = self.terminal.context.lock().unwrap();
|
let success = CommandManager::undo(&self.terminal, self.command_id);
|
||||||
{
|
|
||||||
context.undo_state(self.command_id, &self.terminal);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,96 +1,57 @@
|
|||||||
//! This module contains all the logic for switching between alternate screen and main screen.
|
//! This module contains all the logic for switching between alternate screen and main screen.
|
||||||
|
|
||||||
use Terminal;
|
use Context;
|
||||||
use state::commands::*;
|
use state::commands::*;
|
||||||
|
|
||||||
use std::io::{self, Write};
|
use std::io::{self, Write};
|
||||||
|
|
||||||
//pub struct ToMainScreen;
|
pub struct AlternateScreen<'context> {
|
||||||
//
|
context: &'context Context
|
||||||
//impl fmt::Display for ToMainScreen
|
|
||||||
//{
|
|
||||||
// fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
|
||||||
// get_to_alternate_screen_command().undo();
|
|
||||||
// Ok(())
|
|
||||||
// }
|
|
||||||
//}
|
|
||||||
//
|
|
||||||
///// Struct that switches to alternate screen buffer on display.
|
|
||||||
//pub struct ToAlternateScreen;
|
|
||||||
//
|
|
||||||
//impl fmt::Display for ToAlternateScreen
|
|
||||||
//{
|
|
||||||
// fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
|
||||||
// get_to_alternate_screen_command().execute();
|
|
||||||
// Ok(())
|
|
||||||
// }
|
|
||||||
//}
|
|
||||||
|
|
||||||
/// Struct that can be used for writing to an alternate screen.
|
|
||||||
///
|
|
||||||
/// #Example
|
|
||||||
///
|
|
||||||
/// ```rust
|
|
||||||
/// extern crate crossterm;
|
|
||||||
/// use self::crossterm::terminal::screen;
|
|
||||||
/// use std::{time, thread};
|
|
||||||
/// ...
|
|
||||||
///
|
|
||||||
/// // Initialize and switch to the alternate screen from an std output handle.
|
|
||||||
/// // Now you can write to this screen.
|
|
||||||
/// let mut screen = screen::AlternateScreen::from(stdout());
|
|
||||||
/// // Write some text to the alternate screen.
|
|
||||||
/// write!(screen, "Welcome to the alternate screen. Wait 4 seconds to switch back").unwrap();
|
|
||||||
/// thread::sleep(time::Duration::from_secs(4));
|
|
||||||
/// // switch back to main screen.
|
|
||||||
/// write!(screen, "{}", screen::ToMainScreen);
|
|
||||||
/// write!(screen, "{}", "We are back again at the main screen");
|
|
||||||
///
|
|
||||||
/// ...
|
|
||||||
///
|
|
||||||
/// ```
|
|
||||||
pub struct AlternateScreen<'term> {
|
|
||||||
term: &'term Terminal
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'term> AlternateScreen<'term> {
|
impl<'context> AlternateScreen<'context> {
|
||||||
pub fn from(output: &'term Terminal) -> Self {
|
/// Get the alternate screen from the context.
|
||||||
get_to_alternate_screen_command().execute(&output);
|
/// By calling this method the current screen will be changed to the alternate screen.
|
||||||
AlternateScreen { term: output }
|
/// And you get back an handle for that screen.
|
||||||
|
pub fn from(context: &'context Context) -> Self {
|
||||||
|
get_to_alternate_screen_command().execute(&context);
|
||||||
|
AlternateScreen { context: context }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Change the current screen to the mainscreen.
|
||||||
pub fn to_main(&self)
|
pub fn to_main(&self)
|
||||||
{
|
{
|
||||||
get_to_alternate_screen_command().undo(&self.term);
|
get_to_alternate_screen_command().undo(&self.context);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Change the current screen to alternate screen.
|
||||||
pub fn to_alternate(&self)
|
pub fn to_alternate(&self)
|
||||||
{
|
{
|
||||||
get_to_alternate_screen_command().execute(&self.term);
|
get_to_alternate_screen_command().execute(&self.context);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'term> Write for AlternateScreen<'term> {
|
impl<'context> Write for AlternateScreen<'context> {
|
||||||
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
|
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
|
||||||
let mut screen = self.term.screen_manager.lock().unwrap();
|
let mut screen = self.context.screen_manager.lock().unwrap();
|
||||||
{
|
{
|
||||||
screen.stdout().write(buf)
|
screen.stdout().write(buf)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn flush(&mut self) -> io::Result<()> {
|
fn flush(&mut self) -> io::Result<()> {
|
||||||
let mut screen = self.term.screen_manager.lock().unwrap();
|
let mut screen = self.context.screen_manager.lock().unwrap();
|
||||||
{
|
{
|
||||||
screen.stdout().flush()
|
screen.stdout().flush()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'term> Drop for AlternateScreen<'term>
|
impl<'context> Drop for AlternateScreen<'context>
|
||||||
{
|
{
|
||||||
fn drop(&mut self)
|
fn drop(&mut self)
|
||||||
{
|
{
|
||||||
get_to_alternate_screen_command().undo(&self.term);
|
get_to_alternate_screen_command().undo(&self.context);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,82 +0,0 @@
|
|||||||
use std::sync::Mutex;
|
|
||||||
use std::rc::Rc;
|
|
||||||
|
|
||||||
use { Context, ScreenManager};
|
|
||||||
|
|
||||||
//use super::super::terminal;
|
|
||||||
//use super::super::cursor;
|
|
||||||
use super::super::style;
|
|
||||||
|
|
||||||
use std::fmt;
|
|
||||||
|
|
||||||
pub struct Terminal
|
|
||||||
{
|
|
||||||
pub screen_manager: Rc<Mutex<ScreenManager>>,
|
|
||||||
pub context: Mutex<Context>
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Terminal
|
|
||||||
{
|
|
||||||
pub fn new() -> Terminal
|
|
||||||
{
|
|
||||||
Terminal {
|
|
||||||
screen_manager: Rc::new(Mutex::new(ScreenManager::new())),
|
|
||||||
context: Mutex::new(Context::new())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Get an TerminalColor implementation whereon color related actions can be performed.
|
|
||||||
///
|
|
||||||
/// # Example
|
|
||||||
///
|
|
||||||
/// ```rust
|
|
||||||
/// extern crate crossterm;
|
|
||||||
///
|
|
||||||
/// use self::crossterm::style::{color, Color};
|
|
||||||
///
|
|
||||||
/// // Get colored terminal instance
|
|
||||||
/// let mut colored_terminal = color();
|
|
||||||
///
|
|
||||||
/// // preform some actions on the colored terminal
|
|
||||||
/// colored_terminal.set_fg(Color::Red);
|
|
||||||
/// colored_terminal.set_bg(Color::Blue);
|
|
||||||
/// colored_terminal.reset();
|
|
||||||
/// ```
|
|
||||||
pub fn color(&self) -> Box<style::TerminalColor> {
|
|
||||||
Box::from(style::TerminalColor::new(self.screen_manager.clone()))
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Wraps an displayable object so it can be formatted with colors and attributes.
|
|
||||||
///
|
|
||||||
/// Check `/examples/color` in the libary for more spesific examples.
|
|
||||||
///
|
|
||||||
/// #Example
|
|
||||||
///
|
|
||||||
/// ```rust
|
|
||||||
/// extern crate crossterm;
|
|
||||||
///
|
|
||||||
/// use self::crossterm::style::{paint,Color};
|
|
||||||
///
|
|
||||||
/// fn main()
|
|
||||||
/// {
|
|
||||||
/// // Create an styledobject object from the text 'Unstyled font'
|
|
||||||
/// // Currently it has the default foregroundcolor and backgroundcolor.
|
|
||||||
/// println!("{}",paint("Unstyled font"));
|
|
||||||
///
|
|
||||||
/// // Create an displayable object from the text 'Colored font',
|
|
||||||
/// // Paint this with the `Red` foreground color and `Blue` backgroundcolor.
|
|
||||||
/// // Print the result.
|
|
||||||
/// let styledobject = paint("Colored font").with(Color::Red).on(Color::Blue);
|
|
||||||
/// println!("{}", styledobject);
|
|
||||||
///
|
|
||||||
/// // Or all in one line
|
|
||||||
/// println!("{}", paint("Colored font").with(Color::Red).on(Color::Blue));
|
|
||||||
/// }
|
|
||||||
/// ```
|
|
||||||
pub fn paint<D>(&self, val: D) -> style::StyledObject<D>
|
|
||||||
where
|
|
||||||
D: fmt::Display,
|
|
||||||
{
|
|
||||||
style::ObjectStyle::new().apply_to(val, self.screen_manager.clone())
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,11 +1,3 @@
|
|||||||
|
|
||||||
/// This trait is used for creating an instance of an concrete implementation from an base trait.
|
|
||||||
/// This trait allows the output to be different in size.
|
|
||||||
pub trait Construct{
|
|
||||||
fn new() -> Box<Self>
|
|
||||||
where
|
|
||||||
Self: Sized;
|
|
||||||
}
|
|
||||||
/// This trait can be used to create an empty instance of an struct.
|
/// This trait can be used to create an empty instance of an struct.
|
||||||
pub trait Empty {
|
pub trait Empty {
|
||||||
fn empty() -> Self;
|
fn empty() -> Self;
|
||||||
|
40
src/state/command_manager.rs
Normal file
40
src/state/command_manager.rs
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
use std::rc::Rc;
|
||||||
|
use std::sync::Mutex;
|
||||||
|
use Context;
|
||||||
|
use super::commands::IStateCommand;
|
||||||
|
|
||||||
|
/// Simple wrapper for executing an command.
|
||||||
|
pub struct CommandManager;
|
||||||
|
|
||||||
|
impl CommandManager
|
||||||
|
{
|
||||||
|
/// execute an certain command by id.
|
||||||
|
pub fn execute(terminal: &Context, command_id: u16) -> bool
|
||||||
|
{
|
||||||
|
let mut mutex: Rc<Mutex<Box<IStateCommand>>>;
|
||||||
|
|
||||||
|
let mut state = terminal.state_manager.lock().unwrap();
|
||||||
|
{
|
||||||
|
mutex = state.get(command_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut command = mutex.lock().unwrap();
|
||||||
|
let has_succeeded = command.execute(&terminal);
|
||||||
|
return has_succeeded;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// undo an certain command by id.
|
||||||
|
pub fn undo(terminal: &Context, command_id: u16) -> bool
|
||||||
|
{
|
||||||
|
let mut mutex: Rc<Mutex<Box<IStateCommand>>>;
|
||||||
|
|
||||||
|
let mut state = terminal.state_manager.lock().unwrap();
|
||||||
|
{
|
||||||
|
mutex = state.get(command_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut command = mutex.lock().unwrap();
|
||||||
|
let has_succeeded = command.undo(&terminal);
|
||||||
|
return has_succeeded;
|
||||||
|
}
|
||||||
|
}
|
@ -7,9 +7,10 @@
|
|||||||
//! So where do whe use the `Commands` for? This is so that we can push all or terminal state changes into list.
|
//! So where do whe use the `Commands` for? This is so that we can push all or terminal state changes into list.
|
||||||
//! When we do not need those changes we can revert all the changes by looping true the list and undo all the action.
|
//! When we do not need those changes we can revert all the changes by looping true the list and undo all the action.
|
||||||
//!
|
//!
|
||||||
//! See the `Context` struct where we store the commands for more info.
|
//! See the `StateManager` struct where we store the commands for more info.
|
||||||
|
|
||||||
use std::sync::Mutex;
|
use std::sync::Mutex;
|
||||||
|
use std::rc::Rc;
|
||||||
|
|
||||||
#[cfg(unix)]
|
#[cfg(unix)]
|
||||||
pub mod unix_command;
|
pub mod unix_command;
|
||||||
@ -24,22 +25,21 @@ pub use self::unix_command::*;
|
|||||||
#[cfg(windows)]
|
#[cfg(windows)]
|
||||||
pub use self::win_commands::*;
|
pub use self::win_commands::*;
|
||||||
|
|
||||||
use { Context, Terminal };
|
use {StateManager, Context};
|
||||||
|
|
||||||
/// This command can be used for simple commands witch just have an `undo()` and an `execute()`
|
/// This command can be used for simple commands witch just have an `undo()` and an `execute()`
|
||||||
pub trait ICommand
|
pub trait ICommand
|
||||||
{
|
{
|
||||||
fn new() -> Box<Self> where Self: Sized;
|
fn new() -> Box<Self> where Self: Sized;
|
||||||
fn execute(&mut self, terminal: &Terminal) -> bool;
|
fn execute(&mut self, terminal: &Context) -> bool;
|
||||||
fn undo(&mut self, terminal: &Terminal) -> bool;
|
fn undo(&mut self, terminal: &Context) -> bool;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// This command is used for complex commands whits change the terminal state.
|
/// This command is used for complex commands whits change the terminal state.
|
||||||
/// By passing an `Context` instance this command will register it self to notify the terminal state change.
|
/// By passing an `Context` instance this command will register it self to notify the terminal state change.
|
||||||
|
|
||||||
pub trait IContextCommand
|
pub trait IStateCommand
|
||||||
{
|
{
|
||||||
fn new(context: &Mutex<Context>) -> (Box<Self>, u16) where Self: Sized;
|
fn execute(&mut self, terminal: &Context) -> bool;
|
||||||
fn execute(&mut self, terminal: &Terminal) -> bool;
|
fn undo(&mut self, terminal: &Context) -> bool;
|
||||||
fn undo(&mut self, terminal: &Terminal) -> bool;
|
|
||||||
}
|
}
|
@ -1,6 +1,21 @@
|
|||||||
//! This module contains the commands that can be used for both unix and windows systems.
|
//! This module contains the commands that can be used for both unix and windows systems. Or else said terminals that support ansi codes.
|
||||||
use Terminal ;
|
use Context;
|
||||||
use super::ICommand;
|
use super::{ICommand, IStateCommand};
|
||||||
|
|
||||||
|
pub struct EmptyCommand;
|
||||||
|
|
||||||
|
impl IStateCommand for EmptyCommand
|
||||||
|
{
|
||||||
|
fn execute(&mut self, terminal: &Context) -> bool
|
||||||
|
{
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
fn undo(&mut self, terminal: &Context) -> bool
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// This command is used for switching to alternate screen and back to main screen.
|
/// This command is used for switching to alternate screen and back to main screen.
|
||||||
#[derive(Clone, Copy)]
|
#[derive(Clone, Copy)]
|
||||||
@ -12,7 +27,7 @@ impl ICommand for ToAlternateScreenBufferCommand
|
|||||||
Box::from(ToAlternateScreenBufferCommand {})
|
Box::from(ToAlternateScreenBufferCommand {})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn execute(&mut self, terminal: &Terminal) -> bool
|
fn execute(&mut self, terminal: &Context) -> bool
|
||||||
{
|
{
|
||||||
let mut screen = terminal.screen_manager.lock().unwrap();
|
let mut screen = terminal.screen_manager.lock().unwrap();
|
||||||
{
|
{
|
||||||
@ -22,7 +37,7 @@ impl ICommand for ToAlternateScreenBufferCommand
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn undo(&mut self, terminal: &Terminal) -> bool
|
fn undo(&mut self, terminal: &Context) -> bool
|
||||||
{
|
{
|
||||||
let mut screen = terminal.screen_manager.lock().unwrap();
|
let mut screen = terminal.screen_manager.lock().unwrap();
|
||||||
{
|
{
|
||||||
|
@ -1,13 +1,14 @@
|
|||||||
//! This module contains the commands that can be used for unix systems.
|
//! This module contains the commands that can be used for unix systems.
|
||||||
|
|
||||||
use {Terminal, Context};
|
use {Context, StateManager, CommandManager};
|
||||||
use super::IContextCommand;
|
use super::IStateCommand;
|
||||||
use kernel::unix_kernel::terminal;
|
use kernel::unix_kernel::terminal;
|
||||||
use termios::{Termios, tcsetattr, TCSAFLUSH, ICANON, ECHO, CREAD};
|
use termios::{Termios, tcsetattr, TCSAFLUSH, ICANON, ECHO, CREAD};
|
||||||
|
|
||||||
const FD_STDIN: ::std::os::unix::io::RawFd = 1;
|
const FD_STDIN: ::std::os::unix::io::RawFd = 1;
|
||||||
|
|
||||||
use std::sync::Mutex;
|
use std::sync::Mutex;
|
||||||
|
use std::rc::Rc;
|
||||||
|
|
||||||
/// This command is used for switching to NoncanonicalMode.
|
/// This command is used for switching to NoncanonicalMode.
|
||||||
#[derive(Copy, Clone)]
|
#[derive(Copy, Clone)]
|
||||||
@ -16,20 +17,24 @@ pub struct NoncanonicalModeCommand
|
|||||||
key: u16
|
key: u16
|
||||||
}
|
}
|
||||||
|
|
||||||
impl IContextCommand for NoncanonicalModeCommand
|
impl NoncanonicalModeCommand
|
||||||
{
|
{
|
||||||
fn new(context: &Mutex<Context>) -> (Box<NoncanonicalModeCommand>, u16) {
|
pub fn new(state: &Mutex<StateManager>) -> u16
|
||||||
|
{
|
||||||
let key = 1;
|
let key = 1;
|
||||||
|
|
||||||
let mut context = context.lock().unwrap();
|
let mut state_manager = state.lock().unwrap();
|
||||||
{
|
{
|
||||||
let command = NoncanonicalModeCommand { key: key };
|
let command = Box::from(NoncanonicalModeCommand { key: key });
|
||||||
context.register_change(Box::from(command), key);
|
state_manager.register_change(command, key);
|
||||||
(Box::from(command),key)
|
key
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn execute(&mut self, terminal: &Terminal) -> bool
|
impl IStateCommand for NoncanonicalModeCommand
|
||||||
|
{
|
||||||
|
fn execute(&mut self, terminal: &Context) -> bool
|
||||||
{
|
{
|
||||||
// Set noncanonical mode
|
// Set noncanonical mode
|
||||||
if let Ok(orig) = Termios::from_fd(FD_STDIN)
|
if let Ok(orig) = Termios::from_fd(FD_STDIN)
|
||||||
@ -48,7 +53,7 @@ impl IContextCommand for NoncanonicalModeCommand
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn undo(&mut self, terminal: &Terminal) -> bool
|
fn undo(&mut self, terminal: &Context) -> bool
|
||||||
{
|
{
|
||||||
// Disable noncanonical mode
|
// Disable noncanonical mode
|
||||||
if let Ok(orig) = Termios::from_fd(FD_STDIN)
|
if let Ok(orig) = Termios::from_fd(FD_STDIN)
|
||||||
@ -70,34 +75,35 @@ impl IContextCommand for NoncanonicalModeCommand
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// This command is used for enabling and disabling raw mode for the terminal.
|
/// This command is used for enabling and disabling raw mode for the terminal.
|
||||||
#[derive(Copy, Clone)]
|
|
||||||
pub struct EnableRawModeCommand
|
pub struct EnableRawModeCommand
|
||||||
{
|
{
|
||||||
original_mode: Option<Termios>,
|
original_mode: Option<Box<Termios>>,
|
||||||
command_id: u16
|
command_id: u16
|
||||||
}
|
}
|
||||||
|
|
||||||
impl IContextCommand for EnableRawModeCommand
|
impl EnableRawModeCommand
|
||||||
{
|
{
|
||||||
fn new(context: &Mutex<Context>) -> (Box<EnableRawModeCommand>, u16) {
|
pub fn new(state_manager: &Mutex<StateManager>) -> u16{
|
||||||
let key = 2;
|
let key = 2;
|
||||||
|
|
||||||
let mut context = context.lock().unwrap();
|
let mut state = state_manager.lock().unwrap();
|
||||||
{
|
{
|
||||||
let command = EnableRawModeCommand { original_mode: None, command_id: key };
|
let command = EnableRawModeCommand { original_mode: None, command_id: key };
|
||||||
context.register_change(Box::from(command), key);
|
state.register_change(Box::from(command), key);
|
||||||
(Box::from(command), key)
|
key
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn execute(&mut self, terminal: &Terminal) -> bool
|
impl IStateCommand for EnableRawModeCommand
|
||||||
|
{
|
||||||
|
fn execute(&mut self, terminal: &Context) -> bool
|
||||||
{
|
{
|
||||||
let original_mode = terminal::get_terminal_mode();
|
let original_mode = terminal::get_terminal_mode();
|
||||||
|
|
||||||
if let Ok(original_mode) = original_mode
|
if let Ok(original_mode) = original_mode
|
||||||
{
|
{
|
||||||
panic!("setting {:?}", original_mode);
|
self.original_mode = Some(Box::from(original_mode));
|
||||||
self.original_mode = Some(original_mode);
|
|
||||||
let mut new_mode = original_mode;
|
let mut new_mode = original_mode;
|
||||||
terminal::make_raw(&mut new_mode);
|
terminal::make_raw(&mut new_mode);
|
||||||
terminal::set_terminal_mode(&new_mode);
|
terminal::set_terminal_mode(&new_mode);
|
||||||
@ -108,12 +114,10 @@ impl IContextCommand for EnableRawModeCommand
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn undo(&mut self, terminal: &Terminal) -> bool
|
fn undo(&mut self, terminal: &Context) -> bool
|
||||||
{
|
{
|
||||||
panic!("undoing {:?}", self.original_mode);
|
if let Some(ref original_mode) = self.original_mode
|
||||||
if let Some(original_mode) = self.original_mode
|
|
||||||
{
|
{
|
||||||
|
|
||||||
let result = terminal::set_terminal_mode(&original_mode);
|
let result = terminal::set_terminal_mode(&original_mode);
|
||||||
|
|
||||||
match result
|
match result
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
//! This module contains the commands that can be used for windows systems.
|
//! This module contains the commands that can be used for windows systems.
|
||||||
|
|
||||||
use super::{ICommand, IContextCommand};
|
use super::{ICommand, IStateCommand};
|
||||||
use super::super::Context;
|
use super::super::StateManager;
|
||||||
|
|
||||||
use kernel::windows_kernel::{kernel, ansi_support};
|
use kernel::windows_kernel::{kernel, ansi_support};
|
||||||
use winapi::shared::minwindef::DWORD;
|
use winapi::shared::minwindef::DWORD;
|
||||||
@ -9,6 +9,7 @@ use winapi::um::wincon;
|
|||||||
use winapi::um::wincon::{ENABLE_VIRTUAL_TERMINAL_PROCESSING ,SMALL_RECT, COORD, CHAR_INFO};
|
use winapi::um::wincon::{ENABLE_VIRTUAL_TERMINAL_PROCESSING ,SMALL_RECT, COORD, CHAR_INFO};
|
||||||
use std::mem;
|
use std::mem;
|
||||||
|
|
||||||
|
use std::rc::Rc;
|
||||||
use std::sync::Mutex;
|
use std::sync::Mutex;
|
||||||
|
|
||||||
/// This command is used for enabling and disabling ANSI code support for windows systems,
|
/// This command is used for enabling and disabling ANSI code support for windows systems,
|
||||||
@ -88,15 +89,17 @@ pub struct EnableRawModeCommand
|
|||||||
key: i16
|
key: i16
|
||||||
}
|
}
|
||||||
|
|
||||||
impl IContextCommand for EnableRawModeCommand
|
impl IStateCommand for EnableRawModeCommand
|
||||||
{
|
{
|
||||||
fn new(context: &mut Context) -> (Box<EnableRawModeCommand>, i16) {
|
fn new(state: &mut StateManager) -> (Box<EnableRawModeCommand>, i16) {
|
||||||
use self::wincon::{ENABLE_LINE_INPUT,ENABLE_PROCESSED_INPUT, ENABLE_PROCESSED_OUTPUT, ENABLE_WRAP_AT_EOL_OUTPUT, ENABLE_ECHO_INPUT};
|
use self::wincon::{ENABLE_LINE_INPUT,ENABLE_PROCESSED_INPUT, ENABLE_PROCESSED_OUTPUT, ENABLE_WRAP_AT_EOL_OUTPUT, ENABLE_ECHO_INPUT};
|
||||||
|
|
||||||
let key = super::generate_key();
|
let key = super::generate_key();
|
||||||
let command = EnableRawModeCommand { mask: ENABLE_LINE_INPUT | ENABLE_PROCESSED_INPUT | ENABLE_ECHO_INPUT, key: key };
|
let command = EnableRawModeCommand { mask: ENABLE_LINE_INPUT | ENABLE_PROCESSED_INPUT | ENABLE_ECHO_INPUT, key: key };
|
||||||
context.register_change(Box::from(command), key);
|
let rc = Rc::new(command);
|
||||||
(Box::from(command),key)
|
|
||||||
|
state.register_change(rc.clone(), key);
|
||||||
|
(rc.clone(),key)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn execute(&mut self, terminal: &Terminal) -> bool
|
fn execute(&mut self, terminal: &Terminal) -> bool
|
||||||
@ -154,7 +157,7 @@ impl ICommand for ToAlternateScreenBufferCommand
|
|||||||
Box::from(ToAlternateScreenBufferCommand {})
|
Box::from(ToAlternateScreenBufferCommand {})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn execute(&mut self, context: &Context) -> bool
|
fn execute(&mut self, state: &StateManager) -> bool
|
||||||
{
|
{
|
||||||
let mut chi_buffer: [CHAR_INFO;160] = unsafe {mem::zeroed() };
|
let mut chi_buffer: [CHAR_INFO;160] = unsafe {mem::zeroed() };
|
||||||
|
|
||||||
@ -208,7 +211,7 @@ impl ICommand for ToAlternateScreenBufferCommand
|
|||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
fn undo(&mut self, context: &Context) -> bool
|
fn undo(&mut self, state: &StateManager) -> bool
|
||||||
{
|
{
|
||||||
let handle = kernel::get_output_handle();
|
let handle = kernel::get_output_handle();
|
||||||
kernel::set_active_screen_buffer(handle);
|
kernel::set_active_screen_buffer(handle);
|
||||||
|
@ -1,65 +1,92 @@
|
|||||||
//! This module is used for registering, storing an restoring the terminal state changes.
|
//! This module contains the code for the context of the terminal.
|
||||||
|
|
||||||
use std::collections::HashMap;
|
use std::sync::Mutex;
|
||||||
use super::commands::IContextCommand;
|
use std::rc::Rc;
|
||||||
use Terminal;
|
|
||||||
/// Struct that stores the changed states of the terminal.
|
use super::super::style;
|
||||||
|
use { StateManager, ScreenManager };
|
||||||
|
|
||||||
|
use std::fmt;
|
||||||
|
|
||||||
|
/// This type contains the context of the current terminal. The context surrounds the changed states of the terminal and can be used for managing the output of the terminal.
|
||||||
pub struct Context
|
pub struct Context
|
||||||
{
|
{
|
||||||
changed_states: HashMap<u16, Box<IContextCommand>>,
|
pub screen_manager: Rc<Mutex<ScreenManager>>,
|
||||||
|
pub state_manager: Mutex<StateManager>
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Context
|
impl Context
|
||||||
{
|
{
|
||||||
/// Create new Context where the terminals states can be handled.
|
/// Create new Context instance so that you can provide it to other modules like terminal, cursor and color
|
||||||
|
///
|
||||||
|
/// This context type is just an wrapper that crossterm uses for managin the state the terminal.
|
||||||
|
///
|
||||||
|
/// You must provide this context otherwise crossterm would not be able to restore to the original state of the terminal.
|
||||||
|
/// Also futures like rawscreen and ansi codes can not be used.
|
||||||
|
///
|
||||||
|
/// #Example
|
||||||
|
///
|
||||||
|
/// ```rust
|
||||||
|
///
|
||||||
|
/// use crossterm::Context;
|
||||||
|
///
|
||||||
|
/// use crossterm::cursor;
|
||||||
|
/// use crossterm::color;
|
||||||
|
/// use crossterm::terminal;
|
||||||
|
///
|
||||||
|
/// let cursor = cursor::cursor(&context)
|
||||||
|
/// let terminal = terminal::terminal(&context);
|
||||||
|
/// let color = terminal::color(&context);
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
pub fn new() -> Context
|
pub fn new() -> Context
|
||||||
{
|
{
|
||||||
Context {
|
Context {
|
||||||
changed_states: HashMap::new(),
|
screen_manager: Rc::new(Mutex::new(ScreenManager::new())),
|
||||||
|
state_manager: Mutex::new(StateManager::new())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// /// Restore all changes that are made to the terminal.
|
/// Wraps an displayable object so it can be formatted with colors and attributes.
|
||||||
// pub fn restore_changes(&mut self)
|
///
|
||||||
// {
|
/// Check `/examples/color` in the libary for more spesific examples.
|
||||||
// use std::iter::FromIterator;
|
///
|
||||||
//
|
/// #Example
|
||||||
// let mut buffer = Vec::new();
|
///
|
||||||
//
|
/// ```rust
|
||||||
// for i in 0..self.changed_states.len()
|
/// extern crate crossterm;
|
||||||
// {
|
///
|
||||||
// buffer[i] = self.changed_states.iter().nth(i).unwrap();
|
/// use self::crossterm::style::{paint,Color};
|
||||||
// }
|
///
|
||||||
//
|
/// fn main()
|
||||||
// for i in 0..buffer.len()
|
/// {
|
||||||
// {
|
/// // Create an styledobject object from the text 'Unstyled font'
|
||||||
// buffer[i].1.undo(self);
|
/// // Currently it has the default foregroundcolor and backgroundcolor.
|
||||||
// }
|
/// println!("{}",paint("Unstyled font"));
|
||||||
// }
|
///
|
||||||
|
/// // Create an displayable object from the text 'Colored font',
|
||||||
/// Register new changed state with the given key.
|
/// // Paint this with the `Red` foreground color and `Blue` backgroundcolor.
|
||||||
pub fn register_change(&mut self, change: Box<IContextCommand>, key: u16)
|
/// // Print the result.
|
||||||
|
/// let styledobject = paint("Colored font").with(Color::Red).on(Color::Blue);
|
||||||
|
/// println!("{}", styledobject);
|
||||||
|
///
|
||||||
|
/// // Or all in one line
|
||||||
|
/// println!("{}", paint("Colored font").with(Color::Red).on(Color::Blue));
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
|
pub fn paint<D>(&self, val: D) -> style::StyledObject<D>
|
||||||
|
where
|
||||||
|
D: fmt::Display,
|
||||||
{
|
{
|
||||||
if !self.changed_states.contains_key(&key)
|
style::ObjectStyle::new().apply_to(val, self.screen_manager.clone())
|
||||||
{
|
|
||||||
self.changed_states.insert(key, change);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Undo an specific state by the given state key.
|
|
||||||
pub fn undo_state(&mut self, state_key: u16, terminal: &Terminal)
|
|
||||||
{
|
|
||||||
if self.changed_states.contains_key(&state_key)
|
|
||||||
{
|
|
||||||
{
|
|
||||||
let mut command = self.changed_states.get_mut(&state_key).unwrap();
|
|
||||||
command.undo(&terminal);
|
|
||||||
}
|
|
||||||
&self.changed_states.remove(&state_key);
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Drop for Context
|
||||||
|
{
|
||||||
|
fn drop(&mut self)
|
||||||
|
{
|
||||||
|
let mut changes = self.state_manager.lock().unwrap();
|
||||||
|
changes.restore_changes(&self);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
//! If `crossterm` changes some core state of the terminal like: enabling ANSI or enabling raw mode it should be reverted when the current process ends.
|
//! If `crossterm` changes some core state of the terminal like: enabling ANSI or enabling raw mode it should be reverted when the current process ends.
|
||||||
//! It would be a little lame to let the terminal in raw mode after the the current process ends for the user of this library.
|
//! It would be a little lame to let the terminal in raw mode after the the current process ends for the user of this library.
|
||||||
|
|
||||||
mod context;
|
pub mod state_manager;
|
||||||
pub mod commands;
|
pub mod commands;
|
||||||
|
pub mod command_manager;
|
||||||
pub use self::context::{Context};
|
pub mod context;
|
56
src/state/state_manager.rs
Normal file
56
src/state/state_manager.rs
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
//! This module is used for registering, storing an restoring the terminal state changes.
|
||||||
|
|
||||||
|
use Context;
|
||||||
|
use super::commands::IStateCommand;
|
||||||
|
use super::commands::shared_commands::EmptyCommand;
|
||||||
|
|
||||||
|
use std::rc::Rc;
|
||||||
|
use std::sync::Mutex;
|
||||||
|
use std::collections::HashMap;
|
||||||
|
|
||||||
|
/// Struct that stores the changed states of the terminal.
|
||||||
|
pub struct StateManager
|
||||||
|
{
|
||||||
|
changed_states: HashMap<u16, Rc<Mutex<Box<IStateCommand>>>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl StateManager
|
||||||
|
{
|
||||||
|
/// Create new Context where the terminals states can be handled.
|
||||||
|
pub fn new() -> StateManager
|
||||||
|
{
|
||||||
|
StateManager {
|
||||||
|
changed_states: HashMap::new(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Restore all changes that are made to the terminal.
|
||||||
|
pub fn restore_changes(&mut self, context: &Context)
|
||||||
|
{
|
||||||
|
for (id, item) in self.changed_states.iter_mut()
|
||||||
|
{
|
||||||
|
let mut item = item.lock().unwrap();
|
||||||
|
item.undo(&context);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Register new changed state with the given key.
|
||||||
|
pub fn register_change(&mut self, change: Box<IStateCommand>, key: u16)
|
||||||
|
{
|
||||||
|
self.changed_states.insert(key, Rc::new(Mutex::new(change)));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get an state command from storage by id.
|
||||||
|
pub fn get(&mut self, state_key: u16) -> Rc<Mutex<Box<IStateCommand>>>
|
||||||
|
{
|
||||||
|
if self.changed_states.contains_key(&state_key)
|
||||||
|
{
|
||||||
|
return self.changed_states[&state_key].clone()
|
||||||
|
}
|
||||||
|
|
||||||
|
return Rc::new(Mutex::new(Box::new(EmptyCommand)))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
|||||||
//! This is an ANSI specific implementation for styling related action.
|
//! This is an ANSI specific implementation for styling related action.
|
||||||
//! This module is used for windows 10 terminals and unix terminals by default.
|
//! This module is used for windows 10 terminals and unix terminals by default.
|
||||||
|
|
||||||
use { Construct, ScreenManager };
|
use ScreenManager;
|
||||||
use super::ITerminalColor;
|
use super::ITerminalColor;
|
||||||
use super::super::{Color, ColorType};
|
use super::super::{Color, ColorType};
|
||||||
|
|
||||||
@ -12,8 +12,8 @@ use std::sync::Mutex;
|
|||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct AnsiColor;
|
pub struct AnsiColor;
|
||||||
|
|
||||||
impl Construct for AnsiColor {
|
impl AnsiColor {
|
||||||
fn new() -> Box<AnsiColor> {
|
pub fn new() -> Box<AnsiColor> {
|
||||||
Box::from(AnsiColor {})
|
Box::from(AnsiColor {})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,10 +2,9 @@
|
|||||||
//! Like styling the font, foreground color and background.
|
//! Like styling the font, foreground color and background.
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
use Construct;
|
|
||||||
use style::Color;
|
use style::Color;
|
||||||
|
|
||||||
use std::{ io };
|
use std::io;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
use std::sync::Mutex;
|
use std::sync::Mutex;
|
||||||
|
|
||||||
@ -35,9 +34,12 @@ impl TerminalColor {
|
|||||||
/// extern crate crossterm;
|
/// extern crate crossterm;
|
||||||
///
|
///
|
||||||
/// use self::crossterm::style::{ color, Color};
|
/// use self::crossterm::style::{ color, Color};
|
||||||
|
/// use crossterm::Context;
|
||||||
|
///
|
||||||
|
/// let context = Context::new();
|
||||||
///
|
///
|
||||||
/// // Get colored terminal instance
|
/// // Get colored terminal instance
|
||||||
/// let mut colored_terminal = color();
|
/// let mut colored_terminal = color(&context);
|
||||||
///
|
///
|
||||||
/// // Set foreground color of the font
|
/// // Set foreground color of the font
|
||||||
/// colored_terminal.set_fg(Color::Red);
|
/// colored_terminal.set_fg(Color::Red);
|
||||||
@ -60,9 +62,12 @@ impl TerminalColor {
|
|||||||
/// extern crate crossterm;
|
/// extern crate crossterm;
|
||||||
///
|
///
|
||||||
/// use self::crossterm::style::{ color, Color};
|
/// use self::crossterm::style::{ color, Color};
|
||||||
|
/// use crossterm::Context;
|
||||||
|
///
|
||||||
|
/// let context = Context::new();
|
||||||
///
|
///
|
||||||
/// // Get colored terminal instance
|
/// // Get colored terminal instance
|
||||||
/// let mut colored_terminal = color();
|
/// let mut colored_terminal = color(&context);
|
||||||
///
|
///
|
||||||
/// // Set background color of the font
|
/// // Set background color of the font
|
||||||
/// colored_terminal.set_bg(Color::Red);
|
/// colored_terminal.set_bg(Color::Red);
|
||||||
@ -83,9 +88,12 @@ impl TerminalColor {
|
|||||||
/// extern crate crossterm;
|
/// extern crate crossterm;
|
||||||
///
|
///
|
||||||
/// use self::crossterm::style::color;
|
/// use self::crossterm::style::color;
|
||||||
|
/// use crossterm::Context;
|
||||||
|
///
|
||||||
|
/// let context = Context::new();
|
||||||
///
|
///
|
||||||
/// // Get colored terminal instance
|
/// // Get colored terminal instance
|
||||||
/// let mut colored_terminal = color();
|
/// let mut colored_terminal = color(&context);
|
||||||
///
|
///
|
||||||
/// colored_terminal.reset();
|
/// colored_terminal.reset();
|
||||||
///
|
///
|
||||||
@ -114,6 +122,10 @@ impl TerminalColor {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Get an Color implementation whereon color related actions can be performed.
|
||||||
|
///
|
||||||
|
/// Check `/examples/version/color` in the libary for more specific examples.
|
||||||
|
///
|
||||||
pub fn color(screen_manager: Rc<Mutex<ScreenManager>>) -> Box<TerminalColor> {
|
pub fn color(screen_manager: Rc<Mutex<ScreenManager>>) -> Box<TerminalColor> {
|
||||||
Box::from(TerminalColor::new(screen_manager.clone()))
|
Box::from(TerminalColor::new(screen_manager.clone()))
|
||||||
}
|
}
|
||||||
|
@ -7,13 +7,13 @@ mod ansi_color;
|
|||||||
#[cfg(target_os = "windows")]
|
#[cfg(target_os = "windows")]
|
||||||
use self::winapi_color::WinApiColor;
|
use self::winapi_color::WinApiColor;
|
||||||
use self::ansi_color::AnsiColor;
|
use self::ansi_color::AnsiColor;
|
||||||
|
|
||||||
|
use { ScreenManager };
|
||||||
use super::{Color, ColorType};
|
use super::{Color, ColorType};
|
||||||
|
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
use std::sync::Mutex;
|
use std::sync::Mutex;
|
||||||
|
|
||||||
use { ScreenManager };
|
|
||||||
|
|
||||||
///! This trait defines the actions that can be preformed with the terminal color.
|
///! This trait defines the actions that can be preformed with the terminal color.
|
||||||
///! This trait can be implemented so that an concrete implementation of the ITerminalColor can forfill
|
///! This trait can be implemented so that an concrete implementation of the ITerminalColor can forfill
|
||||||
///! the wishes to work on an specific platform.
|
///! the wishes to work on an specific platform.
|
||||||
|
@ -5,7 +5,6 @@ mod color;
|
|||||||
mod styles;
|
mod styles;
|
||||||
|
|
||||||
pub use self::color::color::{color, TerminalColor };
|
pub use self::color::color::{color, TerminalColor };
|
||||||
|
|
||||||
pub use self::styles::objectstyle::ObjectStyle;
|
pub use self::styles::objectstyle::ObjectStyle;
|
||||||
pub use self::styles::styledobject::StyledObject;
|
pub use self::styles::styledobject::StyledObject;
|
||||||
|
|
||||||
|
@ -5,6 +5,7 @@ use style::{Color, StyledObject};
|
|||||||
use ScreenManager;
|
use ScreenManager;
|
||||||
use std::sync::Mutex;
|
use std::sync::Mutex;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
|
||||||
#[cfg(unix)]
|
#[cfg(unix)]
|
||||||
use super::super::Attribute;
|
use super::super::Attribute;
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
//! This module contains the logic to style an object that contains some context witch can be styled.
|
//! This module contains the logic to style an object that contains some state witch can be styled.
|
||||||
|
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::io::Write;
|
use std::io::Write;
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
//! This is an `ANSI escape code` specific implementation for terminal related action.
|
//! This is an `ANSI escape code` specific implementation for terminal related action.
|
||||||
//! This module is used for windows 10 terminals and unix terminals by default.
|
//! This module is used for windows 10 terminals and unix terminals by default.
|
||||||
|
|
||||||
use {Construct, Terminal};
|
use Context;
|
||||||
use shared::functions;
|
use shared::functions;
|
||||||
use super::{ClearType, ITerminal};
|
use super::{ClearType, ITerminal};
|
||||||
|
|
||||||
@ -10,16 +10,16 @@ use std::io::Write;
|
|||||||
/// This struct is an ansi implementation for terminal related actions.
|
/// This struct is an ansi implementation for terminal related actions.
|
||||||
pub struct AnsiTerminal;
|
pub struct AnsiTerminal;
|
||||||
|
|
||||||
impl Construct for AnsiTerminal {
|
impl AnsiTerminal {
|
||||||
fn new() -> Box<AnsiTerminal> {
|
pub fn new() -> Box<AnsiTerminal> {
|
||||||
Box::from(AnsiTerminal {})
|
Box::from(AnsiTerminal {})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ITerminal for AnsiTerminal {
|
impl ITerminal for AnsiTerminal {
|
||||||
fn clear(&self, clear_type: ClearType, terminal: &Terminal) {
|
fn clear(&self, clear_type: ClearType, context: &Context) {
|
||||||
|
|
||||||
let mut screen_manager = terminal.screen_manager.lock().unwrap();
|
let mut screen_manager = context.screen_manager.lock().unwrap();
|
||||||
{
|
{
|
||||||
let stdout = screen_manager.stdout();
|
let stdout = screen_manager.stdout();
|
||||||
|
|
||||||
@ -43,26 +43,26 @@ impl ITerminal for AnsiTerminal {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn terminal_size(&self, terminal: &Terminal) -> (u16, u16) {
|
fn terminal_size(&self, context: &Context) -> (u16, u16) {
|
||||||
functions::get_terminal_size()
|
functions::get_terminal_size()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn scroll_up(&self, count: i16, terminal: &Terminal) {
|
fn scroll_up(&self, count: i16, context: &Context) {
|
||||||
let mut screen = terminal.screen_manager.lock().unwrap();
|
let mut screen = context.screen_manager.lock().unwrap();
|
||||||
{
|
{
|
||||||
screen.write_ansi(format!(csi!("{}S"), count));
|
screen.write_ansi(format!(csi!("{}S"), count));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn scroll_down(&self, count: i16, terminal: &Terminal) {
|
fn scroll_down(&self, count: i16, context: &Context) {
|
||||||
let mut screen = terminal.screen_manager.lock().unwrap();
|
let mut screen = context.screen_manager.lock().unwrap();
|
||||||
{
|
{
|
||||||
screen.write_ansi(format!(csi!("{}T"), count));
|
screen.write_ansi(format!(csi!("{}T"), count));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_size(&self, width: i16, height: i16, terminal: &Terminal) {
|
fn set_size(&self, width: i16, height: i16, context: &Context) {
|
||||||
let mut screen = terminal.screen_manager.lock().unwrap();
|
let mut screen = context.screen_manager.lock().unwrap();
|
||||||
{
|
{
|
||||||
screen.write_ansi(format!(csi!("8;{};{}t"), width, height));
|
screen.write_ansi(format!(csi!("8;{};{}t"), width, height));
|
||||||
}
|
}
|
||||||
|
@ -4,14 +4,7 @@
|
|||||||
//! - alternate screen
|
//! - alternate screen
|
||||||
//! - raw mode
|
//! - raw mode
|
||||||
//! - clearing resizing scrolling the terminal.
|
//! - clearing resizing scrolling the terminal.
|
||||||
|
//!
|
||||||
use Terminal;
|
|
||||||
use self::ansi_terminal::AnsiTerminal;
|
|
||||||
|
|
||||||
pub use self::terminal::{ terminal};
|
|
||||||
#[cfg(target_os = "windows")]
|
|
||||||
use self::winapi_terminal::WinApiTerminal;
|
|
||||||
|
|
||||||
|
|
||||||
pub mod terminal;
|
pub mod terminal;
|
||||||
|
|
||||||
@ -19,6 +12,13 @@ pub mod terminal;
|
|||||||
mod winapi_terminal;
|
mod winapi_terminal;
|
||||||
mod ansi_terminal;
|
mod ansi_terminal;
|
||||||
|
|
||||||
|
#[cfg(target_os = "windows")]
|
||||||
|
use self::winapi_terminal::WinApiTerminal;
|
||||||
|
use self::ansi_terminal::AnsiTerminal;
|
||||||
|
|
||||||
|
use Context;
|
||||||
|
pub use self::terminal::{ terminal};
|
||||||
|
|
||||||
/// Enum that can be used for the kind of clearing that can be done in the terminal.
|
/// Enum that can be used for the kind of clearing that can be done in the terminal.
|
||||||
pub enum ClearType {
|
pub enum ClearType {
|
||||||
All,
|
All,
|
||||||
@ -38,13 +38,13 @@ pub enum ClearType {
|
|||||||
///! 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.
|
||||||
pub trait ITerminal {
|
pub trait ITerminal {
|
||||||
/// Clear the current cursor by specifying the clear type
|
/// Clear the current cursor by specifying the clear type
|
||||||
fn clear(&self, clear_type: ClearType, terminal: &Terminal);
|
fn clear(&self, clear_type: ClearType, context: &Context);
|
||||||
/// Get the terminal size (x,y)
|
/// Get the terminal size (x,y)
|
||||||
fn terminal_size(&self, terminal: &Terminal) -> (u16, u16);
|
fn terminal_size(&self, context: &Context) -> (u16, u16);
|
||||||
/// Scroll `n` lines up in the current terminal.
|
/// Scroll `n` lines up in the current terminal.
|
||||||
fn scroll_up(&self, count: i16, terminal: &Terminal);
|
fn scroll_up(&self, count: i16, context: &Context);
|
||||||
/// Scroll `n` lines down in the current terminal.
|
/// Scroll `n` lines down in the current terminal.
|
||||||
fn scroll_down(&self, count: i16, terminal: &Terminal);
|
fn scroll_down(&self, count: i16, context: &Context);
|
||||||
/// Resize terminal to the given width and height.
|
/// Resize terminal to the given width and height.
|
||||||
fn set_size(&self,width: i16, height: i16, terminal: &Terminal);
|
fn set_size(&self,width: i16, height: i16, context: &Context);
|
||||||
}
|
}
|
||||||
|
@ -2,25 +2,27 @@
|
|||||||
//! Like clearing and scrolling in the terminal or getting the size of the terminal.
|
//! Like clearing and scrolling in the terminal or getting the size of the terminal.
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
use Construct;
|
use Context;
|
||||||
use super::super::shared::terminal;
|
|
||||||
|
use super::super::style;
|
||||||
|
use std::fmt;
|
||||||
|
|
||||||
/// Struct that stores an specific platform implementation for terminal related actions.
|
/// Struct that stores an specific platform implementation for terminal related actions.
|
||||||
pub struct Terminal<'terminal> {
|
pub struct Terminal<'context> {
|
||||||
terminal: Option<Box<ITerminal>>,
|
terminal: Option<Box<ITerminal>>,
|
||||||
term: &'terminal terminal::Terminal
|
context: &'context Context
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'terminal> Terminal<'terminal> {
|
impl<'context> Terminal<'context> {
|
||||||
/// 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(term: &'terminal terminal::Terminal) -> Terminal<'terminal> {
|
pub fn new(context: &'context Context) -> Terminal<'context> {
|
||||||
#[cfg(target_os = "windows")]
|
#[cfg(target_os = "windows")]
|
||||||
let terminal = functions::get_module::<Box<ITerminal>>(WinApiTerminal::new(), AnsiTerminal::new());
|
let terminal = functions::get_module::<Box<ITerminal>>(WinApiTerminal::new(), AnsiTerminal::new());
|
||||||
|
|
||||||
#[cfg(not(target_os = "windows"))]
|
#[cfg(not(target_os = "windows"))]
|
||||||
let terminal = Some(AnsiTerminal::new() as Box<ITerminal>);
|
let terminal = Some(AnsiTerminal::new() as Box<ITerminal>);
|
||||||
|
|
||||||
Terminal { terminal, term }
|
Terminal { terminal, context: context }
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -32,8 +34,10 @@ impl<'terminal> Terminal<'terminal> {
|
|||||||
///
|
///
|
||||||
/// extern crate crossterm;
|
/// extern crate crossterm;
|
||||||
/// use crossterm::terminal;
|
/// use crossterm::terminal;
|
||||||
|
/// use crossterm::Context;
|
||||||
///
|
///
|
||||||
/// let mut term = terminal::terminal();
|
/// let context = Context::new();
|
||||||
|
/// let mut term = terminal::terminal(&context);
|
||||||
///
|
///
|
||||||
/// // clear all cells in terminal.
|
/// // clear all cells in terminal.
|
||||||
/// term.clear(terminal::ClearType::All);
|
/// term.clear(terminal::ClearType::All);
|
||||||
@ -49,7 +53,7 @@ impl<'terminal> Terminal<'terminal> {
|
|||||||
/// ```
|
/// ```
|
||||||
pub fn clear(&mut self, clear_type: ClearType) {
|
pub fn clear(&mut self, clear_type: ClearType) {
|
||||||
if let Some(ref terminal) = self.terminal {
|
if let Some(ref terminal) = self.terminal {
|
||||||
terminal.clear(clear_type, &self.term);
|
terminal.clear(clear_type, &self.context);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -61,8 +65,10 @@ impl<'terminal> Terminal<'terminal> {
|
|||||||
///
|
///
|
||||||
/// extern crate crossterm;
|
/// extern crate crossterm;
|
||||||
/// use crossterm::terminal;
|
/// use crossterm::terminal;
|
||||||
|
/// use crossterm::Context;
|
||||||
///
|
///
|
||||||
/// let mut term = terminal::terminal();
|
/// let context = Context::new();
|
||||||
|
/// let mut term = terminal::terminal(&context);
|
||||||
///
|
///
|
||||||
/// let size = term.terminal_size();
|
/// let size = term.terminal_size();
|
||||||
/// println!("{:?}", size);
|
/// println!("{:?}", size);
|
||||||
@ -70,7 +76,7 @@ impl<'terminal> Terminal<'terminal> {
|
|||||||
/// ```
|
/// ```
|
||||||
pub fn terminal_size(&mut self) -> (u16, u16) {
|
pub fn terminal_size(&mut self) -> (u16, u16) {
|
||||||
if let Some(ref terminal) = self.terminal {
|
if let Some(ref terminal) = self.terminal {
|
||||||
return terminal.terminal_size(&self.term)
|
return terminal.terminal_size(&self.context)
|
||||||
}
|
}
|
||||||
(0,0)
|
(0,0)
|
||||||
}
|
}
|
||||||
@ -83,8 +89,10 @@ impl<'terminal> Terminal<'terminal> {
|
|||||||
///
|
///
|
||||||
/// extern crate crossterm;
|
/// extern crate crossterm;
|
||||||
/// use crossterm::terminal;
|
/// use crossterm::terminal;
|
||||||
|
/// use crossterm::Context;
|
||||||
///
|
///
|
||||||
/// let mut term = terminal::terminal();
|
/// let context = Context::new();
|
||||||
|
/// let mut term = terminal::terminal(&context);
|
||||||
///
|
///
|
||||||
/// // scroll up by 5 lines
|
/// // scroll up by 5 lines
|
||||||
/// let size = term.scroll_up(5);
|
/// let size = term.scroll_up(5);
|
||||||
@ -92,7 +100,7 @@ impl<'terminal> Terminal<'terminal> {
|
|||||||
/// ```
|
/// ```
|
||||||
pub fn scroll_up(&mut self, count: i16) {
|
pub fn scroll_up(&mut self, count: i16) {
|
||||||
if let Some(ref terminal) = self.terminal {
|
if let Some(ref terminal) = self.terminal {
|
||||||
terminal.scroll_up(count,&self.term);
|
terminal.scroll_up(count,&self.context);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -104,8 +112,10 @@ impl<'terminal> Terminal<'terminal> {
|
|||||||
///
|
///
|
||||||
/// extern crate crossterm;
|
/// extern crate crossterm;
|
||||||
/// use crossterm::terminal;
|
/// use crossterm::terminal;
|
||||||
|
/// use crossterm::Context;
|
||||||
///
|
///
|
||||||
/// let mut term = terminal::terminal();
|
/// let context = Context::new();
|
||||||
|
/// let mut term = terminal::terminal(&context);
|
||||||
///
|
///
|
||||||
/// // scroll down by 5 lines
|
/// // scroll down by 5 lines
|
||||||
/// let size = term.scroll_down(5);
|
/// let size = term.scroll_down(5);
|
||||||
@ -113,7 +123,7 @@ impl<'terminal> Terminal<'terminal> {
|
|||||||
/// ```
|
/// ```
|
||||||
pub fn scroll_down(&mut self, count: i16) {
|
pub fn scroll_down(&mut self, count: i16) {
|
||||||
if let Some(ref terminal) = self.terminal {
|
if let Some(ref terminal) = self.terminal {
|
||||||
terminal.scroll_down(count, &self.term);
|
terminal.scroll_down(count, &self.context);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -125,8 +135,10 @@ impl<'terminal> Terminal<'terminal> {
|
|||||||
///
|
///
|
||||||
/// extern crate crossterm;
|
/// extern crate crossterm;
|
||||||
/// use crossterm::terminal;
|
/// use crossterm::terminal;
|
||||||
|
/// use crossterm::Context;
|
||||||
///
|
///
|
||||||
/// let mut term = terminal::terminal();
|
/// let context = Context::new();
|
||||||
|
/// let mut term = terminal::terminal(&context);
|
||||||
///
|
///
|
||||||
/// // Set of the size to X: 10 and Y: 10
|
/// // Set of the size to X: 10 and Y: 10
|
||||||
/// let size = term.set_size(10,10);
|
/// let size = term.set_size(10,10);
|
||||||
@ -135,14 +147,48 @@ impl<'terminal> Terminal<'terminal> {
|
|||||||
pub fn set_size(&mut self, width: i16, height: i16)
|
pub fn set_size(&mut self, width: i16, height: i16)
|
||||||
{
|
{
|
||||||
if let Some (ref terminal) = self.terminal {
|
if let Some (ref terminal) = self.terminal {
|
||||||
terminal.set_size(width,height,&self.term);
|
terminal.set_size(width,height,&self.context);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Wraps an displayable object so it can be formatted with colors and attributes.
|
||||||
|
///
|
||||||
|
/// Check `/examples/color` in the libary for more spesific examples.
|
||||||
|
///
|
||||||
|
/// #Example
|
||||||
|
///
|
||||||
|
/// ```rust
|
||||||
|
/// extern crate crossterm;
|
||||||
|
///
|
||||||
|
/// use self::crossterm::style::{paint,Color};
|
||||||
|
///
|
||||||
|
/// fn main()
|
||||||
|
/// {
|
||||||
|
/// // Create an styledobject object from the text 'Unstyled font'
|
||||||
|
/// // Currently it has the default foregroundcolor and backgroundcolor.
|
||||||
|
/// println!("{}",paint("Unstyled font"));
|
||||||
|
///
|
||||||
|
/// // Create an displayable object from the text 'Colored font',
|
||||||
|
/// // Paint this with the `Red` foreground color and `Blue` backgroundcolor.
|
||||||
|
/// // Print the result.
|
||||||
|
/// let styledobject = paint("Colored font").with(Color::Red).on(Color::Blue);
|
||||||
|
/// println!("{}", styledobject);
|
||||||
|
///
|
||||||
|
/// // Or all in one line
|
||||||
|
/// println!("{}", paint("Colored font").with(Color::Red).on(Color::Blue));
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
|
pub fn paint<D>(&self, val: D) -> style::StyledObject<D>
|
||||||
|
where
|
||||||
|
D: fmt::Display,
|
||||||
|
{
|
||||||
|
style::ObjectStyle::new().apply_to(val, self.context.screen_manager.clone())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get an Terminal implementation whereon terminal related actions can be performed.
|
/// Get an Terminal implementation whereon terminal related actions can be performed.
|
||||||
///
|
///
|
||||||
/// Check `/examples/terminal` in the libary for more spesific examples.
|
/// Check `/examples/version/terminal` in the libary for more spesific examples.
|
||||||
///
|
///
|
||||||
/// #Example
|
/// #Example
|
||||||
///
|
///
|
||||||
@ -150,16 +196,17 @@ impl<'terminal> Terminal<'terminal> {
|
|||||||
///
|
///
|
||||||
/// extern crate crossterm;
|
/// extern crate crossterm;
|
||||||
/// use crossterm::terminal;
|
/// use crossterm::terminal;
|
||||||
|
/// use crossterm::Context;
|
||||||
///
|
///
|
||||||
/// let mut term = terminal::terminal();
|
/// let context = Context::new();
|
||||||
|
///
|
||||||
|
/// let mut term = terminal::terminal(&context);
|
||||||
///
|
///
|
||||||
/// // scroll down by 5 lines
|
/// // scroll down by 5 lines
|
||||||
/// let size = term.scroll_down(5);
|
/// let size = term.scroll_down(5);
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
///
|
///
|
||||||
///
|
pub fn terminal<'context>(context: &'context Context) -> Box<Terminal<'context>> {
|
||||||
|
Box::from(Terminal::new(&context))
|
||||||
pub fn terminal<'terminal>(terminal: &'terminal terminal::Terminal) -> Box<Terminal<'terminal>> {
|
|
||||||
Box::from(Terminal::new(&terminal))
|
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
//! This is an `WINAPI` specific implementation for terminal related action.
|
//! This is an `WINAPI` specific implementation for terminal related action.
|
||||||
//! This module is used for windows 10 terminals and unix terminals by default.
|
//! This module is used for non supporting `ANSI` windows terminals.
|
||||||
|
|
||||||
use {Construct};
|
use {Construct};
|
||||||
use cursor::cursor;
|
use cursor::cursor;
|
||||||
|
Loading…
Reference in New Issue
Block a user