Added alternate screen support for unix systems
This commit is contained in:
parent
9fbf7481c3
commit
17616100df
1119
.idea/workspace.xml
1119
.idea/workspace.xml
File diff suppressed because it is too large
Load Diff
@ -23,3 +23,7 @@ termios = "0.3.0"
|
|||||||
[lib]
|
[lib]
|
||||||
name = "crossterm"
|
name = "crossterm"
|
||||||
path = "src/lib.rs"
|
path = "src/lib.rs"
|
||||||
|
|
||||||
|
[[bin]]
|
||||||
|
name = "a"
|
||||||
|
path = "examples/bin.rs"
|
||||||
|
@ -11,9 +11,11 @@
|
|||||||
//!
|
//!
|
||||||
//! - Run program with: `cargo run`
|
//! - Run program with: `cargo run`
|
||||||
|
|
||||||
extern crate crossterm;
|
mod cursor;
|
||||||
|
mod terminal;
|
||||||
|
|
||||||
use crossterm::cursor;
|
use terminal::alternate_screen;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
|
alternate_screen::t();
|
||||||
}
|
}
|
@ -5,12 +5,15 @@
|
|||||||
extern crate crossterm;
|
extern crate crossterm;
|
||||||
|
|
||||||
use self::crossterm::cursor::{cursor, TerminalCursor};
|
use self::crossterm::cursor::{cursor, TerminalCursor};
|
||||||
|
use self::crossterm::{Context, Terminal };
|
||||||
|
|
||||||
/// Set the cursor to position X: 10, Y: 5 in the terminal.
|
/// Set the cursor to position X: 10, Y: 5 in the terminal.
|
||||||
pub fn goto()
|
pub fn goto()
|
||||||
{
|
{
|
||||||
|
let context = Terminal::new();
|
||||||
|
|
||||||
// Get the cursor
|
// Get the cursor
|
||||||
let mut cursor = cursor();
|
let mut cursor = cursor(&context);
|
||||||
// Set the cursor to position X: 10, Y: 5 in the terminal
|
// Set the cursor to position X: 10, Y: 5 in the terminal
|
||||||
cursor.goto(10,5);
|
cursor.goto(10,5);
|
||||||
}
|
}
|
||||||
@ -18,8 +21,9 @@ pub fn goto()
|
|||||||
/// Move the cursor 3 up | demonstration.
|
/// Move the cursor 3 up | demonstration.
|
||||||
pub fn move_up()
|
pub fn move_up()
|
||||||
{
|
{
|
||||||
|
let context = Terminal::new();
|
||||||
// Get the cursor
|
// Get the cursor
|
||||||
let mut cursor = cursor();
|
let mut cursor = cursor(&context);
|
||||||
// Move the cursor to position 3 times to the up in the terminal
|
// Move the cursor to position 3 times to the up in the terminal
|
||||||
cursor.move_up(3);
|
cursor.move_up(3);
|
||||||
}
|
}
|
||||||
@ -27,8 +31,9 @@ pub fn move_up()
|
|||||||
/// Move the cursor 3 to the right | demonstration.
|
/// Move the cursor 3 to the right | demonstration.
|
||||||
pub fn move_right()
|
pub fn move_right()
|
||||||
{
|
{
|
||||||
|
let context = Terminal::new();
|
||||||
// Get the cursor
|
// Get the cursor
|
||||||
let mut cursor = cursor();
|
let mut cursor = cursor(&context);
|
||||||
// Move the cursor to position 3 times to the right in the terminal
|
// Move the cursor to position 3 times to the right in the terminal
|
||||||
cursor.move_right(3);
|
cursor.move_right(3);
|
||||||
}
|
}
|
||||||
@ -36,8 +41,9 @@ pub fn move_right()
|
|||||||
/// Move the cursor 3 down | demonstration.
|
/// Move the cursor 3 down | demonstration.
|
||||||
pub fn move_down()
|
pub fn move_down()
|
||||||
{
|
{
|
||||||
|
let context = Terminal::new();
|
||||||
// Get the cursor
|
// Get the cursor
|
||||||
let mut cursor = cursor();
|
let mut cursor = cursor(&context);
|
||||||
// Move the cursor to position 3 times to the down in the terminal
|
// Move the cursor to position 3 times to the down in the terminal
|
||||||
cursor.move_down(3);
|
cursor.move_down(3);
|
||||||
}
|
}
|
||||||
@ -45,8 +51,9 @@ pub fn move_down()
|
|||||||
/// Move the cursor 3 to the left | demonstration.
|
/// Move the cursor 3 to the left | demonstration.
|
||||||
pub fn move_left()
|
pub fn move_left()
|
||||||
{
|
{
|
||||||
|
let context = Terminal::new();
|
||||||
// Get the cursor
|
// Get the cursor
|
||||||
let mut cursor = cursor();
|
let mut cursor = cursor(&context);
|
||||||
// Move the cursor to position 3 times to the left in the terminal
|
// Move the cursor to position 3 times to the left in the terminal
|
||||||
cursor.move_left(3);
|
cursor.move_left(3);
|
||||||
}
|
}
|
||||||
@ -54,10 +61,11 @@ pub fn move_left()
|
|||||||
/// Print character at X: 10 Y: 5 | demonstration.
|
/// Print character at X: 10 Y: 5 | demonstration.
|
||||||
pub fn print()
|
pub fn print()
|
||||||
{
|
{
|
||||||
|
let context = Terminal::new();
|
||||||
// To print an some displayable content on an certain position.
|
// To print an some displayable content on an certain position.
|
||||||
|
|
||||||
// Get the cursor
|
// Get the cursor
|
||||||
let mut cursor = cursor();
|
let mut cursor = cursor(&context);
|
||||||
// Set the cursor to position X: 10, Y: 5 in the terminal
|
// Set the cursor to position X: 10, Y: 5 in the terminal
|
||||||
cursor.goto(10,5);
|
cursor.goto(10,5);
|
||||||
// Print the @ symbol at position X: 10, Y: 5 in the terminal
|
// Print the @ symbol at position X: 10, Y: 5 in the terminal
|
||||||
@ -79,7 +87,8 @@ pub fn print()
|
|||||||
/// Save and reset cursor position | demonstration..
|
/// Save and reset cursor position | demonstration..
|
||||||
pub fn safe_and_reset_position()
|
pub fn safe_and_reset_position()
|
||||||
{
|
{
|
||||||
let mut cursor = cursor();
|
let context = Terminal::new();
|
||||||
|
let mut cursor = cursor(&context);
|
||||||
|
|
||||||
// Goto X: 5 Y: 5
|
// Goto X: 5 Y: 5
|
||||||
cursor.goto(5,5);
|
cursor.goto(5,5);
|
||||||
|
@ -1,73 +1,131 @@
|
|||||||
// alternate screen is not working correctly currently
|
//alternate screen is not working correctly currently
|
||||||
|
|
||||||
|
|
||||||
//extern crate crossterm;
|
extern crate crossterm;
|
||||||
//
|
|
||||||
//use crossterm::terminal::screen::{AlternateScreen, ToAlternateScreen, ToMainScreen};
|
use self::crossterm::{ Context, Terminal };
|
||||||
//use crossterm::cursor::cursor;
|
use self::crossterm::cursor::cursor;
|
||||||
//use crossterm::terminal::{self, ClearType};
|
use self::crossterm::terminal::{self, ClearType};
|
||||||
//
|
use self::crossterm::terminal::screen;
|
||||||
//use std::io::{Write, stdout};
|
|
||||||
//use std::{time, thread};
|
use std::io::{Write, stdout};
|
||||||
//
|
use std::{time, thread};
|
||||||
//fn print_wait_screen(screen: &mut Write)
|
|
||||||
//{
|
/// this will print an example wait screen.
|
||||||
// terminal::terminal().clear(ClearType::All);
|
fn print_wait_screen(terminal: &Terminal)
|
||||||
// write!(screen,
|
{
|
||||||
// "Welcome to the wait screen.\n\
|
// clear the screen and reset the cursor pos
|
||||||
// Please wait a few seconds until we arrive back at the main screen.\n\
|
terminal::terminal(&terminal).clear(ClearType::All);
|
||||||
// Seconds to Go: "
|
let mut cursor = cursor(&terminal);
|
||||||
// );
|
cursor.goto(0, 0);
|
||||||
//
|
|
||||||
// let mut counter = 5;
|
// we need to create a scope so that or mutex gueard will be dropped. we need the output also some lines future from here.
|
||||||
// // get cursor instance
|
let mut screen_manager = &terminal.screen_manager;
|
||||||
// let mut cursor = cursor();
|
{
|
||||||
//
|
let mut output = screen_manager.lock().unwrap();
|
||||||
// // loop until the counter hits 0
|
{
|
||||||
// loop
|
write!(output.stdout(),
|
||||||
// {
|
"Welcome to the wait screen.\n\
|
||||||
// // 1 second delay
|
Please wait a few seconds until we arrive back at the main screen.\n\n
|
||||||
// thread::sleep(time::Duration::from_secs(1));
|
Possessing: "
|
||||||
// // decrement counter
|
);
|
||||||
// counter -= 1;
|
}
|
||||||
//
|
}
|
||||||
// // print the current counter at the line of `Seconds to Go: {counter}`
|
|
||||||
// cursor.goto(15,2).print(counter);
|
for i in 0..5
|
||||||
//
|
{
|
||||||
// if counter <= 0
|
// 1 second delay
|
||||||
// {
|
thread::sleep(time::Duration::from_secs(1));
|
||||||
// break;
|
|
||||||
// }
|
// print the current counter at the line of `Seconds to Go: {counter}`
|
||||||
// }
|
cursor.goto(11, 5).print(format!("{} of the 5 items initialized!", i));
|
||||||
//}
|
}
|
||||||
//
|
}
|
||||||
//pub fn with_alternate_screen_instance()
|
|
||||||
//{
|
/// this will switch the to alternate modes for 3 seconds after that it wil stitch back to main screen.
|
||||||
// // create scope. If this scope ends the screen will be switched back to mainscreen.
|
pub fn switch_to_alternate_screen_and_back()
|
||||||
// // becouse `AlternateScreen` switches back to main screen when switching back.
|
{
|
||||||
// {
|
// create scope for the alternate screen when the scope ends the screen will be switched back to mainscreen.
|
||||||
// // create new alternate screen instance and switch to the alternate screen.
|
let terminal = Terminal::new();
|
||||||
// let mut screen = AlternateScreen::from(stdout());
|
{
|
||||||
//
|
let alternate_screen = screen::AlternateScreen::from(&terminal);
|
||||||
// // Print the wait screen.
|
|
||||||
// print_wait_screen(&mut screen);
|
// Print the wait screen.
|
||||||
// }
|
print_wait_screen(&terminal);
|
||||||
//
|
}
|
||||||
// println!("Whe are back at the main screen");
|
|
||||||
//}
|
terminal::terminal(&terminal).clear(ClearType::All);
|
||||||
//
|
cursor::cursor(&terminal).goto(0,0);
|
||||||
//pub fn manually_switch_to_alternate_screen()
|
println!("Whe are back at the main screen");
|
||||||
//{
|
}
|
||||||
// // You can switch to alternate screen manually but if you forget to switch back your terminal may cause some undefined behavior.
|
|
||||||
//
|
/// This demonstrates how to switch to alternate screen and main screen.
|
||||||
// let mut screen = stdout();
|
pub fn stress_test()
|
||||||
//
|
{
|
||||||
// // switch to alternate screeen
|
let terminal = Terminal::new();
|
||||||
// write!(screen, "{}", ToAlternateScreen);
|
{
|
||||||
// // load wait screen
|
// clear main screen
|
||||||
// print_wait_screen(&mut screen);
|
terminal::terminal(&terminal).clear(ClearType::All);
|
||||||
// // switch back
|
|
||||||
// write!(screen,"{}", ToMainScreen);
|
// create alternate screen and switch into that mode.
|
||||||
// println!("Whe are back at the main screen");
|
let mut alternate_screen = screen::AlternateScreen::from(&terminal);
|
||||||
//
|
|
||||||
//}
|
// clear the alternate screen.
|
||||||
|
terminal::terminal(&terminal).clear(ClearType::All);
|
||||||
|
|
||||||
|
// switch to alternate screen and back to main after three seconds
|
||||||
|
write!(alternate_screen, "{}", "We are at the alternatescreen \n");
|
||||||
|
thread::sleep(time::Duration::from_secs(3));
|
||||||
|
alternate_screen.to_main();
|
||||||
|
write!(alternate_screen, "{}", "We are back at the main screen 1\n");
|
||||||
|
|
||||||
|
// switch to alternate screen and back to main after three seconds
|
||||||
|
thread::sleep(time::Duration::from_secs(3));
|
||||||
|
alternate_screen.to_alternate();
|
||||||
|
write!(alternate_screen, "{}", "We are at the alternatescreen 2\n");
|
||||||
|
thread::sleep(time::Duration::from_secs(3));
|
||||||
|
alternate_screen.to_main();
|
||||||
|
write!(alternate_screen, "{}", "We are back at the main screen 2\n");
|
||||||
|
|
||||||
|
// switch to alternate screen and back to main after three seconds
|
||||||
|
thread::sleep(time::Duration::from_secs(3));
|
||||||
|
alternate_screen.to_alternate();
|
||||||
|
write!(alternate_screen, "{}", "We are at the alternatescreen 3\n");
|
||||||
|
thread::sleep(time::Duration::from_secs(3));
|
||||||
|
alternate_screen.to_main();
|
||||||
|
write!(alternate_screen, "{}", "We are back at the main screen 3\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn t()
|
||||||
|
{
|
||||||
|
use self::crossterm::cursor::cursor;
|
||||||
|
use self::crossterm::style::Color;
|
||||||
|
use std::io;
|
||||||
|
let terminal = Terminal::new();
|
||||||
|
{
|
||||||
|
let mut alternate_screen = screen::AlternateScreen::from(&terminal);
|
||||||
|
terminal::terminal(&terminal).clear(ClearType::All);
|
||||||
|
write!(alternate_screen, "{}", "We are at the alternatescreen \n");
|
||||||
|
|
||||||
|
|
||||||
|
// Goto X: 5 Y: 5
|
||||||
|
cursor(&terminal).goto(5,5);
|
||||||
|
// Safe cursor position: X: 5 Y: 5
|
||||||
|
cursor(&terminal).save_position();
|
||||||
|
// Goto X: 5 Y: 20
|
||||||
|
cursor(&terminal).goto(5,20);
|
||||||
|
// Print at X: 5 Y: 20.
|
||||||
|
write!(io::stdout(), "{}", terminal.paint("Yea").with(Color::Blue));
|
||||||
|
// Reset back to X: 5 Y: 5.
|
||||||
|
cursor(&terminal).reset_position();
|
||||||
|
// Print Back at X: 5 Y: 5.
|
||||||
|
write!(io::stdout(), "{}", terminal.paint("Back").with(Color::Red));
|
||||||
|
|
||||||
|
println!();
|
||||||
|
|
||||||
|
thread::sleep(time::Duration::from_secs(3));
|
||||||
|
}
|
||||||
|
terminal::terminal(&terminal).clear(ClearType::All);
|
||||||
|
println!("Back at the main screen");
|
||||||
|
}
|
@ -1,4 +1,4 @@
|
|||||||
mod alternate_screen;
|
pub mod alternate_screen;
|
||||||
mod raw_mode;
|
mod raw_mode;
|
||||||
|
|
||||||
|
|
||||||
|
@ -4,8 +4,11 @@
|
|||||||
|
|
||||||
extern crate crossterm;
|
extern crate crossterm;
|
||||||
|
|
||||||
use crossterm::terminal::{ Terminal, ClearType, terminal};
|
|
||||||
use crossterm::cursor;
|
use self::crossterm::terminal::{ ClearType, terminal};
|
||||||
|
use self::crossterm::cursor;
|
||||||
|
|
||||||
|
use self::crossterm::{ Context, Terminal };
|
||||||
|
|
||||||
fn print_test_data()
|
fn print_test_data()
|
||||||
{
|
{
|
||||||
@ -17,8 +20,9 @@ fn print_test_data()
|
|||||||
/// Clear all lines in terminal | demonstration
|
/// Clear all lines in terminal | demonstration
|
||||||
pub fn clear_all_lines()
|
pub fn clear_all_lines()
|
||||||
{
|
{
|
||||||
|
let term = Terminal::new();
|
||||||
// Get terminal
|
// Get terminal
|
||||||
let mut terminal = terminal();
|
let mut terminal = terminal(&term);
|
||||||
|
|
||||||
print_test_data();
|
print_test_data();
|
||||||
|
|
||||||
@ -29,13 +33,15 @@ pub fn clear_all_lines()
|
|||||||
/// Clear all lines from cursor position X:4, Y:4 down | demonstration
|
/// Clear all lines from cursor position X:4, Y:4 down | demonstration
|
||||||
pub fn clear_from_cursor_down()
|
pub fn clear_from_cursor_down()
|
||||||
{
|
{
|
||||||
|
let term = Terminal::new();
|
||||||
|
|
||||||
// Get terminal
|
// Get terminal
|
||||||
let mut terminal = terminal();
|
let mut terminal = terminal(&term);
|
||||||
|
|
||||||
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().goto(4,8);
|
cursor::cursor(&term).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);
|
||||||
@ -44,13 +50,14 @@ pub fn clear_from_cursor_down()
|
|||||||
/// Clear all lines from cursor position X:4, Y:4 up | demonstration
|
/// Clear all lines from cursor position X:4, Y:4 up | demonstration
|
||||||
pub fn clear_from_cursor_up()
|
pub fn clear_from_cursor_up()
|
||||||
{
|
{
|
||||||
|
let term = Terminal::new();
|
||||||
// Get terminal
|
// Get terminal
|
||||||
let mut terminal = terminal();
|
let mut terminal = terminal(&term);
|
||||||
|
|
||||||
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().goto(4,4);
|
cursor::cursor(&term).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);
|
||||||
@ -59,13 +66,15 @@ pub fn clear_from_cursor_up()
|
|||||||
/// Clear all lines from cursor position X:4, Y:4 up | demonstration
|
/// Clear all lines from cursor position X:4, Y:4 up | demonstration
|
||||||
pub fn clear_current_line()
|
pub fn clear_current_line()
|
||||||
{
|
{
|
||||||
|
let term = Terminal::new();
|
||||||
|
|
||||||
// Get terminal
|
// Get terminal
|
||||||
let mut terminal = terminal();
|
let mut terminal = terminal(&term);
|
||||||
|
|
||||||
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().goto(4,4);
|
cursor::cursor(&term).goto(4,4);
|
||||||
|
|
||||||
// Clear current line cells.
|
// Clear current line cells.
|
||||||
terminal.clear(ClearType::CurrentLine);
|
terminal.clear(ClearType::CurrentLine);
|
||||||
@ -74,13 +83,15 @@ pub fn clear_current_line()
|
|||||||
/// Clear all lines from cursor position X:4, Y:7 up | demonstration
|
/// Clear all lines from cursor position X:4, Y:7 up | demonstration
|
||||||
pub fn clear_until_new_line()
|
pub fn clear_until_new_line()
|
||||||
{
|
{
|
||||||
|
let term = Terminal::new();
|
||||||
|
|
||||||
// Get terminal
|
// Get terminal
|
||||||
let mut terminal = terminal();
|
let mut terminal = terminal(&term);
|
||||||
|
|
||||||
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().goto(4,20);
|
cursor::cursor(&term).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);
|
||||||
@ -89,8 +100,10 @@ pub fn clear_until_new_line()
|
|||||||
/// Print the the current terminal size | demonstration.
|
/// Print the the current terminal size | demonstration.
|
||||||
pub fn print_terminal_size()
|
pub fn print_terminal_size()
|
||||||
{
|
{
|
||||||
|
let term = Terminal::new();
|
||||||
|
|
||||||
// Get terminal
|
// Get terminal
|
||||||
let mut terminal = terminal();
|
let mut terminal = terminal(&term);
|
||||||
// Get terminal size
|
// Get terminal size
|
||||||
let terminal_size = terminal.terminal_size();
|
let terminal_size = terminal.terminal_size();
|
||||||
// Print results
|
// Print results
|
||||||
@ -100,7 +113,9 @@ pub fn print_terminal_size()
|
|||||||
/// Set the terminal size to width 10, height: 10 | demonstration.
|
/// Set the terminal size to width 10, height: 10 | demonstration.
|
||||||
pub fn set_terminal_size()
|
pub fn set_terminal_size()
|
||||||
{
|
{
|
||||||
let mut terminal = terminal();
|
let term = Terminal::new();
|
||||||
|
|
||||||
|
let mut terminal = terminal(&term);
|
||||||
|
|
||||||
terminal.set_size(10,10);
|
terminal.set_size(10,10);
|
||||||
}
|
}
|
||||||
@ -108,9 +123,11 @@ pub fn set_terminal_size()
|
|||||||
/// Scroll down 10 lines | demonstration.
|
/// Scroll down 10 lines | demonstration.
|
||||||
pub fn scroll_down()
|
pub fn scroll_down()
|
||||||
{
|
{
|
||||||
|
let term = Terminal::new();
|
||||||
|
|
||||||
print_test_data();
|
print_test_data();
|
||||||
// Get terminal
|
// Get terminal
|
||||||
let mut terminal = terminal();
|
let mut terminal = terminal(&term);
|
||||||
// Scroll down 10 lines.
|
// Scroll down 10 lines.
|
||||||
terminal.scroll_down(10);
|
terminal.scroll_down(10);
|
||||||
}
|
}
|
||||||
@ -118,10 +135,12 @@ pub fn scroll_down()
|
|||||||
/// Scroll down 10 lines | demonstration.
|
/// Scroll down 10 lines | demonstration.
|
||||||
pub fn scroll_up()
|
pub fn scroll_up()
|
||||||
{
|
{
|
||||||
|
let term = Terminal::new();
|
||||||
|
|
||||||
print_test_data();
|
print_test_data();
|
||||||
|
|
||||||
// Get terminal
|
// Get terminal
|
||||||
let mut terminal = terminal();
|
let mut terminal = terminal(&term);
|
||||||
// Scroll up 10 lines.
|
// Scroll up 10 lines.
|
||||||
terminal.scroll_up(10);
|
terminal.scroll_up(10);
|
||||||
}
|
}
|
||||||
@ -129,8 +148,10 @@ pub fn scroll_up()
|
|||||||
/// Resize the terminal to X: 10, Y: 10 | demonstration.
|
/// Resize the terminal to X: 10, Y: 10 | demonstration.
|
||||||
pub fn resize_terminal()
|
pub fn resize_terminal()
|
||||||
{
|
{
|
||||||
|
let term = Terminal::new();
|
||||||
|
|
||||||
// Get terminal
|
// Get terminal
|
||||||
let mut terminal = terminal();
|
let mut terminal = terminal(&term);
|
||||||
// Get terminal size
|
// Get terminal size
|
||||||
terminal.set_size(10,10);
|
terminal.set_size(10,10);
|
||||||
}
|
}
|
||||||
|
@ -1,62 +1,80 @@
|
|||||||
//! This is an ANSI specific implementation for cursor related action.
|
//! This is an ANSI specific implementation for cursor related action.
|
||||||
//! This module is used for windows 10 terminals and unix terminals by default.
|
//! This module is used for windows 10 terminals and unix terminals by default.
|
||||||
|
|
||||||
use Construct;
|
use std::sync::Mutex;
|
||||||
|
use { Context, ScreenManager, Terminal };
|
||||||
use shared::functions;
|
use shared::functions;
|
||||||
use super::ITerminalCursor;
|
use super::ITerminalCursor;
|
||||||
|
|
||||||
use std::io::{ self, Write };
|
use std::io::{ self, Write };
|
||||||
|
|
||||||
/// This struct is an ansi implementation for cursor related actions.
|
|
||||||
pub struct AnsiCursor;
|
|
||||||
|
|
||||||
impl Construct for AnsiCursor {
|
/// This struct is an ansi implementation for cursor related actions.
|
||||||
fn new() -> Box<AnsiCursor> {
|
pub struct AnsiCursor
|
||||||
|
{ }
|
||||||
|
|
||||||
|
impl<'output> AnsiCursor {
|
||||||
|
pub fn new() -> Box<AnsiCursor> {
|
||||||
Box::from(AnsiCursor {})
|
Box::from(AnsiCursor {})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ITerminalCursor for AnsiCursor {
|
impl<'term> ITerminalCursor for AnsiCursor {
|
||||||
fn goto(&self, x: u16, y: u16) {
|
|
||||||
let mut some_writer = io::stdout();
|
fn goto(&self, x: u16, y: u16, terminal: &Terminal)
|
||||||
|
{
|
||||||
// ANSI codes are one-based. I want 0 based so we just need to increment and x,y.
|
// ANSI codes are one-based. I want 0 based so we just need to increment and x,y.
|
||||||
write!(&mut some_writer, csi!("{};{}H"), y + 1, x +1);
|
|
||||||
|
let mut screen = terminal.screen_manager.lock().unwrap();
|
||||||
|
{
|
||||||
|
screen.write_ansi(format!(csi!("{};{}H"), y + 1, x +1));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn pos(&self) -> (u16, u16) {
|
fn pos(&self, terminal: &Terminal) -> (u16, u16) {
|
||||||
functions::get_cursor_position()
|
functions::get_cursor_position(&terminal)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn move_up(&self, count: u16) {
|
fn move_up(&self, count: u16, terminal: &Terminal) {
|
||||||
|
let mut screen = terminal.screen_manager.lock().unwrap();
|
||||||
let mut some_writer = io::stdout();
|
{
|
||||||
write!(&mut some_writer, csi!("{}A"), count);
|
screen.write_ansi_str(csi!("{}A"));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn move_right(&self, count: u16) {
|
fn move_right(&self, count: u16, terminal: &Terminal) {
|
||||||
let mut some_writer = io::stdout();
|
let mut screen = terminal.screen_manager.lock().unwrap();
|
||||||
write!(&mut some_writer, csi!("{}C"), count);
|
{
|
||||||
|
screen.write_ansi_str(csi!("{}C"));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn move_down(&self, count: u16) {
|
fn move_down(&self, count: u16, terminal: &Terminal) {
|
||||||
let mut some_writer = io::stdout();
|
let mut screen = terminal.screen_manager.lock().unwrap();
|
||||||
write!(&mut some_writer, csi!("{}B"), count);
|
{
|
||||||
|
screen.write_ansi_str(csi!("{}B"));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn move_left(&self, count: u16) {
|
fn move_left(&self, count: u16, terminal: &Terminal) {
|
||||||
let mut some_writer = io::stdout();
|
let mut screen = terminal.screen_manager.lock().unwrap();
|
||||||
write!(&mut some_writer, csi!("{}D"), count);
|
{
|
||||||
|
screen.write_ansi_str(csi!("{}D"));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn save_position(&mut self)
|
fn save_position(&mut self, terminal: &Terminal)
|
||||||
{
|
{
|
||||||
let mut some_writer = io::stdout();
|
let mut screen = terminal.screen_manager.lock().unwrap();
|
||||||
write!(&mut some_writer, csi!("s"));
|
{
|
||||||
|
screen.write_ansi_str(csi!("s"));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn reset_position(&self)
|
fn reset_position(&self, terminal: &Terminal)
|
||||||
{
|
{
|
||||||
let mut some_writer = io::stdout();
|
let mut screen = terminal.screen_manager.lock().unwrap();
|
||||||
write!(&mut some_writer, csi!("u"));
|
{
|
||||||
|
screen.write_ansi_str(csi!("u"));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,27 +5,31 @@
|
|||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
use shared::functions;
|
use shared::functions;
|
||||||
use {Construct, Context};
|
use { Construct, Context, ScreenManager, Terminal };
|
||||||
|
|
||||||
use std::fmt::Display;
|
use std::fmt::Display;
|
||||||
use std::ops::Drop;
|
use std::ops::Drop;
|
||||||
|
|
||||||
|
use std;
|
||||||
|
use std::io::Write;
|
||||||
|
|
||||||
/// Struct that stores an specific platform implementation for cursor related actions.
|
/// Struct that stores an specific platform implementation for cursor related actions.
|
||||||
pub struct TerminalCursor {
|
pub struct TerminalCursor<'term> {
|
||||||
|
terminal: &'term Terminal,
|
||||||
terminal_cursor: Option<Box<ITerminalCursor>>,
|
terminal_cursor: Option<Box<ITerminalCursor>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TerminalCursor
|
impl <'term> TerminalCursor<'term>
|
||||||
{
|
{
|
||||||
/// 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() -> TerminalCursor {
|
pub fn new(terminal: &'term Terminal) -> TerminalCursor<'term> {
|
||||||
#[cfg(target_os = "windows")]
|
#[cfg(target_os = "windows")]
|
||||||
let cursor = functions::get_module::<Box<ITerminalCursor>>(WinApiCursor::new(), AnsiCursor::new());
|
let cursor = functions::get_module::<Box<ITerminalCursor>>(WinApiCursor::new(), AnsiCursor::new());
|
||||||
|
|
||||||
#[cfg(not(target_os = "windows"))]
|
#[cfg(not(target_os = "windows"))]
|
||||||
let cursor = Some(AnsiCursor::new() as Box<ITerminalCursor>);
|
let cursor = Some(AnsiCursor::new() as Box<ITerminalCursor>);
|
||||||
|
|
||||||
TerminalCursor { terminal_cursor: cursor }
|
TerminalCursor { terminal_cursor: cursor , terminal: terminal}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Goto some position (x,y) in the terminal.
|
/// Goto some position (x,y) in the terminal.
|
||||||
@ -41,9 +45,9 @@ impl TerminalCursor
|
|||||||
/// cursor::cursor().goto(10,10);
|
/// cursor::cursor().goto(10,10);
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
pub fn goto(&mut self, x: u16, y: u16) -> &mut TerminalCursor {
|
pub fn goto(&mut self, x: u16, y: u16) -> &mut TerminalCursor<'term> {
|
||||||
if let Some(ref terminal_cursor) = self.terminal_cursor {
|
if let Some(ref terminal_cursor) = self.terminal_cursor {
|
||||||
terminal_cursor.goto(x, y);
|
terminal_cursor.goto(x, y, &self.terminal);
|
||||||
}
|
}
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
@ -64,7 +68,7 @@ impl TerminalCursor
|
|||||||
/// ```
|
/// ```
|
||||||
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()
|
terminal_cursor.pos(&self.terminal)
|
||||||
} else {
|
} else {
|
||||||
(0, 0)
|
(0, 0)
|
||||||
}
|
}
|
||||||
@ -87,9 +91,9 @@ impl TerminalCursor
|
|||||||
/// cursor::cursor().move_up(2);
|
/// cursor::cursor().move_up(2);
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
pub fn move_up(&mut self, count: u16) -> &mut TerminalCursor {
|
pub fn move_up(&mut self, count: u16) -> &mut TerminalCursor<'term> {
|
||||||
if let Some(ref terminal_cursor) = self.terminal_cursor {
|
if let Some(ref terminal_cursor) = self.terminal_cursor {
|
||||||
terminal_cursor.move_up(count);
|
terminal_cursor.move_up(count, &self.terminal);
|
||||||
}
|
}
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
@ -112,9 +116,9 @@ impl TerminalCursor
|
|||||||
/// cursor::cursor().move_right(2);
|
/// cursor::cursor().move_right(2);
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
pub fn move_right(&mut self, count: u16) -> &mut TerminalCursor {
|
pub fn move_right(&mut self, count: u16) -> &mut TerminalCursor<'term> {
|
||||||
if let Some(ref terminal_cursor) = self.terminal_cursor {
|
if let Some(ref terminal_cursor) = self.terminal_cursor {
|
||||||
terminal_cursor.move_right(count);
|
terminal_cursor.move_right(count, &self.terminal);
|
||||||
}
|
}
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
@ -136,9 +140,9 @@ impl TerminalCursor
|
|||||||
/// cursor::cursor().move_down(2);
|
/// cursor::cursor().move_down(2);
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
pub fn move_down(&mut self, count: u16) -> &mut TerminalCursor {
|
pub fn move_down(&mut self, count: u16) -> &mut TerminalCursor<'term> {
|
||||||
if let Some(ref terminal_cursor) = self.terminal_cursor {
|
if let Some(ref terminal_cursor) = self.terminal_cursor {
|
||||||
terminal_cursor.move_down(count);
|
terminal_cursor.move_down(count, &self.terminal);
|
||||||
}
|
}
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
@ -160,9 +164,9 @@ impl TerminalCursor
|
|||||||
/// cursor::cursor().move_left(2);
|
/// cursor::cursor().move_left(2);
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
pub fn move_left(&mut self, count: u16) -> &mut TerminalCursor {
|
pub fn move_left(&mut self, count: u16) -> &mut TerminalCursor<'term> {
|
||||||
if let Some(ref terminal_cursor) = self.terminal_cursor {
|
if let Some(ref terminal_cursor) = self.terminal_cursor {
|
||||||
terminal_cursor.move_left(count);
|
terminal_cursor.move_left(count, &self.terminal);
|
||||||
}
|
}
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
@ -199,12 +203,13 @@ impl TerminalCursor
|
|||||||
/// .print("@");
|
/// .print("@");
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
pub fn print<D: Display>(&mut self, value: D) -> &mut TerminalCursor {
|
pub fn print<D: Display>(&mut self, value: D) -> &mut TerminalCursor<'term> {
|
||||||
print!("{}", value);
|
let mut screen = self.terminal.screen_manager.lock().unwrap();
|
||||||
use std;
|
{
|
||||||
use std::io::Write;
|
write!(screen.stdout(), "{}", value);
|
||||||
// rust is line buffered so we need to flush the buffer in order to print it at the current cursor position.
|
// rust is line buffered so we need to flush the buffer in order to print it at the current cursor position.
|
||||||
std::io::stdout().flush();
|
screen.stdout().flush();
|
||||||
|
}
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -226,7 +231,7 @@ impl TerminalCursor
|
|||||||
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();
|
terminal_cursor.save_position(&self.terminal);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -248,7 +253,7 @@ impl TerminalCursor
|
|||||||
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();
|
terminal_cursor.reset_position(&self.terminal);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -273,6 +278,6 @@ impl TerminalCursor
|
|||||||
/// cursor::cursor().goto(5,10);
|
/// cursor::cursor().goto(5,10);
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
pub fn cursor() -> Box<TerminalCursor> {
|
pub fn cursor<'term>(terminal: &'term Terminal) -> Box<TerminalCursor<'term>> {
|
||||||
Box::from(TerminalCursor::new())
|
Box::from(TerminalCursor::new(&terminal))
|
||||||
}
|
}
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
//! so that the cursor related actions can be preformed on both unix and windows systems.
|
//! so that the cursor related actions can be preformed on both unix and windows systems.
|
||||||
//!
|
//!
|
||||||
|
|
||||||
mod cursor;
|
pub mod cursor;
|
||||||
#[cfg(target_os = "windows")]
|
#[cfg(target_os = "windows")]
|
||||||
mod winapi_cursor;
|
mod winapi_cursor;
|
||||||
mod ansi_cursor;
|
mod ansi_cursor;
|
||||||
@ -17,8 +17,13 @@ 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, Terminal };
|
||||||
pub use self::cursor::{ cursor, TerminalCursor };
|
pub use self::cursor::{ cursor, TerminalCursor };
|
||||||
|
|
||||||
|
use std::sync::Mutex;
|
||||||
|
|
||||||
|
use ScreenManager;
|
||||||
|
|
||||||
///! 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.
|
||||||
@ -29,19 +34,19 @@ 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 terminal.
|
/// Goto some location (x,y) in the terminal.
|
||||||
fn goto(&self, x: u16, y: u16);
|
fn goto(&self, x: u16, y: u16, terminal: &Terminal);
|
||||||
/// Get the location (x,y) of the current curor in the terminal
|
/// Get the location (x,y) of the current cusror in the terminal
|
||||||
fn pos(&self) -> (u16, u16);
|
fn pos(&self, terminal: &Terminal) -> (u16, u16);
|
||||||
/// Move cursor n times up
|
/// Move cursor n times up
|
||||||
fn move_up(&self, count: u16);
|
fn move_up(&self, count: u16, terminal: &Terminal);
|
||||||
/// Move the cursor `n` times to the right.
|
/// Move the cursor `n` times to the right.
|
||||||
fn move_right(&self, count: u16);
|
fn move_right(&self, count: u16, terminal: &Terminal);
|
||||||
/// Move the cursor `n` times down.
|
/// Move the cursor `n` times down.
|
||||||
fn move_down(&self, count: u16);
|
fn move_down(&self, count: u16, terminal: &Terminal);
|
||||||
/// Move the cursor `n` times left.
|
/// Move the cursor `n` times left.
|
||||||
fn move_left(&self, count: u16);
|
fn move_left(&self, count: u16, terminal: &Terminal);
|
||||||
/// Save cursor position for recall later. Note that this position is stored program based not per instance of the cursor struct.
|
/// Save cursor position for recall later. Note that this position is stored program based not per instance of the cursor struct.
|
||||||
fn save_position(&mut self);
|
fn save_position(&mut self, terminal: &Terminal);
|
||||||
/// Return to saved cursor position
|
/// Return to saved cursor position
|
||||||
fn reset_position(&self);
|
fn reset_position(&self, terminal: &Terminal);
|
||||||
}
|
}
|
@ -1,7 +1,7 @@
|
|||||||
//! 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.
|
||||||
|
|
||||||
use Construct;
|
use {Terminal, Construct};
|
||||||
use super::ITerminalCursor;
|
use super::ITerminalCursor;
|
||||||
use kernel::windows_kernel::{kernel, cursor};
|
use kernel::windows_kernel::{kernel, cursor};
|
||||||
|
|
||||||
@ -16,43 +16,43 @@ impl Construct for WinApiCursor {
|
|||||||
|
|
||||||
impl ITerminalCursor for WinApiCursor {
|
impl ITerminalCursor for WinApiCursor {
|
||||||
|
|
||||||
fn goto(&self, x: u16, y: u16) {
|
fn goto(&self, x: u16, y: u16, terminal: &Terminal) {
|
||||||
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) -> (u16, u16) {
|
fn pos(&self, terminal: &Terminal) -> (u16, u16) {
|
||||||
cursor::pos()
|
cursor::pos()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn move_up(&self, count: u16) {
|
fn move_up(&self, count: u16, terminal: &Terminal) {
|
||||||
let (xpos,ypos) = self.pos();
|
let (xpos,ypos) = self.pos();
|
||||||
self.goto(xpos, ypos - count);
|
self.goto(xpos, ypos - count);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn move_right(&self, count: u16) {
|
fn move_right(&self, count: u16, terminal: &Terminal) {
|
||||||
let (xpos,ypos) = self.pos();
|
let (xpos,ypos) = self.pos();
|
||||||
|
|
||||||
self.goto(xpos + count, ypos);
|
self.goto(xpos + count, ypos);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn move_down(&self, count: u16) {
|
fn move_down(&self, count: u16, terminal: &Terminal) {
|
||||||
let (xpos,ypos) = self.pos();
|
let (xpos,ypos) = self.pos();
|
||||||
|
|
||||||
self.goto(xpos, ypos + count);
|
self.goto(xpos, ypos + count);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn move_left(&self, count: u16) {
|
fn move_left(&self, count: u16, terminal: &Terminal) {
|
||||||
let (xpos,ypos) = self.pos();
|
let (xpos,ypos) = self.pos();
|
||||||
|
|
||||||
self.goto(xpos - count, ypos);
|
self.goto(xpos - count, ypos);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn save_position(&mut self)
|
fn save_position(&mut self, terminal: &Terminal)
|
||||||
{
|
{
|
||||||
cursor::save_cursor_pos();
|
cursor::save_cursor_pos();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn reset_position(&self)
|
fn reset_position(&self, terminal: &Terminal)
|
||||||
{
|
{
|
||||||
cursor::reset_to_saved_position();
|
cursor::reset_to_saved_position();
|
||||||
}
|
}
|
||||||
|
@ -4,3 +4,4 @@
|
|||||||
pub mod unix_kernel;
|
pub mod unix_kernel;
|
||||||
#[cfg(windows)]
|
#[cfg(windows)]
|
||||||
pub mod windows_kernel;
|
pub mod windows_kernel;
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
//! This module contains all `unix` specific terminal related logic.
|
//! This module contains all `unix` specific terminal related logic.
|
||||||
|
|
||||||
use { libc, Context };
|
use { libc, Context, Terminal };
|
||||||
use termios::Termios;
|
use termios::Termios;
|
||||||
pub use self::libc::{termios};
|
pub use self::libc::{termios};
|
||||||
use self::libc::{STDOUT_FILENO, TIOCGWINSZ, c_ushort, ioctl, c_int};
|
use self::libc::{STDOUT_FILENO, TIOCGWINSZ, c_ushort, ioctl, c_int};
|
||||||
@ -40,7 +40,7 @@ pub fn terminal_size() -> (u16,u16) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Get the current cursor position.
|
/// Get the current cursor position.
|
||||||
pub fn pos() -> (u16,u16)
|
pub fn pos(terminal: &Terminal) -> (u16,u16)
|
||||||
{
|
{
|
||||||
use std::io::Error;
|
use std::io::Error;
|
||||||
use std::io::{ Write,Read };
|
use std::io::{ Write,Read };
|
||||||
@ -48,14 +48,15 @@ pub fn pos() -> (u16,u16)
|
|||||||
let mut context = Context::new();
|
let mut context = Context::new();
|
||||||
{
|
{
|
||||||
let mut command = NoncanonicalModeCommand::new(&mut context);
|
let mut command = NoncanonicalModeCommand::new(&mut context);
|
||||||
command.0.execute();
|
command.0.execute(&terminal);
|
||||||
|
|
||||||
// This code is original written by term_cursor credits to them.
|
// This code is original written by term_cursor credits to them.
|
||||||
let mut stdout = io::stdout();
|
|
||||||
|
|
||||||
|
use std::io;
|
||||||
|
let mut std = io::stdout();
|
||||||
// Write command
|
// Write command
|
||||||
stdout.write(b"\x1B[6n");
|
std.write(b"\x1B[6n");
|
||||||
stdout.flush();
|
std.flush();
|
||||||
|
|
||||||
// Read back result
|
// Read back result
|
||||||
let mut buf = [0u8; 2];
|
let mut buf = [0u8; 2];
|
||||||
|
78
src/kernel/windows_kernel/handle.rs
Normal file
78
src/kernel/windows_kernel/handle.rs
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
use winapi::um::winnt::HANDLE;
|
||||||
|
use std::mem::zeroed;
|
||||||
|
use winapi::um::processenv::{GetStdHandle};
|
||||||
|
use winapi::um::winbase::{STD_OUTPUT_HANDLE, STD_INPUT_HANDLE };
|
||||||
|
|
||||||
|
static mut ALTERNATEHANDLE: Option<HANDLE> = None;
|
||||||
|
static mut CONSOLE_OUTPUT_HANDLE: Option<HANDLE> = None;
|
||||||
|
static mut CONSOLE_INPUT_HANDLE: Option<HANDLE> = None;
|
||||||
|
|
||||||
|
|
||||||
|
pub fn register_new_alternate_handle(handle: Handle) -> HANDLE
|
||||||
|
{
|
||||||
|
unsafe
|
||||||
|
{
|
||||||
|
ALTERNATEHANDLE = handle;
|
||||||
|
}
|
||||||
|
|
||||||
|
ALTERNATEHANDLE.unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn clear_alternate_screen()
|
||||||
|
{
|
||||||
|
unsafe
|
||||||
|
{
|
||||||
|
ALTERNATEHANDLE = None;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get the std_output_handle of the console
|
||||||
|
pub fn get_output_handle() -> HANDLE {
|
||||||
|
unsafe {
|
||||||
|
if let Some(alternate_handle) = ALTERNATEHANDLE
|
||||||
|
{
|
||||||
|
alternate_handle
|
||||||
|
}
|
||||||
|
else if let Some(handle) = CONSOLE_OUTPUT_HANDLE {
|
||||||
|
handle
|
||||||
|
} else {
|
||||||
|
let handle = GetStdHandle(STD_OUTPUT_HANDLE);
|
||||||
|
|
||||||
|
if !is_valid_handle(&handle)
|
||||||
|
{
|
||||||
|
panic!("Cannot get output handle")
|
||||||
|
}
|
||||||
|
|
||||||
|
CONSOLE_OUTPUT_HANDLE = Some(handle);
|
||||||
|
handle
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get the std_input_handle of the console
|
||||||
|
pub fn get_input_handle() -> HANDLE {
|
||||||
|
unsafe {
|
||||||
|
if let Some(handle) = CONSOLE_INPUT_HANDLE {
|
||||||
|
handle
|
||||||
|
} else {
|
||||||
|
let handle = GetStdHandle(STD_INPUT_HANDLE);
|
||||||
|
|
||||||
|
if !is_valid_handle(&handle)
|
||||||
|
{
|
||||||
|
panic!("Cannot get input handle")
|
||||||
|
}
|
||||||
|
|
||||||
|
CONSOLE_INPUT_HANDLE = Some(handle);
|
||||||
|
handle
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Checks if the console handle is an invalid handle value.
|
||||||
|
pub fn is_valid_handle(handle: &HANDLE) -> bool {
|
||||||
|
if *handle == INVALID_HANDLE_VALUE {
|
||||||
|
false
|
||||||
|
} else {
|
||||||
|
true
|
||||||
|
}
|
||||||
|
}
|
@ -11,9 +11,12 @@ mod state;
|
|||||||
pub mod cursor;
|
pub mod cursor;
|
||||||
pub mod style;
|
pub mod style;
|
||||||
pub mod terminal;
|
pub mod terminal;
|
||||||
|
pub mod manager;
|
||||||
|
|
||||||
use shared::traits::{Construct};
|
use shared::traits::{Construct};
|
||||||
pub use state::{ Context};
|
pub use state::{ Context };
|
||||||
|
pub use manager::manager::{ ScreenManager };
|
||||||
|
pub use manager::terminal::{ Terminal };
|
||||||
|
|
||||||
#[cfg(windows)]
|
#[cfg(windows)]
|
||||||
extern crate winapi;
|
extern crate winapi;
|
||||||
|
63
src/manager/ansi_manager.rs
Normal file
63
src/manager/ansi_manager.rs
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
use std::io::{self, Write};
|
||||||
|
use { Context, Terminal };
|
||||||
|
use super::IScreenManager;
|
||||||
|
use super::super::state::commands::ICommand;
|
||||||
|
use super::super::state::commands::shared_commands::ToAlternateScreenBufferCommand;
|
||||||
|
|
||||||
|
pub struct AnsiScreenManager<Output:Write>
|
||||||
|
{
|
||||||
|
is_alternate_screen: bool,
|
||||||
|
output: Output,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<Output :Write> IScreenManager<Output> for AnsiScreenManager<Output>
|
||||||
|
{
|
||||||
|
fn stdout(&mut self) -> &mut Output
|
||||||
|
{
|
||||||
|
return &mut self.output
|
||||||
|
}
|
||||||
|
|
||||||
|
fn register_output(&mut self, output: Output, is_alternate_screen: bool)
|
||||||
|
{
|
||||||
|
self.output = output;
|
||||||
|
self.is_alternate_screen = is_alternate_screen;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn write_ansi(&mut self, string: String)
|
||||||
|
{
|
||||||
|
match self.is_alternate_screen
|
||||||
|
{
|
||||||
|
true => write!(self.output, "{}", string),
|
||||||
|
false => write!(io::stdout(), "{}", string),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
fn write_ansi_str(&mut self, string: &str)
|
||||||
|
{
|
||||||
|
match self.is_alternate_screen
|
||||||
|
{
|
||||||
|
true => write!(self.output, "{}", string),
|
||||||
|
false => write!(io::stdout(), "{}", string),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl AnsiScreenManager<Box<Write>> {
|
||||||
|
pub fn new() -> Self {
|
||||||
|
AnsiScreenManager {
|
||||||
|
output: (Box::from(io::stdout()) as Box<Write>),
|
||||||
|
is_alternate_screen: false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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()
|
||||||
|
}
|
||||||
|
}
|
45
src/manager/manager.rs
Normal file
45
src/manager/manager.rs
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
use std::io::Write;
|
||||||
|
|
||||||
|
use { Context, Terminal };
|
||||||
|
use super::IScreenManager;
|
||||||
|
use super::ansi_manager::AnsiScreenManager;
|
||||||
|
|
||||||
|
pub struct ScreenManager
|
||||||
|
{
|
||||||
|
screen_manager: Box<IScreenManager<Box<Write>>>
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ScreenManager
|
||||||
|
{
|
||||||
|
pub fn new() -> ScreenManager {
|
||||||
|
// #[cfg(target_os = "windows")]
|
||||||
|
// let cursor = functions::get_module::<Box<ITerminalCursor>>(WinApiCursor::new(), AnsiCursor::new());
|
||||||
|
//
|
||||||
|
// #[cfg(not(target_os = "windows"))]
|
||||||
|
|
||||||
|
ScreenManager
|
||||||
|
{
|
||||||
|
screen_manager: Box::new(AnsiScreenManager::new()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn stdout(&mut self) -> &mut Box<Write>
|
||||||
|
{
|
||||||
|
self.screen_manager.stdout()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn register_output(&mut self, output: Box<Write>, is_alternate_screen: bool)
|
||||||
|
{
|
||||||
|
self.screen_manager.register_output(output,is_alternate_screen);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn write_ansi(&mut self, string: String)
|
||||||
|
{
|
||||||
|
self.screen_manager.write_ansi(string);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn write_ansi_str(&mut self, string: &str)
|
||||||
|
{
|
||||||
|
self.screen_manager.write_ansi_str(string);
|
||||||
|
}
|
||||||
|
}
|
21
src/manager/mod.rs
Normal file
21
src/manager/mod.rs
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
pub mod manager;
|
||||||
|
pub mod terminal;
|
||||||
|
|
||||||
|
#[cfg(target_os = "windows")]
|
||||||
|
mod win_manager;
|
||||||
|
mod ansi_manager;
|
||||||
|
|
||||||
|
#[cfg(target_os = "windows")]
|
||||||
|
use self::win_manager::WinApiScreenManager;
|
||||||
|
use self::ansi_manager::AnsiScreenManager;
|
||||||
|
|
||||||
|
use { Context, Terminal };
|
||||||
|
pub use self::manager::{ ScreenManager };
|
||||||
|
|
||||||
|
pub trait IScreenManager<Output>
|
||||||
|
{
|
||||||
|
fn stdout(&mut self) -> &mut Output;
|
||||||
|
fn register_output(&mut self, output: Output, is_alternate_screen: bool);
|
||||||
|
fn write_ansi(&mut self, string: String);
|
||||||
|
fn write_ansi_str(&mut self, string: &str);
|
||||||
|
}
|
86
src/manager/terminal.rs
Normal file
86
src/manager/terminal.rs
Normal file
@ -0,0 +1,86 @@
|
|||||||
|
use std::io::Write;
|
||||||
|
use std::io;
|
||||||
|
use std::sync::Mutex;
|
||||||
|
use std::cell::RefCell;
|
||||||
|
use std::rc::Rc;
|
||||||
|
|
||||||
|
use { Context };
|
||||||
|
use super::super::manager::ScreenManager;
|
||||||
|
|
||||||
|
use super::super::terminal;
|
||||||
|
use super::super::cursor;
|
||||||
|
use super::super::style;
|
||||||
|
|
||||||
|
use std::fmt;
|
||||||
|
|
||||||
|
pub struct Terminal
|
||||||
|
{
|
||||||
|
pub screen_manager: Rc<Mutex<ScreenManager>>,
|
||||||
|
context: Context
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Terminal
|
||||||
|
{
|
||||||
|
pub fn new() -> Terminal
|
||||||
|
{
|
||||||
|
Terminal {
|
||||||
|
screen_manager: Rc::new(Mutex::new(ScreenManager::new())),
|
||||||
|
context: Context::new()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get an TerminalColor implementation whereon color related actions can be performed.
|
||||||
|
///
|
||||||
|
/// # Example
|
||||||
|
///
|
||||||
|
/// ```rust
|
||||||
|
/// extern crate crossterm;
|
||||||
|
///
|
||||||
|
/// use self::crossterm::style::{color, Color};
|
||||||
|
///
|
||||||
|
/// // Get colored terminal instance
|
||||||
|
/// let mut colored_terminal = color();
|
||||||
|
///
|
||||||
|
/// // preform some actions on the colored terminal
|
||||||
|
/// colored_terminal.set_fg(Color::Red);
|
||||||
|
/// colored_terminal.set_bg(Color::Blue);
|
||||||
|
/// colored_terminal.reset();
|
||||||
|
/// ```
|
||||||
|
pub fn color(&self) -> Box<style::TerminalColor> {
|
||||||
|
Box::from(style::TerminalColor::new(self.screen_manager.clone()))
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Wraps an displayable object so it can be formatted with colors and attributes.
|
||||||
|
///
|
||||||
|
/// Check `/examples/color` in the libary for more spesific examples.
|
||||||
|
///
|
||||||
|
/// #Example
|
||||||
|
///
|
||||||
|
/// ```rust
|
||||||
|
/// extern crate crossterm;
|
||||||
|
///
|
||||||
|
/// use self::crossterm::style::{paint,Color};
|
||||||
|
///
|
||||||
|
/// fn main()
|
||||||
|
/// {
|
||||||
|
/// // Create an styledobject object from the text 'Unstyled font'
|
||||||
|
/// // Currently it has the default foregroundcolor and backgroundcolor.
|
||||||
|
/// println!("{}",paint("Unstyled font"));
|
||||||
|
///
|
||||||
|
/// // Create an displayable object from the text 'Colored font',
|
||||||
|
/// // Paint this with the `Red` foreground color and `Blue` backgroundcolor.
|
||||||
|
/// // Print the result.
|
||||||
|
/// let styledobject = paint("Colored font").with(Color::Red).on(Color::Blue);
|
||||||
|
/// println!("{}", styledobject);
|
||||||
|
///
|
||||||
|
/// // Or all in one line
|
||||||
|
/// println!("{}", paint("Colored font").with(Color::Red).on(Color::Blue));
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
|
pub fn paint<D>(&self, val: D) -> style::StyledObject<D>
|
||||||
|
where
|
||||||
|
D: fmt::Display,
|
||||||
|
{
|
||||||
|
style::ObjectStyle::new().apply_to(val, self.screen_manager.clone())
|
||||||
|
}
|
||||||
|
}
|
4
src/manager/win_manager.rs
Normal file
4
src/manager/win_manager.rs
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
pub struct WinApiScreenManager
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
@ -1,9 +1,11 @@
|
|||||||
//! 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 std::sync::Mutex;
|
||||||
|
use {Context, ScreenManager, Terminal};
|
||||||
|
|
||||||
#[cfg(windows)]
|
#[cfg(windows)]
|
||||||
use kernel::windows_kernel::terminal::terminal_size;
|
use kernel::windows_kernel::terminal::terminal_size;
|
||||||
|
|
||||||
#[cfg(unix)]
|
#[cfg(unix)]
|
||||||
use kernel::unix_kernel::terminal::terminal_size;
|
use kernel::unix_kernel::terminal::terminal_size;
|
||||||
|
|
||||||
@ -19,9 +21,13 @@ 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() -> (u16,u16)
|
pub fn get_cursor_position(screen: &Terminal) -> (u16,u16)
|
||||||
{
|
{
|
||||||
pos()
|
#[cfg(unix)]
|
||||||
|
return pos(&screen);
|
||||||
|
|
||||||
|
#[cfg(windows)]
|
||||||
|
return pos();
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(windows)]
|
#[cfg(windows)]
|
||||||
@ -38,7 +44,6 @@ pub fn get_module<T>(winapi_impl: T, unix_impl: T) -> Option<T>
|
|||||||
// 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();
|
does_support = try_enable_ansi_support();
|
||||||
|
|
||||||
// println!("does support = {}", does_support);
|
|
||||||
if !does_support
|
if !does_support
|
||||||
{
|
{
|
||||||
term = Some(winapi_impl);
|
term = Some(winapi_impl);
|
||||||
|
@ -1,11 +1,11 @@
|
|||||||
|
|
||||||
/// This trait is used for creating an instance of an concrete implementation from an base trait.
|
/// This trait is used for creating an instance of an concrete implementation from an base trait.
|
||||||
/// This trait allows the output to be different in size.
|
/// This trait allows the output to be different in size.
|
||||||
pub trait Construct {
|
pub trait Construct{
|
||||||
fn new() -> Box<Self>
|
fn new() -> Box<Self>
|
||||||
where
|
where
|
||||||
Self: Sized;
|
Self: Sized;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// This trait can be used to create an empty instance of an struct.
|
/// This trait can be used to create an empty instance of an struct.
|
||||||
pub trait Empty {
|
pub trait Empty {
|
||||||
fn empty() -> Self;
|
fn empty() -> Self;
|
||||||
|
@ -24,23 +24,24 @@ pub use self::unix_command::*;
|
|||||||
#[cfg(windows)]
|
#[cfg(windows)]
|
||||||
pub use self::win_commands::*;
|
pub use self::win_commands::*;
|
||||||
|
|
||||||
use super::Context;
|
use { Context, Terminal };
|
||||||
|
|
||||||
/// This command can be used for simple commands witch just have an `undo()` and an `execute()`
|
/// This command can be used for simple commands witch just have an `undo()` and an `execute()`
|
||||||
pub trait ICommand
|
pub trait ICommand
|
||||||
{
|
{
|
||||||
fn new() -> Box<Self> where Self: Sized;
|
fn new() -> Box<Self> where Self: Sized;
|
||||||
fn execute(&mut self) -> bool;
|
fn execute(&mut self, terminal: &Terminal) -> bool;
|
||||||
fn undo(&mut self) -> bool;
|
fn undo(&mut self, terminal: &Terminal) -> bool;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// This command is used for complex commands whits change the terminal state.
|
/// This command is used for complex commands whits change the terminal state.
|
||||||
/// By passing an `Context` instance this command will register it self to notify the terminal state change.
|
/// By passing an `Context` instance this command will register it self to notify the terminal state change.
|
||||||
|
|
||||||
pub trait IContextCommand
|
pub trait IContextCommand
|
||||||
{
|
{
|
||||||
fn new(context: &mut Context) -> (Box<Self>, i16) where Self: Sized;
|
fn new(context: &mut Context) -> (Box<Self>, i16) where Self: Sized;
|
||||||
fn execute(&mut self) -> bool;
|
fn execute(&mut self, terminal: &Terminal) -> bool;
|
||||||
fn undo(&mut self) -> bool;
|
fn undo(&mut self, terminal: &Terminal) -> bool;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// This generates an random key for the `ContextCommand`.
|
/// This generates an random key for the `ContextCommand`.
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
//! This module contains the commands that can be used for both unix and windows systems.
|
//! This module contains the commands that can be used for both unix and windows systems.
|
||||||
|
use { Context, Terminal };
|
||||||
use super::ICommand;
|
use super::{ ICommand, IContextCommand };
|
||||||
use std::io;
|
use std::io;
|
||||||
use std::io::Write;
|
use std::io::Write;
|
||||||
|
|
||||||
@ -11,26 +11,24 @@ pub struct ToAlternateScreenBufferCommand;
|
|||||||
impl ICommand for ToAlternateScreenBufferCommand
|
impl ICommand for ToAlternateScreenBufferCommand
|
||||||
{
|
{
|
||||||
fn new() -> Box<ToAlternateScreenBufferCommand> {
|
fn new() -> Box<ToAlternateScreenBufferCommand> {
|
||||||
Box::from(ToAlternateScreenBufferCommand { })
|
Box::from(ToAlternateScreenBufferCommand {})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn execute(&mut self) -> bool
|
fn execute(&mut self, terminal: &Terminal) -> bool
|
||||||
{
|
{
|
||||||
let mut some_writer = io::stdout();
|
let mut screen = terminal.screen_manager.lock().unwrap();
|
||||||
match write!(some_writer, csi!("?1049h"))
|
|
||||||
{
|
{
|
||||||
Ok(_) => true,
|
screen.write_ansi_str(csi!("?1049h"));
|
||||||
Err(_) => false
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn undo(&mut self) -> bool
|
fn undo(&mut self, terminal: &Terminal) -> bool
|
||||||
{
|
{
|
||||||
let mut some_writer = io::stdout();
|
let mut screen = terminal.screen_manager.lock().unwrap();
|
||||||
match write!(some_writer, csi!("?1049l"))
|
|
||||||
{
|
{
|
||||||
Ok(_) => true,
|
screen.write_ansi_str(csi!("?1049l"));
|
||||||
Err(_) => false
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,6 +1,6 @@
|
|||||||
//! This module contains the commands that can be used for unix systems.
|
//! This module contains the commands that can be used for unix systems.
|
||||||
|
|
||||||
use Context;
|
use {Terminal, Context};
|
||||||
use super::IContextCommand;
|
use super::IContextCommand;
|
||||||
use kernel::unix_kernel::terminal;
|
use kernel::unix_kernel::terminal;
|
||||||
use termios::{Termios, tcsetattr, TCSAFLUSH, ICANON, ECHO, CREAD};
|
use termios::{Termios, tcsetattr, TCSAFLUSH, ICANON, ECHO, CREAD};
|
||||||
@ -23,7 +23,7 @@ impl IContextCommand for NoncanonicalModeCommand
|
|||||||
(Box::from(command),key)
|
(Box::from(command),key)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn execute(&mut self) -> bool
|
fn execute(&mut self, terminal: &Terminal) -> 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)
|
||||||
@ -42,7 +42,7 @@ impl IContextCommand for NoncanonicalModeCommand
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn undo(&mut self) -> bool
|
fn undo(&mut self, terminal: &Terminal) -> 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)
|
||||||
@ -80,7 +80,7 @@ impl IContextCommand for EnableRawModeCommand
|
|||||||
(Box::from(command),key)
|
(Box::from(command),key)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn execute(&mut self) -> bool
|
fn execute(&mut self, terminal: &Terminal) -> bool
|
||||||
{
|
{
|
||||||
if let Ok(original_mode) = terminal::get_terminal_mode()
|
if let Ok(original_mode) = terminal::get_terminal_mode()
|
||||||
{
|
{
|
||||||
@ -95,7 +95,7 @@ impl IContextCommand for EnableRawModeCommand
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn undo(&mut self) -> bool
|
fn undo(&mut self, terminal: &Terminal) -> bool
|
||||||
{
|
{
|
||||||
if let Ok(original_mode) = terminal::get_terminal_mode()
|
if let Ok(original_mode) = terminal::get_terminal_mode()
|
||||||
{
|
{
|
||||||
|
@ -97,7 +97,7 @@ impl IContextCommand for EnableRawModeCommand
|
|||||||
(Box::from(command),key)
|
(Box::from(command),key)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn execute(&mut self) -> bool
|
fn execute(&mut self, terminal: &Terminal) -> bool
|
||||||
{
|
{
|
||||||
use self::wincon::{ENABLE_LINE_INPUT,ENABLE_PROCESSED_INPUT, ENABLE_ECHO_INPUT};
|
use self::wincon::{ENABLE_LINE_INPUT,ENABLE_PROCESSED_INPUT, ENABLE_ECHO_INPUT};
|
||||||
|
|
||||||
@ -119,7 +119,7 @@ impl IContextCommand for EnableRawModeCommand
|
|||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
fn undo(&mut self) -> bool
|
fn undo(&mut self, terminal: &Terminal) -> bool
|
||||||
{
|
{
|
||||||
let output_handle = kernel::get_output_handle();
|
let output_handle = kernel::get_output_handle();
|
||||||
|
|
||||||
@ -152,7 +152,7 @@ impl ICommand for ToAlternateScreenBufferCommand
|
|||||||
Box::from(ToAlternateScreenBufferCommand {})
|
Box::from(ToAlternateScreenBufferCommand {})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn execute(&mut self) -> bool
|
fn execute(&mut self, context: &Context) -> bool
|
||||||
{
|
{
|
||||||
let mut chi_buffer: [CHAR_INFO;160] = unsafe {mem::zeroed() };
|
let mut chi_buffer: [CHAR_INFO;160] = unsafe {mem::zeroed() };
|
||||||
|
|
||||||
@ -206,7 +206,7 @@ impl ICommand for ToAlternateScreenBufferCommand
|
|||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
fn undo(&mut self) -> bool
|
fn undo(&mut self, context: &Context) -> 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);
|
||||||
|
@ -2,12 +2,16 @@
|
|||||||
|
|
||||||
use std::ops::Drop;
|
use std::ops::Drop;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use super::commands::IContextCommand;
|
use std::io::Write;
|
||||||
|
use std::sync::Mutex;
|
||||||
|
|
||||||
|
use super::commands::{ ICommand, IContextCommand};
|
||||||
|
use super::super::manager::ScreenManager;
|
||||||
|
|
||||||
/// Struct that stores the changed states of the terminal.
|
/// Struct that stores the changed states of the terminal.
|
||||||
pub struct Context
|
pub struct Context
|
||||||
{
|
{
|
||||||
changed_states: HashMap<i16, (Box<IContextCommand>) >,
|
changed_states: HashMap<i16, Box<IContextCommand>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Context
|
impl Context
|
||||||
@ -15,17 +19,27 @@ impl Context
|
|||||||
/// Create new Context where the terminals states can be handled.
|
/// Create new Context where the terminals states can be handled.
|
||||||
pub fn new() -> Context
|
pub fn new() -> Context
|
||||||
{
|
{
|
||||||
println!("Context has been created");
|
Context {
|
||||||
Context { changed_states: HashMap::new() }
|
changed_states: HashMap::new(),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Restore all changes that are made to the terminal.
|
/// Restore all changes that are made to the terminal.
|
||||||
pub fn restore_changes(&mut self)
|
pub fn restore_changes(&mut self)
|
||||||
{
|
{
|
||||||
for (x, state) in self.changed_states.iter_mut()
|
// use std::iter::FromIterator;
|
||||||
{
|
//
|
||||||
state.undo();
|
// let mut buffer = Vec::new();
|
||||||
}
|
//
|
||||||
|
// for i in 0..self.changed_states.len()
|
||||||
|
// {
|
||||||
|
// buffer[i] = self.changed_states.iter().nth(i).unwrap();
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// for i in 0..buffer.len()
|
||||||
|
// {
|
||||||
|
// buffer[i].1.undo(self);
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Register new changed state with the given key.
|
/// Register new changed state with the given key.
|
||||||
|
@ -1,11 +1,13 @@
|
|||||||
//! This is an ANSI specific implementation for styling related action.
|
//! This is an ANSI specific implementation for styling related action.
|
||||||
//! This module is used for windows 10 terminals and unix terminals by default.
|
//! This module is used for windows 10 terminals and unix terminals by default.
|
||||||
|
|
||||||
use Construct;
|
use { Construct, Terminal, ScreenManager };
|
||||||
use super::ITerminalColor;
|
use super::ITerminalColor;
|
||||||
use super::super::{Color, ColorType};
|
use super::super::{Color, ColorType};
|
||||||
|
|
||||||
use std::io::{self, Write};
|
use std::io::{self, Write};
|
||||||
|
use std::rc::Rc;
|
||||||
|
use std::sync::Mutex;
|
||||||
|
|
||||||
/// This struct is an ansi implementation for color related actions.
|
/// This struct is an ansi implementation for color related actions.
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
@ -18,19 +20,26 @@ impl Construct for AnsiColor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl ITerminalColor for AnsiColor {
|
impl ITerminalColor for AnsiColor {
|
||||||
fn set_fg(&self, fg_color: Color) {
|
fn set_fg(&self, fg_color: Color, screen_manager: Rc<Mutex<ScreenManager>>) {
|
||||||
let mut some_writer = io::stdout();
|
|
||||||
write!(&mut some_writer, csi!("{}m"), self.color_value(fg_color, ColorType::Foreground));
|
let mut screen = screen_manager.lock().unwrap();
|
||||||
|
{
|
||||||
|
screen.write_ansi(format!(csi!("{}m"),self.color_value(fg_color, ColorType::Foreground)));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_bg(&self, bg_color: Color) {
|
fn set_bg(&self, bg_color: Color, screen_manager: Rc<Mutex<ScreenManager>>) {
|
||||||
let mut some_writer = io::stdout();
|
let mut screen = screen_manager.lock().unwrap();
|
||||||
write!(&mut some_writer, csi!("{}m"), self.color_value(bg_color, ColorType::Background));
|
{
|
||||||
|
screen.write_ansi(format!(csi!("{}m"),self.color_value(bg_color, ColorType::Background)));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn reset(&self) {
|
fn reset(&self, screen_manager: Rc<Mutex<ScreenManager>>) {
|
||||||
let mut some_writer = io::stdout();
|
let mut screen = screen_manager.lock().unwrap();
|
||||||
write!(&mut some_writer, csi!("0m"));
|
{
|
||||||
|
screen.write_ansi_str(csi!("0m"));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn color_value(&self, color: Color, color_type: ColorType) -> String {
|
fn color_value(&self, color: Color, color_type: ColorType) -> String {
|
||||||
|
@ -3,27 +3,30 @@
|
|||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
use shared::functions;
|
use shared::functions;
|
||||||
use { Construct, Context };
|
use { Construct, Context, Terminal };
|
||||||
use style::{Color, ObjectStyle, StyledObject};
|
use style::{Color, ObjectStyle, StyledObject};
|
||||||
|
|
||||||
use std::ops::Drop;
|
use std::ops::Drop;
|
||||||
use std::{ fmt, io };
|
use std::{ fmt, io };
|
||||||
|
use std::rc::Rc;
|
||||||
|
use std::sync::Mutex;
|
||||||
|
|
||||||
/// Struct that stores an specific platform implementation for color related actions.
|
/// Struct that stores an specific platform implementation for color related actions.
|
||||||
pub struct TerminalColor {
|
pub struct TerminalColor {
|
||||||
terminal_color: Option<Box<ITerminalColor>>,
|
color: Option<Box<ITerminalColor>>,
|
||||||
|
screen_manager: Rc<Mutex<ScreenManager>>
|
||||||
}
|
}
|
||||||
|
|
||||||
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() -> TerminalColor {
|
pub fn new(screen_manager: Rc<Mutex<ScreenManager>> ) -> TerminalColor {
|
||||||
#[cfg(target_os = "windows")]
|
#[cfg(target_os = "windows")]
|
||||||
let color = functions::get_module::<Box<ITerminalColor>>(WinApiColor::new(), AnsiColor::new());
|
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>);
|
||||||
|
|
||||||
TerminalColor { terminal_color: color }
|
TerminalColor { color: color, screen_manager: screen_manager.clone() }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Set the foreground color to the given color.
|
/// Set the foreground color to the given color.
|
||||||
@ -45,8 +48,8 @@ impl TerminalColor {
|
|||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
pub fn set_fg(&mut self, color: Color) {
|
pub fn set_fg(&mut self, color: Color) {
|
||||||
if let Some(ref terminal_color) = self.terminal_color {
|
if let Some(ref terminal_color) = self.color {
|
||||||
terminal_color.set_fg(color);
|
terminal_color.set_fg(color, self.screen_manager.clone());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -70,8 +73,8 @@ impl TerminalColor {
|
|||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
pub fn set_bg(&mut self, color: Color) {
|
pub fn set_bg(&mut self, color: Color) {
|
||||||
if let Some(ref terminal_color) = self.terminal_color {
|
if let Some(ref terminal_color) = self.color {
|
||||||
terminal_color.set_bg(color);
|
terminal_color.set_bg(color, self.screen_manager.clone());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -90,8 +93,8 @@ impl TerminalColor {
|
|||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
pub fn reset(&mut self) {
|
pub fn reset(&mut self) {
|
||||||
if let Some(ref terminal_color) = self.terminal_color {
|
if let Some(ref terminal_color) = self.color {
|
||||||
terminal_color.reset();
|
terminal_color.reset(self.screen_manager.clone());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -113,59 +116,6 @@ impl TerminalColor {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get an TerminalColor implementation whereon color related actions can be performed.
|
pub fn color(screen_manager: Rc<Mutex<ScreenManager>>) -> Box<TerminalColor> {
|
||||||
///
|
Box::from(TerminalColor::new(screen_manager.clone()))
|
||||||
/// # Example
|
|
||||||
///
|
|
||||||
/// ```rust
|
|
||||||
/// extern crate crossterm;
|
|
||||||
///
|
|
||||||
/// use self::crossterm::style::{color, Color};
|
|
||||||
///
|
|
||||||
/// // Get colored terminal instance
|
|
||||||
/// let mut colored_terminal = color();
|
|
||||||
///
|
|
||||||
/// // preform some actions on the colored terminal
|
|
||||||
/// colored_terminal.set_fg(Color::Red);
|
|
||||||
/// colored_terminal.set_bg(Color::Blue);
|
|
||||||
/// colored_terminal.reset();
|
|
||||||
/// ```
|
|
||||||
pub fn color() -> Box<TerminalColor> {
|
|
||||||
Box::from(TerminalColor::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>(val: D) -> StyledObject<D>
|
|
||||||
where
|
|
||||||
D: fmt::Display,
|
|
||||||
{
|
|
||||||
ObjectStyle::new().apply_to(val)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -9,6 +9,11 @@ use self::winapi_color::WinApiColor;
|
|||||||
use self::ansi_color::AnsiColor;
|
use self::ansi_color::AnsiColor;
|
||||||
use super::{Color, ColorType};
|
use super::{Color, ColorType};
|
||||||
|
|
||||||
|
use std::rc::Rc;
|
||||||
|
use std::sync::Mutex;
|
||||||
|
|
||||||
|
use { Terminal, ScreenManager };
|
||||||
|
|
||||||
///! This trait defines the actions that can be preformed with the terminal color.
|
///! This trait defines the actions that can be preformed with the terminal color.
|
||||||
///! This trait can be implemented so that an concrete implementation of the ITerminalColor can forfill
|
///! This trait can be implemented so that an concrete implementation of the ITerminalColor can forfill
|
||||||
///! the wishes to work on an specific platform.
|
///! the wishes to work on an specific platform.
|
||||||
@ -19,11 +24,11 @@ use super::{Color, ColorType};
|
|||||||
///! so that color related actions can be preformed on both unix and windows systems.
|
///! so that color related actions can be preformed on both unix and windows systems.
|
||||||
pub trait ITerminalColor {
|
pub trait ITerminalColor {
|
||||||
/// Set the foreground color to the given color.
|
/// Set the foreground color to the given color.
|
||||||
fn set_fg(&self, fg_color: Color);
|
fn set_fg(&self, fg_color: Color, screen_manager: Rc<Mutex<ScreenManager>>);
|
||||||
/// Set the background color to the given color.
|
/// Set the background color to the given color.
|
||||||
fn set_bg(&self, fg_color: Color);
|
fn set_bg(&self, fg_color: Color, screen_manager: Rc<Mutex<ScreenManager>>);
|
||||||
/// Reset the terminal color to default.
|
/// Reset the terminal color to default.
|
||||||
fn reset(&self);
|
fn reset(&self,screen_manager: Rc<Mutex<ScreenManager>>);
|
||||||
/// Gets an value that represents an color from the given `Color` and `ColorType`.
|
/// Gets an value that represents an color from the given `Color` and `ColorType`.
|
||||||
fn color_value(&self, color: Color, color_type: ColorType) -> String;
|
fn color_value(&self, color: Color, color_type: ColorType) -> String;
|
||||||
}
|
}
|
@ -4,7 +4,7 @@
|
|||||||
mod color;
|
mod color;
|
||||||
mod styles;
|
mod styles;
|
||||||
|
|
||||||
pub use self::color::color::{color, paint, TerminalColor };
|
pub use self::color::color::{color, TerminalColor };
|
||||||
|
|
||||||
pub use self::styles::objectstyle::ObjectStyle;
|
pub use self::styles::objectstyle::ObjectStyle;
|
||||||
pub use self::styles::styledobject::StyledObject;
|
pub use self::styles::styledobject::StyledObject;
|
||||||
|
@ -2,7 +2,9 @@
|
|||||||
|
|
||||||
use std::fmt::Display;
|
use std::fmt::Display;
|
||||||
use style::{Color, StyledObject};
|
use style::{Color, StyledObject};
|
||||||
|
use { Terminal, ScreenManager };
|
||||||
|
use std::sync::Mutex;
|
||||||
|
use std::rc::Rc;
|
||||||
#[cfg(unix)]
|
#[cfg(unix)]
|
||||||
use super::super::Attribute;
|
use super::super::Attribute;
|
||||||
|
|
||||||
@ -29,12 +31,13 @@ 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<D>(&self, val: D) -> StyledObject<D>
|
pub fn apply_to<D>(&self, val: D, screen: Rc<Mutex<ScreenManager>>) -> StyledObject<D>
|
||||||
where
|
where
|
||||||
D: Display,
|
D: Display,
|
||||||
{
|
{
|
||||||
StyledObject {
|
StyledObject {
|
||||||
object_style: self.clone(),
|
object_style: self.clone(),
|
||||||
|
screen_manager: screen,
|
||||||
content: val,
|
content: val,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,9 @@
|
|||||||
|
|
||||||
use std::{ self, fmt };
|
use std::{ self, fmt };
|
||||||
use std::io::Write;
|
use std::io::Write;
|
||||||
|
use std::sync::Mutex;
|
||||||
|
use std::rc::Rc;
|
||||||
|
use { Terminal, ScreenManager };
|
||||||
|
|
||||||
#[cfg(unix)]
|
#[cfg(unix)]
|
||||||
use super::super::Attribute;
|
use super::super::Attribute;
|
||||||
@ -12,6 +15,7 @@ use style::{Color, ObjectStyle};
|
|||||||
pub struct StyledObject<D> {
|
pub struct StyledObject<D> {
|
||||||
pub object_style: ObjectStyle,
|
pub object_style: ObjectStyle,
|
||||||
pub content: D,
|
pub content: D,
|
||||||
|
pub screen_manager: Rc<Mutex<ScreenManager>>
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<D> StyledObject<D> {
|
impl<D> StyledObject<D> {
|
||||||
@ -112,7 +116,7 @@ macro_rules! impl_fmt
|
|||||||
impl<D: fmt::$name> fmt::$name for StyledObject<D> {
|
impl<D: fmt::$name> fmt::$name for StyledObject<D> {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result
|
||||||
{
|
{
|
||||||
let mut colored_terminal = super::super::color();
|
let mut colored_terminal = super::super::color(self.screen_manager.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
|
||||||
@ -133,7 +137,12 @@ macro_rules! impl_fmt
|
|||||||
}
|
}
|
||||||
|
|
||||||
fmt::$name::fmt(&self.content, f)?;
|
fmt::$name::fmt(&self.content, f)?;
|
||||||
std::io::stdout().flush().expect("Flush stdout failed");
|
|
||||||
|
let mut mutex = &self.screen_manager;
|
||||||
|
{
|
||||||
|
let mut screen = mutex.lock().unwrap();
|
||||||
|
screen.stdout().flush().expect("Flush stdout failed");
|
||||||
|
}
|
||||||
|
|
||||||
if reset
|
if reset
|
||||||
{
|
{
|
||||||
|
@ -1,15 +1,19 @@
|
|||||||
//! This is an `ANSI escape code` specific implementation for terminal related action.
|
//! This is an `ANSI escape code` specific implementation for terminal related action.
|
||||||
//! This module is used for windows 10 terminals and unix terminals by default.
|
//! This module is used for windows 10 terminals and unix terminals by default.
|
||||||
|
|
||||||
use Construct;
|
use {Construct, Terminal};
|
||||||
use shared::functions;
|
use shared::functions;
|
||||||
use super::{ClearType, ITerminal};
|
use super::{ClearType, ITerminal};
|
||||||
|
|
||||||
use std::io;
|
use std::io;
|
||||||
use std::io::Write;
|
use std::io::Write;
|
||||||
|
use std::sync::Mutex;
|
||||||
|
use std::cell::RefCell;
|
||||||
|
|
||||||
|
use ScreenManager;
|
||||||
|
|
||||||
/// This struct is an ansi implementation for terminal related actions.
|
/// This struct is an ansi implementation for terminal related actions.
|
||||||
pub struct AnsiTerminal ;
|
pub struct AnsiTerminal;
|
||||||
|
|
||||||
impl Construct for AnsiTerminal {
|
impl Construct for AnsiTerminal {
|
||||||
fn new() -> Box<AnsiTerminal> {
|
fn new() -> Box<AnsiTerminal> {
|
||||||
@ -18,43 +22,54 @@ impl Construct for AnsiTerminal {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl ITerminal for AnsiTerminal {
|
impl ITerminal for AnsiTerminal {
|
||||||
fn clear(&self, clear_type: ClearType) {
|
fn clear(&self, clear_type: ClearType, terminal: &Terminal) {
|
||||||
let mut some_writer = io::stdout();
|
|
||||||
match clear_type {
|
let mut screen_manager = terminal.screen_manager.lock().unwrap();
|
||||||
ClearType::All => {
|
{
|
||||||
write!(&mut some_writer, csi!("2J"));
|
let mut stdout = screen_manager.stdout();
|
||||||
},
|
|
||||||
ClearType::FromCursorDown=> {
|
match clear_type {
|
||||||
write!(&mut some_writer, csi!("J"));
|
ClearType::All => {
|
||||||
},
|
write!(stdout, csi!("2J"));
|
||||||
ClearType::FromCursorUp => {
|
},
|
||||||
write!(&mut some_writer, csi!("1J"));
|
ClearType::FromCursorDown => {
|
||||||
},
|
write!(stdout, csi!("J"));
|
||||||
ClearType::CurrentLine => {
|
},
|
||||||
write!(&mut some_writer, csi!("2K"));
|
ClearType::FromCursorUp => {
|
||||||
},
|
write!(stdout, csi!("1J"));
|
||||||
ClearType::UntilNewLine => {
|
},
|
||||||
write!(&mut some_writer, csi!("K"));
|
ClearType::CurrentLine => {
|
||||||
},
|
write!(stdout, csi!("2K"));
|
||||||
};
|
},
|
||||||
|
ClearType::UntilNewLine => {
|
||||||
|
write!(stdout, csi!("K"));
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn terminal_size(&self) -> (u16, u16) {
|
fn terminal_size(&self, terminal: &Terminal) -> (u16, u16) {
|
||||||
functions::get_terminal_size()
|
functions::get_terminal_size()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn scroll_up(&self, count: i16) {
|
fn scroll_up(&self, count: i16, terminal: &Terminal) {
|
||||||
let mut some_writer = io::stdout();
|
let mut screen = terminal.screen_manager.lock().unwrap();
|
||||||
write!(&mut some_writer, csi!("{}S"), count);
|
{
|
||||||
|
screen.write_ansi(format!(csi!("{}S"), count));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn scroll_down(&self, count: i16) {
|
fn scroll_down(&self, count: i16, terminal: &Terminal) {
|
||||||
let mut some_writer = io::stdout();
|
let mut screen = terminal.screen_manager.lock().unwrap();
|
||||||
write!(&mut some_writer, csi!("{}T"), count);
|
{
|
||||||
|
screen.write_ansi(format!(csi!("{}T"), count));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_size(&self, width: i16, height: i16) {
|
fn set_size(&self, width: i16, height: i16, terminal: &Terminal) {
|
||||||
let mut some_writer = io::stdout();
|
let mut screen = terminal.screen_manager.lock().unwrap();
|
||||||
write!(&mut some_writer, csi!("8;{};{}t"), width, height);
|
{
|
||||||
|
screen.write_ansi(format!(csi!("8;{};{}t"), width, height));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,21 +5,23 @@
|
|||||||
//! - raw mode
|
//! - raw mode
|
||||||
//! - clearing resizing scrolling the terminal.
|
//! - clearing resizing scrolling the terminal.
|
||||||
|
|
||||||
mod terminal;
|
use {Context, ScreenManager, Terminal};
|
||||||
|
use self::ansi_terminal::AnsiTerminal;
|
||||||
|
pub use self::terminal::{ terminal};
|
||||||
|
#[cfg(target_os = "windows")]
|
||||||
|
use self::winapi_terminal::WinApiTerminal;
|
||||||
|
use std::cell::RefCell;
|
||||||
|
use std::sync::Mutex;
|
||||||
|
|
||||||
|
pub mod terminal;
|
||||||
|
|
||||||
#[cfg(target_os = "windows")]
|
#[cfg(target_os = "windows")]
|
||||||
mod winapi_terminal;
|
mod winapi_terminal;
|
||||||
mod ansi_terminal;
|
mod ansi_terminal;
|
||||||
|
|
||||||
mod screen;
|
pub mod screen;
|
||||||
mod raw;
|
mod raw;
|
||||||
|
|
||||||
#[cfg(target_os = "windows")]
|
|
||||||
use self::winapi_terminal::WinApiTerminal;
|
|
||||||
use self::ansi_terminal::AnsiTerminal;
|
|
||||||
|
|
||||||
pub use self::terminal::{ Terminal, terminal};
|
|
||||||
|
|
||||||
/// Enum that can be used for the kind of clearing that can be done in the terminal.
|
/// Enum that can be used for the kind of clearing that can be done in the terminal.
|
||||||
pub enum ClearType {
|
pub enum ClearType {
|
||||||
All,
|
All,
|
||||||
@ -39,13 +41,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);
|
fn clear(&self, clear_type: ClearType, terminal: &Terminal);
|
||||||
/// Get the terminal size (x,y)
|
/// Get the terminal size (x,y)
|
||||||
fn terminal_size(&self) -> (u16, u16);
|
fn terminal_size(&self, terminal: &Terminal) -> (u16, u16);
|
||||||
/// Scroll `n` lines up in the current terminal.
|
/// Scroll `n` lines up in the current terminal.
|
||||||
fn scroll_up(&self, count: i16);
|
fn scroll_up(&self, count: i16, terminal: &Terminal);
|
||||||
/// Scroll `n` lines down in the current terminal.
|
/// Scroll `n` lines down in the current terminal.
|
||||||
fn scroll_down(&self, count: i16);
|
fn scroll_down(&self, count: i16, terminal: &Terminal);
|
||||||
/// Resize terminal to the given width and height.
|
/// Resize terminal to the given width and height.
|
||||||
fn set_size(&self,width: i16, height: i16);
|
fn set_size(&self,width: i16, height: i16, terminal: &Terminal);
|
||||||
}
|
}
|
||||||
|
@ -1,82 +1,82 @@
|
|||||||
//! This module is used for enabling and disabling raw mode for the terminal.
|
////! This module is used for enabling and disabling raw mode for the terminal.
|
||||||
//!
|
////!
|
||||||
//! What exactly is raw state:
|
////! What exactly is raw state:
|
||||||
//! - No line buffering.
|
////! - No line buffering.
|
||||||
//! Normally the terminals uses line buffering. This means that the input will be send to the terminal line by line.
|
////! Normally the terminals uses line buffering. This means that the input will be send to the terminal line by line.
|
||||||
//! With raw mode the input will be send one byte at a time.
|
////! With raw mode the input will be send one byte at a time.
|
||||||
//! - Input
|
////! - Input
|
||||||
//! All input has to be written manually by the programmer.
|
////! All input has to be written manually by the programmer.
|
||||||
//! - Characters
|
////! - Characters
|
||||||
//! The characters are not processed by the terminal driver, but are sent straight through.
|
////! The characters are not processed by the terminal driver, but are sent straight through.
|
||||||
//! Special character have no meaning, like backspace will not be interpret as backspace but instead will be directly send to the terminal.
|
////! Special character have no meaning, like backspace will not be interpret as backspace but instead will be directly send to the terminal.
|
||||||
//!
|
////!
|
||||||
//! With these modes you can easier design the terminal screen.
|
////! With these modes you can easier design the terminal screen.
|
||||||
//!
|
////!
|
||||||
//! # Example
|
////! # Example
|
||||||
//!
|
////!
|
||||||
//! ```rust
|
////! ```rust
|
||||||
//! to be implemented
|
////! to be implemented
|
||||||
//!
|
////!
|
||||||
//! ```
|
////! ```
|
||||||
|
//
|
||||||
#[cfg(not(windows))]
|
//#[cfg(not(windows))]
|
||||||
use state::commands::unix_command::EnableRawModeCommand;
|
//use state::commands::unix_command::EnableRawModeCommand;
|
||||||
#[cfg(windows)]
|
//#[cfg(windows)]
|
||||||
use state::commands::win_commands::EnableRawModeCommand;
|
//use state::commands::win_commands::EnableRawModeCommand;
|
||||||
|
//
|
||||||
use Context;
|
//use Context;
|
||||||
use state::commands::IContextCommand;
|
//use state::commands::IContextCommand;
|
||||||
|
//
|
||||||
use std::io::{ self, Write};
|
//use std::io::{ self, Write};
|
||||||
|
//
|
||||||
/// 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, W: Write>
|
//pub struct RawTerminal<'a, W: Write>
|
||||||
{
|
//{
|
||||||
output: W,
|
// output: W,
|
||||||
context : &'a mut Context
|
// context : &'a mut Context
|
||||||
}
|
//}
|
||||||
|
//
|
||||||
/// Trait withs contains a method for switching into raw mode.
|
///// Trait withs contains a method for switching into raw mode.
|
||||||
pub trait IntoRawMode: Write + Sized
|
//pub trait IntoRawMode: Write + Sized
|
||||||
{
|
//{
|
||||||
fn into_raw_mode<'a>(self, context: &'a mut Context) -> io::Result<RawTerminal<Self>>;
|
// fn into_raw_mode<'a>(self, context: &'a mut Context) -> io::Result<RawTerminal<Self>>;
|
||||||
}
|
//}
|
||||||
|
//
|
||||||
impl<W: Write> IntoRawMode for W
|
//impl<W: Write> IntoRawMode for W
|
||||||
{
|
//{
|
||||||
/// Switch to raw mode.
|
// /// Switch to raw mode.
|
||||||
///
|
// ///
|
||||||
/// 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<'a>(self, context: &'a mut Context) -> io::Result<RawTerminal<Self>>
|
// fn into_raw_mode<'a>(self, context: &'a mut Context) -> io::Result<RawTerminal<Self>>
|
||||||
{
|
// {
|
||||||
let (mut command, _) = EnableRawModeCommand::new(context);
|
// let (mut command, _) = EnableRawModeCommand::new(context);
|
||||||
let success = command.execute();
|
// let success = command.execute(&context);
|
||||||
|
//
|
||||||
if success
|
// if success
|
||||||
{
|
// {
|
||||||
Ok(RawTerminal { output: self, context: context})
|
// Ok(RawTerminal { output: self, context: context})
|
||||||
|
//
|
||||||
}else { panic!("cannot move into raw mode") }
|
// }else { panic!("cannot move into raw mode") }
|
||||||
}
|
// }
|
||||||
}
|
//}
|
||||||
|
//
|
||||||
impl<'a, W: Write> Write for RawTerminal<'a, W> {
|
//impl<'a, W: Write> Write for RawTerminal<'a, W> {
|
||||||
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
|
// fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
|
||||||
self.output.write(buf)
|
// self.output.write(buf)
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
fn flush(&mut self) -> io::Result<()> {
|
// fn flush(&mut self) -> io::Result<()> {
|
||||||
self.output.flush()
|
// self.output.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, W: Write> Drop for RawTerminal<'a, W>
|
//impl <'a, W: Write> Drop for RawTerminal<'a, W>
|
||||||
{
|
//{
|
||||||
fn drop(&mut self)
|
// fn drop(&mut self)
|
||||||
{
|
// {
|
||||||
self.context.restore_changes();
|
// self.context.restore_changes();
|
||||||
}
|
// }
|
||||||
}
|
//}
|
@ -1,32 +1,32 @@
|
|||||||
//! This module contains all the logic for switching between alternate screen and main screen.
|
//! This module contains all the logic for switching between alternate screen and main screen.
|
||||||
|
|
||||||
use shared::functions;
|
use shared::functions;
|
||||||
use Context;
|
use { Context, Terminal };
|
||||||
use state::commands::*;
|
use state::commands::*;
|
||||||
|
|
||||||
use std::{ fmt, ops };
|
use std::{ fmt, ops };
|
||||||
use std::io::{self, Write};
|
use std::io::{self, Write};
|
||||||
|
|
||||||
pub struct ToMainScreen;
|
//pub struct ToMainScreen;
|
||||||
|
//
|
||||||
impl fmt::Display for ToMainScreen
|
//impl fmt::Display for ToMainScreen
|
||||||
{
|
//{
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
// fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
get_to_alternate_screen_command().undo();
|
// get_to_alternate_screen_command().undo();
|
||||||
Ok(())
|
// Ok(())
|
||||||
}
|
// }
|
||||||
}
|
//}
|
||||||
|
//
|
||||||
/// Struct that switches to alternate screen buffer on display.
|
///// Struct that switches to alternate screen buffer on display.
|
||||||
pub struct ToAlternateScreen;
|
//pub struct ToAlternateScreen;
|
||||||
|
//
|
||||||
impl fmt::Display for ToAlternateScreen
|
//impl fmt::Display for ToAlternateScreen
|
||||||
{
|
//{
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
// fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
get_to_alternate_screen_command().execute();
|
// get_to_alternate_screen_command().execute();
|
||||||
Ok(())
|
// Ok(())
|
||||||
}
|
// }
|
||||||
}
|
//}
|
||||||
|
|
||||||
/// Struct that can be used for writing to an alternate screen.
|
/// Struct that can be used for writing to an alternate screen.
|
||||||
///
|
///
|
||||||
@ -51,52 +51,57 @@ impl fmt::Display for ToAlternateScreen
|
|||||||
/// ...
|
/// ...
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
pub struct AlternateScreen<W: Write> {
|
pub struct AlternateScreen<'term> {
|
||||||
/// The output target.
|
term: &'term Terminal
|
||||||
output: W,
|
|
||||||
context: Context
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<W: Write> AlternateScreen<W> {
|
impl<'term> AlternateScreen<'term> {
|
||||||
pub fn from(mut output: W) -> Self {
|
pub fn from(output: &'term Terminal) -> Self {
|
||||||
write!(output, "{}", ToAlternateScreen);
|
get_to_alternate_screen_command().execute(&output);
|
||||||
AlternateScreen { output: output, context: Context::new()}
|
//
|
||||||
|
// let mut screen = output.screen_manager.lock().unwrap();
|
||||||
|
// {
|
||||||
|
// screen.register_output(Box::from(o), true);
|
||||||
|
// }
|
||||||
|
AlternateScreen { term: output }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn to_main(&self)
|
||||||
|
{
|
||||||
|
get_to_alternate_screen_command().undo(&self.term);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn to_alternate(&self)
|
||||||
|
{
|
||||||
|
get_to_alternate_screen_command().execute(&self.term);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<W: Write> ops::Deref for AlternateScreen<W> {
|
impl<'term> Write for AlternateScreen<'term> {
|
||||||
type Target = W;
|
|
||||||
|
|
||||||
fn deref(&self) -> &W {
|
|
||||||
&self.output
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<W: Write> ops::DerefMut for AlternateScreen<W> {
|
|
||||||
fn deref_mut(&mut self) -> &mut W {
|
|
||||||
&mut self.output
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<W: Write> Write for AlternateScreen<W> {
|
|
||||||
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
|
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
|
||||||
self.output.write(buf)
|
let mut screen = self.term.screen_manager.lock().unwrap();
|
||||||
|
{
|
||||||
|
screen.stdout().write(buf)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn flush(&mut self) -> io::Result<()> {
|
fn flush(&mut self) -> io::Result<()> {
|
||||||
self.output.flush()
|
let mut screen = self.term.screen_manager.lock().unwrap();
|
||||||
|
{
|
||||||
|
screen.stdout().flush()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<W: Write> Drop for AlternateScreen<W>
|
impl<'term> Drop for AlternateScreen<'term>
|
||||||
{
|
{
|
||||||
fn drop(&mut self)
|
fn drop(&mut self)
|
||||||
{
|
{
|
||||||
write!(self, "{}", ToMainScreen).expect("switch to main screen");
|
get_to_alternate_screen_command().undo(&self.term);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// 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() -> Box<ICommand>
|
fn get_to_alternate_screen_command() -> Box<ICommand>
|
||||||
{
|
{
|
||||||
#[cfg(target_os = "windows")]
|
#[cfg(target_os = "windows")]
|
||||||
|
@ -3,25 +3,28 @@
|
|||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
use shared::functions;
|
use shared::functions;
|
||||||
use {Construct, Context};
|
use { Construct, Context };
|
||||||
|
use super::super::manager::terminal;
|
||||||
|
|
||||||
use std::ops::Drop;
|
use std::ops::Drop;
|
||||||
|
|
||||||
/// 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 {
|
pub struct Terminal<'terminal> {
|
||||||
terminal: Option<Box<ITerminal>>,
|
terminal: Option<Box<ITerminal>>,
|
||||||
|
term: &'terminal terminal::Terminal
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Terminal {
|
impl<'terminal> Terminal<'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() -> Terminal {
|
pub fn new(term: &'terminal terminal::Terminal) -> Terminal<'terminal> {
|
||||||
#[cfg(target_os = "windows")]
|
#[cfg(target_os = "windows")]
|
||||||
let terminal = functions::get_module::<Box<ITerminal>>(WinApiTerminal::new(), AnsiTerminal::new());
|
let terminal = functions::get_module::<Box<ITerminal>>(WinApiTerminal::new(), AnsiTerminal::new());
|
||||||
|
|
||||||
#[cfg(not(target_os = "windows"))]
|
#[cfg(not(target_os = "windows"))]
|
||||||
let terminal = Some(AnsiTerminal::new() as Box<ITerminal>);
|
let terminal = Some(AnsiTerminal::new() as Box<ITerminal>);
|
||||||
|
|
||||||
Terminal { terminal: terminal }
|
Terminal { terminal, term }
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Clear the current cursor by specifying the clear type
|
/// Clear the current cursor by specifying the clear type
|
||||||
@ -49,7 +52,7 @@ impl Terminal {
|
|||||||
/// ```
|
/// ```
|
||||||
pub fn clear(&mut self, clear_type: ClearType) {
|
pub fn clear(&mut self, clear_type: ClearType) {
|
||||||
if let Some(ref terminal) = self.terminal {
|
if let Some(ref terminal) = self.terminal {
|
||||||
terminal.clear(clear_type);
|
terminal.clear(clear_type, &self.term);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -70,7 +73,7 @@ impl Terminal {
|
|||||||
/// ```
|
/// ```
|
||||||
pub fn terminal_size(&mut self) -> (u16, u16) {
|
pub fn terminal_size(&mut self) -> (u16, u16) {
|
||||||
if let Some(ref terminal) = self.terminal {
|
if let Some(ref terminal) = self.terminal {
|
||||||
return terminal.terminal_size()
|
return terminal.terminal_size(&self.term)
|
||||||
}
|
}
|
||||||
(0,0)
|
(0,0)
|
||||||
}
|
}
|
||||||
@ -92,7 +95,7 @@ impl Terminal {
|
|||||||
/// ```
|
/// ```
|
||||||
pub fn scroll_up(&mut self, count: i16) {
|
pub fn scroll_up(&mut self, count: i16) {
|
||||||
if let Some(ref terminal) = self.terminal {
|
if let Some(ref terminal) = self.terminal {
|
||||||
terminal.scroll_up(count);
|
terminal.scroll_up(count,&self.term);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -113,7 +116,7 @@ impl Terminal {
|
|||||||
/// ```
|
/// ```
|
||||||
pub fn scroll_down(&mut self, count: i16) {
|
pub fn scroll_down(&mut self, count: i16) {
|
||||||
if let Some(ref terminal) = self.terminal {
|
if let Some(ref terminal) = self.terminal {
|
||||||
terminal.scroll_down(count);
|
terminal.scroll_down(count, &self.term);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -135,7 +138,7 @@ impl Terminal {
|
|||||||
pub fn set_size(&mut self, width: i16, height: i16)
|
pub fn set_size(&mut self, width: i16, height: i16)
|
||||||
{
|
{
|
||||||
if let Some (ref terminal) = self.terminal {
|
if let Some (ref terminal) = self.terminal {
|
||||||
terminal.set_size(width,height);
|
terminal.set_size(width,height,&self.term);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -158,7 +161,8 @@ impl Terminal {
|
|||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
///
|
///
|
||||||
pub fn terminal() -> Box<Terminal>
|
///
|
||||||
{
|
|
||||||
Box::from(Terminal::new())
|
pub fn terminal<'terminal>(terminal: &'terminal terminal::Terminal) -> Box<Terminal<'terminal>> {
|
||||||
|
Box::from(Terminal::new(&terminal))
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user