diff --git a/.idea/workspace.xml b/.idea/workspace.xml
index 4be070b..34650e9 100644
--- a/.idea/workspace.xml
+++ b/.idea/workspace.xml
@@ -3,22 +3,39 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
+
@@ -31,20 +48,20 @@
-
-
+
+
-
-
+
+
-
-
+
+
-
-
+
+
@@ -52,87 +69,79 @@
-
-
+
+
-
-
+
+
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
-
+
-
+
-
-
+
+
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -148,36 +157,36 @@
- self.
- output
- std
- stdout
- 'terminal
- &Terminal
- &self.term
- HANDLE
- command
- End
- termina
- screen
- colored_terminal
- ObjectStyle
- changed_states
- state
- context
- Context
TerminalColor
conte
terminal_cursor
term
ScreenManager
color
- terminal
cursor(
IStateCommand
execute
- get_to_alternate_screen_command
functions
+ set
+ cursor_vis
+ write
+ ToAlternateScreenBufferCommand
+ new
+ terminal
+ ICommand
+ Write
+ StyledObject
+ get_to_alternate_screen_command
+ &context
+ cursor
+ context
+ data
+ Mutex
+ WriteConsoleOutputW
+ CONSOLE_CURSOR_INFO
+ use
+ Borrow
+ fmt
crossterm_cursor
@@ -186,11 +195,13 @@
&Context
Terminal
context
+ context.clone()
D:\Windows\GIT\crossterm\src
D:\Windows\GIT\crossterm
$PROJECT_DIR$/src
+ C:\Users\Timon\Documents\Programming\rust\crossterm\src
@@ -204,52 +215,52 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
-
+
+
+
-
-
-
+
+
+
+
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -263,10 +274,10 @@
-
-
-
-
+
+
+
+
@@ -289,6 +300,7 @@
+
@@ -307,6 +319,27 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -386,9 +419,8 @@
-
-
+
@@ -581,12 +613,16 @@
-
+
+
+
+
+
-
+
@@ -603,12 +639,11 @@
-
+
-
@@ -620,22 +655,22 @@
+
-
-
+
-
+
-
+
@@ -645,6 +680,7 @@
+
@@ -658,39 +694,10 @@
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
@@ -715,20 +722,6 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
@@ -736,306 +729,337 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
-
-
+
+
-
+
-
-
+
+
-
+
-
-
+
+
-
+
+
+
+
+
+
+
+
-
-
+
+
-
-
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
-
+
+
-
+
-
-
+
+
+
+
+
+
-
+
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
+
+
-
-
+
-
+
+
-
+
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
+
+
-
+
-
+
-
-
-
-
-
+
+
-
-
+
+
-
-
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
diff --git a/examples/Crossterm 0.2.2 - New Version (Not finished)/bin.rs b/examples/Crossterm 0.2.2 - New Version (Not finished)/bin.rs
index 61e656e..ba25251 100644
--- a/examples/Crossterm 0.2.2 - New Version (Not finished)/bin.rs
+++ b/examples/Crossterm 0.2.2 - New Version (Not finished)/bin.rs
@@ -32,5 +32,8 @@ use std::{time, thread};
fn main() {
// alternate_screen::switch_between_main_and_alternate_screen();
let context = Context::new();
- raw_mode::print_wait_screen_on_alternate_window();
+ let mut scre = screen::AlternateScreen::from(context.clone());
+ write!(scre, "asdf");
+ scre.flush();
+ thread::sleep(time::Duration::from_secs(3));
}
\ No newline at end of file
diff --git a/examples/Crossterm 0.2.2 - New Version (Not finished)/color/mod.rs b/examples/Crossterm 0.2.2 - New Version (Not finished)/color/mod.rs
index fdb6815..81b65af 100644
--- a/examples/Crossterm 0.2.2 - New Version (Not finished)/color/mod.rs
+++ b/examples/Crossterm 0.2.2 - New Version (Not finished)/color/mod.rs
@@ -12,7 +12,7 @@ use self::crossterm::Context;
pub fn paint_foreground()
{
let context = Context::new();
- let terminal = terminal::terminal(&context);
+ let terminal = terminal::terminal(context.clone());
// Pass an string to the `paint()` method with you want to paint.
// This will give you an object back wits can be styled and displayed.
@@ -30,7 +30,7 @@ pub fn paint_foreground()
pub fn paint_background()
{
let context = Context::new();
- let terminal = terminal::terminal(&context);
+ let terminal = terminal::terminal(context.clone());
// Pass an string to the `paint()` method with you want to paint.
// This will give you an object back wits can be styled and displayed.
@@ -48,7 +48,7 @@ pub fn paint_background()
pub fn paint_foreground_and_background()
{
let context = Context::new();
- let terminal = terminal::terminal(&context);
+ let terminal = terminal::terminal(context.clone());
// Pass an string to the `paint()` method with you want to paint.
// This will give you an object back wits can be styled and displayed.
@@ -74,7 +74,7 @@ pub fn paint_foreground_and_background()
pub fn print_all_foreground_colors()
{
let context = Context::new();
- let terminal = terminal::terminal(&context);
+ let terminal = terminal::terminal(context.clone());
println!("Black : \t {}", terminal.paint("â– ").with(Color::Black));
println!("Red : \t\t {}", terminal.paint("â– ").with(Color::Red));
@@ -97,7 +97,7 @@ pub fn print_all_foreground_colors()
pub fn print_all_background_colors()
{
let context = Context::new();
- let terminal = terminal::terminal(&context);
+ let terminal = terminal::terminal(context.clone());
println!("Black : \t {}", terminal.paint(" ").on(Color::Black));
println!("Red : \t\t {}", terminal.paint(" ").on(Color::Red));
@@ -125,7 +125,7 @@ pub fn print_all_background_colors()
pub fn print_font_with_attributes()
{
let context = Context::new();
- let terminal = terminal::terminal(&context);
+ let terminal = terminal::terminal(context.clone());
println!("{}", terminal.paint("Normal text"));
println!("{}", terminal.paint("Bold text").bold());
@@ -144,7 +144,7 @@ pub fn print_font_with_attributes()
pub fn print_supported_colors()
{
let context = Context::new();
- let terminal = terminal::terminal(&context);
+ let terminal = terminal::terminal(context.clone());
let count = crossterm::style::color(context.screen_manager.clone()).get_available_color_count().unwrap();
diff --git a/examples/Crossterm 0.2.2 - New Version (Not finished)/cursor/mod.rs b/examples/Crossterm 0.2.2 - New Version (Not finished)/cursor/mod.rs
index 3c3480f..6671060 100644
--- a/examples/Crossterm 0.2.2 - New Version (Not finished)/cursor/mod.rs
+++ b/examples/Crossterm 0.2.2 - New Version (Not finished)/cursor/mod.rs
@@ -12,7 +12,7 @@ pub fn goto()
let context = Context::new();
// Get the cursor
- let mut cursor = cursor(&context);
+ let mut cursor = cursor(context.clone());
// Set the cursor to position X: 10, Y: 5 in the terminal
cursor.goto(10,5);
}
@@ -23,7 +23,7 @@ pub fn pos()
let context = Context::new();
// Get the cursor
- let mut cursor = cursor(&context);
+ let mut cursor = cursor(context.clone());
// get the cursor position.
let (x,y) = cursor.pos();
}
@@ -34,7 +34,7 @@ pub fn move_up()
let context = Context::new();
// Get the cursor
- let mut cursor = cursor(&context);
+ let mut cursor = cursor(context.clone());
// Move the cursor to position 3 times to the up in the terminal
cursor.move_up(3);
}
@@ -45,7 +45,7 @@ pub fn move_right()
let context = Context::new();
// Get the cursor
- let mut cursor = cursor(&context);
+ let mut cursor = cursor(context.clone());
// Move the cursor to position 3 times to the right in the terminal
cursor.move_right(3);
}
@@ -56,7 +56,7 @@ pub fn move_down()
let context = Context::new();
// Get the cursor
- let mut cursor = cursor(&context);
+ let mut cursor = cursor(context.clone());
// Move the cursor to position 3 times to the down in the terminal
cursor.move_down(3);
}
@@ -67,7 +67,7 @@ pub fn move_left()
let context = Context::new();
// Get the cursor
- let mut cursor = cursor(&context);
+ let mut cursor = cursor(context.clone());
// Move the cursor to position 3 times to the left in the terminal
cursor.move_left(3);
}
@@ -80,7 +80,7 @@ pub fn print()
// To print an some displayable content on an certain position.
// Get the cursor
- let mut cursor = cursor(&context);
+ let mut cursor = cursor(context.clone());
// Set the cursor to position X: 10, Y: 5 in the terminal
cursor.goto(10,5);
// Print the @ symbol at position X: 10, Y: 5 in the terminal
@@ -104,7 +104,7 @@ pub fn safe_and_reset_position()
{
let context = Context::new();
- let mut cursor = cursor(&context);
+ let mut cursor = cursor(context.clone());
// Goto X: 5 Y: 5
cursor.goto(5,5);
diff --git a/examples/Crossterm 0.2.2 - New Version (Not finished)/terminal/alternate_screen.rs b/examples/Crossterm 0.2.2 - New Version (Not finished)/terminal/alternate_screen.rs
index 379125d..4fa45a0 100644
--- a/examples/Crossterm 0.2.2 - New Version (Not finished)/terminal/alternate_screen.rs
+++ b/examples/Crossterm 0.2.2 - New Version (Not finished)/terminal/alternate_screen.rs
@@ -7,18 +7,18 @@ use crossterm::terminal::{self, ClearType};
use std::io::{Write, stdout};
use std::{time, thread};
-
-fn print_wait_screen(terminal: &Context)
+use std::rc::Rc;
+fn print_wait_screen(context: Rc)
{
- terminal::terminal(&terminal).clear(ClearType::All);
+ terminal::terminal(context.clone()).clear(ClearType::All);
- let mut cursor = cursor(&terminal);
+ let mut cursor = cursor(context.clone());
cursor.goto(0,0);
{
- let mut screen_manager = terminal.screen_manager.lock().unwrap();
+ let mut screen_manager = context.screen_manager.lock().unwrap();
{
- write!(screen_manager.stdout(),
+ write!(screen_manager,
"Welcome to the wait screen.\n\
Please wait a few seconds until we arrive back at the main screen.\n\
Progress: "
@@ -45,10 +45,10 @@ pub fn print_wait_screen_on_alternate_window()
// because `AlternateScreen` switches back to main screen when switching back.
{
// create new alternate screen instance and switch to the alternate screen.
- let mut screen = AlternateScreen::from(&context);
+ let mut screen = AlternateScreen::from(context.clone());
// Print the wait screen.
- print_wait_screen(&context);
+ print_wait_screen(context.clone());
}
println!("Whe are back at the main screen");
@@ -57,11 +57,11 @@ pub fn print_wait_screen_on_alternate_window()
pub fn switch_between_main_and_alternate_screen()
{
let context = Context::new();
- let mut cursor = cursor(&context);
+ let mut cursor = cursor(context.clone());
{
// create new alternate screen instance and switch to the alternate screen.
- let mut screen = AlternateScreen::from(&context);
+ let mut screen = AlternateScreen::from(context.clone());
cursor.goto(0,0);
write!(screen, "we are at the alternate screen!");
screen.flush();
diff --git a/examples/Crossterm 0.2.2 - New Version (Not finished)/terminal/raw_mode.rs b/examples/Crossterm 0.2.2 - New Version (Not finished)/terminal/raw_mode.rs
index b76e2d2..025d73c 100644
--- a/examples/Crossterm 0.2.2 - New Version (Not finished)/terminal/raw_mode.rs
+++ b/examples/Crossterm 0.2.2 - New Version (Not finished)/terminal/raw_mode.rs
@@ -7,15 +7,16 @@ use crossterm::terminal::{self, ClearType};
use std::io::{Write, stdout};
use std::{time, thread};
+use std::rc::Rc;
use crossterm::raw::IntoRawMode;
// raw screen is not working correctly currently
-fn print_wait_screen(context: &Context)
+fn print_wait_screen(context: Rc)
{
- terminal::terminal(&context).clear(ClearType::All);
+ terminal::terminal(context.clone()).clear(ClearType::All);
- let mut cursor = cursor(&context);
+ let mut cursor = cursor(context.clone());
cursor.goto(0,0).print("Welcome to the wait screen.");
cursor.goto(0,1).print("Please wait a few seconds until we arrive back at the main screen.");
cursor.goto(0,2).print("Progress: ");
@@ -41,11 +42,11 @@ pub fn print_wait_screen_on_alternate_window()
// create new alternate screen instance this call is also switching the screen to alternate screen.
// then convert the output of the program to raw mode.
// then print the wait screen on the alternate screen in raw mode.
- let mut screen = AlternateScreen::from(&context);
- let alternate_screen = screen.into_raw_mode(&context);
+ let mut screen = AlternateScreen::from(context.clone());
+ let alternate_screen = screen.into_raw_mode(context.clone());
// Print the wait screen.
- print_wait_screen(&context);
+ print_wait_screen(context.clone());
screen.flush();
}
diff --git a/examples/Crossterm 0.2.2 - New Version (Not finished)/terminal/terminal.rs b/examples/Crossterm 0.2.2 - New Version (Not finished)/terminal/terminal.rs
index 5c32604..8d904f4 100644
--- a/examples/Crossterm 0.2.2 - New Version (Not finished)/terminal/terminal.rs
+++ b/examples/Crossterm 0.2.2 - New Version (Not finished)/terminal/terminal.rs
@@ -21,7 +21,7 @@ pub fn clear_all_lines()
let context = Context::new();
// Get terminal
- let mut terminal = terminal(&context);
+ let mut terminal = terminal(context);
print_test_data();
@@ -35,12 +35,12 @@ pub fn clear_from_cursor_down()
let context = Context::new();
// Get terminal
- let mut terminal = terminal(&context);
+ let mut terminal = terminal(context.clone());
print_test_data();
// Set terminal cursor position (see example for more info).
- cursor::cursor(&context).goto(4,8);
+ cursor::cursor(context.clone()).goto(4,8);
// Clear all cells from current cursor position down.
terminal.clear(ClearType::FromCursorDown);
@@ -52,12 +52,12 @@ pub fn clear_from_cursor_up()
let context = Context::new();
// Get terminal
- let mut terminal = terminal(&context);
+ let mut terminal = terminal(context.clone());
print_test_data();
// Set terminal cursor position (see example for more info).
- cursor::cursor(&context).goto(4,4);
+ cursor::cursor(context.clone()).goto(4,4);
// Clear all cells from current cursor position down.
terminal.clear(ClearType::FromCursorUp);
@@ -69,12 +69,12 @@ pub fn clear_current_line()
let context = Context::new();
// Get terminal
- let mut terminal = terminal(&context);
+ let mut terminal = terminal(context.clone());
print_test_data();
// Set terminal cursor position (see example for more info).
- cursor::cursor(&context).goto(4,4);
+ cursor::cursor(context.clone()).goto(4,4);
// Clear current line cells.
terminal.clear(ClearType::CurrentLine);
@@ -86,12 +86,12 @@ pub fn clear_until_new_line()
let context = Context::new();
// Get terminal
- let mut terminal = terminal(&context);
+ let mut terminal = terminal(context.clone());
print_test_data();
// Set terminal cursor position (see example for more info).
- cursor::cursor(&context).goto(4,20);
+ cursor::cursor(context.clone()).goto(4,20);
// Clear all the cells until next line.
terminal.clear(ClearType::UntilNewLine);
@@ -103,7 +103,7 @@ pub fn print_terminal_size()
let context = Context::new();
// Get terminal
- let mut terminal = terminal(&context);
+ let mut terminal = terminal(context.clone());
// Get terminal size
let terminal_size = terminal.terminal_size();
// Print results
@@ -115,7 +115,7 @@ pub fn set_terminal_size()
{
let context = Context::new();
- let mut terminal = terminal(&context);
+ let mut terminal = terminal(context);
terminal.set_size(10,10);
}
@@ -127,7 +127,7 @@ pub fn scroll_down()
print_test_data();
// Get terminal
- let mut terminal = terminal(&context);
+ let mut terminal = terminal(context.clone());
// Scroll down 10 lines.
terminal.scroll_down(10);
}
@@ -140,7 +140,7 @@ pub fn scroll_up()
print_test_data();
// Get terminal
- let mut terminal = terminal(&context);
+ let mut terminal = terminal(context.clone());
// Scroll up 10 lines.
terminal.scroll_up(10);
}
@@ -151,7 +151,7 @@ pub fn resize_terminal()
let context = Context::new();
// Get terminal
- let mut terminal = terminal(&context);
+ let mut terminal = terminal(context.clone());
// Get terminal size
terminal.set_size(10,10);
}
diff --git a/src/cursor/ansi_cursor.rs b/src/cursor/ansi_cursor.rs
index 02c2769..fcf4e84 100644
--- a/src/cursor/ansi_cursor.rs
+++ b/src/cursor/ansi_cursor.rs
@@ -4,72 +4,91 @@
use Context;
use shared::functions;
-use super::ITerminalCursor;
+use super::*;
/// This struct is an ansi implementation for cursor related actions.
-pub struct AnsiCursor;
+pub struct AnsiCursor
+{
+ context: Rc
+}
impl AnsiCursor {
- pub fn new() -> Box {
- Box::from(AnsiCursor {})
+ pub fn new(context: Rc) -> Box {
+ Box::from(AnsiCursor { context })
}
}
impl ITerminalCursor for AnsiCursor {
- fn goto(&self, x: u16, y: u16, context: &Context)
+ fn goto(&self, x: u16, y: u16)
{
- let mut screen = context.screen_manager.lock().unwrap();
+ let mut screen = self.context.screen_manager.lock().unwrap();
{
screen.write_ansi(format!(csi!("{};{}H"), y + 1, x +1));
}
}
- fn pos(&self, context: &Context) -> (u16, u16) {
- functions::get_cursor_position(&context)
+ fn pos(&self) -> (u16, u16) {
+ functions::get_cursor_position(self.context.clone())
}
- fn move_up(&self, count: u16, context: &Context) {
- let mut screen = context.screen_manager.lock().unwrap();
+ fn move_up(&self, count: u16) {
+ let mut screen = self.context.screen_manager.lock().unwrap();
{
screen.write_ansi(format!(csi!("{}A"), count));
}
}
- fn move_right(&self, count: u16, context: &Context) {
- let mut screen = context.screen_manager.lock().unwrap();
+ fn move_right(&self, count: u16) {
+ let mut screen = self.context.screen_manager.lock().unwrap();
{
screen.write_ansi(format!(csi!("{}C"), count));
}
}
- fn move_down(&self, count: u16, context: &Context) {
- let mut screen = context.screen_manager.lock().unwrap();
+ fn move_down(&self, count: u16) {
+ let mut screen = self.context.screen_manager.lock().unwrap();
{
screen.write_ansi(format!(csi!("{}B"), count));
}
}
- fn move_left(&self, count: u16, context: &Context) {
- let mut screen = context.screen_manager.lock().unwrap();
+ fn move_left(&self, count: u16) {
+ let mut screen = self.context.screen_manager.lock().unwrap();
{
screen.write_ansi(format!(csi!("{}D"), count));
}
}
- fn save_position(&mut self, context: &Context)
+ fn save_position(&mut self)
{
- let mut screen = context.screen_manager.lock().unwrap();
+ let mut screen = self.context.screen_manager.lock().unwrap();
{
screen.write_ansi_str(csi!("s"));
}
}
- fn reset_position(&self, context: &Context)
+ fn reset_position(&self)
{
- let mut screen = context.screen_manager.lock().unwrap();
+ let mut screen = self.context.screen_manager.lock().unwrap();
{
screen.write_ansi_str(csi!("u"));
}
}
+
+ fn hide(&self)
+ {
+ let mut screen = self.context.screen_manager.lock().unwrap();
+ {
+ screen.write_ansi_str(csi!("?25l"));
+ }
+ }
+
+ fn show(&self)
+ {
+ let mut screen = self.context.screen_manager.lock().unwrap();
+ {
+ screen.write_ansi_str(csi!("?25h"));
+ }
+ }
}
diff --git a/src/cursor/cursor.rs b/src/cursor/cursor.rs
index 69a94d2..604b8c5 100644
--- a/src/cursor/cursor.rs
+++ b/src/cursor/cursor.rs
@@ -8,23 +8,23 @@ use Context;
use super::super::shared::functions;
use std::fmt::Display;
-use std::io::Write;
+use std::rc::Rc;
/// Struct that stores an specific platform implementation for cursor related actions.
-pub struct TerminalCursor<'context> {
- context: &'context Context,
+pub struct TerminalCursor {
+ context: Rc,
terminal_cursor: Option>,
}
-impl <'context> TerminalCursor<'context>
+impl TerminalCursor
{
/// Create new cursor instance whereon cursor related actions can be performed.
- pub fn new(context: &'context Context) -> TerminalCursor<'context> {
+ pub fn new(context: Rc) -> TerminalCursor {
#[cfg(target_os = "windows")]
- let cursor = functions::get_module::>(WinApiCursor::new(), AnsiCursor::new(), context);
+ let cursor = functions::get_module::>(WinApiCursor::new(), AnsiCursor::new(context.clone()));
#[cfg(not(target_os = "windows"))]
- let cursor = Some(AnsiCursor::new() as Box);
+ let cursor = Some(AnsiCursor::new(context.clone()) as Box);
TerminalCursor { terminal_cursor: cursor , context}
}
@@ -39,20 +39,20 @@ impl <'context> TerminalCursor<'context>
/// use self::crossterm::Context;
/// use self::crossterm::cursor;
///
- // pub fn goto()
- // {
- // let context = Context::new();
- //
- // // Get the cursor
- // let mut cursor = cursor(&context);
- // // Set the cursor to position X: 10, Y: 5 in the terminal
- // cursor.goto(10,5);
- // }
+ /// pub fn goto()
+ /// {
+ /// let context = Context::new();
+ ///
+ /// // Get the cursor
+ /// let mut cursor = cursor(&context);
+ /// // Set the cursor to position X: 10, Y: 5 in the terminal
+ /// cursor.goto(10,5);
+ /// }
///
/// ```
- pub fn goto(&mut self, x: u16, y: u16) -> &mut TerminalCursor<'context> {
+ pub fn goto(&mut self, x: u16, y: u16) -> &mut TerminalCursor {
if let Some(ref terminal_cursor) = self.terminal_cursor {
- terminal_cursor.goto(x, y, &self.context);
+ terminal_cursor.goto(x, y);
}
self
}
@@ -80,7 +80,7 @@ impl <'context> TerminalCursor<'context>
/// ```
pub fn pos(&mut self) -> (u16, u16) {
if let Some(ref terminal_cursor) = self.terminal_cursor {
- terminal_cursor.pos(&self.context)
+ terminal_cursor.pos()
} else {
(0, 0)
}
@@ -107,9 +107,9 @@ impl <'context> TerminalCursor<'context>
/// }
///
/// ```
- pub fn move_up(&mut self, count: u16) -> &mut TerminalCursor<'context> {
+ pub fn move_up(&mut self, count: u16) -> &mut TerminalCursor {
if let Some(ref terminal_cursor) = self.terminal_cursor {
- terminal_cursor.move_up(count, &self.context);
+ terminal_cursor.move_up(count);
}
self
}
@@ -123,19 +123,19 @@ impl <'context> TerminalCursor<'context>
/// use self::crossterm::Context;
/// use self::crossterm::cursor;
///
- // pub fn move_right()
- // {
- // let context = Context::new();
- //
- // // Get the cursor
- // let mut cursor = cursor(&context);
- // // Move the cursor to position 3 times to the right in the terminal
- // cursor.move_right(3);
- // }
+ /// pub fn move_right()
+ /// {
+ /// let context = Context::new();
+ ///
+ /// // Get the cursor
+ /// let mut cursor = cursor(&context);
+ /// // Move the cursor to position 3 times to the right in the terminal
+ /// cursor.move_right(3);
+ /// }
/// ```
- pub fn move_right(&mut self, count: u16) -> &mut TerminalCursor<'context> {
+ pub fn move_right(&mut self, count: u16) -> &mut TerminalCursor {
if let Some(ref terminal_cursor) = self.terminal_cursor {
- terminal_cursor.move_right(count, &self.context);
+ terminal_cursor.move_right(count);
}
self
}
@@ -161,9 +161,9 @@ impl <'context> TerminalCursor<'context>
/// }
///
/// ```
- pub fn move_down(&mut self, count: u16) -> &mut TerminalCursor<'context> {
+ pub fn move_down(&mut self, count: u16) -> &mut TerminalCursor {
if let Some(ref terminal_cursor) = self.terminal_cursor {
- terminal_cursor.move_down(count, &self.context);
+ terminal_cursor.move_down(count);
}
self
}
@@ -189,9 +189,9 @@ impl <'context> TerminalCursor<'context>
/// }
///
/// ```
- pub fn move_left(&mut self, count: u16) -> &mut TerminalCursor<'context> {
+ pub fn move_left(&mut self, count: u16) -> &mut TerminalCursor {
if let Some(ref terminal_cursor) = self.terminal_cursor {
- terminal_cursor.move_left(count, &self.context);
+ terminal_cursor.move_left(count);
}
self
}
@@ -232,12 +232,18 @@ impl <'context> TerminalCursor<'context>
/// .print("@");
///
/// ```
- pub fn print(&mut self, value: D) -> &mut TerminalCursor<'context> {
- let mut screen = self.context.screen_manager.lock().unwrap();
+ pub fn print(&mut self, value: D) -> &mut TerminalCursor {
{
- 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.
- screen.stdout().flush();
+ let mut mutex = &self.context.screen_manager;
+ {
+ let mut screen_manager = mutex.lock().unwrap();
+
+ use std::fmt::Write;
+ let mut string = String::new();
+ write!(string, "{}", value).unwrap();
+
+ screen_manager.write_ansi(string);
+ }
}
self
}
@@ -261,7 +267,7 @@ impl <'context> TerminalCursor<'context>
pub fn save_position(&mut self)
{
if let Some(ref mut terminal_cursor) = self.terminal_cursor {
- terminal_cursor.save_position(&self.context);
+ terminal_cursor.save_position();
}
}
@@ -284,7 +290,7 @@ impl <'context> TerminalCursor<'context>
pub fn reset_position(&mut self)
{
if let Some(ref terminal_cursor) = self.terminal_cursor {
- terminal_cursor.reset_position(&self.context);
+ terminal_cursor.reset_position();
}
}
}
@@ -311,6 +317,6 @@ impl <'context> TerminalCursor<'context>
/// cursor::cursor(&context).goto(5,10);
///
/// ```
-pub fn cursor<'context>(context: &'context Context) -> Box> {
- Box::from(TerminalCursor::new(&context))
+pub fn cursor(context: Rc) -> Box {
+ Box::from(TerminalCursor::new(context.clone()))
}
diff --git a/src/cursor/mod.rs b/src/cursor/mod.rs
index f44d246..e01898f 100644
--- a/src/cursor/mod.rs
+++ b/src/cursor/mod.rs
@@ -18,9 +18,10 @@ mod ansi_cursor;
use self::winapi_cursor::WinApiCursor;
use self::ansi_cursor::AnsiCursor;
-use Context;
pub use self::cursor::{ cursor, TerminalCursor };
+use std::rc::Rc;
+
///! This trait defines the actions that can be preformed with the terminal cursor.
///! This trait can be implemented so that an concrete implementation of the ITerminalCursor can forfill
///! the wishes to work on an specific platform.
@@ -31,19 +32,23 @@ pub use self::cursor::{ cursor, TerminalCursor };
///! so that cursor related actions can be preformed on both unix and windows systems.
pub trait ITerminalCursor {
/// Goto some location (x,y) in the context.
- fn goto(&self, x: u16, y: u16, context: &Context);
+ fn goto(&self, x: u16, y: u16);
/// Get the location (x,y) of the current cusror in the context
- fn pos(&self, context: &Context) -> (u16, u16);
+ fn pos(&self) -> (u16, u16);
/// Move cursor n times up
- fn move_up(&self, count: u16, context: &Context);
+ fn move_up(&self, count: u16);
/// Move the cursor `n` times to the right.
- fn move_right(&self, count: u16, context: &Context);
+ fn move_right(&self, count: u16);
/// Move the cursor `n` times down.
- fn move_down(&self, count: u16, context: &Context);
+ fn move_down(&self, count: u16);
/// Move the cursor `n` times left.
- fn move_left(&self, count: u16, context: &Context);
+ fn move_left(&self, count: u16);
/// Save cursor position so that its saved position can be recalled later. Note that this position is stored program based not per instance of the cursor struct.
- fn save_position(&mut self, context: &Context);
+ fn save_position(&mut self);
/// Return to saved cursor position
- fn reset_position(&self, context: &Context);
+ fn reset_position(&self);
+ /// Hide the terminal cursor.
+ fn hide(&self);
+ /// Show the terminal cursor
+ fn show(&self);
}
\ No newline at end of file
diff --git a/src/cursor/winapi_cursor.rs b/src/cursor/winapi_cursor.rs
index 55751d4..4326804 100644
--- a/src/cursor/winapi_cursor.rs
+++ b/src/cursor/winapi_cursor.rs
@@ -1,8 +1,6 @@
//! This is an WINAPI specific implementation for cursor related action.
//! This module is used for windows terminals that do not support ANSI escape codes.
//! Note that the cursor position is 0 based. This means that we start counting at 0 when setting the cursor position ect.
-
-use Context;
use super::ITerminalCursor;
use kernel::windows_kernel::{kernel, cursor};
@@ -17,41 +15,51 @@ impl WinApiCursor {
impl ITerminalCursor for WinApiCursor {
- fn goto(&self, x: u16, y: u16, context: &Context) {
+ fn goto(&self, x: u16, y: u16) {
kernel::set_console_cursor_position(x as i16, y as i16);
}
- fn pos(&self, context: &Context) -> (u16, u16) {
+ fn pos(&self) -> (u16, u16) {
cursor::pos()
}
- fn move_up(&self, count: u16, context: &Context) {
- let (xpos,ypos) = self.pos(context);
- self.goto(xpos, ypos - count, context);
+ fn move_up(&self, count: u16) {
+ let (xpos,ypos) = self.pos();
+ self.goto(xpos, ypos - count);
}
- fn move_right(&self, count: u16, context: &Context) {
- let (xpos,ypos) = self.pos(context);
- self.goto(xpos + count, ypos, context);
+ fn move_right(&self, count: u16) {
+ let (xpos,ypos) = self.pos();
+ self.goto(xpos + count, ypos);
}
- fn move_down(&self, count: u16, context: &Context) {
- let (xpos,ypos) = self.pos(context);
- self.goto(xpos, ypos + count,context);
+ fn move_down(&self, count: u16) {
+ let (xpos,ypos) = self.pos();
+ self.goto(xpos, ypos + count);
}
- fn move_left(&self, count: u16, context: &Context) {
- let (xpos,ypos) = self.pos(context);
- self.goto(xpos - count, ypos,context);
+ fn move_left(&self, count: u16) {
+ let (xpos,ypos) = self.pos();
+ self.goto(xpos - count, ypos);
}
- fn save_position(&mut self, context: &Context)
+ fn save_position(&mut self)
{
cursor::save_cursor_pos();
}
- fn reset_position(&self, context: &Context)
+ fn reset_position(&self)
{
cursor::reset_to_saved_position();
}
+
+ fn hide(&self)
+ {
+ kernel::cursor_visibility(false);
+ }
+
+ fn show(&self)
+ {
+ kernel::cursor_visibility(true);
+ }
}
diff --git a/src/kernel/windows_kernel/ansi_support.rs b/src/kernel/windows_kernel/ansi_support.rs
index 33b8d5e..109f9ff 100644
--- a/src/kernel/windows_kernel/ansi_support.rs
+++ b/src/kernel/windows_kernel/ansi_support.rs
@@ -1,24 +1,27 @@
//! This module handles the enabling `ANSI escape codes` for windows terminals.
-use {Context, StateManager};
-use state::commands::ICommand;
+use IStateCommand;
+use std::sync::{Once, ONCE_INIT};
static mut HAS_BEEN_TRYED_TO_ENABLE: bool = false;
static mut IS_ANSI_ON_WINDOWS_ENABLED: Option = None;
static mut DOES_WINDOWS_SUPPORT_ANSI: Option = None;
-
+static START: Once = ONCE_INIT;
/// Try enable `ANSI escape codes` and return the result.
-pub fn try_enable_ansi_support(context: &Context) -> bool
+pub fn try_enable_ansi_support() -> bool
{
- use state::commands::win_commands::EnableAnsiCommand;
- let mut command = EnableAnsiCommand::new();
- let success = command.execute(&context);
+ START.call_once(|| {
+ use state::commands::win_commands::EnableAnsiCommand;
+ let mut command = EnableAnsiCommand::new();
+ let success = command.execute();
- set_is_windows_ansi_supportable(success);
- set_ansi_enabled(success);
- has_been_tried_to_enable(true);
+ set_is_windows_ansi_supportable(success);
+ set_ansi_enabled(success);
+ has_been_tried_to_enable(true);
- success
+ });
+
+ windows_supportable()
}
/// Get whether ansi has been enabled.
diff --git a/src/kernel/windows_kernel/cursor.rs b/src/kernel/windows_kernel/cursor.rs
index 903d75a..150f4c9 100644
--- a/src/kernel/windows_kernel/cursor.rs
+++ b/src/kernel/windows_kernel/cursor.rs
@@ -28,4 +28,4 @@ pub fn pos() -> (u16,u16)
{
let csbi = kernel::get_console_screen_buffer_info();
( csbi.dwCursorPosition.X as u16, csbi.dwCursorPosition.Y as u16 )
-}
+}
\ No newline at end of file
diff --git a/src/kernel/windows_kernel/kernel.rs b/src/kernel/windows_kernel/kernel.rs
index 4b12d15..7341c85 100644
--- a/src/kernel/windows_kernel/kernel.rs
+++ b/src/kernel/windows_kernel/kernel.rs
@@ -1,18 +1,17 @@
//! This module is the core of all the `WINAPI` actions. All unsafe `WINAPI` function call are done here.
-
use winapi::um::winnt::HANDLE;
use winapi::um::winbase::{STD_OUTPUT_HANDLE, STD_INPUT_HANDLE };
use winapi::um::handleapi::INVALID_HANDLE_VALUE;
use winapi::um::processenv::{GetStdHandle};
use winapi::um::consoleapi::{SetConsoleMode,GetConsoleMode, };
-use winapi::shared::minwindef::{TRUE};
+use winapi::shared::minwindef::{TRUE, FALSE};
use winapi::um::wincon;
use winapi::um::wincon::
{
- SetConsoleWindowInfo, SetConsoleCursorPosition, SetConsoleTextAttribute, SetConsoleScreenBufferSize, CreateConsoleScreenBuffer,SetConsoleActiveScreenBuffer,
+ SetConsoleWindowInfo, SetConsoleCursorPosition, SetConsoleTextAttribute, SetConsoleScreenBufferSize, CreateConsoleScreenBuffer,SetConsoleActiveScreenBuffer, SetConsoleCursorInfo,
GetLargestConsoleWindowSize, GetConsoleScreenBufferInfo,
- FillConsoleOutputCharacterA, FillConsoleOutputAttribute,
- CONSOLE_SCREEN_BUFFER_INFO, SMALL_RECT, COORD, CHAR_INFO, PSMALL_RECT
+ FillConsoleOutputCharacterA, FillConsoleOutputAttribute,WriteConsoleOutputCharacterA,WriteConsoleOutputAttribute,
+ CONSOLE_SCREEN_BUFFER_INFO, SMALL_RECT, COORD, CHAR_INFO, PSMALL_RECT, CONSOLE_CURSOR_INFO
};
use super::{Empty};
@@ -132,6 +131,22 @@ pub fn set_console_cursor_position(x: i16, y: i16)
}
}
+pub fn cursor_visibility(visable: bool)
+{
+ let handle = get_output_handle();
+
+ let cursor_info = CONSOLE_CURSOR_INFO
+ {
+ dwSize: 100,
+ bVisible: if visable { FALSE } else {TRUE}
+ };
+
+ unsafe
+ {
+ SetConsoleCursorInfo(handle, &cursor_info);
+ }
+}
+
pub fn set_console_text_attribute(value: u16)
{
let output_handle = get_output_handle();
@@ -282,6 +297,32 @@ pub fn write_console_output(write_buffer: &HANDLE, copy_buffer: &mut [CHAR_INFO;
}
}
+pub fn write_char_buffer(handle: HANDLE, buf: &[u8])
+{
+ use std::ffi::CString;
+ use std::str;
+
+ // get buffer info
+ let csbi = get_console_screen_buffer_info();
+
+ // get string from u8[] and parse it to an c_str
+ let mut data = str::from_utf8(buf).unwrap();
+ let c_str = CString::new(data);
+ let ptr: *const u16 = c_str.unwrap().as_ptr() as *const u16;
+
+ // get current position
+ let current_pos = COORD {X: csbi.dwCursorPosition.X, Y: csbi.dwCursorPosition.Y};
+
+ let mut cells_written: u32 = 0;
+
+ // write to console
+ unsafe
+ {
+
+ WriteConsoleOutputAttribute(handle, ptr, data.len() as u32, current_pos, &mut cells_written);
+ }
+}
+
/// Parse integer to an bool
fn is_true(value: i32) -> bool
{
diff --git a/src/lib.rs b/src/lib.rs
index 26b172d..c324999 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -16,6 +16,7 @@ pub mod manager;
pub use shared::{screen, raw};
pub use state::context::Context;
+use state::commands::IStateCommand;
use state::command_manager::CommandManager;
use state::state_manager::StateManager;
use manager::ScreenManager;
diff --git a/src/manager/ansi_manager.rs b/src/manager/ansi_manager.rs
index aec57f6..5f83fa5 100644
--- a/src/manager/ansi_manager.rs
+++ b/src/manager/ansi_manager.rs
@@ -3,6 +3,7 @@
//! This module uses the stdout to write to the console.
use std::io::{self, Write};
+use std::any::Any;
use super::IScreenManager;
@@ -14,12 +15,11 @@ pub struct AnsiScreenManager
impl IScreenManager for AnsiScreenManager
{
- type Output = Box;
- fn stdout(&mut self) -> &mut Self::Output
- {
- return &mut self.output
- }
+// fn stdout(&mut self) -> &mut Self::Output
+// {
+// return &mut self.output
+// }
fn toggle_is_alternate_screen(&mut self, is_alternate_screen: bool)
{
@@ -37,6 +37,19 @@ impl IScreenManager for AnsiScreenManager
write!(self.output, "{}", string);
self.flush();
}
+
+ fn write(&mut self, buf: &[u8]) -> io::Result {
+ self.output.write(buf)
+ }
+
+ fn flush(&mut self) -> io::Result<()> {
+ self.output.flush()
+ }
+
+ fn as_any(&mut self) -> &mut Any
+ {
+ self
+ }
}
impl AnsiScreenManager {
@@ -46,15 +59,4 @@ impl AnsiScreenManager {
is_alternate_screen: false
}
}
-}
-
-impl Write for AnsiScreenManager
-{
- fn write(&mut self, buf: &[u8]) -> io::Result {
- self.output.write(buf)
- }
-
- fn flush(&mut self) -> io::Result<()> {
- self.stdout().flush()
- }
}
\ No newline at end of file
diff --git a/src/manager/manager.rs b/src/manager/manager.rs
index 9b91451..2a8d1e5 100644
--- a/src/manager/manager.rs
+++ b/src/manager/manager.rs
@@ -1,39 +1,38 @@
//! This module provides an interface for working with the sceen. With that I mean that you can get or wirte to the handle of the current screen. stdout.
//! Because crossterm can work with alternate screen, we need a place that holds the handle to the current screen. And this module provides this place.
+use super::{AnsiScreenManager, WinApiScreenManager, IScreenManager };
+use super::super::shared::functions;
+use std::any::Any;
-use super::IScreenManager;
-use super::ansi_manager::AnsiScreenManager;
+use std::fmt::Display;
+use std::io::{ self, Write };
-use std::io::Write;
+#[cfg(target_os = "windows")]
+use winapi::um::winnt::HANDLE;
/// Struct that stores an specific platform implementation for screen related actions.
pub struct ScreenManager
{
- screen_manager: Box>>
+ screen_manager: Box
}
impl ScreenManager
{
/// Create new screen manager instance whereon screen related actions can be performed.
pub fn new() -> ScreenManager {
- // #[cfg(target_os = "windows")]
- // let cursor = functions::get_module::>(WinApiCursor::new(), AnsiCursor::new());
- //
- // #[cfg(not(target_os = "windows"))]
+// #[cfg(target_os = "windows")]
+// let screen_manager = functions::get_module::>(Box::from(WinApiScreenManager::new()), Box::from(AnsiScreenManager::new())).unwrap();
+//
+// #[cfg(not(target_os = "windows"))]
+// let screen_manager = Box::new(AnsiScreenManager::new());
ScreenManager
{
- screen_manager: Box::new(AnsiScreenManager::new()),
+ screen_manager: Box::from(WinApiScreenManager::new()),
}
}
- /// Get the stdout of the current screen
- pub fn stdout(&mut self) -> &mut Box
- {
- self.screen_manager.stdout()
- }
-
- pub fn toggle_is_alternate_screen(&mut self,is_alternate_screen: bool)
+ pub fn toggle_is_alternate_screen(&mut self, is_alternate_screen: bool)
{
self.screen_manager.toggle_is_alternate_screen(is_alternate_screen);
}
@@ -49,4 +48,17 @@ impl ScreenManager
{
self.screen_manager.write_ansi_str(string);
}
-}
\ No newline at end of file
+
+ pub fn as_any(&mut self) -> &mut Any { self.screen_manager.as_any() }
+}
+
+impl Write for ScreenManager
+{
+ fn write(&mut self, buf: &[u8]) -> io::Result {
+ self.screen_manager.write(buf)
+ }
+
+ fn flush(&mut self) -> io::Result<()> {
+ self.screen_manager.flush()
+ }
+}
diff --git a/src/manager/mod.rs b/src/manager/mod.rs
index 95c9f1a..3f8484a 100644
--- a/src/manager/mod.rs
+++ b/src/manager/mod.rs
@@ -8,20 +8,26 @@ mod win_manager;
mod ansi_manager;
#[cfg(target_os = "windows")]
-use self::win_manager::WinApiScreenManager;
-use self::ansi_manager::AnsiScreenManager;
+pub use self::win_manager::WinApiScreenManager;
+pub use self::ansi_manager::AnsiScreenManager;
pub use self::manager::{ ScreenManager };
+use std::io;
+use std::any::Any;
pub trait IScreenManager
{
- type Output;
-
/// get the stdout of the screen. This can be used to write to the
- fn stdout(&mut self) -> &mut Self::Output;
+// fn stdout(&mut self) -> &mut Self::Output;
fn toggle_is_alternate_screen(&mut self, is_alternate_screen: bool);
/// Write ansi code as String to the current stdout.
fn write_ansi(&mut self, string: String);
/// Write a &str to the current stdout.
fn write_ansi_str(&mut self, string: &str);
+
+ fn write(&mut self, buf: &[u8]) -> io::Result;
+
+ fn flush(&mut self) -> io::Result<()>;
+
+ fn as_any(&mut self) -> &mut Any;
}
\ No newline at end of file
diff --git a/src/manager/win_manager.rs b/src/manager/win_manager.rs
index d5792c1..0f61962 100644
--- a/src/manager/win_manager.rs
+++ b/src/manager/win_manager.rs
@@ -2,21 +2,18 @@ use super::IScreenManager;
use kernel::windows_kernel::kernel;
use winapi::um::winnt::HANDLE;
+use std::io::{self,Write};
+use std::any::Any;
+
pub struct WinApiScreenManager
{
pub is_alternate_screen: bool,
- output: Box,
+ output: HANDLE,
+ alternate_handle: HANDLE
}
-impl IScreenManager for WinApiScreenManager where
+impl IScreenManager for WinApiScreenManager
{
- type Output = HANDLE;
-
- fn stdout(&mut self) -> &mut Self::Output
- {
- return &mut self.output
- }
-
fn toggle_is_alternate_screen(&mut self, is_alternate_screen: bool)
{
self.is_alternate_screen = is_alternate_screen;
@@ -33,24 +30,39 @@ impl IScreenManager for WinApiScreenManager where
// write!(self.output, "{}", string);
// self.flush();
}
+
+ fn write(&mut self, buf: &[u8]) -> io::Result {
+ if self.is_alternate_screen
+ {
+ kernel::write_char_buffer(self.alternate_handle, buf);
+ }
+ else {
+ kernel::write_char_buffer(self.output, buf);
+ }
+ Ok(0)
+ }
+
+ fn flush(&mut self) -> io::Result<()> {
+ Ok(())
+ }
+
+ fn as_any(&mut self) -> &mut Any
+ {
+ self
+ }
}
impl WinApiScreenManager {
pub fn new() -> Self {
WinApiScreenManager {
- output: (Box::from(kernel::get_output_handle())),
- is_alternate_screen: false
+ output: kernel::get_output_handle(),
+ is_alternate_screen: false,
+ alternate_handle: kernel::get_output_handle(),
}
}
-}
-//impl Write for AnsiScreenManager