added unix cursor hide show, fixed windows and added alternate screen
functionality. Also refactored and cleaned up code.:
This commit is contained in:
parent
bb2067ed7b
commit
62fbb6b6a9
File diff suppressed because it is too large
Load Diff
@ -32,5 +32,8 @@ use std::{time, thread};
|
|||||||
fn main() {
|
fn main() {
|
||||||
// alternate_screen::switch_between_main_and_alternate_screen();
|
// alternate_screen::switch_between_main_and_alternate_screen();
|
||||||
let context = Context::new();
|
let context = Context::new();
|
||||||
raw_mode::print_wait_screen_on_alternate_window();
|
let mut scre = screen::AlternateScreen::from(context.clone());
|
||||||
|
write!(scre, "asdf");
|
||||||
|
scre.flush();
|
||||||
|
thread::sleep(time::Duration::from_secs(3));
|
||||||
}
|
}
|
@ -12,7 +12,7 @@ use self::crossterm::Context;
|
|||||||
pub fn paint_foreground()
|
pub fn paint_foreground()
|
||||||
{
|
{
|
||||||
let context = Context::new();
|
let context = Context::new();
|
||||||
let terminal = terminal::terminal(&context);
|
let terminal = terminal::terminal(context.clone());
|
||||||
|
|
||||||
// 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.
|
||||||
@ -30,7 +30,7 @@ pub fn paint_foreground()
|
|||||||
pub fn paint_background()
|
pub fn paint_background()
|
||||||
{
|
{
|
||||||
let context = Context::new();
|
let context = Context::new();
|
||||||
let terminal = terminal::terminal(&context);
|
let terminal = terminal::terminal(context.clone());
|
||||||
|
|
||||||
// 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.
|
||||||
@ -48,7 +48,7 @@ pub fn paint_background()
|
|||||||
pub fn paint_foreground_and_background()
|
pub fn paint_foreground_and_background()
|
||||||
{
|
{
|
||||||
let context = Context::new();
|
let context = Context::new();
|
||||||
let terminal = terminal::terminal(&context);
|
let terminal = terminal::terminal(context.clone());
|
||||||
|
|
||||||
// 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.
|
||||||
@ -74,7 +74,7 @@ pub fn paint_foreground_and_background()
|
|||||||
pub fn print_all_foreground_colors()
|
pub fn print_all_foreground_colors()
|
||||||
{
|
{
|
||||||
let context = Context::new();
|
let context = Context::new();
|
||||||
let terminal = terminal::terminal(&context);
|
let terminal = terminal::terminal(context.clone());
|
||||||
|
|
||||||
println!("Black : \t {}", terminal.paint("■").with(Color::Black));
|
println!("Black : \t {}", terminal.paint("■").with(Color::Black));
|
||||||
println!("Red : \t\t {}", terminal.paint("■").with(Color::Red));
|
println!("Red : \t\t {}", terminal.paint("■").with(Color::Red));
|
||||||
@ -97,7 +97,7 @@ pub fn print_all_foreground_colors()
|
|||||||
pub fn print_all_background_colors()
|
pub fn print_all_background_colors()
|
||||||
{
|
{
|
||||||
let context = Context::new();
|
let context = Context::new();
|
||||||
let terminal = terminal::terminal(&context);
|
let terminal = terminal::terminal(context.clone());
|
||||||
|
|
||||||
println!("Black : \t {}", terminal.paint(" ").on(Color::Black));
|
println!("Black : \t {}", terminal.paint(" ").on(Color::Black));
|
||||||
println!("Red : \t\t {}", terminal.paint(" ").on(Color::Red));
|
println!("Red : \t\t {}", terminal.paint(" ").on(Color::Red));
|
||||||
@ -125,7 +125,7 @@ pub fn print_all_background_colors()
|
|||||||
pub fn print_font_with_attributes()
|
pub fn print_font_with_attributes()
|
||||||
{
|
{
|
||||||
let context = Context::new();
|
let context = Context::new();
|
||||||
let terminal = terminal::terminal(&context);
|
let terminal = terminal::terminal(context.clone());
|
||||||
|
|
||||||
println!("{}", terminal.paint("Normal text"));
|
println!("{}", terminal.paint("Normal text"));
|
||||||
println!("{}", terminal.paint("Bold text").bold());
|
println!("{}", terminal.paint("Bold text").bold());
|
||||||
@ -144,7 +144,7 @@ pub fn print_font_with_attributes()
|
|||||||
pub fn print_supported_colors()
|
pub fn print_supported_colors()
|
||||||
{
|
{
|
||||||
let context = Context::new();
|
let context = Context::new();
|
||||||
let terminal = terminal::terminal(&context);
|
let terminal = terminal::terminal(context.clone());
|
||||||
|
|
||||||
let count = crossterm::style::color(context.screen_manager.clone()).get_available_color_count().unwrap();
|
let count = crossterm::style::color(context.screen_manager.clone()).get_available_color_count().unwrap();
|
||||||
|
|
||||||
|
@ -12,7 +12,7 @@ pub fn goto()
|
|||||||
let context = Context::new();
|
let context = Context::new();
|
||||||
|
|
||||||
// Get the cursor
|
// Get the cursor
|
||||||
let mut cursor = cursor(&context);
|
let mut cursor = cursor(context.clone());
|
||||||
// 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);
|
||||||
}
|
}
|
||||||
@ -23,7 +23,7 @@ pub fn pos()
|
|||||||
let context = Context::new();
|
let context = Context::new();
|
||||||
|
|
||||||
// Get the cursor
|
// Get the cursor
|
||||||
let mut cursor = cursor(&context);
|
let mut cursor = cursor(context.clone());
|
||||||
// get the cursor position.
|
// get the cursor position.
|
||||||
let (x,y) = cursor.pos();
|
let (x,y) = cursor.pos();
|
||||||
}
|
}
|
||||||
@ -34,7 +34,7 @@ pub fn move_up()
|
|||||||
let context = Context::new();
|
let context = Context::new();
|
||||||
|
|
||||||
// Get the cursor
|
// Get the cursor
|
||||||
let mut cursor = cursor(&context);
|
let mut cursor = cursor(context.clone());
|
||||||
// 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);
|
||||||
}
|
}
|
||||||
@ -45,7 +45,7 @@ pub fn move_right()
|
|||||||
let context = Context::new();
|
let context = Context::new();
|
||||||
|
|
||||||
// Get the cursor
|
// Get the cursor
|
||||||
let mut cursor = cursor(&context);
|
let mut cursor = cursor(context.clone());
|
||||||
// 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);
|
||||||
}
|
}
|
||||||
@ -56,7 +56,7 @@ pub fn move_down()
|
|||||||
let context = Context::new();
|
let context = Context::new();
|
||||||
|
|
||||||
// Get the cursor
|
// Get the cursor
|
||||||
let mut cursor = cursor(&context);
|
let mut cursor = cursor(context.clone());
|
||||||
// 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);
|
||||||
}
|
}
|
||||||
@ -67,7 +67,7 @@ pub fn move_left()
|
|||||||
let context = Context::new();
|
let context = Context::new();
|
||||||
|
|
||||||
// Get the cursor
|
// Get the cursor
|
||||||
let mut cursor = cursor(&context);
|
let mut cursor = cursor(context.clone());
|
||||||
// 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);
|
||||||
}
|
}
|
||||||
@ -80,7 +80,7 @@ pub fn print()
|
|||||||
// 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(&context);
|
let mut cursor = cursor(context.clone());
|
||||||
// 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
|
||||||
@ -104,7 +104,7 @@ pub fn safe_and_reset_position()
|
|||||||
{
|
{
|
||||||
let context = Context::new();
|
let context = Context::new();
|
||||||
|
|
||||||
let mut cursor = cursor(&context);
|
let mut cursor = cursor(context.clone());
|
||||||
|
|
||||||
// Goto X: 5 Y: 5
|
// Goto X: 5 Y: 5
|
||||||
cursor.goto(5,5);
|
cursor.goto(5,5);
|
||||||
|
@ -7,18 +7,18 @@ use crossterm::terminal::{self, ClearType};
|
|||||||
|
|
||||||
use std::io::{Write, stdout};
|
use std::io::{Write, stdout};
|
||||||
use std::{time, thread};
|
use std::{time, thread};
|
||||||
|
use std::rc::Rc;
|
||||||
fn print_wait_screen(terminal: &Context)
|
fn print_wait_screen(context: Rc<Context>)
|
||||||
{
|
{
|
||||||
terminal::terminal(&terminal).clear(ClearType::All);
|
terminal::terminal(context.clone()).clear(ClearType::All);
|
||||||
|
|
||||||
let mut cursor = cursor(&terminal);
|
let mut cursor = cursor(context.clone());
|
||||||
cursor.goto(0,0);
|
cursor.goto(0,0);
|
||||||
|
|
||||||
{
|
{
|
||||||
let mut screen_manager = terminal.screen_manager.lock().unwrap();
|
let mut screen_manager = context.screen_manager.lock().unwrap();
|
||||||
{
|
{
|
||||||
write!(screen_manager.stdout(),
|
write!(screen_manager,
|
||||||
"Welcome to the wait screen.\n\
|
"Welcome to the wait screen.\n\
|
||||||
Please wait a few seconds until we arrive back at the main screen.\n\
|
Please wait a few seconds until we arrive back at the main screen.\n\
|
||||||
Progress: "
|
Progress: "
|
||||||
@ -45,10 +45,10 @@ pub fn print_wait_screen_on_alternate_window()
|
|||||||
// 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(&context);
|
let mut screen = AlternateScreen::from(context.clone());
|
||||||
|
|
||||||
// Print the wait screen.
|
// Print the wait screen.
|
||||||
print_wait_screen(&context);
|
print_wait_screen(context.clone());
|
||||||
}
|
}
|
||||||
|
|
||||||
println!("Whe are back at the main screen");
|
println!("Whe are back at the main screen");
|
||||||
@ -57,11 +57,11 @@ 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 context = Context::new();
|
let context = Context::new();
|
||||||
let mut cursor = cursor(&context);
|
let mut cursor = cursor(context.clone());
|
||||||
|
|
||||||
{
|
{
|
||||||
// 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(&context);
|
let mut screen = AlternateScreen::from(context.clone());
|
||||||
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();
|
||||||
|
@ -7,15 +7,16 @@ use crossterm::terminal::{self, ClearType};
|
|||||||
|
|
||||||
use std::io::{Write, stdout};
|
use std::io::{Write, stdout};
|
||||||
use std::{time, thread};
|
use std::{time, thread};
|
||||||
|
use std::rc::Rc;
|
||||||
|
|
||||||
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(context: &Context)
|
fn print_wait_screen(context: Rc<Context>)
|
||||||
{
|
{
|
||||||
terminal::terminal(&context).clear(ClearType::All);
|
terminal::terminal(context.clone()).clear(ClearType::All);
|
||||||
|
|
||||||
let mut cursor = cursor(&context);
|
let mut cursor = cursor(context.clone());
|
||||||
cursor.goto(0,0).print("Welcome to the wait screen.");
|
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,1).print("Please wait a few seconds until we arrive back at the main screen.");
|
||||||
cursor.goto(0,2).print("Progress: ");
|
cursor.goto(0,2).print("Progress: ");
|
||||||
@ -41,11 +42,11 @@ pub fn print_wait_screen_on_alternate_window()
|
|||||||
// create new alternate screen instance this call is also switching the screen to alternate screen.
|
// 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 convert the output of the program to raw mode.
|
||||||
// then print the wait screen on the alternate screen in raw mode.
|
// then print the wait screen on the alternate screen in raw mode.
|
||||||
let mut screen = AlternateScreen::from(&context);
|
let mut screen = AlternateScreen::from(context.clone());
|
||||||
let alternate_screen = screen.into_raw_mode(&context);
|
let alternate_screen = screen.into_raw_mode(context.clone());
|
||||||
|
|
||||||
// Print the wait screen.
|
// Print the wait screen.
|
||||||
print_wait_screen(&context);
|
print_wait_screen(context.clone());
|
||||||
|
|
||||||
screen.flush();
|
screen.flush();
|
||||||
}
|
}
|
||||||
|
@ -21,7 +21,7 @@ pub fn clear_all_lines()
|
|||||||
let context = Context::new();
|
let context = Context::new();
|
||||||
|
|
||||||
// Get terminal
|
// Get terminal
|
||||||
let mut terminal = terminal(&context);
|
let mut terminal = terminal(context);
|
||||||
|
|
||||||
print_test_data();
|
print_test_data();
|
||||||
|
|
||||||
@ -35,12 +35,12 @@ pub fn clear_from_cursor_down()
|
|||||||
let context = Context::new();
|
let context = Context::new();
|
||||||
|
|
||||||
// Get terminal
|
// Get terminal
|
||||||
let mut terminal = terminal(&context);
|
let mut terminal = terminal(context.clone());
|
||||||
|
|
||||||
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(&context).goto(4,8);
|
cursor::cursor(context.clone()).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);
|
||||||
@ -52,12 +52,12 @@ pub fn clear_from_cursor_up()
|
|||||||
let context = Context::new();
|
let context = Context::new();
|
||||||
|
|
||||||
// Get terminal
|
// Get terminal
|
||||||
let mut terminal = terminal(&context);
|
let mut terminal = terminal(context.clone());
|
||||||
|
|
||||||
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(&context).goto(4,4);
|
cursor::cursor(context.clone()).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);
|
||||||
@ -69,12 +69,12 @@ pub fn clear_current_line()
|
|||||||
let context = Context::new();
|
let context = Context::new();
|
||||||
|
|
||||||
// Get terminal
|
// Get terminal
|
||||||
let mut terminal = terminal(&context);
|
let mut terminal = terminal(context.clone());
|
||||||
|
|
||||||
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(&context).goto(4,4);
|
cursor::cursor(context.clone()).goto(4,4);
|
||||||
|
|
||||||
// Clear current line cells.
|
// Clear current line cells.
|
||||||
terminal.clear(ClearType::CurrentLine);
|
terminal.clear(ClearType::CurrentLine);
|
||||||
@ -86,12 +86,12 @@ pub fn clear_until_new_line()
|
|||||||
let context = Context::new();
|
let context = Context::new();
|
||||||
|
|
||||||
// Get terminal
|
// Get terminal
|
||||||
let mut terminal = terminal(&context);
|
let mut terminal = terminal(context.clone());
|
||||||
|
|
||||||
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(&context).goto(4,20);
|
cursor::cursor(context.clone()).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);
|
||||||
@ -103,7 +103,7 @@ pub fn print_terminal_size()
|
|||||||
let context = Context::new();
|
let context = Context::new();
|
||||||
|
|
||||||
// Get terminal
|
// Get terminal
|
||||||
let mut terminal = terminal(&context);
|
let mut terminal = terminal(context.clone());
|
||||||
// Get terminal size
|
// Get terminal size
|
||||||
let terminal_size = terminal.terminal_size();
|
let terminal_size = terminal.terminal_size();
|
||||||
// Print results
|
// Print results
|
||||||
@ -115,7 +115,7 @@ pub fn set_terminal_size()
|
|||||||
{
|
{
|
||||||
let context = Context::new();
|
let context = Context::new();
|
||||||
|
|
||||||
let mut terminal = terminal(&context);
|
let mut terminal = terminal(context);
|
||||||
|
|
||||||
terminal.set_size(10,10);
|
terminal.set_size(10,10);
|
||||||
}
|
}
|
||||||
@ -127,7 +127,7 @@ pub fn scroll_down()
|
|||||||
|
|
||||||
print_test_data();
|
print_test_data();
|
||||||
// Get terminal
|
// Get terminal
|
||||||
let mut terminal = terminal(&context);
|
let mut terminal = terminal(context.clone());
|
||||||
// Scroll down 10 lines.
|
// Scroll down 10 lines.
|
||||||
terminal.scroll_down(10);
|
terminal.scroll_down(10);
|
||||||
}
|
}
|
||||||
@ -140,7 +140,7 @@ pub fn scroll_up()
|
|||||||
print_test_data();
|
print_test_data();
|
||||||
|
|
||||||
// Get terminal
|
// Get terminal
|
||||||
let mut terminal = terminal(&context);
|
let mut terminal = terminal(context.clone());
|
||||||
// Scroll up 10 lines.
|
// Scroll up 10 lines.
|
||||||
terminal.scroll_up(10);
|
terminal.scroll_up(10);
|
||||||
}
|
}
|
||||||
@ -151,7 +151,7 @@ pub fn resize_terminal()
|
|||||||
let context = Context::new();
|
let context = Context::new();
|
||||||
|
|
||||||
// Get terminal
|
// Get terminal
|
||||||
let mut terminal = terminal(&context);
|
let mut terminal = terminal(context.clone());
|
||||||
// Get terminal size
|
// Get terminal size
|
||||||
terminal.set_size(10,10);
|
terminal.set_size(10,10);
|
||||||
}
|
}
|
||||||
|
@ -4,72 +4,91 @@
|
|||||||
|
|
||||||
use Context;
|
use Context;
|
||||||
use shared::functions;
|
use shared::functions;
|
||||||
use super::ITerminalCursor;
|
use super::*;
|
||||||
|
|
||||||
/// 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
|
||||||
|
{
|
||||||
|
context: Rc<Context>
|
||||||
|
}
|
||||||
|
|
||||||
impl AnsiCursor {
|
impl AnsiCursor {
|
||||||
pub fn new() -> Box<AnsiCursor> {
|
pub fn new(context: Rc<Context>) -> Box<AnsiCursor> {
|
||||||
Box::from(AnsiCursor {})
|
Box::from(AnsiCursor { context })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ITerminalCursor for AnsiCursor {
|
impl ITerminalCursor for AnsiCursor {
|
||||||
|
|
||||||
fn goto(&self, x: u16, y: u16, context: &Context)
|
fn goto(&self, x: u16, y: u16)
|
||||||
{
|
{
|
||||||
let mut screen = context.screen_manager.lock().unwrap();
|
let mut screen = self.context.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, context: &Context) -> (u16, u16) {
|
fn pos(&self) -> (u16, u16) {
|
||||||
functions::get_cursor_position(&context)
|
functions::get_cursor_position(self.context.clone())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn move_up(&self, count: u16, context: &Context) {
|
fn move_up(&self, count: u16) {
|
||||||
let mut screen = context.screen_manager.lock().unwrap();
|
let mut screen = self.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, context: &Context) {
|
fn move_right(&self, count: u16) {
|
||||||
let mut screen = context.screen_manager.lock().unwrap();
|
let mut screen = self.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, context: &Context) {
|
fn move_down(&self, count: u16) {
|
||||||
let mut screen = context.screen_manager.lock().unwrap();
|
let mut screen = self.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, context: &Context) {
|
fn move_left(&self, count: u16) {
|
||||||
let mut screen = context.screen_manager.lock().unwrap();
|
let mut screen = self.context.screen_manager.lock().unwrap();
|
||||||
{
|
{
|
||||||
screen.write_ansi(format!(csi!("{}D"), count));
|
screen.write_ansi(format!(csi!("{}D"), count));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn save_position(&mut self, context: &Context)
|
fn save_position(&mut self)
|
||||||
{
|
{
|
||||||
let mut screen = context.screen_manager.lock().unwrap();
|
let mut screen = self.context.screen_manager.lock().unwrap();
|
||||||
{
|
{
|
||||||
screen.write_ansi_str(csi!("s"));
|
screen.write_ansi_str(csi!("s"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn reset_position(&self, context: &Context)
|
fn reset_position(&self)
|
||||||
{
|
{
|
||||||
let mut screen = context.screen_manager.lock().unwrap();
|
let mut screen = self.context.screen_manager.lock().unwrap();
|
||||||
{
|
{
|
||||||
screen.write_ansi_str(csi!("u"));
|
screen.write_ansi_str(csi!("u"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn hide(&self)
|
||||||
|
{
|
||||||
|
let mut screen = self.context.screen_manager.lock().unwrap();
|
||||||
|
{
|
||||||
|
screen.write_ansi_str(csi!("?25l"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn show(&self)
|
||||||
|
{
|
||||||
|
let mut screen = self.context.screen_manager.lock().unwrap();
|
||||||
|
{
|
||||||
|
screen.write_ansi_str(csi!("?25h"));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -8,23 +8,23 @@ use Context;
|
|||||||
use super::super::shared::functions;
|
use super::super::shared::functions;
|
||||||
|
|
||||||
use std::fmt::Display;
|
use std::fmt::Display;
|
||||||
use std::io::Write;
|
use std::rc::Rc;
|
||||||
|
|
||||||
/// 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<'context> {
|
pub struct TerminalCursor {
|
||||||
context: &'context Context,
|
context: Rc<Context>,
|
||||||
terminal_cursor: Option<Box<ITerminalCursor>>,
|
terminal_cursor: Option<Box<ITerminalCursor>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl <'context> TerminalCursor<'context>
|
impl TerminalCursor
|
||||||
{
|
{
|
||||||
/// 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(context: &'context Context) -> TerminalCursor<'context> {
|
pub fn new(context: Rc<Context>) -> TerminalCursor {
|
||||||
#[cfg(target_os = "windows")]
|
#[cfg(target_os = "windows")]
|
||||||
let cursor = functions::get_module::<Box<ITerminalCursor>>(WinApiCursor::new(), AnsiCursor::new(), context);
|
let cursor = functions::get_module::<Box<ITerminalCursor>>(WinApiCursor::new(), AnsiCursor::new(context.clone()));
|
||||||
|
|
||||||
#[cfg(not(target_os = "windows"))]
|
#[cfg(not(target_os = "windows"))]
|
||||||
let cursor = Some(AnsiCursor::new() as Box<ITerminalCursor>);
|
let cursor = Some(AnsiCursor::new(context.clone()) as Box<ITerminalCursor>);
|
||||||
|
|
||||||
TerminalCursor { terminal_cursor: cursor , context}
|
TerminalCursor { terminal_cursor: cursor , context}
|
||||||
}
|
}
|
||||||
@ -39,20 +39,20 @@ impl <'context> TerminalCursor<'context>
|
|||||||
/// use self::crossterm::Context;
|
/// use self::crossterm::Context;
|
||||||
/// use self::crossterm::cursor;
|
/// use self::crossterm::cursor;
|
||||||
///
|
///
|
||||||
// pub fn goto()
|
/// pub fn goto()
|
||||||
// {
|
/// {
|
||||||
// let context = Context::new();
|
/// let context = Context::new();
|
||||||
//
|
///
|
||||||
// // Get the cursor
|
/// // Get the cursor
|
||||||
// let mut cursor = cursor(&context);
|
/// 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);
|
||||||
// }
|
/// }
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
pub fn goto(&mut self, x: u16, y: u16) -> &mut TerminalCursor<'context> {
|
pub fn goto(&mut self, x: u16, y: u16) -> &mut TerminalCursor {
|
||||||
if let Some(ref terminal_cursor) = self.terminal_cursor {
|
if let Some(ref terminal_cursor) = self.terminal_cursor {
|
||||||
terminal_cursor.goto(x, y, &self.context);
|
terminal_cursor.goto(x, y);
|
||||||
}
|
}
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
@ -80,7 +80,7 @@ impl <'context> TerminalCursor<'context>
|
|||||||
/// ```
|
/// ```
|
||||||
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.context)
|
terminal_cursor.pos()
|
||||||
} else {
|
} else {
|
||||||
(0, 0)
|
(0, 0)
|
||||||
}
|
}
|
||||||
@ -107,9 +107,9 @@ impl <'context> TerminalCursor<'context>
|
|||||||
/// }
|
/// }
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
pub fn move_up(&mut self, count: u16) -> &mut TerminalCursor<'context> {
|
pub fn move_up(&mut self, count: u16) -> &mut TerminalCursor {
|
||||||
if let Some(ref terminal_cursor) = self.terminal_cursor {
|
if let Some(ref terminal_cursor) = self.terminal_cursor {
|
||||||
terminal_cursor.move_up(count, &self.context);
|
terminal_cursor.move_up(count);
|
||||||
}
|
}
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
@ -123,19 +123,19 @@ impl <'context> TerminalCursor<'context>
|
|||||||
/// use self::crossterm::Context;
|
/// use self::crossterm::Context;
|
||||||
/// use self::crossterm::cursor;
|
/// use self::crossterm::cursor;
|
||||||
///
|
///
|
||||||
// pub fn move_right()
|
/// pub fn move_right()
|
||||||
// {
|
/// {
|
||||||
// let context = Context::new();
|
/// let context = Context::new();
|
||||||
//
|
///
|
||||||
// // Get the cursor
|
/// // Get the cursor
|
||||||
// let mut cursor = cursor(&context);
|
/// let mut cursor = cursor(&context);
|
||||||
// // Move the cursor to position 3 times to the right in the terminal
|
/// // Move the cursor to position 3 times to the right in the terminal
|
||||||
// cursor.move_right(3);
|
/// cursor.move_right(3);
|
||||||
// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
pub fn move_right(&mut self, count: u16) -> &mut TerminalCursor<'context> {
|
pub fn move_right(&mut self, count: u16) -> &mut TerminalCursor {
|
||||||
if let Some(ref terminal_cursor) = self.terminal_cursor {
|
if let Some(ref terminal_cursor) = self.terminal_cursor {
|
||||||
terminal_cursor.move_right(count, &self.context);
|
terminal_cursor.move_right(count);
|
||||||
}
|
}
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
@ -161,9 +161,9 @@ impl <'context> TerminalCursor<'context>
|
|||||||
/// }
|
/// }
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
pub fn move_down(&mut self, count: u16) -> &mut TerminalCursor<'context> {
|
pub fn move_down(&mut self, count: u16) -> &mut TerminalCursor {
|
||||||
if let Some(ref terminal_cursor) = self.terminal_cursor {
|
if let Some(ref terminal_cursor) = self.terminal_cursor {
|
||||||
terminal_cursor.move_down(count, &self.context);
|
terminal_cursor.move_down(count);
|
||||||
}
|
}
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
@ -189,9 +189,9 @@ impl <'context> TerminalCursor<'context>
|
|||||||
/// }
|
/// }
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
pub fn move_left(&mut self, count: u16) -> &mut TerminalCursor<'context> {
|
pub fn move_left(&mut self, count: u16) -> &mut TerminalCursor {
|
||||||
if let Some(ref terminal_cursor) = self.terminal_cursor {
|
if let Some(ref terminal_cursor) = self.terminal_cursor {
|
||||||
terminal_cursor.move_left(count, &self.context);
|
terminal_cursor.move_left(count);
|
||||||
}
|
}
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
@ -232,12 +232,18 @@ impl <'context> TerminalCursor<'context>
|
|||||||
/// .print("@");
|
/// .print("@");
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
pub fn print<D: Display>(&mut self, value: D) -> &mut TerminalCursor<'context> {
|
pub fn print<D: Display>(&mut self, value: D) -> &mut TerminalCursor {
|
||||||
let mut screen = self.context.screen_manager.lock().unwrap();
|
|
||||||
{
|
{
|
||||||
write!(screen.stdout(), "{}", value);
|
let mut mutex = &self.context.screen_manager;
|
||||||
// rust is line buffered so we need to flush the buffer in order to print it at the current cursor position.
|
{
|
||||||
screen.stdout().flush();
|
let mut screen_manager = mutex.lock().unwrap();
|
||||||
|
|
||||||
|
use std::fmt::Write;
|
||||||
|
let mut string = String::new();
|
||||||
|
write!(string, "{}", value).unwrap();
|
||||||
|
|
||||||
|
screen_manager.write_ansi(string);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
@ -261,7 +267,7 @@ impl <'context> TerminalCursor<'context>
|
|||||||
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.context);
|
terminal_cursor.save_position();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -284,7 +290,7 @@ impl <'context> TerminalCursor<'context>
|
|||||||
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.context);
|
terminal_cursor.reset_position();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -311,6 +317,6 @@ impl <'context> TerminalCursor<'context>
|
|||||||
/// cursor::cursor(&context).goto(5,10);
|
/// cursor::cursor(&context).goto(5,10);
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
pub fn cursor<'context>(context: &'context Context) -> Box<TerminalCursor<'context>> {
|
pub fn cursor(context: Rc<Context>) -> Box<TerminalCursor> {
|
||||||
Box::from(TerminalCursor::new(&context))
|
Box::from(TerminalCursor::new(context.clone()))
|
||||||
}
|
}
|
||||||
|
@ -18,9 +18,10 @@ mod ansi_cursor;
|
|||||||
use self::winapi_cursor::WinApiCursor;
|
use self::winapi_cursor::WinApiCursor;
|
||||||
use self::ansi_cursor::AnsiCursor;
|
use self::ansi_cursor::AnsiCursor;
|
||||||
|
|
||||||
use Context;
|
|
||||||
pub use self::cursor::{ cursor, TerminalCursor };
|
pub use self::cursor::{ cursor, TerminalCursor };
|
||||||
|
|
||||||
|
use std::rc::Rc;
|
||||||
|
|
||||||
///! 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.
|
||||||
///! This trait can be implemented so that an concrete implementation of the ITerminalCursor can forfill
|
///! This trait can be implemented so that an concrete implementation of the ITerminalCursor can forfill
|
||||||
///! the wishes to work on an specific platform.
|
///! the wishes to work on an specific platform.
|
||||||
@ -31,19 +32,23 @@ pub use self::cursor::{ cursor, TerminalCursor };
|
|||||||
///! 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 context.
|
/// Goto some location (x,y) in the context.
|
||||||
fn goto(&self, x: u16, y: u16, context: &Context);
|
fn goto(&self, x: u16, y: u16);
|
||||||
/// Get the location (x,y) of the current cusror in the context
|
/// Get the location (x,y) of the current cusror in the context
|
||||||
fn pos(&self, context: &Context) -> (u16, u16);
|
fn pos(&self) -> (u16, u16);
|
||||||
/// Move cursor n times up
|
/// Move cursor n times up
|
||||||
fn move_up(&self, count: u16, context: &Context);
|
fn move_up(&self, count: u16);
|
||||||
/// Move the cursor `n` times to the right.
|
/// Move the cursor `n` times to the right.
|
||||||
fn move_right(&self, count: u16, context: &Context);
|
fn move_right(&self, count: u16);
|
||||||
/// Move the cursor `n` times down.
|
/// Move the cursor `n` times down.
|
||||||
fn move_down(&self, count: u16, context: &Context);
|
fn move_down(&self, count: u16);
|
||||||
/// Move the cursor `n` times left.
|
/// Move the cursor `n` times left.
|
||||||
fn move_left(&self, count: u16, context: &Context);
|
fn move_left(&self, count: u16);
|
||||||
/// Save cursor position so that its saved position can be recalled later. Note that this position is stored program based not per instance of the cursor struct.
|
/// Save cursor position so that its saved position can be recalled later. Note that this position is stored program based not per instance of the cursor struct.
|
||||||
fn save_position(&mut self, context: &Context);
|
fn save_position(&mut self);
|
||||||
/// Return to saved cursor position
|
/// Return to saved cursor position
|
||||||
fn reset_position(&self, context: &Context);
|
fn reset_position(&self);
|
||||||
|
/// Hide the terminal cursor.
|
||||||
|
fn hide(&self);
|
||||||
|
/// Show the terminal cursor
|
||||||
|
fn show(&self);
|
||||||
}
|
}
|
@ -1,8 +1,6 @@
|
|||||||
//! This is an WINAPI specific implementation for cursor related action.
|
//! This is an WINAPI specific implementation for cursor related action.
|
||||||
//! This module is used for windows terminals that do not support ANSI escape codes.
|
//! This module is used for windows terminals that do not support ANSI escape codes.
|
||||||
//! Note that the cursor position is 0 based. This means that we start counting at 0 when setting the cursor position ect.
|
//! Note that the cursor position is 0 based. This means that we start counting at 0 when setting the cursor position ect.
|
||||||
|
|
||||||
use Context;
|
|
||||||
use super::ITerminalCursor;
|
use super::ITerminalCursor;
|
||||||
use kernel::windows_kernel::{kernel, cursor};
|
use kernel::windows_kernel::{kernel, cursor};
|
||||||
|
|
||||||
@ -17,41 +15,51 @@ impl WinApiCursor {
|
|||||||
|
|
||||||
impl ITerminalCursor for WinApiCursor {
|
impl ITerminalCursor for WinApiCursor {
|
||||||
|
|
||||||
fn goto(&self, x: u16, y: u16, context: &Context) {
|
fn goto(&self, x: u16, y: u16) {
|
||||||
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, context: &Context) -> (u16, u16) {
|
fn pos(&self) -> (u16, u16) {
|
||||||
cursor::pos()
|
cursor::pos()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn move_up(&self, count: u16, context: &Context) {
|
fn move_up(&self, count: u16) {
|
||||||
let (xpos,ypos) = self.pos(context);
|
let (xpos,ypos) = self.pos();
|
||||||
self.goto(xpos, ypos - count, context);
|
self.goto(xpos, ypos - count);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn move_right(&self, count: u16, context: &Context) {
|
fn move_right(&self, count: u16) {
|
||||||
let (xpos,ypos) = self.pos(context);
|
let (xpos,ypos) = self.pos();
|
||||||
self.goto(xpos + count, ypos, context);
|
self.goto(xpos + count, ypos);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn move_down(&self, count: u16, context: &Context) {
|
fn move_down(&self, count: u16) {
|
||||||
let (xpos,ypos) = self.pos(context);
|
let (xpos,ypos) = self.pos();
|
||||||
self.goto(xpos, ypos + count,context);
|
self.goto(xpos, ypos + count);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn move_left(&self, count: u16, context: &Context) {
|
fn move_left(&self, count: u16) {
|
||||||
let (xpos,ypos) = self.pos(context);
|
let (xpos,ypos) = self.pos();
|
||||||
self.goto(xpos - count, ypos,context);
|
self.goto(xpos - count, ypos);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn save_position(&mut self, context: &Context)
|
fn save_position(&mut self)
|
||||||
{
|
{
|
||||||
cursor::save_cursor_pos();
|
cursor::save_cursor_pos();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn reset_position(&self, context: &Context)
|
fn reset_position(&self)
|
||||||
{
|
{
|
||||||
cursor::reset_to_saved_position();
|
cursor::reset_to_saved_position();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn hide(&self)
|
||||||
|
{
|
||||||
|
kernel::cursor_visibility(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn show(&self)
|
||||||
|
{
|
||||||
|
kernel::cursor_visibility(true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,24 +1,27 @@
|
|||||||
//! This module handles the enabling `ANSI escape codes` for windows terminals.
|
//! This module handles the enabling `ANSI escape codes` for windows terminals.
|
||||||
|
|
||||||
use {Context, StateManager};
|
use IStateCommand;
|
||||||
use state::commands::ICommand;
|
use std::sync::{Once, ONCE_INIT};
|
||||||
|
|
||||||
static mut HAS_BEEN_TRYED_TO_ENABLE: bool = false;
|
static mut HAS_BEEN_TRYED_TO_ENABLE: bool = false;
|
||||||
static mut IS_ANSI_ON_WINDOWS_ENABLED: Option<bool> = None;
|
static mut IS_ANSI_ON_WINDOWS_ENABLED: Option<bool> = None;
|
||||||
static mut DOES_WINDOWS_SUPPORT_ANSI: Option<bool> = None;
|
static mut DOES_WINDOWS_SUPPORT_ANSI: Option<bool> = None;
|
||||||
|
static START: Once = ONCE_INIT;
|
||||||
/// Try enable `ANSI escape codes` and return the result.
|
/// Try enable `ANSI escape codes` and return the result.
|
||||||
pub fn try_enable_ansi_support(context: &Context) -> bool
|
pub fn try_enable_ansi_support() -> bool
|
||||||
{
|
{
|
||||||
|
START.call_once(|| {
|
||||||
use state::commands::win_commands::EnableAnsiCommand;
|
use state::commands::win_commands::EnableAnsiCommand;
|
||||||
let mut command = EnableAnsiCommand::new();
|
let mut command = EnableAnsiCommand::new();
|
||||||
let success = command.execute(&context);
|
let success = command.execute();
|
||||||
|
|
||||||
set_is_windows_ansi_supportable(success);
|
set_is_windows_ansi_supportable(success);
|
||||||
set_ansi_enabled(success);
|
set_ansi_enabled(success);
|
||||||
has_been_tried_to_enable(true);
|
has_been_tried_to_enable(true);
|
||||||
|
|
||||||
success
|
});
|
||||||
|
|
||||||
|
windows_supportable()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get whether ansi has been enabled.
|
/// Get whether ansi has been enabled.
|
||||||
|
@ -1,18 +1,17 @@
|
|||||||
//! This module is the core of all the `WINAPI` actions. All unsafe `WINAPI` function call are done here.
|
//! This module is the core of all the `WINAPI` actions. All unsafe `WINAPI` function call are done here.
|
||||||
|
|
||||||
use winapi::um::winnt::HANDLE;
|
use winapi::um::winnt::HANDLE;
|
||||||
use winapi::um::winbase::{STD_OUTPUT_HANDLE, STD_INPUT_HANDLE };
|
use winapi::um::winbase::{STD_OUTPUT_HANDLE, STD_INPUT_HANDLE };
|
||||||
use winapi::um::handleapi::INVALID_HANDLE_VALUE;
|
use winapi::um::handleapi::INVALID_HANDLE_VALUE;
|
||||||
use winapi::um::processenv::{GetStdHandle};
|
use winapi::um::processenv::{GetStdHandle};
|
||||||
use winapi::um::consoleapi::{SetConsoleMode,GetConsoleMode, };
|
use winapi::um::consoleapi::{SetConsoleMode,GetConsoleMode, };
|
||||||
use winapi::shared::minwindef::{TRUE};
|
use winapi::shared::minwindef::{TRUE, FALSE};
|
||||||
use winapi::um::wincon;
|
use winapi::um::wincon;
|
||||||
use winapi::um::wincon::
|
use winapi::um::wincon::
|
||||||
{
|
{
|
||||||
SetConsoleWindowInfo, SetConsoleCursorPosition, SetConsoleTextAttribute, SetConsoleScreenBufferSize, CreateConsoleScreenBuffer,SetConsoleActiveScreenBuffer,
|
SetConsoleWindowInfo, SetConsoleCursorPosition, SetConsoleTextAttribute, SetConsoleScreenBufferSize, CreateConsoleScreenBuffer,SetConsoleActiveScreenBuffer, SetConsoleCursorInfo,
|
||||||
GetLargestConsoleWindowSize, GetConsoleScreenBufferInfo,
|
GetLargestConsoleWindowSize, GetConsoleScreenBufferInfo,
|
||||||
FillConsoleOutputCharacterA, FillConsoleOutputAttribute,
|
FillConsoleOutputCharacterA, FillConsoleOutputAttribute,WriteConsoleOutputCharacterA,WriteConsoleOutputAttribute,
|
||||||
CONSOLE_SCREEN_BUFFER_INFO, SMALL_RECT, COORD, CHAR_INFO, PSMALL_RECT
|
CONSOLE_SCREEN_BUFFER_INFO, SMALL_RECT, COORD, CHAR_INFO, PSMALL_RECT, CONSOLE_CURSOR_INFO
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::{Empty};
|
use super::{Empty};
|
||||||
@ -132,6 +131,22 @@ pub fn set_console_cursor_position(x: i16, y: i16)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn cursor_visibility(visable: bool)
|
||||||
|
{
|
||||||
|
let handle = get_output_handle();
|
||||||
|
|
||||||
|
let cursor_info = CONSOLE_CURSOR_INFO
|
||||||
|
{
|
||||||
|
dwSize: 100,
|
||||||
|
bVisible: if visable { FALSE } else {TRUE}
|
||||||
|
};
|
||||||
|
|
||||||
|
unsafe
|
||||||
|
{
|
||||||
|
SetConsoleCursorInfo(handle, &cursor_info);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn set_console_text_attribute(value: u16)
|
pub fn set_console_text_attribute(value: u16)
|
||||||
{
|
{
|
||||||
let output_handle = get_output_handle();
|
let output_handle = get_output_handle();
|
||||||
@ -282,6 +297,32 @@ pub fn write_console_output(write_buffer: &HANDLE, copy_buffer: &mut [CHAR_INFO;
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn write_char_buffer(handle: HANDLE, buf: &[u8])
|
||||||
|
{
|
||||||
|
use std::ffi::CString;
|
||||||
|
use std::str;
|
||||||
|
|
||||||
|
// get buffer info
|
||||||
|
let csbi = get_console_screen_buffer_info();
|
||||||
|
|
||||||
|
// get string from u8[] and parse it to an c_str
|
||||||
|
let mut data = str::from_utf8(buf).unwrap();
|
||||||
|
let c_str = CString::new(data);
|
||||||
|
let ptr: *const u16 = c_str.unwrap().as_ptr() as *const u16;
|
||||||
|
|
||||||
|
// get current position
|
||||||
|
let current_pos = COORD {X: csbi.dwCursorPosition.X, Y: csbi.dwCursorPosition.Y};
|
||||||
|
|
||||||
|
let mut cells_written: u32 = 0;
|
||||||
|
|
||||||
|
// write to console
|
||||||
|
unsafe
|
||||||
|
{
|
||||||
|
|
||||||
|
WriteConsoleOutputAttribute(handle, ptr, data.len() as u32, current_pos, &mut cells_written);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Parse integer to an bool
|
/// Parse integer to an bool
|
||||||
fn is_true(value: i32) -> bool
|
fn is_true(value: i32) -> bool
|
||||||
{
|
{
|
||||||
|
@ -16,6 +16,7 @@ pub mod manager;
|
|||||||
pub use shared::{screen, raw};
|
pub use shared::{screen, raw};
|
||||||
pub use state::context::Context;
|
pub use state::context::Context;
|
||||||
|
|
||||||
|
use state::commands::IStateCommand;
|
||||||
use state::command_manager::CommandManager;
|
use state::command_manager::CommandManager;
|
||||||
use state::state_manager::StateManager;
|
use state::state_manager::StateManager;
|
||||||
use manager::ScreenManager;
|
use manager::ScreenManager;
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
//! This module uses the stdout to write to the console.
|
//! This module uses the stdout to write to the console.
|
||||||
|
|
||||||
use std::io::{self, Write};
|
use std::io::{self, Write};
|
||||||
|
use std::any::Any;
|
||||||
|
|
||||||
use super::IScreenManager;
|
use super::IScreenManager;
|
||||||
|
|
||||||
@ -14,12 +15,11 @@ pub struct AnsiScreenManager
|
|||||||
|
|
||||||
impl IScreenManager for AnsiScreenManager
|
impl IScreenManager for AnsiScreenManager
|
||||||
{
|
{
|
||||||
type Output = Box<Write>;
|
|
||||||
|
|
||||||
fn stdout(&mut self) -> &mut Self::Output
|
// fn stdout(&mut self) -> &mut Self::Output
|
||||||
{
|
// {
|
||||||
return &mut self.output
|
// return &mut self.output
|
||||||
}
|
// }
|
||||||
|
|
||||||
fn toggle_is_alternate_screen(&mut self, is_alternate_screen: bool)
|
fn toggle_is_alternate_screen(&mut self, is_alternate_screen: bool)
|
||||||
{
|
{
|
||||||
@ -37,6 +37,19 @@ impl IScreenManager for AnsiScreenManager
|
|||||||
write!(self.output, "{}", string);
|
write!(self.output, "{}", string);
|
||||||
self.flush();
|
self.flush();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
|
||||||
|
self.output.write(buf)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn flush(&mut self) -> io::Result<()> {
|
||||||
|
self.output.flush()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn as_any(&mut self) -> &mut Any
|
||||||
|
{
|
||||||
|
self
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AnsiScreenManager {
|
impl AnsiScreenManager {
|
||||||
@ -47,14 +60,3 @@ impl AnsiScreenManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Write for AnsiScreenManager
|
|
||||||
{
|
|
||||||
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
|
|
||||||
self.output.write(buf)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn flush(&mut self) -> io::Result<()> {
|
|
||||||
self.stdout().flush()
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,39 +1,38 @@
|
|||||||
//! 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.
|
//! 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.
|
//! 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::{AnsiScreenManager, WinApiScreenManager, IScreenManager };
|
||||||
|
use super::super::shared::functions;
|
||||||
|
use std::any::Any;
|
||||||
|
|
||||||
use super::IScreenManager;
|
use std::fmt::Display;
|
||||||
use super::ansi_manager::AnsiScreenManager;
|
use std::io::{ self, Write };
|
||||||
|
|
||||||
use std::io::Write;
|
#[cfg(target_os = "windows")]
|
||||||
|
use winapi::um::winnt::HANDLE;
|
||||||
|
|
||||||
/// Struct that stores an specific platform implementation for screen related actions.
|
/// Struct that stores an specific platform implementation for screen related actions.
|
||||||
pub struct ScreenManager
|
pub struct ScreenManager
|
||||||
{
|
{
|
||||||
screen_manager: Box<IScreenManager<Output=Box<Write>>>
|
screen_manager: Box<IScreenManager>
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ScreenManager
|
impl ScreenManager
|
||||||
{
|
{
|
||||||
/// Create new screen manager instance whereon screen related actions can be performed.
|
/// 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 screen_manager = functions::get_module::<Box<IScreenManager>>(Box::from(WinApiScreenManager::new()), Box::from(AnsiScreenManager::new())).unwrap();
|
||||||
//
|
//
|
||||||
// #[cfg(not(target_os = "windows"))]
|
// #[cfg(not(target_os = "windows"))]
|
||||||
|
// let screen_manager = Box::new(AnsiScreenManager::new());
|
||||||
|
|
||||||
ScreenManager
|
ScreenManager
|
||||||
{
|
{
|
||||||
screen_manager: Box::new(AnsiScreenManager::new()),
|
screen_manager: Box::from(WinApiScreenManager::new()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the stdout of the current screen
|
pub fn toggle_is_alternate_screen(&mut self, is_alternate_screen: bool)
|
||||||
pub fn stdout(&mut self) -> &mut Box<Write>
|
|
||||||
{
|
|
||||||
self.screen_manager.stdout()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn toggle_is_alternate_screen(&mut self,is_alternate_screen: bool)
|
|
||||||
{
|
{
|
||||||
self.screen_manager.toggle_is_alternate_screen(is_alternate_screen);
|
self.screen_manager.toggle_is_alternate_screen(is_alternate_screen);
|
||||||
}
|
}
|
||||||
@ -49,4 +48,17 @@ impl ScreenManager
|
|||||||
{
|
{
|
||||||
self.screen_manager.write_ansi_str(string);
|
self.screen_manager.write_ansi_str(string);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn as_any(&mut self) -> &mut Any { self.screen_manager.as_any() }
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Write for ScreenManager
|
||||||
|
{
|
||||||
|
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
|
||||||
|
self.screen_manager.write(buf)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn flush(&mut self) -> io::Result<()> {
|
||||||
|
self.screen_manager.flush()
|
||||||
|
}
|
||||||
}
|
}
|
@ -8,20 +8,26 @@ mod win_manager;
|
|||||||
mod ansi_manager;
|
mod ansi_manager;
|
||||||
|
|
||||||
#[cfg(target_os = "windows")]
|
#[cfg(target_os = "windows")]
|
||||||
use self::win_manager::WinApiScreenManager;
|
pub use self::win_manager::WinApiScreenManager;
|
||||||
use self::ansi_manager::AnsiScreenManager;
|
pub use self::ansi_manager::AnsiScreenManager;
|
||||||
|
|
||||||
pub use self::manager::{ ScreenManager };
|
pub use self::manager::{ ScreenManager };
|
||||||
|
use std::io;
|
||||||
|
use std::any::Any;
|
||||||
|
|
||||||
pub trait IScreenManager
|
pub trait IScreenManager
|
||||||
{
|
{
|
||||||
type Output;
|
|
||||||
|
|
||||||
/// get the stdout of the screen. This can be used to write to the
|
/// get the stdout of the screen. This can be used to write to the
|
||||||
fn stdout(&mut self) -> &mut Self::Output;
|
// fn stdout(&mut self) -> &mut Self::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.
|
/// 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.
|
/// Write a &str to the current stdout.
|
||||||
fn write_ansi_str(&mut self, string: &str);
|
fn write_ansi_str(&mut self, string: &str);
|
||||||
|
|
||||||
|
fn write(&mut self, buf: &[u8]) -> io::Result<usize>;
|
||||||
|
|
||||||
|
fn flush(&mut self) -> io::Result<()>;
|
||||||
|
|
||||||
|
fn as_any(&mut self) -> &mut Any;
|
||||||
}
|
}
|
@ -2,21 +2,18 @@ use super::IScreenManager;
|
|||||||
use kernel::windows_kernel::kernel;
|
use kernel::windows_kernel::kernel;
|
||||||
use winapi::um::winnt::HANDLE;
|
use winapi::um::winnt::HANDLE;
|
||||||
|
|
||||||
|
use std::io::{self,Write};
|
||||||
|
use std::any::Any;
|
||||||
|
|
||||||
pub struct WinApiScreenManager
|
pub struct WinApiScreenManager
|
||||||
{
|
{
|
||||||
pub is_alternate_screen: bool,
|
pub is_alternate_screen: bool,
|
||||||
output: Box<HANDLE>,
|
output: HANDLE,
|
||||||
|
alternate_handle: HANDLE
|
||||||
}
|
}
|
||||||
|
|
||||||
impl IScreenManager for WinApiScreenManager where
|
impl IScreenManager for WinApiScreenManager
|
||||||
{
|
{
|
||||||
type Output = HANDLE;
|
|
||||||
|
|
||||||
fn stdout(&mut self) -> &mut Self::Output
|
|
||||||
{
|
|
||||||
return &mut self.output
|
|
||||||
}
|
|
||||||
|
|
||||||
fn toggle_is_alternate_screen(&mut self, is_alternate_screen: bool)
|
fn toggle_is_alternate_screen(&mut self, is_alternate_screen: bool)
|
||||||
{
|
{
|
||||||
self.is_alternate_screen = is_alternate_screen;
|
self.is_alternate_screen = is_alternate_screen;
|
||||||
@ -33,24 +30,39 @@ impl IScreenManager for WinApiScreenManager where
|
|||||||
// write!(self.output, "{}", string);
|
// write!(self.output, "{}", string);
|
||||||
// self.flush();
|
// self.flush();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
|
||||||
|
if self.is_alternate_screen
|
||||||
|
{
|
||||||
|
kernel::write_char_buffer(self.alternate_handle, buf);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
kernel::write_char_buffer(self.output, buf);
|
||||||
|
}
|
||||||
|
Ok(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn flush(&mut self) -> io::Result<()> {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn as_any(&mut self) -> &mut Any
|
||||||
|
{
|
||||||
|
self
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl WinApiScreenManager {
|
impl WinApiScreenManager {
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
WinApiScreenManager {
|
WinApiScreenManager {
|
||||||
output: (Box::from(kernel::get_output_handle())),
|
output: kernel::get_output_handle(),
|
||||||
is_alternate_screen: false
|
is_alternate_screen: false,
|
||||||
|
alternate_handle: kernel::get_output_handle(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn set_alternate_handle(&mut self, alternate_handle: HANDLE)
|
||||||
|
{
|
||||||
|
self.alternate_handle = alternate_handle;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//impl<Output:Write> Write for AnsiScreenManager<Output>
|
|
||||||
//{
|
|
||||||
// fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
|
|
||||||
// self.output.write(buf)
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// fn flush(&mut self) -> io::Result<()> {
|
|
||||||
// self.stdout().flush()
|
|
||||||
// }
|
|
||||||
//}
|
|
@ -1,6 +1,7 @@
|
|||||||
//! 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 Context;
|
use Context;
|
||||||
|
use std::rc::Rc;
|
||||||
|
|
||||||
#[cfg(windows)]
|
#[cfg(windows)]
|
||||||
use kernel::windows_kernel::terminal::terminal_size;
|
use kernel::windows_kernel::terminal::terminal_size;
|
||||||
@ -20,7 +21,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: &Context) -> (u16, u16)
|
pub fn get_cursor_position(screen: Rc<Context>) -> (u16, u16)
|
||||||
{
|
{
|
||||||
#[cfg(unix)]
|
#[cfg(unix)]
|
||||||
return pos(&screen);
|
return pos(&screen);
|
||||||
@ -31,7 +32,7 @@ pub fn get_cursor_position(screen: &Context) -> (u16, u16)
|
|||||||
|
|
||||||
#[cfg(windows)]
|
#[cfg(windows)]
|
||||||
/// Get an module specific implementation based on the current platform.
|
/// Get an module specific implementation based on the current platform.
|
||||||
pub fn get_module<T>(winapi_impl: T, unix_impl: T, context: &Context) -> Option<T>
|
pub fn get_module<T>(winapi_impl: T, unix_impl: T) -> Option<T>
|
||||||
{
|
{
|
||||||
let mut term: Option<T> = None;
|
let mut term: Option<T> = None;
|
||||||
let mut does_support = true;
|
let mut does_support = true;
|
||||||
@ -41,7 +42,7 @@ pub fn get_module<T>(winapi_impl: T, unix_impl: T, context: &Context) -> Option<
|
|||||||
use kernel::windows_kernel::ansi_support::try_enable_ansi_support;
|
use kernel::windows_kernel::ansi_support::try_enable_ansi_support;
|
||||||
|
|
||||||
// Try to enable ansi on windows if not than use WINAPI.
|
// Try to enable ansi on windows if not than use WINAPI.
|
||||||
does_support = try_enable_ansi_support(&context);
|
does_support = try_enable_ansi_support();
|
||||||
|
|
||||||
if !does_support
|
if !does_support
|
||||||
{
|
{
|
||||||
|
@ -31,56 +31,56 @@ use std::io::{ self, Write};
|
|||||||
use std::rc::Rc;
|
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
|
||||||
{
|
{
|
||||||
terminal : &'a Context,
|
context : Rc<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: Write + Sized
|
||||||
{
|
{
|
||||||
fn into_raw_mode(&self, terminal: &'a Context) -> io::Result<RawTerminal<'a>>;
|
fn into_raw_mode(&self, context:Rc<Context>) -> io::Result<RawTerminal>;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl <'a, W: Write> IntoRawMode<'a> for W
|
impl <W: Write> IntoRawMode for W
|
||||||
{
|
{
|
||||||
/// Raw mode means that input (stdin) won't be printed it will instead have to be written manually by
|
/// 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
|
/// the program. The input isn't canonicalised or line buffered (that is, you can
|
||||||
/// read from input(stdin) one byte of a time).
|
/// read from input(stdin) one byte of a time).
|
||||||
fn into_raw_mode(&self, terminal: &'a Context) -> io::Result<RawTerminal<'a>> {
|
fn into_raw_mode(&self, context: Rc<Context>) -> io::Result<RawTerminal> {
|
||||||
let command_id = EnableRawModeCommand::new(&terminal.state_manager);
|
let command_id = EnableRawModeCommand::new(&context.state_manager);
|
||||||
|
|
||||||
let success = CommandManager::execute(terminal, command_id);
|
let success = CommandManager::execute(context.clone(), command_id);
|
||||||
|
|
||||||
if success
|
if success
|
||||||
{
|
{
|
||||||
Ok(RawTerminal { terminal: &terminal, command_id: command_id})
|
Ok(RawTerminal { context: context.clone(), command_id: command_id})
|
||||||
}else { panic!("cannot move into raw mode") }
|
}else { panic!("cannot move into raw mode") }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Write for RawTerminal<'a> {
|
impl Write for RawTerminal {
|
||||||
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
|
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
|
||||||
let mut screen = self.terminal.screen_manager.lock().unwrap();
|
let mut screen = self.context.screen_manager.lock().unwrap();
|
||||||
{
|
{
|
||||||
screen.stdout().write(buf)
|
screen.write(buf)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn flush(&mut self) -> io::Result<()> {
|
fn flush(&mut self) -> io::Result<()> {
|
||||||
let mut screen = self.terminal.screen_manager.lock().unwrap();
|
let mut screen = self.context.screen_manager.lock().unwrap();
|
||||||
{
|
{
|
||||||
screen.stdout().flush()
|
screen.flush()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// If an instance of `RawTerminal` will be dropped all terminal changes that are made will be undone.
|
/// If an instance of `RawTerminal` will be dropped all terminal changes that are made will be undone.
|
||||||
impl <'a> Drop for RawTerminal<'a>
|
impl Drop for RawTerminal
|
||||||
{
|
{
|
||||||
fn drop(&mut self)
|
fn drop(&mut self)
|
||||||
{
|
{
|
||||||
let success = CommandManager::undo(&self.terminal, self.command_id);
|
let success = CommandManager::undo(self.context.clone(), self.command_id);
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -2,67 +2,97 @@
|
|||||||
|
|
||||||
use Context;
|
use Context;
|
||||||
use state::commands::*;
|
use state::commands::*;
|
||||||
use super::functions;
|
|
||||||
use std::io::{self, Write};
|
|
||||||
|
|
||||||
pub struct AlternateScreen<'context> {
|
use std::io::{self, Write};
|
||||||
context: &'context Context
|
use std::rc::Rc;
|
||||||
|
|
||||||
|
pub struct AlternateScreen {
|
||||||
|
context: Rc<Context>,
|
||||||
|
command_id: u16
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'context> AlternateScreen<'context> {
|
impl AlternateScreen {
|
||||||
/// Get the alternate screen from the context.
|
/// Get the alternate screen from the context.
|
||||||
/// By calling this method the current screen will be changed to the alternate screen.
|
/// By calling this method the current screen will be changed to the alternate screen.
|
||||||
/// And you get back an handle for that screen.
|
/// And you get back an handle for that screen.
|
||||||
pub fn from(context: &'context Context) -> Self {
|
pub fn from(context: Rc<Context>) -> Self {
|
||||||
get_to_alternate_screen_command(context).execute(&context);
|
let command_id = get_to_alternate_screen_command(context.clone());
|
||||||
AlternateScreen { context: context }
|
|
||||||
|
let screen = AlternateScreen { context: context, command_id: command_id };
|
||||||
|
screen.to_alternate();
|
||||||
|
return screen;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Change the current screen to the mainscreen.
|
/// Change the current screen to the mainscreen.
|
||||||
pub fn to_main(&self)
|
pub fn to_main(&self)
|
||||||
{
|
{
|
||||||
get_to_alternate_screen_command(&self.context).undo(&self.context);
|
let mut mutex = &self.context.state_manager;
|
||||||
|
{
|
||||||
|
let mut state_manager = mutex.lock().unwrap();
|
||||||
|
|
||||||
|
let mut mx = &state_manager.get(self.command_id);
|
||||||
|
{
|
||||||
|
let mut command = mx.lock().unwrap();
|
||||||
|
command.undo();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Change the current screen to alternate screen.
|
/// Change the current screen to alternate screen.
|
||||||
pub fn to_alternate(&self)
|
pub fn to_alternate(&self)
|
||||||
{
|
{
|
||||||
get_to_alternate_screen_command(&self.context).execute(&self.context);
|
let mut mutex = &self.context.state_manager;
|
||||||
|
{
|
||||||
|
let mut state_manager = mutex.lock().unwrap();
|
||||||
|
|
||||||
|
let mut mx = &state_manager.get(self.command_id);
|
||||||
|
{
|
||||||
|
let mut command = mx.lock().unwrap();
|
||||||
|
command.execute();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'context> Write for AlternateScreen<'context> {
|
impl Write for AlternateScreen {
|
||||||
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
|
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
|
||||||
let mut screen = self.context.screen_manager.lock().unwrap();
|
let mut screen = self.context.screen_manager.lock().unwrap();
|
||||||
{
|
{
|
||||||
screen.stdout().write(buf)
|
screen.write(buf)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn flush(&mut self) -> io::Result<()> {
|
fn flush(&mut self) -> io::Result<()> {
|
||||||
let mut screen = self.context.screen_manager.lock().unwrap();
|
let mut screen = self.context.screen_manager.lock().unwrap();
|
||||||
{
|
{
|
||||||
screen.stdout().flush()
|
screen.flush()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'context> Drop for AlternateScreen<'context>
|
impl Drop for AlternateScreen
|
||||||
{
|
{
|
||||||
fn drop(&mut self)
|
fn drop(&mut self)
|
||||||
{
|
{
|
||||||
get_to_alternate_screen_command(&self.context).undo(&self.context);
|
let mut mutex = &self.context.state_manager;
|
||||||
|
{
|
||||||
|
let mut state_manager = mutex.lock().unwrap();
|
||||||
|
|
||||||
|
let mut mx = &state_manager.get(self.command_id);
|
||||||
|
{
|
||||||
|
let mut command = mx.lock().unwrap();
|
||||||
|
command.undo();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get the alternate screen command to enable and disable alternate screen based on the current platform
|
// Get the alternate screen command to enable and disable alternate screen based on the current platform
|
||||||
fn get_to_alternate_screen_command(context: &Context) -> Box<ICommand>
|
fn get_to_alternate_screen_command(context: Rc<Context>) -> u16
|
||||||
{
|
{
|
||||||
#[cfg(target_os = "windows")]
|
// #[cfg(target_os = "windows")]
|
||||||
let command = functions::get_module::<Box<ICommand>>(win_commands::ToAlternateScreenBufferCommand::new(), shared_commands::ToAlternateScreenBufferCommand::new(), context).unwrap();
|
// let command = functions::get_module::<Box<ICommand>>(win_commands::ToAlternateScreenBufferCommand::new(), shared_commands::ToAlternateScreenBufferCommand::new(), context).unwrap();
|
||||||
|
|
||||||
#[cfg(not(target_os = "windows"))]
|
// #[cfg(not(target_os = "windows"))]
|
||||||
let command = shared_commands::ToAlternateScreenBufferCommand::new();
|
win_commands::ToAlternateScreenBufferCommand::new(context)
|
||||||
|
|
||||||
command
|
|
||||||
}
|
}
|
@ -9,32 +9,32 @@ pub struct CommandManager;
|
|||||||
impl CommandManager
|
impl CommandManager
|
||||||
{
|
{
|
||||||
/// execute an certain command by id.
|
/// execute an certain command by id.
|
||||||
pub fn execute(terminal: &Context, command_id: u16) -> bool
|
pub fn execute(context: Rc<Context>, command_id: u16) -> bool
|
||||||
{
|
{
|
||||||
let mut mutex: Rc<Mutex<Box<IStateCommand>>>;
|
let mut mutex: Rc<Mutex<Box<IStateCommand>>>;
|
||||||
|
|
||||||
let mut state = terminal.state_manager.lock().unwrap();
|
let mut state = context.state_manager.lock().unwrap();
|
||||||
{
|
{
|
||||||
mutex = state.get(command_id);
|
mutex = state.get(command_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut command = mutex.lock().unwrap();
|
let mut command = mutex.lock().unwrap();
|
||||||
let has_succeeded = command.execute(&terminal);
|
let has_succeeded = command.execute();
|
||||||
return has_succeeded;
|
return has_succeeded;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// undo an certain command by id.
|
/// undo an certain command by id.
|
||||||
pub fn undo(terminal: &Context, command_id: u16) -> bool
|
pub fn undo(context: Rc<Context>, command_id: u16) -> bool
|
||||||
{
|
{
|
||||||
let mut mutex: Rc<Mutex<Box<IStateCommand>>>;
|
let mut mutex: Rc<Mutex<Box<IStateCommand>>>;
|
||||||
|
|
||||||
let mut state = terminal.state_manager.lock().unwrap();
|
let mut state = context.state_manager.lock().unwrap();
|
||||||
{
|
{
|
||||||
mutex = state.get(command_id);
|
mutex = state.get(command_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut command = mutex.lock().unwrap();
|
let mut command = mutex.lock().unwrap();
|
||||||
let has_succeeded = command.undo(&terminal);
|
let has_succeeded = command.undo();
|
||||||
return has_succeeded;
|
return has_succeeded;
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -25,21 +25,11 @@ pub use self::unix_command::*;
|
|||||||
#[cfg(windows)]
|
#[cfg(windows)]
|
||||||
pub use self::win_commands::*;
|
pub use self::win_commands::*;
|
||||||
|
|
||||||
use {StateManager, Context};
|
|
||||||
|
|
||||||
/// This command can be used for simple commands witch just have an `undo()` and an `execute()`
|
|
||||||
pub trait ICommand
|
|
||||||
{
|
|
||||||
fn new() -> Box<Self> where Self: Sized;
|
|
||||||
fn execute(&mut self, terminal: &Context) -> 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 IStateCommand
|
pub trait IStateCommand
|
||||||
{
|
{
|
||||||
fn execute(&mut self, terminal: &Context) -> bool;
|
fn execute(&mut self) -> bool;
|
||||||
fn undo(&mut self, terminal: &Context) -> bool;
|
fn undo(&mut self) -> bool;
|
||||||
}
|
}
|
@ -1,35 +1,40 @@
|
|||||||
//! This module contains the commands that can be used for both unix and windows systems. Or else said terminals that support ansi codes.
|
//! This module contains the commands that can be used for both unix and windows systems. Or else said terminals that support ansi codes.
|
||||||
use Context;
|
use Context;
|
||||||
use super::{ICommand, IStateCommand};
|
use super::{IStateCommand};
|
||||||
|
|
||||||
pub struct EmptyCommand;
|
pub struct EmptyCommand;
|
||||||
|
|
||||||
impl IStateCommand for EmptyCommand
|
impl IStateCommand for EmptyCommand
|
||||||
{
|
{
|
||||||
fn execute(&mut self, terminal: &Context) -> bool
|
fn execute(&mut self) -> bool
|
||||||
{
|
{
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
fn undo(&mut self, terminal: &Context) -> bool
|
fn undo(&mut self) -> bool
|
||||||
{
|
{
|
||||||
return false;
|
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)]
|
pub struct ToAlternateScreenBufferCommand<'a>
|
||||||
pub struct ToAlternateScreenBufferCommand;
|
|
||||||
|
|
||||||
impl ICommand for ToAlternateScreenBufferCommand
|
|
||||||
{
|
{
|
||||||
fn new() -> Box<ToAlternateScreenBufferCommand> {
|
context: &'a Context
|
||||||
Box::from(ToAlternateScreenBufferCommand {})
|
}
|
||||||
}
|
|
||||||
|
|
||||||
fn execute(&mut self, terminal: &Context) -> bool
|
impl<'a> ToAlternateScreenBufferCommand<'a>
|
||||||
|
{
|
||||||
|
pub fn new(context: & 'a Context) -> Box < ToAlternateScreenBufferCommand > {
|
||||||
|
Box::from(ToAlternateScreenBufferCommand {context: context})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'context> IStateCommand for ToAlternateScreenBufferCommand<'context>
|
||||||
|
{
|
||||||
|
fn execute(&mut self) -> bool
|
||||||
{
|
{
|
||||||
let mut screen = terminal.screen_manager.lock().unwrap();
|
let mut screen = self.context.screen_manager.lock().unwrap();
|
||||||
{
|
{
|
||||||
screen.write_ansi_str(csi!("?1049h"));
|
screen.write_ansi_str(csi!("?1049h"));
|
||||||
screen.toggle_is_alternate_screen(true);
|
screen.toggle_is_alternate_screen(true);
|
||||||
@ -37,9 +42,9 @@ impl ICommand for ToAlternateScreenBufferCommand
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn undo(&mut self, terminal: &Context) -> bool
|
fn undo(&mut self) -> bool
|
||||||
{
|
{
|
||||||
let mut screen = terminal.screen_manager.lock().unwrap();
|
let mut screen = self.context.screen_manager.lock().unwrap();
|
||||||
{
|
{
|
||||||
screen.write_ansi_str(csi!("?1049l"));
|
screen.write_ansi_str(csi!("?1049l"));
|
||||||
screen.toggle_is_alternate_screen(false);
|
screen.toggle_is_alternate_screen(false);
|
||||||
|
@ -34,7 +34,7 @@ impl NoncanonicalModeCommand
|
|||||||
|
|
||||||
impl IStateCommand for NoncanonicalModeCommand
|
impl IStateCommand for NoncanonicalModeCommand
|
||||||
{
|
{
|
||||||
fn execute(&mut self, terminal: &Context) -> bool
|
fn execute(&mut self) -> 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)
|
||||||
@ -53,7 +53,7 @@ impl IStateCommand for NoncanonicalModeCommand
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn undo(&mut self, terminal: &Context) -> bool
|
fn undo(&mut self) -> 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)
|
||||||
@ -97,7 +97,7 @@ impl EnableRawModeCommand
|
|||||||
|
|
||||||
impl IStateCommand for EnableRawModeCommand
|
impl IStateCommand for EnableRawModeCommand
|
||||||
{
|
{
|
||||||
fn execute(&mut self, terminal: &Context) -> bool
|
fn execute(&mut self) -> bool
|
||||||
{
|
{
|
||||||
let original_mode = terminal::get_terminal_mode();
|
let original_mode = terminal::get_terminal_mode();
|
||||||
|
|
||||||
@ -114,7 +114,7 @@ impl IStateCommand for EnableRawModeCommand
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn undo(&mut self, terminal: &Context) -> bool
|
fn undo(&mut self) -> bool
|
||||||
{
|
{
|
||||||
if let Some(ref original_mode) = self.original_mode
|
if let Some(ref original_mode) = self.original_mode
|
||||||
{
|
{
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
//! 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, IStateCommand};
|
use super::IStateCommand;
|
||||||
use { StateManager, Context };
|
use { StateManager, Context };
|
||||||
|
|
||||||
use kernel::windows_kernel::{kernel, ansi_support};
|
use kernel::windows_kernel::{kernel, ansi_support};
|
||||||
@ -20,14 +20,18 @@ pub struct EnableAnsiCommand
|
|||||||
mask: DWORD,
|
mask: DWORD,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ICommand for EnableAnsiCommand
|
impl EnableAnsiCommand
|
||||||
{
|
{
|
||||||
fn new() -> Box<EnableAnsiCommand> {
|
pub fn new() -> Box<EnableAnsiCommand> {
|
||||||
let command = EnableAnsiCommand { mask: ENABLE_VIRTUAL_TERMINAL_PROCESSING };
|
let command = EnableAnsiCommand { mask: ENABLE_VIRTUAL_TERMINAL_PROCESSING };
|
||||||
Box::from(command)
|
Box::from(command)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn execute(&mut self, context: &Context) -> bool
|
|
||||||
|
impl IStateCommand for EnableAnsiCommand
|
||||||
|
{
|
||||||
|
fn execute(&mut self,) -> bool
|
||||||
{
|
{
|
||||||
// we need to check whether we tried to enable ansi before. If we have we can just return if that had succeeded.
|
// we need to check whether we tried to enable ansi before. If we have we can just return if that had succeeded.
|
||||||
if ansi_support::has_been_tried_to_enable_ansi() && ansi_support::ansi_enabled()
|
if ansi_support::has_been_tried_to_enable_ansi() && ansi_support::ansi_enabled()
|
||||||
@ -39,14 +43,12 @@ impl ICommand for EnableAnsiCommand
|
|||||||
let mut dw_mode: DWORD = 0;
|
let mut dw_mode: DWORD = 0;
|
||||||
if !kernel::get_console_mode(&output_handle, &mut dw_mode)
|
if !kernel::get_console_mode(&output_handle, &mut dw_mode)
|
||||||
{
|
{
|
||||||
panic!("Cannot get console mode");
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
dw_mode |= self.mask;
|
dw_mode |= self.mask;
|
||||||
if !kernel::set_console_mode(&output_handle, dw_mode)
|
if !kernel::set_console_mode(&output_handle, dw_mode)
|
||||||
{
|
{
|
||||||
panic!("Cannot get console mode");
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -54,7 +56,7 @@ impl ICommand for EnableAnsiCommand
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn undo(&mut self, context: &Context) -> bool
|
fn undo(&mut self) -> bool
|
||||||
{
|
{
|
||||||
if ansi_support::ansi_enabled()
|
if ansi_support::ansi_enabled()
|
||||||
{
|
{
|
||||||
@ -90,8 +92,7 @@ pub struct EnableRawModeCommand
|
|||||||
impl EnableRawModeCommand
|
impl EnableRawModeCommand
|
||||||
{
|
{
|
||||||
pub fn new(state_manager: &Mutex<StateManager>) -> u16 {
|
pub fn new(state_manager: &Mutex<StateManager>) -> u16 {
|
||||||
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_ECHO_INPUT};
|
||||||
|
|
||||||
|
|
||||||
let mut state = state_manager.lock().unwrap();
|
let mut state = state_manager.lock().unwrap();
|
||||||
{
|
{
|
||||||
@ -105,10 +106,8 @@ impl EnableRawModeCommand
|
|||||||
|
|
||||||
impl IStateCommand for EnableRawModeCommand
|
impl IStateCommand for EnableRawModeCommand
|
||||||
{
|
{
|
||||||
fn execute(&mut self, context: &Context) -> bool
|
fn execute(&mut self) -> bool
|
||||||
{
|
{
|
||||||
use self::wincon::{ENABLE_LINE_INPUT,ENABLE_PROCESSED_INPUT, ENABLE_ECHO_INPUT};
|
|
||||||
|
|
||||||
let input_handle = kernel::get_input_handle();
|
let input_handle = kernel::get_input_handle();
|
||||||
|
|
||||||
let mut dw_mode: DWORD = 0;
|
let mut dw_mode: DWORD = 0;
|
||||||
@ -127,7 +126,7 @@ impl IStateCommand for EnableRawModeCommand
|
|||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
fn undo(&mut self, context: &Context) -> bool
|
fn undo(&mut self) -> bool
|
||||||
{
|
{
|
||||||
let output_handle = kernel::get_output_handle();
|
let output_handle = kernel::get_output_handle();
|
||||||
|
|
||||||
@ -150,18 +149,39 @@ impl IStateCommand for EnableRawModeCommand
|
|||||||
|
|
||||||
/// 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.
|
||||||
/// check https://docs.microsoft.com/en-us/windows/console/reading-and-writing-blocks-of-characters-and-attributes for more info
|
/// check https://docs.microsoft.com/en-us/windows/console/reading-and-writing-blocks-of-characters-and-attributes for more info
|
||||||
#[derive(Clone, Copy)]
|
pub struct ToAlternateScreenBufferCommand
|
||||||
pub struct ToAlternateScreenBufferCommand;
|
|
||||||
|
|
||||||
impl ICommand for ToAlternateScreenBufferCommand
|
|
||||||
{
|
{
|
||||||
fn new() -> Box<ToAlternateScreenBufferCommand>
|
context: Rc<Context>
|
||||||
{
|
}
|
||||||
Box::from(ToAlternateScreenBufferCommand {})
|
|
||||||
}
|
|
||||||
|
|
||||||
fn execute(&mut self, context: &Context) -> bool
|
impl ToAlternateScreenBufferCommand
|
||||||
|
{
|
||||||
|
pub fn new(context: Rc<Context>) -> u16
|
||||||
{
|
{
|
||||||
|
let key = 2;
|
||||||
|
|
||||||
|
let mut state = context.state_manager.lock().unwrap();
|
||||||
|
{
|
||||||
|
let command = ToAlternateScreenBufferCommand {context: context.clone()};
|
||||||
|
|
||||||
|
state.register_change(Box::from(command), key);
|
||||||
|
key
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl IStateCommand for ToAlternateScreenBufferCommand
|
||||||
|
{
|
||||||
|
fn execute(&mut self) -> bool
|
||||||
|
{
|
||||||
|
use super::super::super::kernel::windows_kernel::ansi_support;
|
||||||
|
use super::super::super::manager::WinApiScreenManager;
|
||||||
|
|
||||||
|
let does_support = ansi_support::try_enable_ansi_support();
|
||||||
|
let mut screen_manager = self.context.screen_manager.lock().unwrap();
|
||||||
|
|
||||||
|
screen_manager.toggle_is_alternate_screen(true);
|
||||||
|
|
||||||
let mut chi_buffer: [CHAR_INFO;160] = unsafe {mem::zeroed() };
|
let mut chi_buffer: [CHAR_INFO;160] = unsafe {mem::zeroed() };
|
||||||
|
|
||||||
let handle = kernel::get_output_handle();
|
let handle = kernel::get_output_handle();
|
||||||
@ -172,6 +192,13 @@ impl ICommand for ToAlternateScreenBufferCommand
|
|||||||
// Make the new screen buffer the active screen buffer.
|
// Make the new screen buffer the active screen buffer.
|
||||||
kernel::set_active_screen_buffer(new_handle);
|
kernel::set_active_screen_buffer(new_handle);
|
||||||
|
|
||||||
|
let b: &mut WinApiScreenManager = match screen_manager.as_any().downcast_mut::<WinApiScreenManager>() {
|
||||||
|
Some(b) => { b },
|
||||||
|
None => panic!("&a isn't a B!")
|
||||||
|
};
|
||||||
|
|
||||||
|
b.set_alternate_handle(new_handle);
|
||||||
|
|
||||||
// Set the source rectangle.
|
// Set the source rectangle.
|
||||||
let mut srct_read_rect = SMALL_RECT
|
let mut srct_read_rect = SMALL_RECT
|
||||||
{
|
{
|
||||||
@ -214,10 +241,16 @@ impl ICommand for ToAlternateScreenBufferCommand
|
|||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
fn undo(&mut self, context: &Context) -> bool
|
fn undo(&mut self) -> 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);
|
||||||
|
|
||||||
|
{
|
||||||
|
let mut screen_manager = self.context.screen_manager.lock().unwrap();
|
||||||
|
screen_manager.toggle_is_alternate_screen(false);
|
||||||
|
}
|
||||||
|
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,13 +1,9 @@
|
|||||||
//! This module contains the code for the context of the terminal.
|
//! This module contains the code for the context of the terminal.
|
||||||
|
use { StateManager, ScreenManager };
|
||||||
|
|
||||||
use std::sync::Mutex;
|
use std::sync::Mutex;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
|
||||||
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.
|
/// 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
|
||||||
{
|
{
|
||||||
@ -39,46 +35,12 @@ impl Context
|
|||||||
/// let color = terminal::color(&context);
|
/// let color = terminal::color(&context);
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
pub fn new() -> Context
|
pub fn new() -> Rc<Context>
|
||||||
{
|
{
|
||||||
Context {
|
Rc::new(Context {
|
||||||
screen_manager: Rc::new(Mutex::new(ScreenManager::new())),
|
screen_manager: Rc::new(Mutex::new(ScreenManager::new())),
|
||||||
state_manager: Mutex::new(StateManager::new())
|
state_manager: Mutex::new(StateManager::new())
|
||||||
}
|
})
|
||||||
}
|
|
||||||
|
|
||||||
/// 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)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -87,6 +49,6 @@ impl Drop for Context
|
|||||||
fn drop(&mut self)
|
fn drop(&mut self)
|
||||||
{
|
{
|
||||||
let mut changes = self.state_manager.lock().unwrap();
|
let mut changes = self.state_manager.lock().unwrap();
|
||||||
changes.restore_changes(&self);
|
changes.restore_changes();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,11 +1,9 @@
|
|||||||
//! This module is used for registering, storing an restoring the terminal state changes.
|
//! This module is used for registering, storing an restoring the terminal state changes.
|
||||||
|
|
||||||
use Context;
|
|
||||||
use super::commands::IStateCommand;
|
use super::commands::IStateCommand;
|
||||||
use super::commands::shared_commands::EmptyCommand;
|
use super::commands::shared_commands::EmptyCommand;
|
||||||
|
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
use std::sync::Mutex;
|
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
|
||||||
/// Struct that stores the changed states of the terminal.
|
/// Struct that stores the changed states of the terminal.
|
||||||
@ -25,12 +23,12 @@ impl StateManager
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Restore all changes that are made to the terminal.
|
/// Restore all changes that are made to the terminal.
|
||||||
pub fn restore_changes(&mut self, context: &Context)
|
pub fn restore_changes(&mut self)
|
||||||
{
|
{
|
||||||
for (id, item) in self.changed_states.iter_mut()
|
for (id, item) in self.changed_states.iter_mut()
|
||||||
{
|
{
|
||||||
let mut item = item.lock().unwrap();
|
let mut item = item.lock().unwrap();
|
||||||
item.undo(&context);
|
item.undo();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -17,9 +17,9 @@ pub struct TerminalColor {
|
|||||||
|
|
||||||
impl TerminalColor {
|
impl TerminalColor {
|
||||||
/// Create new instance whereon color related actions can be performed.
|
/// Create new instance whereon color related actions can be performed.
|
||||||
pub fn new(context: &Context ) -> TerminalColor {
|
pub fn new(context: Rc<Context>) -> TerminalColor {
|
||||||
#[cfg(target_os = "windows")]
|
#[cfg(target_os = "windows")]
|
||||||
let color = functions::get_module::<Box<ITerminalColor>>(WinApiColor::new(), AnsiColor::new(), context);
|
let color = functions::get_module::<Box<ITerminalColor>>(WinApiColor::new(), AnsiColor::new());
|
||||||
|
|
||||||
#[cfg(not(target_os = "windows"))]
|
#[cfg(not(target_os = "windows"))]
|
||||||
let color = Some(AnsiColor::new() as Box<ITerminalColor>);
|
let color = Some(AnsiColor::new() as Box<ITerminalColor>);
|
||||||
@ -127,6 +127,6 @@ impl TerminalColor {
|
|||||||
///
|
///
|
||||||
/// Check `/examples/version/color` in the libary for more specific examples.
|
/// Check `/examples/version/color` in the libary for more specific examples.
|
||||||
///
|
///
|
||||||
pub fn color(context: &Context) -> Box<TerminalColor> {
|
pub fn color(context: Rc<Context>) -> Box<TerminalColor> {
|
||||||
Box::from(TerminalColor::new(context))
|
Box::from(TerminalColor::new(context))
|
||||||
}
|
}
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
//! This module contains the `object style` that can be applied to an `styled object`.
|
//! This module contains the `object style` that can be applied to an `styled object`.
|
||||||
|
|
||||||
use std::fmt::Display;
|
use Context;
|
||||||
use style::{Color, StyledObject};
|
use style::{Color, StyledObject};
|
||||||
use { ScreenManager, Context };
|
|
||||||
use std::sync::Mutex;
|
use std::fmt::Display;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
|
||||||
#[cfg(unix)]
|
#[cfg(unix)]
|
||||||
@ -32,7 +32,7 @@ impl Default for ObjectStyle {
|
|||||||
|
|
||||||
impl ObjectStyle {
|
impl ObjectStyle {
|
||||||
/// Apply an `StyledObject` to the passed displayable object.
|
/// Apply an `StyledObject` to the passed displayable object.
|
||||||
pub fn apply_to<'a, D>(&self, val: D, context: &'a Context) -> StyledObject<'a, D>
|
pub fn apply_to<D>(&self, val: D, context: Rc<Context>) -> StyledObject<D>
|
||||||
where
|
where
|
||||||
D: Display,
|
D: Display,
|
||||||
{
|
{
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
//! This module contains the logic to style an object that contains some state witch can be styled.
|
//! This module contains the logic to style an object that contains some state witch can be styled.
|
||||||
|
|
||||||
|
use Context;
|
||||||
|
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::io::Write;
|
use std::io::Write;
|
||||||
use std::sync::Mutex;
|
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
use { ScreenManager, Context};
|
|
||||||
|
|
||||||
#[cfg(unix)]
|
#[cfg(unix)]
|
||||||
use super::super::Attribute;
|
use super::super::Attribute;
|
||||||
@ -12,13 +12,13 @@ use super::super::Attribute;
|
|||||||
use style::{Color, ObjectStyle};
|
use style::{Color, ObjectStyle};
|
||||||
|
|
||||||
/// Struct that contains both the style and the content wits can be styled.
|
/// Struct that contains both the style and the content wits can be styled.
|
||||||
pub struct StyledObject<'a, D> {
|
pub struct StyledObject<D> {
|
||||||
pub object_style: ObjectStyle,
|
pub object_style: ObjectStyle,
|
||||||
pub content: D,
|
pub content: D,
|
||||||
pub context: &'a Context
|
pub context: Rc<Context>
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, D> StyledObject<'a,D> {
|
impl<D> StyledObject<D> {
|
||||||
/// Set the foreground of the styled object to the passed `Color`
|
/// Set the foreground of the styled object to the passed `Color`
|
||||||
///
|
///
|
||||||
/// #Example
|
/// #Example
|
||||||
@ -39,7 +39,7 @@ impl<'a, D> StyledObject<'a,D> {
|
|||||||
/// println!("{}", paint("I am colored green").with(Color::Green));
|
/// println!("{}", paint("I am colored green").with(Color::Green));
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
pub fn with(mut self, foreground_color: Color) -> StyledObject<'a,D> {
|
pub fn with(mut self, foreground_color: Color) -> StyledObject<D> {
|
||||||
self.object_style = self.object_style.fg(foreground_color);
|
self.object_style = self.object_style.fg(foreground_color);
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
@ -64,7 +64,7 @@ impl<'a, D> StyledObject<'a,D> {
|
|||||||
/// println!("{}", paint("I am colored green").on(Color::Green))
|
/// println!("{}", paint("I am colored green").on(Color::Green))
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
pub fn on(mut self, background_color: Color) -> StyledObject<'a,D> {
|
pub fn on(mut self, background_color: Color) -> StyledObject<D> {
|
||||||
self.object_style = self.object_style.bg(background_color);
|
self.object_style = self.object_style.bg(background_color);
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
@ -82,7 +82,7 @@ impl<'a, D> StyledObject<'a,D> {
|
|||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
#[cfg(unix)]
|
#[cfg(unix)]
|
||||||
pub fn attr(mut self, attr: Attribute) -> StyledObject<'a,D>
|
pub fn attr(mut self, attr: Attribute) -> StyledObject<D>
|
||||||
{
|
{
|
||||||
&self.object_style.add_attr(attr);
|
&self.object_style.add_attr(attr);
|
||||||
self
|
self
|
||||||
@ -113,10 +113,10 @@ impl<'a, D> StyledObject<'a,D> {
|
|||||||
macro_rules! impl_fmt
|
macro_rules! impl_fmt
|
||||||
{
|
{
|
||||||
($name:ident) => {
|
($name:ident) => {
|
||||||
impl<'a, D: fmt::$name> fmt::$name for StyledObject<'a, D> {
|
impl<D: fmt::$name> fmt::$name for StyledObject<D> {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result
|
||||||
{
|
{
|
||||||
let mut colored_terminal = super::super::color(&self.context);
|
let mut colored_terminal = super::super::color(self.context.clone());
|
||||||
let mut reset = true;
|
let mut reset = true;
|
||||||
|
|
||||||
if let Some(bg) = self.object_style.bg_color
|
if let Some(bg) = self.object_style.bg_color
|
||||||
@ -132,7 +132,11 @@ macro_rules! impl_fmt
|
|||||||
|
|
||||||
#[cfg(unix)]
|
#[cfg(unix)]
|
||||||
for attr in self.object_style.attrs.iter() {
|
for attr in self.object_style.attrs.iter() {
|
||||||
write!(f, csi!("{}m"), *attr as i16);
|
let mutex = self.context.screen_manager;
|
||||||
|
{
|
||||||
|
let mut screen = mutex.lock().unwrap();
|
||||||
|
screen.write_ansi_str(format!(csi!("{}m"), *attr as i16)).expect("Flush failed");
|
||||||
|
}
|
||||||
reset = true;
|
reset = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -141,7 +145,8 @@ macro_rules! impl_fmt
|
|||||||
let mutex = &self.context.screen_manager;
|
let mutex = &self.context.screen_manager;
|
||||||
{
|
{
|
||||||
let mut screen = mutex.lock().unwrap();
|
let mut screen = mutex.lock().unwrap();
|
||||||
screen.stdout().flush().expect("Flush stdout failed");
|
|
||||||
|
screen.flush().expect("Flush failed");
|
||||||
}
|
}
|
||||||
|
|
||||||
if reset
|
if reset
|
||||||
|
@ -3,66 +3,65 @@
|
|||||||
|
|
||||||
use Context;
|
use Context;
|
||||||
use shared::functions;
|
use shared::functions;
|
||||||
use super::{ClearType, ITerminal};
|
use super::{ClearType, ITerminal, Rc};
|
||||||
|
|
||||||
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
|
||||||
|
{
|
||||||
|
context: Rc<Context>
|
||||||
|
}
|
||||||
|
|
||||||
impl AnsiTerminal {
|
impl AnsiTerminal {
|
||||||
pub fn new() -> Box<AnsiTerminal> {
|
pub fn new(context: Rc<Context>) -> Box<AnsiTerminal> {
|
||||||
Box::from(AnsiTerminal {})
|
Box::from(AnsiTerminal {context: context})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ITerminal for AnsiTerminal {
|
impl ITerminal for AnsiTerminal {
|
||||||
fn clear(&self, clear_type: ClearType, context: &Context) {
|
fn clear(&self, clear_type: ClearType)
|
||||||
|
{
|
||||||
let mut screen_manager = context.screen_manager.lock().unwrap();
|
let mut screen_manager = self.context.screen_manager.lock().unwrap();
|
||||||
{
|
{
|
||||||
let stdout = screen_manager.stdout();
|
|
||||||
|
|
||||||
match clear_type {
|
match clear_type {
|
||||||
ClearType::All => {
|
ClearType::All => {
|
||||||
write!(stdout, csi!("2J"));
|
screen_manager.write_ansi_str(csi!("2J"));
|
||||||
},
|
},
|
||||||
ClearType::FromCursorDown => {
|
ClearType::FromCursorDown => {
|
||||||
write!(stdout, csi!("J"));
|
screen_manager.write_ansi_str(csi!("J"));
|
||||||
},
|
},
|
||||||
ClearType::FromCursorUp => {
|
ClearType::FromCursorUp => {
|
||||||
write!(stdout, csi!("1J"));
|
screen_manager.write_ansi_str(csi!("1J"));
|
||||||
},
|
},
|
||||||
ClearType::CurrentLine => {
|
ClearType::CurrentLine => {
|
||||||
write!(stdout, csi!("2K"));
|
screen_manager.write_ansi_str(csi!("2K"));
|
||||||
},
|
},
|
||||||
ClearType::UntilNewLine => {
|
ClearType::UntilNewLine => {
|
||||||
write!(stdout, csi!("K"));
|
screen_manager.write_ansi_str(csi!("K"));
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn terminal_size(&self, context: &Context) -> (u16, u16) {
|
fn terminal_size(&self) -> (u16, u16) {
|
||||||
functions::get_terminal_size()
|
functions::get_terminal_size()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn scroll_up(&self, count: i16, context: &Context) {
|
fn scroll_up(&self, count: i16) {
|
||||||
let mut screen = context.screen_manager.lock().unwrap();
|
let mut screen = self.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, context: &Context) {
|
fn scroll_down(&self, count: i16) {
|
||||||
let mut screen = context.screen_manager.lock().unwrap();
|
let mut screen = self.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, context: &Context) {
|
fn set_size(&self, width: i16, height: i16) {
|
||||||
let mut screen = context.screen_manager.lock().unwrap();
|
let mut screen = self.context.screen_manager.lock().unwrap();
|
||||||
{
|
{
|
||||||
screen.write_ansi(format!(csi!("8;{};{}t"), width, height));
|
screen.write_ansi(format!(csi!("8;{};{}t"), width, height));
|
||||||
}
|
}
|
||||||
|
@ -15,6 +15,7 @@ mod ansi_terminal;
|
|||||||
#[cfg(target_os = "windows")]
|
#[cfg(target_os = "windows")]
|
||||||
use self::winapi_terminal::WinApiTerminal;
|
use self::winapi_terminal::WinApiTerminal;
|
||||||
use self::ansi_terminal::AnsiTerminal;
|
use self::ansi_terminal::AnsiTerminal;
|
||||||
|
use std::rc::Rc;
|
||||||
|
|
||||||
use Context;
|
use Context;
|
||||||
pub use self::terminal::{ terminal};
|
pub use self::terminal::{ terminal};
|
||||||
@ -38,13 +39,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, context: &Context);
|
fn clear(&self, clear_type: ClearType);
|
||||||
/// Get the terminal size (x,y)
|
/// Get the terminal size (x,y)
|
||||||
fn terminal_size(&self, context: &Context) -> (u16, u16);
|
fn terminal_size(&self) -> (u16, u16);
|
||||||
/// Scroll `n` lines up in the current terminal.
|
/// Scroll `n` lines up in the current terminal.
|
||||||
fn scroll_up(&self, count: i16, context: &Context);
|
fn scroll_up(&self, count: i16);
|
||||||
/// Scroll `n` lines down in the current terminal.
|
/// Scroll `n` lines down in the current terminal.
|
||||||
fn scroll_down(&self, count: i16, context: &Context);
|
fn scroll_down(&self, count: i16);
|
||||||
/// Resize terminal to the given width and height.
|
/// Resize terminal to the given width and height.
|
||||||
fn set_size(&self,width: i16, height: i16, context: &Context);
|
fn set_size(&self,width: i16, height: i16);
|
||||||
}
|
}
|
||||||
|
@ -3,25 +3,26 @@
|
|||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
use Context;
|
use Context;
|
||||||
|
|
||||||
use std::fmt;
|
|
||||||
use super::super::style;
|
use super::super::style;
|
||||||
use super::super::shared::functions;
|
use super::super::shared::functions;
|
||||||
|
|
||||||
|
use std::fmt;
|
||||||
|
use std::rc::Rc;
|
||||||
|
|
||||||
/// 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<'context> {
|
pub struct Terminal {
|
||||||
terminal: Option<Box<ITerminal>>,
|
terminal: Option<Box<ITerminal>>,
|
||||||
context: &'context Context
|
context: Rc<Context>
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'context> Terminal<'context> {
|
impl Terminal {
|
||||||
/// 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(context: &'context Context) -> Terminal<'context> {
|
pub fn new(context: Rc<Context>) -> Terminal {
|
||||||
#[cfg(target_os = "windows")]
|
#[cfg(target_os = "windows")]
|
||||||
let terminal = functions::get_module::<Box<ITerminal>>(WinApiTerminal::new(), AnsiTerminal::new(), context);
|
let terminal = functions::get_module::<Box<ITerminal>>(WinApiTerminal::new(context.clone()), AnsiTerminal::new(context.clone()));
|
||||||
|
|
||||||
#[cfg(not(target_os = "windows"))]
|
#[cfg(not(target_os = "windows"))]
|
||||||
let terminal = Some(AnsiTerminal::new() as Box<ITerminal>);
|
let terminal = Some(AnsiTerminal::new(context.clone()) as Box<ITerminal>);
|
||||||
|
|
||||||
Terminal { terminal, context: context }
|
Terminal { terminal, context: context }
|
||||||
|
|
||||||
@ -54,7 +55,7 @@ impl<'context> Terminal<'context> {
|
|||||||
/// ```
|
/// ```
|
||||||
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.context);
|
terminal.clear(clear_type);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -77,7 +78,7 @@ impl<'context> Terminal<'context> {
|
|||||||
/// ```
|
/// ```
|
||||||
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.context)
|
return terminal.terminal_size()
|
||||||
}
|
}
|
||||||
(0,0)
|
(0,0)
|
||||||
}
|
}
|
||||||
@ -101,7 +102,7 @@ impl<'context> Terminal<'context> {
|
|||||||
/// ```
|
/// ```
|
||||||
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.context);
|
terminal.scroll_up(count);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -124,7 +125,7 @@ impl<'context> Terminal<'context> {
|
|||||||
/// ```
|
/// ```
|
||||||
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.context);
|
terminal.scroll_down(count);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -148,7 +149,7 @@ impl<'context> Terminal<'context> {
|
|||||||
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.context);
|
terminal.set_size(width,height);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -183,7 +184,7 @@ impl<'context> Terminal<'context> {
|
|||||||
where
|
where
|
||||||
D: fmt::Display,
|
D: fmt::Display,
|
||||||
{
|
{
|
||||||
style::ObjectStyle::new().apply_to(val, &self.context)
|
style::ObjectStyle::new().apply_to(val, self.context.clone())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -208,6 +209,6 @@ impl<'context> Terminal<'context> {
|
|||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
///
|
///
|
||||||
pub fn terminal<'context>(context: &'context Context) -> Box<Terminal<'context>> {
|
pub fn terminal(context: Rc<Context>) -> Box<Terminal> {
|
||||||
Box::from(Terminal::new(&context))
|
Box::from(Terminal::new(context.clone()))
|
||||||
}
|
}
|
||||||
|
@ -3,44 +3,47 @@
|
|||||||
|
|
||||||
use Context;
|
use Context;
|
||||||
use cursor::cursor;
|
use cursor::cursor;
|
||||||
use super::{ClearType, ITerminal};
|
use super::{ClearType, ITerminal, Rc};
|
||||||
use winapi::um::wincon::{SMALL_RECT, COORD, CONSOLE_SCREEN_BUFFER_INFO,};
|
use winapi::um::wincon::{SMALL_RECT, COORD, CONSOLE_SCREEN_BUFFER_INFO,};
|
||||||
use kernel::windows_kernel::{kernel, terminal};
|
use kernel::windows_kernel::{kernel, terminal};
|
||||||
|
|
||||||
/// This struct is an windows implementation for terminal related actions.
|
/// This struct is an windows implementation for terminal related actions.
|
||||||
pub struct WinApiTerminal;
|
pub struct WinApiTerminal
|
||||||
|
{
|
||||||
|
context: Rc<Context>
|
||||||
|
}
|
||||||
|
|
||||||
impl WinApiTerminal {
|
impl WinApiTerminal {
|
||||||
pub fn new() -> Box<WinApiTerminal> {
|
pub fn new(context: Rc<Context>) -> Box<WinApiTerminal> {
|
||||||
Box::from(WinApiTerminal {})
|
Box::from(WinApiTerminal { context })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ITerminal for WinApiTerminal {
|
impl ITerminal for WinApiTerminal {
|
||||||
|
|
||||||
fn clear(&self, clear_type: ClearType, context: &Context) {
|
fn clear(&self, clear_type: ClearType) {
|
||||||
let csbi = kernel::get_console_screen_buffer_info();
|
let csbi = kernel::get_console_screen_buffer_info();
|
||||||
let pos = cursor(&context).pos();
|
let pos = cursor(self.context.clone()).pos();
|
||||||
|
|
||||||
match clear_type
|
match clear_type
|
||||||
{
|
{
|
||||||
ClearType::All => clear_entire_screen(csbi, &context),
|
ClearType::All => clear_entire_screen(csbi, self.context.clone()),
|
||||||
ClearType::FromCursorDown => clear_after_cursor(pos,csbi,&context),
|
ClearType::FromCursorDown => clear_after_cursor(pos,csbi, self.context.clone()),
|
||||||
ClearType::FromCursorUp => clear_before_cursor(pos, csbi, &context),
|
ClearType::FromCursorUp => clear_before_cursor(pos, csbi, self.context.clone()),
|
||||||
ClearType::CurrentLine => clear_current_line(pos, csbi, &context),
|
ClearType::CurrentLine => clear_current_line(pos, csbi, self.context.clone()),
|
||||||
ClearType::UntilNewLine => clear_until_line(pos, csbi,&context),
|
ClearType::UntilNewLine => clear_until_line(pos, csbi,self.context.clone()),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
fn terminal_size(&self, context: &Context) -> (u16, u16) {
|
fn terminal_size(&self) -> (u16, u16) {
|
||||||
terminal::terminal_size()
|
terminal::terminal_size()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn scroll_up(&self, count: i16, context: &Context) {
|
fn scroll_up(&self, count: i16) {
|
||||||
// yet to be inplemented
|
// yet to be inplemented
|
||||||
}
|
}
|
||||||
|
|
||||||
fn scroll_down(&self, count: i16, context: &Context) {
|
fn scroll_down(&self, count: i16) {
|
||||||
let csbi = kernel::get_console_screen_buffer_info();
|
let csbi = kernel::get_console_screen_buffer_info();
|
||||||
let mut srct_window;
|
let mut srct_window;
|
||||||
|
|
||||||
@ -60,7 +63,7 @@ impl ITerminal for WinApiTerminal {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Set the current terminal size
|
/// Set the current terminal size
|
||||||
fn set_size(&self, width: i16, height: i16, context: &Context) {
|
fn set_size(&self, width: i16, height: i16) {
|
||||||
if width <= 0
|
if width <= 0
|
||||||
{
|
{
|
||||||
panic!("Cannot set the terminal width lower than 1");
|
panic!("Cannot set the terminal width lower than 1");
|
||||||
@ -136,7 +139,7 @@ impl ITerminal for WinApiTerminal {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn clear_after_cursor(pos: (u16,u16), csbi: CONSOLE_SCREEN_BUFFER_INFO, context: &Context) {
|
pub fn clear_after_cursor(pos: (u16,u16), csbi: CONSOLE_SCREEN_BUFFER_INFO, context: Rc<Context>) {
|
||||||
let (mut x,mut y) = pos;
|
let (mut x,mut y) = pos;
|
||||||
|
|
||||||
// if cursor position is at the outer right position
|
// if cursor position is at the outer right position
|
||||||
@ -154,7 +157,7 @@ pub fn clear_after_cursor(pos: (u16,u16), csbi: CONSOLE_SCREEN_BUFFER_INFO, cont
|
|||||||
clear(start_location,cells_to_write);
|
clear(start_location,cells_to_write);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn clear_before_cursor(pos: (u16,u16), csbi: CONSOLE_SCREEN_BUFFER_INFO, context: &Context) {
|
pub fn clear_before_cursor(pos: (u16,u16), csbi: CONSOLE_SCREEN_BUFFER_INFO, context: Rc<Context>) {
|
||||||
let (xpos,ypos) = pos;
|
let (xpos,ypos) = pos;
|
||||||
|
|
||||||
// one cell after cursor position
|
// one cell after cursor position
|
||||||
@ -170,7 +173,7 @@ pub fn clear_before_cursor(pos: (u16,u16), csbi: CONSOLE_SCREEN_BUFFER_INFO, con
|
|||||||
clear(start_location, cells_to_write);
|
clear(start_location, cells_to_write);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn clear_entire_screen(csbi: CONSOLE_SCREEN_BUFFER_INFO, context: &Context) {
|
pub fn clear_entire_screen(csbi: CONSOLE_SCREEN_BUFFER_INFO, context: Rc<Context>) {
|
||||||
// position x at start
|
// position x at start
|
||||||
let x = 0;
|
let x = 0;
|
||||||
// position y at start
|
// position y at start
|
||||||
@ -185,10 +188,10 @@ pub fn clear_entire_screen(csbi: CONSOLE_SCREEN_BUFFER_INFO, context: &Context)
|
|||||||
clear( start_location, cells_to_write);
|
clear( start_location, cells_to_write);
|
||||||
|
|
||||||
// put the cursor back at (0, 0)
|
// put the cursor back at (0, 0)
|
||||||
cursor(&context).goto(0, 0);
|
cursor(context.clone()).goto(0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn clear_current_line(pos: (u16,u16), csbi: CONSOLE_SCREEN_BUFFER_INFO, context: &Context)
|
pub fn clear_current_line(pos: (u16,u16), csbi: CONSOLE_SCREEN_BUFFER_INFO, context: Rc<Context>)
|
||||||
{
|
{
|
||||||
// position x at start
|
// position x at start
|
||||||
let x = 0;
|
let x = 0;
|
||||||
@ -204,10 +207,10 @@ pub fn clear_current_line(pos: (u16,u16), csbi: CONSOLE_SCREEN_BUFFER_INFO, cont
|
|||||||
clear(start_location, cells_to_write);
|
clear(start_location, cells_to_write);
|
||||||
|
|
||||||
// put the cursor back at 1 cell on current row
|
// put the cursor back at 1 cell on current row
|
||||||
cursor(&context).goto(0, y);
|
cursor(context.clone()).goto(0, y);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn clear_until_line(pos: (u16,u16), csbi: CONSOLE_SCREEN_BUFFER_INFO, context: &Context)
|
pub fn clear_until_line(pos: (u16,u16), csbi: CONSOLE_SCREEN_BUFFER_INFO, context: Rc<Context>)
|
||||||
{
|
{
|
||||||
let (x,y) = pos;
|
let (x,y) = pos;
|
||||||
|
|
||||||
@ -219,7 +222,7 @@ pub fn clear_until_line(pos: (u16,u16), csbi: CONSOLE_SCREEN_BUFFER_INFO, contex
|
|||||||
clear(start_location, cells_to_write);
|
clear(start_location, cells_to_write);
|
||||||
|
|
||||||
// put the cursor back at original cursor position
|
// put the cursor back at original cursor position
|
||||||
cursor(&context).goto(x,y);
|
cursor(context.clone()).goto(x,y);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn clear(
|
fn clear(
|
||||||
|
Loading…
Reference in New Issue
Block a user