From 2a40d10ae9437403c138545b41cc94cd6bcde681 Mon Sep 17 00:00:00 2001 From: = <=> Date: Sat, 16 Jun 2018 20:10:51 +0200 Subject: [PATCH] refactored code comments fixed examples and invalid comments. Also added documentation --- .idea/workspace.xml | 958 ++++++++++-------- .../bin.rs | 17 +- .../color/mod.rs | 131 ++- .../cursor/mod.rs | 41 +- .../terminal/alternate_screen.rs | 16 +- .../terminal/raw_mode.rs | 52 +- .../terminal/terminal.rs | 50 +- src/cursor/ansi_cursor.rs | 44 +- src/cursor/cursor.rs | 204 ++-- src/cursor/mod.rs | 25 +- src/cursor/winapi_cursor.rs | 26 +- src/kernel/unix_kernel/terminal.rs | 18 +- src/kernel/windows_kernel/ansi_support.rs | 2 +- src/kernel/windows_kernel/cursor.rs | 3 +- src/kernel/windows_kernel/handle.rs | 78 -- src/kernel/windows_kernel/kernel.rs | 2 +- src/kernel/windows_kernel/mod.rs | 2 +- src/lib.rs | 13 +- src/manager/ansi_manager.rs | 16 +- src/manager/manager.rs | 10 +- src/manager/mod.rs | 6 + src/shared/functions.rs | 4 +- src/shared/mod.rs | 1 - src/shared/raw.rs | 44 +- src/shared/screen.rs | 77 +- src/shared/terminal.rs | 82 -- src/shared/traits.rs | 8 - src/state/command_manager.rs | 40 + src/state/commands/mod.rs | 16 +- src/state/commands/shared_commands.rs | 25 +- src/state/commands/unix_command.rs | 52 +- src/state/commands/win_commands.rs | 19 +- src/state/context.rs | 123 ++- src/state/mod.rs | 6 +- src/state/state_manager.rs | 56 + src/style/color/ansi_color.rs | 6 +- src/style/color/color.rs | 22 +- src/style/color/mod.rs | 4 +- src/style/mod.rs | 3 +- src/style/styles/mod.rs | 2 +- src/style/styles/objectstyle.rs | 1 + src/style/styles/styledobject.rs | 2 +- src/terminal/ansi_terminal.rs | 24 +- src/terminal/mod.rs | 26 +- src/terminal/terminal.rs | 95 +- src/terminal/winapi_terminal.rs | 2 +- 46 files changed, 1313 insertions(+), 1141 deletions(-) delete mode 100644 src/kernel/windows_kernel/handle.rs delete mode 100644 src/shared/terminal.rs create mode 100644 src/state/command_manager.rs create mode 100644 src/state/state_manager.rs diff --git a/.idea/workspace.xml b/.idea/workspace.xml index a753f7a..b2e5059 100644 --- a/.idea/workspace.xml +++ b/.idea/workspace.xml @@ -2,30 +2,51 @@ - + + + - + + + + + + + + - + + + + + - + + + + + + + + + + - - + - - + + - - + + + + + + + + + + + + @@ -49,18 +80,18 @@ - - + + - - + + - - + + @@ -69,71 +100,58 @@ - - - - - - - - - - - - + + - + - - - - - - - - - - - - - - - + + - - + + - - + + - - + + - - + + - - + + - - + + + + + + + + + + + + @@ -150,14 +168,6 @@ - set - make - get - Display - get_mode - wincon - Empty - winapi Construct EnableRawModeCommandretu return @@ -172,26 +182,35 @@ &self.term HANDLE command - Context End termina screen colored_terminal ObjectStyle + changed_states + state context + Context + TerminalColor + conte + terminal_cursor + term + ScreenManager + color terminal crossterm_cursor 'context - context &self.context &Context Terminal + context D:\Windows\GIT\crossterm\src D:\Windows\GIT\crossterm + $PROJECT_DIR$/src @@ -205,57 +224,57 @@ @@ -305,8 +324,9 @@ - + + @@ -325,6 +345,20 @@ + + + + + + + + + + + + + + @@ -332,6 +366,12 @@ + + + + + + @@ -341,14 +381,7 @@ - - - - - - - - + @@ -381,6 +414,13 @@ + + + + + + + @@ -399,24 +439,23 @@ - - + + + - - @@ -611,15 +650,18 @@ - + + + + - - + @@ -630,26 +672,26 @@ - + + - + - @@ -692,343 +734,409 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + - - - - - - - - - - - - - - - - - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - - + + - + - - + + - + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 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 3a5f91e..61e656e 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 @@ -14,14 +14,23 @@ extern crate crossterm; mod terminal; +mod cursor; +mod color; use terminal::alternate_screen; use terminal::raw_mode; +use terminal::terminal as term; -use crossterm::cursor; - +use self::crossterm::Context; +use self::crossterm::terminal::ClearType; +use crossterm::raw; +use crossterm::screen; +use crossterm::raw::IntoRawMode; +use std::io::Write; +use std::{time, thread}; fn main() { - - raw_mode::print_wait_screen_on_alternate_window(); +// alternate_screen::switch_between_main_and_alternate_screen(); + let context = Context::new(); + raw_mode::print_wait_screen_on_alternate_window(); } \ 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 e07c49b..fdb6815 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 @@ -5,43 +5,54 @@ extern crate crossterm; use self::crossterm::style::{ Color }; +use self::crossterm::terminal; +use self::crossterm::Context; /// print some red font | demonstration. pub fn paint_foreground() -{ +{ + let context = Context::new(); + let terminal = terminal::terminal(&context); + // Pass an string to the `paint()` method with you want to paint. // This will give you an object back wits can be styled and displayed. - let mut styledobject = paint("Red font"); + let mut styledobject = terminal.paint("Red font"); // Call the method `with()` on the object given by `paint()` and pass in any Color from the Color enum. styledobject = styledobject.with(Color::Red); // Print the object to the console and see the result. println!("{}", styledobject); // Crossterm provides method chaining so that the above points can be inlined. - println!("{}", paint("Red font").with(Color::Red)); + println!("{}", terminal.paint("Red font").with(Color::Red)); } /// print some font on red background | demonstration. pub fn paint_background() -{ +{ + let context = Context::new(); + let terminal = terminal::terminal(&context); + // Pass an string to the `paint()` method with you want to paint. // This will give you an object back wits can be styled and displayed. - let mut styledobject = paint("Red background color"); + let mut styledobject = terminal.paint("Red background color"); // Call the method `on()` on the object given by `paint()` and pass in an Color from the Color enum. styledobject = styledobject.on(Color::Red); // Print the object to the console and check see the result println!("{}", styledobject); // Crossterm provides method chaining so that the above points can be inlined. - println!("{}", paint("Red background color").on(Color::Red)); + println!("{}", terminal.paint("Red background color").on(Color::Red)); } /// print font with fore- background color | demonstration. pub fn paint_foreground_and_background() -{ +{ + let context = Context::new(); + let terminal = terminal::terminal(&context); + // Pass an string to the `paint()` method with you want to paint. // This will give you an object back wits can be styled and displayed. - let mut styledobject = paint("Red font on blue background color"); + let mut styledobject = terminal.paint("Red font on blue background color"); /* Foreground color: Call the method `with()` on the object given by `paint()` Pass in an Color from the Color enum. @@ -56,77 +67,89 @@ pub fn paint_foreground_and_background() println!("{}", styledobject); // Crossterm provides method chaining so that the above points can be inlined. - println!("{}", paint("Red font on blue background color").with(Color::Red).on(Color::Blue)); + println!("{}", terminal.paint("Red font on blue background color").with(Color::Red).on(Color::Blue)); } /// Print all available foreground colors | demonstration. pub fn print_all_foreground_colors() { - println!("Black : \t {}", paint("â– ").with(Color::Black)); - println!("Red : \t\t {}", paint("â– ").with(Color::Red)); - println!("Dark Red: \t {}", paint("â– ").with(Color::DarkRed)); - println!("Green : \t {}", paint("â– ").with(Color::Green)); - println!("Dark Green : \t {}", paint("â– ").with(Color::DarkGreen)); - println!("Yellow : \t {}", paint("â– ").with(Color::Yellow)); - println!("Dark Yellow : \t {}", paint("â– ").with(Color::DarkYellow)); - println!("Blue : \t\t {}", paint("â– ").with(Color::Blue)); - println!("Dark Blue : \t {}", paint("â– ").with(Color::DarkBlue)); - println!("Magenta : \t {}", paint("â– ").with(Color::Magenta)); - println!("Dark Magenta : \t {}", paint("â– ").with(Color::DarkMagenta)); - println!("Cyan : \t\t {}", paint("â– ").with(Color::Cyan)); - println!("Dark Cyan : \t {}", paint("â– ").with(Color::DarkCyan)); - println!("Grey : \t\t {}", paint("â– ").with(Color::Grey)); - println!("White : \t {}", paint("â– ").with(Color::White)); + let context = Context::new(); + let terminal = terminal::terminal(&context); + + println!("Black : \t {}", terminal.paint("â– ").with(Color::Black)); + println!("Red : \t\t {}", terminal.paint("â– ").with(Color::Red)); + println!("Dark Red: \t {}", terminal.paint("â– ").with(Color::DarkRed)); + println!("Green : \t {}", terminal.paint("â– ").with(Color::Green)); + println!("Dark Green : \t {}", terminal.paint("â– ").with(Color::DarkGreen)); + println!("Yellow : \t {}", terminal.paint("â– ").with(Color::Yellow)); + println!("Dark Yellow : \t {}", terminal.paint("â– ").with(Color::DarkYellow)); + println!("Blue : \t\t {}", terminal.paint("â– ").with(Color::Blue)); + println!("Dark Blue : \t {}", terminal.paint("â– ").with(Color::DarkBlue)); + println!("Magenta : \t {}", terminal.paint("â– ").with(Color::Magenta)); + println!("Dark Magenta : \t {}", terminal.paint("â– ").with(Color::DarkMagenta)); + println!("Cyan : \t\t {}", terminal.paint("â– ").with(Color::Cyan)); + println!("Dark Cyan : \t {}", terminal.paint("â– ").with(Color::DarkCyan)); + println!("Grey : \t\t {}", terminal.paint("â– ").with(Color::Grey)); + println!("White : \t {}", terminal.paint("â– ").with(Color::White)); } /// Print all available foreground colors | demonstration. pub fn print_all_background_colors() { - println!("Black : \t {}", paint(" ").on(Color::Black)); - println!("Red : \t\t {}", paint(" ").on(Color::Red)); - println!("Dark Red: \t {}", paint(" ").on(Color::DarkRed)); - println!("Green : \t {}", paint(" ").on(Color::Green)); - println!("Dark Green : \t {}", paint(" ").on(Color::DarkGreen)); - println!("Yellow : \t {}", paint(" ").on(Color::Yellow)); - println!("Dark Yellow : \t {}", paint(" ").on(Color::DarkYellow)); - println!("Blue : \t\t {}", paint(" ").on(Color::Blue)); - println!("Dark Blue : \t {}", paint(" ").on(Color::DarkBlue)); - println!("Magenta : \t {}", paint(" ").on(Color::Magenta)); - println!("Dark Magenta : \t {}", paint(" ").on(Color::DarkMagenta)); - println!("Cyan : \t\t {}", paint(" ").on(Color::Cyan)); - println!("Dark Cyan : \t {}", paint(" ").on(Color::DarkCyan)); - println!("Grey : \t\t {}", paint(" ").on(Color::Grey)); - println!("White : \t {}", paint(" ").on(Color::White)); + let context = Context::new(); + let terminal = terminal::terminal(&context); + + println!("Black : \t {}", terminal.paint(" ").on(Color::Black)); + println!("Red : \t\t {}", terminal.paint(" ").on(Color::Red)); + println!("Dark Red: \t {}", terminal.paint(" ").on(Color::DarkRed)); + println!("Green : \t {}", terminal.paint(" ").on(Color::Green)); + println!("Dark Green : \t {}", terminal.paint(" ").on(Color::DarkGreen)); + println!("Yellow : \t {}", terminal.paint(" ").on(Color::Yellow)); + println!("Dark Yellow : \t {}", terminal.paint(" ").on(Color::DarkYellow)); + println!("Blue : \t\t {}", terminal.paint(" ").on(Color::Blue)); + println!("Dark Blue : \t {}", terminal.paint(" ").on(Color::DarkBlue)); + println!("Magenta : \t {}", terminal.paint(" ").on(Color::Magenta)); + println!("Dark Magenta : \t {}", terminal.paint(" ").on(Color::DarkMagenta)); + println!("Cyan : \t\t {}", terminal.paint(" ").on(Color::Cyan)); + println!("Dark Cyan : \t {}", terminal.paint(" ").on(Color::DarkCyan)); + println!("Grey : \t\t {}", terminal.paint(" ").on(Color::Grey)); + println!("White : \t {}", terminal.paint(" ").on(Color::White)); #[cfg(unix)] - println!("RGB (10,10,10): \t {}", paint(" ").on(Color::Rgb {r: 10, g: 10, b: 10})); + println!("RGB (10,10,10): \t {}", terminal.paint(" ").on(Color::Rgb {r: 10, g: 10, b: 10})); #[cfg(unix)] - println!("RGB (10,10,10): \t {}", paint(" ").on(Color::AnsiValue(50))); + println!("RGB (10,10,10): \t {}", terminal.paint(" ").on(Color::AnsiValue(50))); } /// Print font with all available attributes. Note that this can only be used at unix systems and that some are not supported widely | demonstration.. #[cfg(unix)] pub fn print_font_with_attributes() { - println!("{}", paint("Normal text")); - println!("{}", paint("Bold text").bold()); - println!("{}", paint("Italic text").italic()); - println!("{}", paint("Slow blinking text").slow_blink()); - println!("{}", paint("Rapid blinking text").rapid_blink()); - println!("{}", paint("Hidden text").hidden()); - println!("{}", paint("Underlined text").underlined()); - println!("{}", paint("Reversed color").reverse()); - println!("{}", paint("Dim text color").dim()); - println!("{}", paint("Crossed out font").crossed_out()); + let context = Context::new(); + let terminal = terminal::terminal(&context); + + println!("{}", terminal.paint("Normal text")); + println!("{}", terminal.paint("Bold text").bold()); + println!("{}", terminal.paint("Italic text").italic()); + println!("{}", terminal.paint("Slow blinking text").slow_blink()); + println!("{}", terminal.paint("Rapid blinking text").rapid_blink()); + println!("{}", terminal.paint("Hidden text").hidden()); + println!("{}", terminal.paint("Underlined text").underlined()); + println!("{}", terminal.paint("Reversed color").reverse()); + println!("{}", terminal.paint("Dim text color").dim()); + println!("{}", terminal.paint("Crossed out font").crossed_out()); } /// Print all supported rgb colors | demonstration. #[cfg(unix)] pub fn print_supported_colors() -{ - let count = crossterm::style::color().get_available_color_count().unwrap(); +{ + let context = Context::new(); + let terminal = terminal::terminal(&context); + + let count = crossterm::style::color(context.screen_manager.clone()).get_available_color_count().unwrap(); for i in 0..count { - println!("{}", paint(format!("Color: {}",i)).with(Color::AnsiValue(i as u8))); + println!("{}", terminal.paint(format!("Color: {}",i)).with(Color::AnsiValue(i as u8))); } } \ No newline at end of file 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 9e0f949..3c3480f 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 @@ -3,23 +3,38 @@ //! extern crate crossterm; - use self::crossterm::cursor::{cursor, TerminalCursor}; +use self::crossterm::Context; /// Set the cursor to position X: 10, Y: 5 in the terminal. pub fn goto() { + let context = Context::new(); + // Get the cursor - let mut cursor = cursor(); + let mut cursor = cursor(&context); // Set the cursor to position X: 10, Y: 5 in the terminal cursor.goto(10,5); } +/// get the cursor position +pub fn pos() +{ + let context = Context::new(); + + // Get the cursor + let mut cursor = cursor(&context); + // get the cursor position. + let (x,y) = cursor.pos(); +} + /// Move the cursor 3 up | demonstration. pub fn move_up() { + let context = Context::new(); + // 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 cursor.move_up(3); } @@ -27,8 +42,10 @@ pub fn move_up() /// Move the cursor 3 to the right | demonstration. pub fn move_right() { + let context = Context::new(); + // 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 cursor.move_right(3); } @@ -36,8 +53,10 @@ pub fn move_right() /// Move the cursor 3 down | demonstration. pub fn move_down() { + let context = Context::new(); + // 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 cursor.move_down(3); } @@ -45,8 +64,10 @@ pub fn move_down() /// Move the cursor 3 to the left | demonstration. pub fn move_left() { + let context = Context::new(); + // 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 cursor.move_left(3); } @@ -54,10 +75,12 @@ pub fn move_left() /// Print character at X: 10 Y: 5 | demonstration. pub fn print() { + let context = Context::new(); + // To print an some displayable content on an certain position. // Get the cursor - let mut cursor = cursor(); + let mut cursor = cursor(&context); // 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 @@ -79,7 +102,9 @@ pub fn print() /// Save and reset cursor position | demonstration.. pub fn safe_and_reset_position() { - let mut cursor = cursor(); + let context = Context::new(); + + let mut cursor = cursor(&context); // 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 08b27d2..379125d 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 @@ -1,6 +1,6 @@ extern crate crossterm; -use crossterm::Terminal; +use crossterm::Context; use crossterm::screen::AlternateScreen; use crossterm::cursor::cursor; use crossterm::terminal::{self, ClearType}; @@ -8,7 +8,7 @@ use crossterm::terminal::{self, ClearType}; use std::io::{Write, stdout}; use std::{time, thread}; -fn print_wait_screen(terminal: &Terminal) +fn print_wait_screen(terminal: &Context) { terminal::terminal(&terminal).clear(ClearType::All); @@ -39,16 +39,16 @@ fn print_wait_screen(terminal: &Terminal) pub fn print_wait_screen_on_alternate_window() { - let terminal = Terminal::new(); + let context = Context::new(); // create scope. If this scope ends the screen will be switched back to mainscreen. // 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(&terminal); + let mut screen = AlternateScreen::from(&context); // Print the wait screen. - print_wait_screen(&terminal); + print_wait_screen(&context); } println!("Whe are back at the main screen"); @@ -56,12 +56,12 @@ pub fn print_wait_screen_on_alternate_window() pub fn switch_between_main_and_alternate_screen() { - let terminal = Terminal::new(); - let mut cursor = cursor(&terminal); + let context = Context::new(); + let mut cursor = cursor(&context); { // create new alternate screen instance and switch to the alternate screen. - let mut screen = AlternateScreen::from(&terminal); + let mut screen = AlternateScreen::from(&context); cursor.goto(0,0); 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 36f76e0..b76e2d2 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 @@ -1,6 +1,6 @@ extern crate crossterm; -use crossterm::Terminal; +use crossterm::Context; use crossterm::screen::AlternateScreen; use crossterm::cursor::cursor; use crossterm::terminal::{self, ClearType}; @@ -11,49 +11,43 @@ use std::{time, thread}; use crossterm::raw::IntoRawMode; // raw screen is not working correctly currently -fn print_wait_screen(terminal: &Terminal) +fn print_wait_screen(context: &Context) { - terminal::terminal(&terminal).clear(ClearType::All); + terminal::terminal(&context).clear(ClearType::All); - let mut cursor = cursor(&terminal); - cursor.goto(0,0); - - { - let mut screen_manager = terminal.screen_manager.lock().unwrap(); - { - write!(screen_manager.stdout(), - "Welcome to the wait screen.\n\ - Please wait a few seconds until we arrive back at the main screen.\n\ - Progress: " - ); - } - } + let mut cursor = cursor(&context); + 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: "); // print some progress example. for i in 1..5 - { - // print the current counter at the line of `Seconds to Go: {counter}` - cursor.goto(10,2).print(format!("{} of the 5 items processed", i)); + { + // print the current counter at the line of `Seconds to Go: {counter}` + cursor.goto(10,2).print(format!("{} of the 5 items processed", i)); - // 1 second delay - thread::sleep(time::Duration::from_secs(1)); - } + // 1 second delay + thread::sleep(time::Duration::from_secs(1)); + } } pub fn print_wait_screen_on_alternate_window() { - let terminal = Terminal::new(); + let context = Context::new(); // create scope. If this scope ends the screen will be switched back to mainscreen. - // because `AlternateScreen` switches back to main screen when switching back. + // because `AlternateScreen` switches back to main screen when going out of scope. { - let a = stdout().into_raw_mode(&terminal); + // create new alternate screen instance this call is also switching the screen to alternate screen. + // then convert the output of the program to raw mode. + // then print the wait screen on the alternate screen in raw mode. + let mut screen = AlternateScreen::from(&context); + let alternate_screen = screen.into_raw_mode(&context); - thread::sleep(time::Duration::from_secs(3)); + // Print the wait screen. + print_wait_screen(&context); - -// // Print the wait screen. -// print_wait_screen(&terminal); + screen.flush(); } println!("Whe are back at the main screen"); 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 58451c2..5c32604 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 @@ -4,7 +4,7 @@ extern crate crossterm; -use crossterm::Terminal; +use crossterm::Context; use crossterm::terminal::{ ClearType, terminal }; use crossterm::cursor; @@ -18,10 +18,10 @@ fn print_test_data() /// Clear all lines in terminal | demonstration pub fn clear_all_lines() { - let term = Terminal::new(); + let context = Context::new(); // Get terminal - let mut terminal = terminal(&term); + let mut terminal = terminal(&context); print_test_data(); @@ -32,15 +32,15 @@ pub fn clear_all_lines() /// Clear all lines from cursor position X:4, Y:4 down | demonstration pub fn clear_from_cursor_down() { - let term = Terminal::new(); + let context = Context::new(); // Get terminal - let mut terminal = terminal(&term); + let mut terminal = terminal(&context); print_test_data(); // Set terminal cursor position (see example for more info). - cursor::cursor(&term).goto(4,8); + cursor::cursor(&context).goto(4,8); // Clear all cells from current cursor position down. terminal.clear(ClearType::FromCursorDown); @@ -49,15 +49,15 @@ pub fn clear_from_cursor_down() /// Clear all lines from cursor position X:4, Y:4 up | demonstration pub fn clear_from_cursor_up() { - let term = Terminal::new(); + let context = Context::new(); // Get terminal - let mut terminal = terminal(&term); + let mut terminal = terminal(&context); print_test_data(); // Set terminal cursor position (see example for more info). - cursor::cursor(&term).goto(4,4); + cursor::cursor(&context).goto(4,4); // Clear all cells from current cursor position down. terminal.clear(ClearType::FromCursorUp); @@ -66,15 +66,15 @@ pub fn clear_from_cursor_up() /// Clear all lines from cursor position X:4, Y:4 up | demonstration pub fn clear_current_line() { - let term = Terminal::new(); + let context = Context::new(); // Get terminal - let mut terminal = terminal(&term); + let mut terminal = terminal(&context); print_test_data(); // Set terminal cursor position (see example for more info). - cursor::cursor(&term).goto(4,4); + cursor::cursor(&context).goto(4,4); // Clear current line cells. terminal.clear(ClearType::CurrentLine); @@ -83,15 +83,15 @@ pub fn clear_current_line() /// Clear all lines from cursor position X:4, Y:7 up | demonstration pub fn clear_until_new_line() { - let term = Terminal::new(); + let context = Context::new(); // Get terminal - let mut terminal = terminal(&term); + let mut terminal = terminal(&context); print_test_data(); // Set terminal cursor position (see example for more info). - cursor::cursor(&term).goto(4,20); + cursor::cursor(&context).goto(4,20); // Clear all the cells until next line. terminal.clear(ClearType::UntilNewLine); @@ -100,10 +100,10 @@ pub fn clear_until_new_line() /// Print the the current terminal size | demonstration. pub fn print_terminal_size() { - let term = Terminal::new(); + let context = Context::new(); // Get terminal - let mut terminal = terminal(&term); + let mut terminal = terminal(&context); // Get terminal size let terminal_size = terminal.terminal_size(); // Print results @@ -113,9 +113,9 @@ pub fn print_terminal_size() /// Set the terminal size to width 10, height: 10 | demonstration. pub fn set_terminal_size() { - let term = Terminal::new(); + let context = Context::new(); - let mut terminal = terminal(&term); + let mut terminal = terminal(&context); terminal.set_size(10,10); } @@ -123,11 +123,11 @@ pub fn set_terminal_size() /// Scroll down 10 lines | demonstration. pub fn scroll_down() { - let term = Terminal::new(); + let context = Context::new(); print_test_data(); // Get terminal - let mut terminal = terminal(&term); + let mut terminal = terminal(&context); // Scroll down 10 lines. terminal.scroll_down(10); } @@ -135,12 +135,12 @@ pub fn scroll_down() /// Scroll down 10 lines | demonstration. pub fn scroll_up() { - let term = Terminal::new(); + let context = Context::new(); print_test_data(); // Get terminal - let mut terminal = terminal(&term); + let mut terminal = terminal(&context); // Scroll up 10 lines. terminal.scroll_up(10); } @@ -148,10 +148,10 @@ pub fn scroll_up() /// Resize the terminal to X: 10, Y: 10 | demonstration. pub fn resize_terminal() { - let term = Terminal::new(); + let context = Context::new(); // Get terminal - let mut terminal = terminal(&term); + let mut terminal = terminal(&context); // Get terminal size terminal.set_size(10,10); } diff --git a/src/cursor/ansi_cursor.rs b/src/cursor/ansi_cursor.rs index 8d91add..02c2769 100644 --- a/src/cursor/ansi_cursor.rs +++ b/src/cursor/ansi_cursor.rs @@ -1,75 +1,73 @@ //! This is an ANSI specific implementation for cursor related action. //! This module is used for windows 10 terminals and unix terminals by default. +//! Note that the cursor position is 0 based. This means that we start counting at 0 when setting the cursor position ect. -use Terminal ; +use Context; use shared::functions; use super::ITerminalCursor; - /// This struct is an ansi implementation for cursor related actions. -pub struct AnsiCursor -{ } +pub struct AnsiCursor; -impl<'output> AnsiCursor { +impl AnsiCursor { pub fn new() -> Box { Box::from(AnsiCursor {}) } } -impl<'term> ITerminalCursor for AnsiCursor { +impl ITerminalCursor for AnsiCursor { - fn goto(&self, x: u16, y: u16, terminal: &Terminal) + fn goto(&self, x: u16, y: u16, context: &Context) { - // ANSI codes are one-based. I want 0 based so we just need to increment and x,y. - let mut screen = terminal.screen_manager.lock().unwrap(); + let mut screen = context.screen_manager.lock().unwrap(); { screen.write_ansi(format!(csi!("{};{}H"), y + 1, x +1)); } } - fn pos(&self, terminal: &Terminal) -> (u16, u16) { - functions::get_cursor_position(&terminal) + fn pos(&self, context: &Context) -> (u16, u16) { + functions::get_cursor_position(&context) } - fn move_up(&self, count: u16, terminal: &Terminal) { - let mut screen = terminal.screen_manager.lock().unwrap(); + fn move_up(&self, count: u16, context: &Context) { + let mut screen = context.screen_manager.lock().unwrap(); { screen.write_ansi(format!(csi!("{}A"), count)); } } - fn move_right(&self, count: u16, terminal: &Terminal) { - let mut screen = terminal.screen_manager.lock().unwrap(); + fn move_right(&self, count: u16, context: &Context) { + let mut screen = context.screen_manager.lock().unwrap(); { screen.write_ansi(format!(csi!("{}C"), count)); } } - fn move_down(&self, count: u16, terminal: &Terminal) { - let mut screen = terminal.screen_manager.lock().unwrap(); + fn move_down(&self, count: u16, context: &Context) { + let mut screen = context.screen_manager.lock().unwrap(); { screen.write_ansi(format!(csi!("{}B"), count)); } } - fn move_left(&self, count: u16, terminal: &Terminal) { - let mut screen = terminal.screen_manager.lock().unwrap(); + fn move_left(&self, count: u16, context: &Context) { + let mut screen = context.screen_manager.lock().unwrap(); { screen.write_ansi(format!(csi!("{}D"), count)); } } - fn save_position(&mut self, terminal: &Terminal) + fn save_position(&mut self, context: &Context) { - let mut screen = terminal.screen_manager.lock().unwrap(); + let mut screen = context.screen_manager.lock().unwrap(); { screen.write_ansi_str(csi!("s")); } } - fn reset_position(&self, terminal: &Terminal) + fn reset_position(&self, context: &Context) { - let mut screen = terminal.screen_manager.lock().unwrap(); + let mut screen = context.screen_manager.lock().unwrap(); { screen.write_ansi_str(csi!("u")); } diff --git a/src/cursor/cursor.rs b/src/cursor/cursor.rs index f12e923..d86c0a3 100644 --- a/src/cursor/cursor.rs +++ b/src/cursor/cursor.rs @@ -1,31 +1,31 @@ //! With this module you can perform actions that are cursor related. -//! Like changing and displaying the position of the cursor in terminal. +//! Like changing and display the position of the cursor in terminal. //! -//! Note that positions of the cursor are 0 -based witch means that the coordinates starts counting from 0 +//! Note that positions of the cursor are 0 -based witch means that the coordinates (cells) starts counting from 0 use super::*; -use Terminal; +use Context; use std::fmt::Display; use std::io::Write; /// Struct that stores an specific platform implementation for cursor related actions. -pub struct TerminalCursor<'term> { - terminal: &'term Terminal, +pub struct TerminalCursor<'context> { + context: &'context Context, terminal_cursor: Option>, } -impl <'term> TerminalCursor<'term> +impl <'context> TerminalCursor<'context> { /// Create new cursor instance whereon cursor related actions can be performed. - pub fn new(terminal: &'term Terminal) -> TerminalCursor<'term> { + pub fn new(context: &'context Context) -> TerminalCursor<'context> { #[cfg(target_os = "windows")] let cursor = functions::get_module::>(WinApiCursor::new(), AnsiCursor::new()); #[cfg(not(target_os = "windows"))] let cursor = Some(AnsiCursor::new() as Box); - TerminalCursor { terminal_cursor: cursor , terminal: terminal} + TerminalCursor { terminal_cursor: cursor , context} } /// Goto some position (x,y) in the terminal. @@ -34,16 +34,24 @@ impl <'term> TerminalCursor<'term> /// /// ```rust /// - /// extern crate crossterm; + /// extern crate crossterm; + /// 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); + // } /// - /// use self::crossterm::cursor; - /// - /// cursor::cursor().goto(10,10); - /// /// ``` - pub fn goto(&mut self, x: u16, y: u16) -> &mut TerminalCursor<'term> { + pub fn goto(&mut self, x: u16, y: u16) -> &mut TerminalCursor<'context> { if let Some(ref terminal_cursor) = self.terminal_cursor { - terminal_cursor.goto(x, y, &self.terminal); + terminal_cursor.goto(x, y, &self.context); } self } @@ -54,17 +62,24 @@ impl <'term> TerminalCursor<'term> /// /// ```rust /// - /// extern crate crossterm; + /// extern crate crossterm; + /// use self::crossterm::Context; + /// use self::crossterm::cursor; + /// + /// pub fn pos() + /// { + /// let context = Context::new(); + /// + /// // Get the cursor + /// let mut cursor = cursor(&context); + /// // get the cursor position. + /// let (x,y) = cursor.pos(); + /// } /// - /// use self::crossterm::cursor; - /// - /// let pos = cursor::cursor().pos(); - /// println!("{:?}", pos); - /// /// ``` pub fn pos(&mut self) -> (u16, u16) { if let Some(ref terminal_cursor) = self.terminal_cursor { - terminal_cursor.pos(&self.terminal) + terminal_cursor.pos(&self.context) } else { (0, 0) } @@ -75,21 +90,25 @@ impl <'term> TerminalCursor<'term> /// #Example /// /// ```rust - /// - /// extern crate crossterm; /// - /// use self::crossterm::cursor; - /// - /// // Move 1 time up - /// cursor::cursor().move_up(1); - /// - /// // Move 2 times up - /// cursor::cursor().move_up(2); + /// extern crate crossterm; + /// use self::crossterm::Context; + /// use self::crossterm::cursor; + /// + /// pub fn move_up() + /// { + /// let context = Context::new(); + /// + /// // Get the cursor + /// let mut cursor = cursor(&context); + /// // Move the cursor to position 3 times to the up in the terminal + /// cursor.move_up(3); + /// } /// /// ``` - pub fn move_up(&mut self, count: u16) -> &mut TerminalCursor<'term> { + pub fn move_up(&mut self, count: u16) -> &mut TerminalCursor<'context> { if let Some(ref terminal_cursor) = self.terminal_cursor { - terminal_cursor.move_up(count, &self.terminal); + terminal_cursor.move_up(count, &self.context); } self } @@ -99,22 +118,23 @@ impl <'term> TerminalCursor<'term> /// #Example /// /// ```rust + /// extern crate crossterm; + /// use self::crossterm::Context; + /// use self::crossterm::cursor; /// - /// extern crate crossterm; - /// - /// use self::crossterm::cursor; - /// - /// - /// // move 1 time right - /// cursor::cursor().move_right(1); - /// - /// // move 2 times right - /// cursor::cursor().move_right(2); - /// + // 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<'term> { + pub fn move_right(&mut self, count: u16) -> &mut TerminalCursor<'context> { if let Some(ref terminal_cursor) = self.terminal_cursor { - terminal_cursor.move_right(count, &self.terminal); + terminal_cursor.move_right(count, &self.context); } self } @@ -125,20 +145,24 @@ impl <'term> TerminalCursor<'term> /// /// ```rust /// - /// extern crate crossterm; + /// extern crate crossterm; + /// use self::crossterm::Context; + /// use self::crossterm::cursor; /// - /// use self::crossterm::cursor; - /// - /// // move 1 time down - /// cursor::cursor().move_down(1); - /// - /// // move 2 times down - /// cursor::cursor().move_down(2); + /// pub fn move_down() + /// { + /// let context = Context::new(); + /// + /// // Get the cursor + /// let mut cursor = cursor(&context); + /// // Move the cursor to position 3 times to the down in the terminal + /// cursor.move_down(3); + /// } /// /// ``` - pub fn move_down(&mut self, count: u16) -> &mut TerminalCursor<'term> { + pub fn move_down(&mut self, count: u16) -> &mut TerminalCursor<'context> { if let Some(ref terminal_cursor) = self.terminal_cursor { - terminal_cursor.move_down(count, &self.terminal); + terminal_cursor.move_down(count, &self.context); } self } @@ -149,20 +173,24 @@ impl <'term> TerminalCursor<'term> /// /// ```rust /// - /// extern crate crossterm; + /// extern crate crossterm; + /// use self::crossterm::Context; + /// use self::crossterm::cursor; /// - /// use self::crossterm::cursor; + /// pub fn move_left() + /// { + /// let context = Context::new(); + /// + /// // Get the cursor + /// let mut cursor = cursor(&context); + /// // Move the cursor to position 3 times to the left in the terminal + /// cursor.move_left(3); + /// } /// - /// // move 1 time left - /// cursor::cursor().move_left(1); - /// - /// // move 2 time left - /// cursor::cursor().move_left(2); - /// /// ``` - pub fn move_left(&mut self, count: u16) -> &mut TerminalCursor<'term> { + pub fn move_left(&mut self, count: u16) -> &mut TerminalCursor<'context> { if let Some(ref terminal_cursor) = self.terminal_cursor { - terminal_cursor.move_left(count, &self.terminal); + terminal_cursor.move_left(count, &self.context); } self } @@ -184,23 +212,27 @@ impl <'term> TerminalCursor<'term> /// /// extern crate crossterm; /// + /// use self::crossterm::Context; /// use self::crossterm::cursor; + /// /// use std; /// use std::io::Write; /// + /// let context = Context::new(); + /// /// // of course we can just do this. - /// cursor::cursor().goto(10,10); + /// cursor::cursor(&context).goto(10,10); /// print!("@"); /// std::io::stdout().flush(); /// /// // but now we can chain the methods so it looks cleaner and it automatically flushes the buffer. - /// cursor::cursor() + /// cursor::cursor(&context) /// .goto(10,10) /// .print("@"); /// /// ``` - pub fn print(&mut self, value: D) -> &mut TerminalCursor<'term> { - let mut screen = self.terminal.screen_manager.lock().unwrap(); + pub fn print(&mut self, value: D) -> &mut TerminalCursor<'context> { + let mut screen = self.context.screen_manager.lock().unwrap(); { 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. @@ -218,16 +250,17 @@ impl <'term> TerminalCursor<'term> /// ```rust /// /// extern crate crossterm; - /// + /// use self::crossterm::Context; /// use self::crossterm::cursor; /// - /// cursor::cursor().safe_position(); + /// let context = Context::new(); + /// cursor::cursor(&context).safe_position(); /// /// ``` pub fn save_position(&mut self) { if let Some(ref mut terminal_cursor) = self.terminal_cursor { - terminal_cursor.save_position(&self.terminal); + terminal_cursor.save_position(&self.context); } } @@ -240,40 +273,43 @@ impl <'term> TerminalCursor<'term> /// ```rust /// /// extern crate crossterm; - /// /// use self::crossterm::cursor::cursor; + /// use self::crossterm::Context; /// - /// cursor().reset_position(); + /// let context = Context::new(); + /// cursor(&context).reset_position(); /// /// ``` pub fn reset_position(&mut self) { if let Some(ref terminal_cursor) = self.terminal_cursor { - terminal_cursor.reset_position(&self.terminal); + terminal_cursor.reset_position(&self.context); } } } /// Get an TerminalCursor implementation whereon cursor related actions can be performed. /// -/// Check `/examples/cursor` in the libary for more spesific examples. +/// Check `/examples/version/cursor` in the libary for more spesific examples. /// /// #Example /// /// ```rust /// -/// extern crate crossterm; +/// extern crate crossterm; +/// use self::crossterm::Context; +/// use self::crossterm::cursor; +/// +/// let context = Context::new(); /// -/// use self::crossterm::cursor; -/// /// // Get cursor and goto pos X: 5, Y: 10 -/// let mut cursor = cursor::cursor(); +/// let mut cursor = cursor::cursor(&context); /// cursor.goto(5,10); /// /// //Or you can do it in one line. -/// cursor::cursor().goto(5,10); +/// cursor::cursor(&context).goto(5,10); /// /// ``` -pub fn cursor<'term>(terminal: &'term Terminal) -> Box> { - Box::from(TerminalCursor::new(&terminal)) +pub fn cursor<'context>(context: &'context Context) -> Box> { + Box::from(TerminalCursor::new(&context)) } diff --git a/src/cursor/mod.rs b/src/cursor/mod.rs index 8389102..f44d246 100644 --- a/src/cursor/mod.rs +++ b/src/cursor/mod.rs @@ -9,6 +9,7 @@ //! pub mod cursor; + #[cfg(target_os = "windows")] mod winapi_cursor; mod ansi_cursor; @@ -17,7 +18,7 @@ mod ansi_cursor; use self::winapi_cursor::WinApiCursor; use self::ansi_cursor::AnsiCursor; -use Terminal; +use Context; pub use self::cursor::{ cursor, TerminalCursor }; ///! This trait defines the actions that can be preformed with the terminal cursor. @@ -29,20 +30,20 @@ pub use self::cursor::{ cursor, TerminalCursor }; ///! This trait is implemented for `WINAPI` (Windows specific) and `ANSI` (Unix specific), ///! so that cursor related actions can be preformed on both unix and windows systems. pub trait ITerminalCursor { - /// Goto some location (x,y) in the terminal. - fn goto(&self, x: u16, y: u16, terminal: &Terminal); - /// Get the location (x,y) of the current cusror in the terminal - fn pos(&self, terminal: &Terminal) -> (u16, u16); + /// Goto some location (x,y) in the context. + fn goto(&self, x: u16, y: u16, context: &Context); + /// Get the location (x,y) of the current cusror in the context + fn pos(&self, context: &Context) -> (u16, u16); /// Move cursor n times up - fn move_up(&self, count: u16, terminal: &Terminal); + fn move_up(&self, count: u16, context: &Context); /// Move the cursor `n` times to the right. - fn move_right(&self, count: u16, terminal: &Terminal); + fn move_right(&self, count: u16, context: &Context); /// Move the cursor `n` times down. - fn move_down(&self, count: u16, terminal: &Terminal); + fn move_down(&self, count: u16, context: &Context); /// Move the cursor `n` times left. - 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. - fn save_position(&mut self, terminal: &Terminal); + fn move_left(&self, count: u16, context: &Context); + /// 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); /// Return to saved cursor position - fn reset_position(&self, terminal: &Terminal); + fn reset_position(&self, context: &Context); } \ No newline at end of file diff --git a/src/cursor/winapi_cursor.rs b/src/cursor/winapi_cursor.rs index 770ac24..0dc37c7 100644 --- a/src/cursor/winapi_cursor.rs +++ b/src/cursor/winapi_cursor.rs @@ -1,58 +1,56 @@ //! 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 {Terminal, Construct}; +use Context; use super::ITerminalCursor; use kernel::windows_kernel::{kernel, cursor}; /// This struct is an windows implementation for cursor related actions. pub struct WinApiCursor; -impl Construct for WinApiCursor { - fn new() -> Box { +impl WinApiCursor { + pub fn new() -> Box { Box::from(WinApiCursor { }) } } impl ITerminalCursor for WinApiCursor { - fn goto(&self, x: u16, y: u16, terminal: &Terminal) { + fn goto(&self, x: u16, y: u16, context: &Context) { kernel::set_console_cursor_position(x as i16, y as i16); } - fn pos(&self, terminal: &Terminal) -> (u16, u16) { + fn pos(&self, context: &Context) -> (u16, u16) { cursor::pos() } - fn move_up(&self, count: u16, terminal: &Terminal) { + fn move_up(&self, count: u16, context: &Context) { let (xpos,ypos) = self.pos(); self.goto(xpos, ypos - count); } - fn move_right(&self, count: u16, terminal: &Terminal) { + fn move_right(&self, count: u16, context: &Context) { let (xpos,ypos) = self.pos(); - self.goto(xpos + count, ypos); } - fn move_down(&self, count: u16, terminal: &Terminal) { + fn move_down(&self, count: u16, context: &Context) { let (xpos,ypos) = self.pos(); - self.goto(xpos, ypos + count); } - fn move_left(&self, count: u16, terminal: &Terminal) { + fn move_left(&self, count: u16, context: &Context) { let (xpos,ypos) = self.pos(); - self.goto(xpos - count, ypos); } - fn save_position(&mut self, terminal: &Terminal) + fn save_position(&mut self, context: &Context) { cursor::save_cursor_pos(); } - fn reset_position(&self, terminal: &Terminal) + fn reset_position(&self, context: &Context) { cursor::reset_to_saved_position(); } diff --git a/src/kernel/unix_kernel/terminal.rs b/src/kernel/unix_kernel/terminal.rs index d7b6f17..a44a2cc 100644 --- a/src/kernel/unix_kernel/terminal.rs +++ b/src/kernel/unix_kernel/terminal.rs @@ -1,13 +1,14 @@ //! This module contains all `unix` specific terminal related logic. -use { libc, Context, Terminal }; +use {libc, StateManager, Context, CommandManager}; use termios::Termios; pub use self::libc::{termios}; use self::libc::{STDOUT_FILENO, TIOCGWINSZ, c_ushort, ioctl, c_int}; -use state::commands::{ NoncanonicalModeCommand, IContextCommand} ; +use state::commands::{ NoncanonicalModeCommand, IStateCommand} ; use std::io::Error; use std::{ io, mem }; +use std::rc::Rc; /// A representation of the size of the current terminal. #[repr(C)] @@ -40,16 +41,15 @@ pub fn terminal_size() -> (u16,u16) { } /// Get the current cursor position. -pub fn pos(terminal: &Terminal) -> (u16,u16) +pub fn pos(terminal: &Context) -> (u16, u16) { use std::io::{ Write,Read }; + let mut command_id = NoncanonicalModeCommand::new(&terminal.state_manager); - let mut command = NoncanonicalModeCommand::new(&terminal.context); - command.0.execute(&terminal); + CommandManager::execute(terminal, command_id); // This code is original written by term_cursor credits to them. - use std::io; let mut std = io::stdout(); // Write command @@ -97,10 +97,8 @@ pub fn pos(terminal: &Terminal) -> (u16,u16) // Expect `R` let res = if c == 'R' { (cols as u16, rows as u16) } else { return (0, 0) }; - let mut context = terminal.context.lock().unwrap(); - { - context.undo_state(command.1, terminal); - } + CommandManager::undo(terminal, command_id); + res } diff --git a/src/kernel/windows_kernel/ansi_support.rs b/src/kernel/windows_kernel/ansi_support.rs index 47ab3ac..b8c3bf4 100644 --- a/src/kernel/windows_kernel/ansi_support.rs +++ b/src/kernel/windows_kernel/ansi_support.rs @@ -1,6 +1,6 @@ //! This module handles the enabling `ANSI escape codes` for windows terminals. -use Context; +use StateManager; use state::commands::ICommand; static mut HAS_BEEN_TRYED_TO_ENABLE: bool = false; diff --git a/src/kernel/windows_kernel/cursor.rs b/src/kernel/windows_kernel/cursor.rs index 9f8c434..903d75a 100644 --- a/src/kernel/windows_kernel/cursor.rs +++ b/src/kernel/windows_kernel/cursor.rs @@ -3,7 +3,7 @@ use super::kernel; /// This stores the cursor pos, at program level. So it can be recalled later. -static mut SAVED_CURSOR_POS:(u16,u16) = (0,0); +static mut SAVED_CURSOR_POS:(u16,u16) = (0,0); /// Reset to saved cursor position pub fn reset_to_saved_position() @@ -23,6 +23,7 @@ pub fn save_cursor_pos() } } +/// get the current cursor position. pub fn pos() -> (u16,u16) { let csbi = kernel::get_console_screen_buffer_info(); diff --git a/src/kernel/windows_kernel/handle.rs b/src/kernel/windows_kernel/handle.rs deleted file mode 100644 index 5ba04f2..0000000 --- a/src/kernel/windows_kernel/handle.rs +++ /dev/null @@ -1,78 +0,0 @@ -use winapi::um::winnt::HANDLE; -use std::mem::zeroed; -use winapi::um::processenv::{GetStdHandle}; -use winapi::um::winbase::{STD_OUTPUT_HANDLE, STD_INPUT_HANDLE }; - -static mut ALTERNATEHANDLE: Option = None; -static mut CONSOLE_OUTPUT_HANDLE: Option = None; -static mut CONSOLE_INPUT_HANDLE: Option = 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 - } -} \ No newline at end of file diff --git a/src/kernel/windows_kernel/kernel.rs b/src/kernel/windows_kernel/kernel.rs index bfb4829..4b12d15 100644 --- a/src/kernel/windows_kernel/kernel.rs +++ b/src/kernel/windows_kernel/kernel.rs @@ -58,7 +58,7 @@ pub fn get_input_handle() -> HANDLE { } /// Checks if the console handle is an invalid handle value. -pub fn is_valid_handle(handle: &HANDLE) -> bool { +fn is_valid_handle(handle: &HANDLE) -> bool { if *handle == INVALID_HANDLE_VALUE { false } else { diff --git a/src/kernel/windows_kernel/mod.rs b/src/kernel/windows_kernel/mod.rs index 2d73681..0b9449f 100644 --- a/src/kernel/windows_kernel/mod.rs +++ b/src/kernel/windows_kernel/mod.rs @@ -1,4 +1,4 @@ -//! This module contains the `windows` specific (unsafe) logic. +//! This module contains the `windows` specific logic. pub mod kernel; pub mod cursor; diff --git a/src/lib.rs b/src/lib.rs index 0c581a3..26b172d 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -14,18 +14,15 @@ pub mod terminal; pub mod manager; pub use shared::{screen, raw}; +pub use state::context::Context; -use shared::traits::{Construct}; -pub use state::{ Context }; -pub use manager::manager::{ ScreenManager }; -pub use shared::terminal::Terminal; - +use state::command_manager::CommandManager; +use state::state_manager::StateManager; +use manager::ScreenManager; #[cfg(windows)] extern crate winapi; #[cfg(unix)] extern crate libc; #[cfg(unix)] -extern crate termios; - -extern crate rand; \ No newline at end of file +extern crate termios; \ No newline at end of file diff --git a/src/manager/ansi_manager.rs b/src/manager/ansi_manager.rs index 1bc5458..842642e 100644 --- a/src/manager/ansi_manager.rs +++ b/src/manager/ansi_manager.rs @@ -1,3 +1,7 @@ +//! This is an ANSI specific implementation for the screen manager +//! This module is used for windows 10 terminals and unix terminals by default. +//! This module uses the stdout to write to the console. + use std::io::{self, Write}; use super::IScreenManager; @@ -24,24 +28,12 @@ impl IScreenManager for AnsiScreenManager { write!(self.output, "{}", string); self.flush(); -// println!("test"); -// match self.is_alternate_screen -// { -// true => , -// false => write!(io::stdout(), "{}", string), -// }; } fn write_ansi_str(&mut self, string: &str) { write!(self.output, "{}", string); self.flush(); -// println!("test"); -// match self.is_alternate_screen -// { -// true => write!(self.output, "{}", string), -// false => write!(io::stdout(), "{}", string), -// }; } } diff --git a/src/manager/manager.rs b/src/manager/manager.rs index aad6424..c814514 100644 --- a/src/manager/manager.rs +++ b/src/manager/manager.rs @@ -1,8 +1,12 @@ -use std::io::Write; +//! This module provides an interface for working with the sceen. With that I mean that you can get or wirte to the handle of the current screen. stdout. +//! Because crossterm can work with alternate screen, we need a place that holds the handle to the current screen. And this module provides this place. use super::IScreenManager; use super::ansi_manager::AnsiScreenManager; +use std::io::Write; + +/// Struct that stores an specific platform implementation for screen related actions. pub struct ScreenManager { screen_manager: Box>> @@ -10,6 +14,7 @@ pub struct ScreenManager 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()); @@ -22,6 +27,7 @@ impl ScreenManager } } + /// Get the stdout of the current screen pub fn stdout(&mut self) -> &mut Box { self.screen_manager.stdout() @@ -32,11 +38,13 @@ impl ScreenManager self.screen_manager.toggle_is_alternate_screen(is_alternate_screen); } + /// Write an ANSI code as String. pub fn write_ansi(&mut self, string: String) { self.screen_manager.write_ansi(string); } + /// Write an ANSI code as &str pub fn write_ansi_str(&mut self, string: &str) { self.screen_manager.write_ansi_str(string); diff --git a/src/manager/mod.rs b/src/manager/mod.rs index 7edf70d..0ef3b3f 100644 --- a/src/manager/mod.rs +++ b/src/manager/mod.rs @@ -1,3 +1,6 @@ +//! This module provides one place to work with the screen. +//! For example whe can write to the console true this module. + pub mod manager; #[cfg(target_os = "windows")] @@ -12,8 +15,11 @@ pub use self::manager::{ ScreenManager }; pub trait IScreenManager { + /// get the stdout of the screen. This can be used to write to the fn stdout(&mut self) -> &mut 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); } \ No newline at end of file diff --git a/src/shared/functions.rs b/src/shared/functions.rs index 7335674..c93c59b 100644 --- a/src/shared/functions.rs +++ b/src/shared/functions.rs @@ -1,6 +1,6 @@ //! Some actions need to preformed platform independently since they can not be solved `ANSI escape codes`. -use Terminal; +use Context; #[cfg(windows)] use kernel::windows_kernel::terminal::terminal_size; @@ -20,7 +20,7 @@ pub fn get_terminal_size() -> (u16, u16) } /// Get the cursor position based on the current platform. -pub fn get_cursor_position(screen: &Terminal) -> (u16,u16) +pub fn get_cursor_position(screen: &Context) -> (u16, u16) { #[cfg(unix)] return pos(&screen); diff --git a/src/shared/mod.rs b/src/shared/mod.rs index 81cb588..66c2cf7 100644 --- a/src/shared/mod.rs +++ b/src/shared/mod.rs @@ -4,6 +4,5 @@ pub mod macros; pub mod traits; pub mod functions; -pub mod terminal; pub mod screen; pub mod raw; \ No newline at end of file diff --git a/src/shared/raw.rs b/src/shared/raw.rs index 1d13801..5e19ba3 100644 --- a/src/shared/raw.rs +++ b/src/shared/raw.rs @@ -24,49 +24,34 @@ use super::super::state::commands::unix_command::EnableRawModeCommand; #[cfg(windows)] use state::commands::win_commands::EnableRawModeCommand; -use { Terminal }; -use state::commands::IContextCommand; +use {Context, CommandManager }; +use state::commands::IStateCommand; use std::io::{ self, Write}; +use std::rc::Rc; /// A wrapper for the raw terminal state. Which can be used to write to. pub struct RawTerminal<'a> { - terminal : &'a Terminal, + terminal : &'a Context, command_id: u16, } /// Trait withs contains a method for switching into raw mode. pub trait IntoRawMode<'a>: Write + Sized { - fn into_raw_mode(&self, terminal: &'a Terminal) -> io::Result>; + fn into_raw_mode(&self, terminal: &'a Context) -> io::Result>; } -//impl<'a> IntoRawMode<'a> for RawTerminal<'a> -//{ -// /// Switch to raw mode. -// /// -// /// Raw mode means that input (stdin) won't be printed it will instead have to be written manually by -// /// the program. The input isn't canonicalised or line buffered (that is, you can -// /// read from input(stdin) one byte of a time). -// fn into_raw_mode(self, terminal: &'a Terminal) -> io::Result -// { -// let (mut command, command_id) = EnableRawModeCommand::new(&terminal.context); -// let success = command.execute(&terminal); -// -// if success -// { -// Ok(RawTerminal { terminal: terminal, command_id: command_id}) -// -// }else { panic!("cannot move into raw mode") } -// } -//} - impl <'a, W: Write> IntoRawMode<'a> for W { - fn into_raw_mode(&self, terminal: &'a Terminal) -> io::Result> { - let (mut command, command_id) = EnableRawModeCommand::new(&terminal.context); - let success = command.execute(&terminal); + /// Raw mode means that input (stdin) won't be printed it will instead have to be written manually by + /// the program. The input isn't canonicalised or line buffered (that is, you can + /// read from input(stdin) one byte of a time). + fn into_raw_mode(&self, terminal: &'a Context) -> io::Result> { + let command_id = EnableRawModeCommand::new(&terminal.state_manager); + + let success = CommandManager::execute(terminal, command_id); if success { @@ -96,9 +81,6 @@ impl <'a> Drop for RawTerminal<'a> { fn drop(&mut self) { - let mut context = self.terminal.context.lock().unwrap(); - { - context.undo_state(self.command_id, &self.terminal); - } + let success = CommandManager::undo(&self.terminal, self.command_id); } } \ No newline at end of file diff --git a/src/shared/screen.rs b/src/shared/screen.rs index ae2e269..ae93135 100644 --- a/src/shared/screen.rs +++ b/src/shared/screen.rs @@ -1,96 +1,57 @@ //! This module contains all the logic for switching between alternate screen and main screen. -use Terminal; +use Context; use state::commands::*; use std::io::{self, Write}; -//pub struct ToMainScreen; -// -//impl fmt::Display for ToMainScreen -//{ -// fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { -// get_to_alternate_screen_command().undo(); -// Ok(()) -// } -//} -// -///// Struct that switches to alternate screen buffer on display. -//pub struct ToAlternateScreen; -// -//impl fmt::Display for ToAlternateScreen -//{ -// fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { -// get_to_alternate_screen_command().execute(); -// Ok(()) -// } -//} - -/// Struct that can be used for writing to an alternate screen. -/// -/// #Example -/// -/// ```rust -/// extern crate crossterm; -/// use self::crossterm::terminal::screen; -/// use std::{time, thread}; -/// ... -/// -/// // Initialize and switch to the alternate screen from an std output handle. -/// // Now you can write to this screen. -/// let mut screen = screen::AlternateScreen::from(stdout()); -/// // Write some text to the alternate screen. -/// write!(screen, "Welcome to the alternate screen. Wait 4 seconds to switch back").unwrap(); -/// thread::sleep(time::Duration::from_secs(4)); -/// // switch back to main screen. -/// write!(screen, "{}", screen::ToMainScreen); -/// write!(screen, "{}", "We are back again at the main screen"); -/// -/// ... -/// -/// ``` -pub struct AlternateScreen<'term> { - term: &'term Terminal +pub struct AlternateScreen<'context> { + context: &'context Context } -impl<'term> AlternateScreen<'term> { - pub fn from(output: &'term Terminal) -> Self { - get_to_alternate_screen_command().execute(&output); - AlternateScreen { term: output } +impl<'context> AlternateScreen<'context> { + /// Get the alternate screen from the context. + /// By calling this method the current screen will be changed to the alternate screen. + /// And you get back an handle for that screen. + pub fn from(context: &'context Context) -> Self { + get_to_alternate_screen_command().execute(&context); + AlternateScreen { context: context } } + /// Change the current screen to the mainscreen. pub fn to_main(&self) { - get_to_alternate_screen_command().undo(&self.term); + get_to_alternate_screen_command().undo(&self.context); } + /// Change the current screen to alternate screen. pub fn to_alternate(&self) { - get_to_alternate_screen_command().execute(&self.term); + get_to_alternate_screen_command().execute(&self.context); } } -impl<'term> Write for AlternateScreen<'term> { +impl<'context> Write for AlternateScreen<'context> { fn write(&mut self, buf: &[u8]) -> io::Result { - let mut screen = self.term.screen_manager.lock().unwrap(); + let mut screen = self.context.screen_manager.lock().unwrap(); { screen.stdout().write(buf) } } fn flush(&mut self) -> io::Result<()> { - let mut screen = self.term.screen_manager.lock().unwrap(); + let mut screen = self.context.screen_manager.lock().unwrap(); { screen.stdout().flush() } } } -impl<'term> Drop for AlternateScreen<'term> +impl<'context> Drop for AlternateScreen<'context> { fn drop(&mut self) { - get_to_alternate_screen_command().undo(&self.term); + get_to_alternate_screen_command().undo(&self.context); } } diff --git a/src/shared/terminal.rs b/src/shared/terminal.rs deleted file mode 100644 index 987b2fa..0000000 --- a/src/shared/terminal.rs +++ /dev/null @@ -1,82 +0,0 @@ -use std::sync::Mutex; -use std::rc::Rc; - -use { Context, ScreenManager}; - -//use super::super::terminal; -//use super::super::cursor; -use super::super::style; - -use std::fmt; - -pub struct Terminal -{ - pub screen_manager: Rc>, - pub context: Mutex -} - -impl Terminal -{ - pub fn new() -> Terminal - { - Terminal { - screen_manager: Rc::new(Mutex::new(ScreenManager::new())), - context: Mutex::new(Context::new()) - } - } - - /// Get an TerminalColor implementation whereon color related actions can be performed. - /// - /// # Example - /// - /// ```rust - /// extern crate crossterm; - /// - /// use self::crossterm::style::{color, Color}; - /// - /// // Get colored terminal instance - /// let mut colored_terminal = color(); - /// - /// // preform some actions on the colored terminal - /// colored_terminal.set_fg(Color::Red); - /// colored_terminal.set_bg(Color::Blue); - /// colored_terminal.reset(); - /// ``` - pub fn color(&self) -> Box { - 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(&self, val: D) -> style::StyledObject - where - D: fmt::Display, - { - style::ObjectStyle::new().apply_to(val, self.screen_manager.clone()) - } -} diff --git a/src/shared/traits.rs b/src/shared/traits.rs index 843280a..6cb9ddf 100644 --- a/src/shared/traits.rs +++ b/src/shared/traits.rs @@ -1,11 +1,3 @@ - -/// This trait is used for creating an instance of an concrete implementation from an base trait. -/// This trait allows the output to be different in size. -pub trait Construct{ - fn new() -> Box - where - Self: Sized; -} /// This trait can be used to create an empty instance of an struct. pub trait Empty { fn empty() -> Self; diff --git a/src/state/command_manager.rs b/src/state/command_manager.rs new file mode 100644 index 0000000..d3fd2cc --- /dev/null +++ b/src/state/command_manager.rs @@ -0,0 +1,40 @@ +use std::rc::Rc; +use std::sync::Mutex; +use Context; +use super::commands::IStateCommand; + +/// Simple wrapper for executing an command. +pub struct CommandManager; + +impl CommandManager +{ + /// execute an certain command by id. + pub fn execute(terminal: &Context, command_id: u16) -> bool + { + let mut mutex: Rc>>; + + let mut state = terminal.state_manager.lock().unwrap(); + { + mutex = state.get(command_id); + } + + let mut command = mutex.lock().unwrap(); + let has_succeeded = command.execute(&terminal); + return has_succeeded; + } + + /// undo an certain command by id. + pub fn undo(terminal: &Context, command_id: u16) -> bool + { + let mut mutex: Rc>>; + + let mut state = terminal.state_manager.lock().unwrap(); + { + mutex = state.get(command_id); + } + + let mut command = mutex.lock().unwrap(); + let has_succeeded = command.undo(&terminal); + return has_succeeded; + } +} \ No newline at end of file diff --git a/src/state/commands/mod.rs b/src/state/commands/mod.rs index 1096c35..8fa5c21 100644 --- a/src/state/commands/mod.rs +++ b/src/state/commands/mod.rs @@ -7,9 +7,10 @@ //! So where do whe use the `Commands` for? This is so that we can push all or terminal state changes into list. //! When we do not need those changes we can revert all the changes by looping true the list and undo all the action. //! -//! See the `Context` struct where we store the commands for more info. +//! See the `StateManager` struct where we store the commands for more info. use std::sync::Mutex; +use std::rc::Rc; #[cfg(unix)] pub mod unix_command; @@ -24,22 +25,21 @@ pub use self::unix_command::*; #[cfg(windows)] pub use self::win_commands::*; -use { Context, Terminal }; +use {StateManager, Context}; /// This command can be used for simple commands witch just have an `undo()` and an `execute()` pub trait ICommand { fn new() -> Box where Self: Sized; - fn execute(&mut self, terminal: &Terminal) -> bool; - fn undo(&mut self, terminal: &Terminal) -> bool; + fn execute(&mut self, terminal: &Context) -> bool; + fn undo(&mut self, terminal: &Context) -> bool; } /// This command is used for complex commands whits change the terminal state. /// By passing an `Context` instance this command will register it self to notify the terminal state change. -pub trait IContextCommand +pub trait IStateCommand { - fn new(context: &Mutex) -> (Box, u16) where Self: Sized; - fn execute(&mut self, terminal: &Terminal) -> bool; - fn undo(&mut self, terminal: &Terminal) -> bool; + fn execute(&mut self, terminal: &Context) -> bool; + fn undo(&mut self, terminal: &Context) -> bool; } \ No newline at end of file diff --git a/src/state/commands/shared_commands.rs b/src/state/commands/shared_commands.rs index e3357c6..8e5342d 100644 --- a/src/state/commands/shared_commands.rs +++ b/src/state/commands/shared_commands.rs @@ -1,6 +1,21 @@ -//! This module contains the commands that can be used for both unix and windows systems. -use Terminal ; -use super::ICommand; +//! This module contains the commands that can be used for both unix and windows systems. Or else said terminals that support ansi codes. +use Context; +use super::{ICommand, IStateCommand}; + +pub struct EmptyCommand; + +impl IStateCommand for EmptyCommand +{ + fn execute(&mut self, terminal: &Context) -> bool + { + return false + } + + fn undo(&mut self, terminal: &Context) -> bool + { + return false; + } +} /// This command is used for switching to alternate screen and back to main screen. #[derive(Clone, Copy)] @@ -12,7 +27,7 @@ impl ICommand for ToAlternateScreenBufferCommand Box::from(ToAlternateScreenBufferCommand {}) } - fn execute(&mut self, terminal: &Terminal) -> bool + fn execute(&mut self, terminal: &Context) -> bool { let mut screen = terminal.screen_manager.lock().unwrap(); { @@ -22,7 +37,7 @@ impl ICommand for ToAlternateScreenBufferCommand } } - fn undo(&mut self, terminal: &Terminal) -> bool + fn undo(&mut self, terminal: &Context) -> bool { let mut screen = terminal.screen_manager.lock().unwrap(); { diff --git a/src/state/commands/unix_command.rs b/src/state/commands/unix_command.rs index 680c9a7..3352d75 100644 --- a/src/state/commands/unix_command.rs +++ b/src/state/commands/unix_command.rs @@ -1,13 +1,14 @@ //! This module contains the commands that can be used for unix systems. -use {Terminal, Context}; -use super::IContextCommand; +use {Context, StateManager, CommandManager}; +use super::IStateCommand; use kernel::unix_kernel::terminal; use termios::{Termios, tcsetattr, TCSAFLUSH, ICANON, ECHO, CREAD}; const FD_STDIN: ::std::os::unix::io::RawFd = 1; use std::sync::Mutex; +use std::rc::Rc; /// This command is used for switching to NoncanonicalMode. #[derive(Copy, Clone)] @@ -16,20 +17,24 @@ pub struct NoncanonicalModeCommand key: u16 } -impl IContextCommand for NoncanonicalModeCommand +impl NoncanonicalModeCommand { - fn new(context: &Mutex) -> (Box, u16) { + pub fn new(state: &Mutex) -> u16 + { let key = 1; - let mut context = context.lock().unwrap(); + let mut state_manager = state.lock().unwrap(); { - let command = NoncanonicalModeCommand { key: key }; - context.register_change(Box::from(command), key); - (Box::from(command),key) + let command = Box::from(NoncanonicalModeCommand { key: key }); + state_manager.register_change(command, key); + key } } +} - fn execute(&mut self, terminal: &Terminal) -> bool +impl IStateCommand for NoncanonicalModeCommand +{ + fn execute(&mut self, terminal: &Context) -> bool { // Set noncanonical mode if let Ok(orig) = Termios::from_fd(FD_STDIN) @@ -48,7 +53,7 @@ impl IContextCommand for NoncanonicalModeCommand } } - fn undo(&mut self, terminal: &Terminal) -> bool + fn undo(&mut self, terminal: &Context) -> bool { // Disable noncanonical mode if let Ok(orig) = Termios::from_fd(FD_STDIN) @@ -70,34 +75,35 @@ impl IContextCommand for NoncanonicalModeCommand } /// This command is used for enabling and disabling raw mode for the terminal. -#[derive(Copy, Clone)] pub struct EnableRawModeCommand { - original_mode: Option, + original_mode: Option>, command_id: u16 } -impl IContextCommand for EnableRawModeCommand +impl EnableRawModeCommand { - fn new(context: &Mutex) -> (Box, u16) { + pub fn new(state_manager: &Mutex) -> u16{ let key = 2; - let mut context = context.lock().unwrap(); + let mut state = state_manager.lock().unwrap(); { let command = EnableRawModeCommand { original_mode: None, command_id: key }; - context.register_change(Box::from(command), key); - (Box::from(command), key) + state.register_change(Box::from(command), key); + key } } +} - fn execute(&mut self, terminal: &Terminal) -> bool +impl IStateCommand for EnableRawModeCommand +{ + fn execute(&mut self, terminal: &Context) -> bool { let original_mode = terminal::get_terminal_mode(); if let Ok(original_mode) = original_mode { - panic!("setting {:?}", original_mode); - self.original_mode = Some(original_mode); + self.original_mode = Some(Box::from(original_mode)); let mut new_mode = original_mode; terminal::make_raw(&mut new_mode); terminal::set_terminal_mode(&new_mode); @@ -108,12 +114,10 @@ impl IContextCommand for EnableRawModeCommand } } - fn undo(&mut self, terminal: &Terminal) -> bool + fn undo(&mut self, terminal: &Context) -> bool { - panic!("undoing {:?}", self.original_mode); - if let Some(original_mode) = self.original_mode + if let Some(ref original_mode) = self.original_mode { - let result = terminal::set_terminal_mode(&original_mode); match result diff --git a/src/state/commands/win_commands.rs b/src/state/commands/win_commands.rs index f97a659..f4bef9f 100644 --- a/src/state/commands/win_commands.rs +++ b/src/state/commands/win_commands.rs @@ -1,7 +1,7 @@ //! This module contains the commands that can be used for windows systems. -use super::{ICommand, IContextCommand}; -use super::super::Context; +use super::{ICommand, IStateCommand}; +use super::super::StateManager; use kernel::windows_kernel::{kernel, ansi_support}; use winapi::shared::minwindef::DWORD; @@ -9,6 +9,7 @@ use winapi::um::wincon; use winapi::um::wincon::{ENABLE_VIRTUAL_TERMINAL_PROCESSING ,SMALL_RECT, COORD, CHAR_INFO}; use std::mem; +use std::rc::Rc; use std::sync::Mutex; /// This command is used for enabling and disabling ANSI code support for windows systems, @@ -88,15 +89,17 @@ pub struct EnableRawModeCommand key: i16 } -impl IContextCommand for EnableRawModeCommand +impl IStateCommand for EnableRawModeCommand { - fn new(context: &mut Context) -> (Box, i16) { + fn new(state: &mut StateManager) -> (Box, i16) { use self::wincon::{ENABLE_LINE_INPUT,ENABLE_PROCESSED_INPUT, ENABLE_PROCESSED_OUTPUT, ENABLE_WRAP_AT_EOL_OUTPUT, ENABLE_ECHO_INPUT}; let key = super::generate_key(); let command = EnableRawModeCommand { mask: ENABLE_LINE_INPUT | ENABLE_PROCESSED_INPUT | ENABLE_ECHO_INPUT, key: key }; - context.register_change(Box::from(command), key); - (Box::from(command),key) + let rc = Rc::new(command); + + state.register_change(rc.clone(), key); + (rc.clone(),key) } fn execute(&mut self, terminal: &Terminal) -> bool @@ -154,7 +157,7 @@ impl ICommand for ToAlternateScreenBufferCommand Box::from(ToAlternateScreenBufferCommand {}) } - fn execute(&mut self, context: &Context) -> bool + fn execute(&mut self, state: &StateManager) -> bool { let mut chi_buffer: [CHAR_INFO;160] = unsafe {mem::zeroed() }; @@ -208,7 +211,7 @@ impl ICommand for ToAlternateScreenBufferCommand true } - fn undo(&mut self, context: &Context) -> bool + fn undo(&mut self, state: &StateManager) -> bool { let handle = kernel::get_output_handle(); kernel::set_active_screen_buffer(handle); diff --git a/src/state/context.rs b/src/state/context.rs index 72669d9..08c10a0 100644 --- a/src/state/context.rs +++ b/src/state/context.rs @@ -1,65 +1,92 @@ -//! This module is used for registering, storing an restoring the terminal state changes. +//! This module contains the code for the context of the terminal. -use std::collections::HashMap; -use super::commands::IContextCommand; -use Terminal; -/// Struct that stores the changed states of the terminal. +use std::sync::Mutex; +use std::rc::Rc; + +use super::super::style; +use { StateManager, ScreenManager }; + +use std::fmt; + +/// This type contains the context of the current terminal. The context surrounds the changed states of the terminal and can be used for managing the output of the terminal. pub struct Context { - changed_states: HashMap>, + pub screen_manager: Rc>, + pub state_manager: Mutex } impl Context { - /// Create new Context where the terminals states can be handled. + /// Create new Context instance so that you can provide it to other modules like terminal, cursor and color + /// + /// This context type is just an wrapper that crossterm uses for managin the state the terminal. + /// + /// You must provide this context otherwise crossterm would not be able to restore to the original state of the terminal. + /// Also futures like rawscreen and ansi codes can not be used. + /// + /// #Example + /// + /// ```rust + /// + /// use crossterm::Context; + /// + /// use crossterm::cursor; + /// use crossterm::color; + /// use crossterm::terminal; + /// + /// let cursor = cursor::cursor(&context) + /// let terminal = terminal::terminal(&context); + /// let color = terminal::color(&context); + /// + /// ``` pub fn new() -> Context { Context { - changed_states: HashMap::new(), + screen_manager: Rc::new(Mutex::new(ScreenManager::new())), + state_manager: Mutex::new(StateManager::new()) } } -// /// Restore all changes that are made to the terminal. -// pub fn restore_changes(&mut self) -// { -// use std::iter::FromIterator; -// -// 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. - pub fn register_change(&mut self, change: Box, key: u16) + /// 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(&self, val: D) -> style::StyledObject + where + D: fmt::Display, { - if !self.changed_states.contains_key(&key) - { - self.changed_states.insert(key, change); - } - } - - /// Undo an specific state by the given state key. - pub fn undo_state(&mut self, state_key: u16, terminal: &Terminal) - { - if self.changed_states.contains_key(&state_key) - { - { - let mut command = self.changed_states.get_mut(&state_key).unwrap(); - command.undo(&terminal); - } - &self.changed_states.remove(&state_key); - - } + style::ObjectStyle::new().apply_to(val, self.screen_manager.clone()) } } - - +impl Drop for Context +{ + fn drop(&mut self) + { + let mut changes = self.state_manager.lock().unwrap(); + changes.restore_changes(&self); + } +} diff --git a/src/state/mod.rs b/src/state/mod.rs index 2c4cc7d..33795cc 100644 --- a/src/state/mod.rs +++ b/src/state/mod.rs @@ -3,7 +3,7 @@ //! If `crossterm` changes some core state of the terminal like: enabling ANSI or enabling raw mode it should be reverted when the current process ends. //! It would be a little lame to let the terminal in raw mode after the the current process ends for the user of this library. -mod context; +pub mod state_manager; pub mod commands; - -pub use self::context::{Context}; \ No newline at end of file +pub mod command_manager; +pub mod context; \ No newline at end of file diff --git a/src/state/state_manager.rs b/src/state/state_manager.rs new file mode 100644 index 0000000..21e1968 --- /dev/null +++ b/src/state/state_manager.rs @@ -0,0 +1,56 @@ +//! This module is used for registering, storing an restoring the terminal state changes. + +use Context; +use super::commands::IStateCommand; +use super::commands::shared_commands::EmptyCommand; + +use std::rc::Rc; +use std::sync::Mutex; +use std::collections::HashMap; + +/// Struct that stores the changed states of the terminal. +pub struct StateManager +{ + changed_states: HashMap>>>, +} + +impl StateManager +{ + /// Create new Context where the terminals states can be handled. + pub fn new() -> StateManager + { + StateManager { + changed_states: HashMap::new(), + } + } + + /// Restore all changes that are made to the terminal. + pub fn restore_changes(&mut self, context: &Context) + { + for (id, item) in self.changed_states.iter_mut() + { + let mut item = item.lock().unwrap(); + item.undo(&context); + } + } + + /// Register new changed state with the given key. + pub fn register_change(&mut self, change: Box, key: u16) + { + self.changed_states.insert(key, Rc::new(Mutex::new(change))); + } + + /// Get an state command from storage by id. + pub fn get(&mut self, state_key: u16) -> Rc>> + { + if self.changed_states.contains_key(&state_key) + { + return self.changed_states[&state_key].clone() + } + + return Rc::new(Mutex::new(Box::new(EmptyCommand))) + } +} + + + diff --git a/src/style/color/ansi_color.rs b/src/style/color/ansi_color.rs index 072823c..2d21606 100644 --- a/src/style/color/ansi_color.rs +++ b/src/style/color/ansi_color.rs @@ -1,7 +1,7 @@ //! This is an ANSI specific implementation for styling related action. //! This module is used for windows 10 terminals and unix terminals by default. -use { Construct, ScreenManager }; +use ScreenManager; use super::ITerminalColor; use super::super::{Color, ColorType}; @@ -12,8 +12,8 @@ use std::sync::Mutex; #[derive(Debug)] pub struct AnsiColor; -impl Construct for AnsiColor { - fn new() -> Box { +impl AnsiColor { + pub fn new() -> Box { Box::from(AnsiColor {}) } } diff --git a/src/style/color/color.rs b/src/style/color/color.rs index 0f60821..7d659a1 100644 --- a/src/style/color/color.rs +++ b/src/style/color/color.rs @@ -2,10 +2,9 @@ //! Like styling the font, foreground color and background. use super::*; -use Construct; use style::Color; -use std::{ io }; +use std::io; use std::rc::Rc; use std::sync::Mutex; @@ -35,9 +34,12 @@ impl TerminalColor { /// extern crate crossterm; /// /// use self::crossterm::style::{ color, Color}; + /// use crossterm::Context; + /// + /// let context = Context::new(); /// /// // Get colored terminal instance - /// let mut colored_terminal = color(); + /// let mut colored_terminal = color(&context); /// /// // Set foreground color of the font /// colored_terminal.set_fg(Color::Red); @@ -60,9 +62,12 @@ impl TerminalColor { /// extern crate crossterm; /// /// use self::crossterm::style::{ color, Color}; + /// use crossterm::Context; + /// + /// let context = Context::new(); /// /// // Get colored terminal instance - /// let mut colored_terminal = color(); + /// let mut colored_terminal = color(&context); /// /// // Set background color of the font /// colored_terminal.set_bg(Color::Red); @@ -83,9 +88,12 @@ impl TerminalColor { /// extern crate crossterm; /// /// use self::crossterm::style::color; + /// use crossterm::Context; + /// + /// let context = Context::new(); /// /// // Get colored terminal instance - /// let mut colored_terminal = color(); + /// let mut colored_terminal = color(&context); /// /// colored_terminal.reset(); /// @@ -114,6 +122,10 @@ impl TerminalColor { } } +/// Get an Color implementation whereon color related actions can be performed. +/// +/// Check `/examples/version/color` in the libary for more specific examples. +/// pub fn color(screen_manager: Rc>) -> Box { Box::from(TerminalColor::new(screen_manager.clone())) } diff --git a/src/style/color/mod.rs b/src/style/color/mod.rs index 435e43c..b685ced 100644 --- a/src/style/color/mod.rs +++ b/src/style/color/mod.rs @@ -7,13 +7,13 @@ mod ansi_color; #[cfg(target_os = "windows")] use self::winapi_color::WinApiColor; use self::ansi_color::AnsiColor; + +use { ScreenManager }; use super::{Color, ColorType}; use std::rc::Rc; use std::sync::Mutex; -use { ScreenManager }; - ///! 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 ///! the wishes to work on an specific platform. diff --git a/src/style/mod.rs b/src/style/mod.rs index 8304ef6..b252a1f 100644 --- a/src/style/mod.rs +++ b/src/style/mod.rs @@ -5,7 +5,6 @@ mod color; mod styles; pub use self::color::color::{color, TerminalColor }; - pub use self::styles::objectstyle::ObjectStyle; pub use self::styles::styledobject::StyledObject; @@ -101,4 +100,4 @@ impl FromStr for Color { _ => Ok(Color::White), } } -} +} \ No newline at end of file diff --git a/src/style/styles/mod.rs b/src/style/styles/mod.rs index cd40b69..fa25d2e 100644 --- a/src/style/styles/mod.rs +++ b/src/style/styles/mod.rs @@ -1,4 +1,4 @@ //! This module contains the modules that are responsible for storing the styling displayable objects or simply set text. pub mod objectstyle; -pub mod styledobject; +pub mod styledobject; \ No newline at end of file diff --git a/src/style/styles/objectstyle.rs b/src/style/styles/objectstyle.rs index 52edd5f..841c09e 100644 --- a/src/style/styles/objectstyle.rs +++ b/src/style/styles/objectstyle.rs @@ -5,6 +5,7 @@ use style::{Color, StyledObject}; use ScreenManager; use std::sync::Mutex; use std::rc::Rc; + #[cfg(unix)] use super::super::Attribute; diff --git a/src/style/styles/styledobject.rs b/src/style/styles/styledobject.rs index fc6681c..e2e057e 100644 --- a/src/style/styles/styledobject.rs +++ b/src/style/styles/styledobject.rs @@ -1,4 +1,4 @@ -//! This module contains the logic to style an object that contains some context witch can be styled. +//! This module contains the logic to style an object that contains some state witch can be styled. use std::fmt; use std::io::Write; diff --git a/src/terminal/ansi_terminal.rs b/src/terminal/ansi_terminal.rs index f5c4b40..de09743 100644 --- a/src/terminal/ansi_terminal.rs +++ b/src/terminal/ansi_terminal.rs @@ -1,7 +1,7 @@ //! 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. -use {Construct, Terminal}; +use Context; use shared::functions; use super::{ClearType, ITerminal}; @@ -10,16 +10,16 @@ use std::io::Write; /// This struct is an ansi implementation for terminal related actions. pub struct AnsiTerminal; -impl Construct for AnsiTerminal { - fn new() -> Box { +impl AnsiTerminal { + pub fn new() -> Box { Box::from(AnsiTerminal {}) } } impl ITerminal for AnsiTerminal { - fn clear(&self, clear_type: ClearType, terminal: &Terminal) { + fn clear(&self, clear_type: ClearType, context: &Context) { - let mut screen_manager = terminal.screen_manager.lock().unwrap(); + let mut screen_manager = context.screen_manager.lock().unwrap(); { let stdout = screen_manager.stdout(); @@ -43,26 +43,26 @@ impl ITerminal for AnsiTerminal { } } - fn terminal_size(&self, terminal: &Terminal) -> (u16, u16) { + fn terminal_size(&self, context: &Context) -> (u16, u16) { functions::get_terminal_size() } - fn scroll_up(&self, count: i16, terminal: &Terminal) { - let mut screen = terminal.screen_manager.lock().unwrap(); + fn scroll_up(&self, count: i16, context: &Context) { + let mut screen = context.screen_manager.lock().unwrap(); { screen.write_ansi(format!(csi!("{}S"), count)); } } - fn scroll_down(&self, count: i16, terminal: &Terminal) { - let mut screen = terminal.screen_manager.lock().unwrap(); + fn scroll_down(&self, count: i16, context: &Context) { + let mut screen = context.screen_manager.lock().unwrap(); { screen.write_ansi(format!(csi!("{}T"), count)); } } - fn set_size(&self, width: i16, height: i16, terminal: &Terminal) { - let mut screen = terminal.screen_manager.lock().unwrap(); + fn set_size(&self, width: i16, height: i16, context: &Context) { + let mut screen = context.screen_manager.lock().unwrap(); { screen.write_ansi(format!(csi!("8;{};{}t"), width, height)); } diff --git a/src/terminal/mod.rs b/src/terminal/mod.rs index da262be..3743e80 100644 --- a/src/terminal/mod.rs +++ b/src/terminal/mod.rs @@ -4,14 +4,7 @@ //! - alternate screen //! - raw mode //! - clearing resizing scrolling the terminal. - -use Terminal; -use self::ansi_terminal::AnsiTerminal; - -pub use self::terminal::{ terminal}; -#[cfg(target_os = "windows")] -use self::winapi_terminal::WinApiTerminal; - +//! pub mod terminal; @@ -19,6 +12,13 @@ pub mod terminal; mod winapi_terminal; mod ansi_terminal; +#[cfg(target_os = "windows")] +use self::winapi_terminal::WinApiTerminal; +use self::ansi_terminal::AnsiTerminal; + +use Context; +pub use self::terminal::{ terminal}; + /// Enum that can be used for the kind of clearing that can be done in the terminal. pub enum ClearType { All, @@ -38,13 +38,13 @@ pub enum ClearType { ///! so that cursor related actions can be preformed on both unix and windows systems. pub trait ITerminal { /// Clear the current cursor by specifying the clear type - fn clear(&self, clear_type: ClearType, terminal: &Terminal); + fn clear(&self, clear_type: ClearType, context: &Context); /// Get the terminal size (x,y) - fn terminal_size(&self, terminal: &Terminal) -> (u16, u16); + fn terminal_size(&self, context: &Context) -> (u16, u16); /// Scroll `n` lines up in the current terminal. - fn scroll_up(&self, count: i16, terminal: &Terminal); + fn scroll_up(&self, count: i16, context: &Context); /// Scroll `n` lines down in the current terminal. - fn scroll_down(&self, count: i16, terminal: &Terminal); + fn scroll_down(&self, count: i16, context: &Context); /// Resize terminal to the given width and height. - fn set_size(&self,width: i16, height: i16, terminal: &Terminal); + fn set_size(&self,width: i16, height: i16, context: &Context); } diff --git a/src/terminal/terminal.rs b/src/terminal/terminal.rs index b06db87..4b9951a 100644 --- a/src/terminal/terminal.rs +++ b/src/terminal/terminal.rs @@ -2,25 +2,27 @@ //! Like clearing and scrolling in the terminal or getting the size of the terminal. use super::*; -use Construct; -use super::super::shared::terminal; +use Context; + +use super::super::style; +use std::fmt; /// Struct that stores an specific platform implementation for terminal related actions. -pub struct Terminal<'terminal> { +pub struct Terminal<'context> { terminal: Option>, - term: &'terminal terminal::Terminal + context: &'context Context } -impl<'terminal> Terminal<'terminal> { +impl<'context> Terminal<'context> { /// Create new terminal instance whereon terminal related actions can be performed. - pub fn new(term: &'terminal terminal::Terminal) -> Terminal<'terminal> { + pub fn new(context: &'context Context) -> Terminal<'context> { #[cfg(target_os = "windows")] let terminal = functions::get_module::>(WinApiTerminal::new(), AnsiTerminal::new()); #[cfg(not(target_os = "windows"))] let terminal = Some(AnsiTerminal::new() as Box); - Terminal { terminal, term } + Terminal { terminal, context: context } } @@ -32,8 +34,10 @@ impl<'terminal> Terminal<'terminal> { /// /// extern crate crossterm; /// use crossterm::terminal; + /// use crossterm::Context; /// - /// let mut term = terminal::terminal(); + /// let context = Context::new(); + /// let mut term = terminal::terminal(&context); /// /// // clear all cells in terminal. /// term.clear(terminal::ClearType::All); @@ -49,7 +53,7 @@ impl<'terminal> Terminal<'terminal> { /// ``` pub fn clear(&mut self, clear_type: ClearType) { if let Some(ref terminal) = self.terminal { - terminal.clear(clear_type, &self.term); + terminal.clear(clear_type, &self.context); } } @@ -61,8 +65,10 @@ impl<'terminal> Terminal<'terminal> { /// /// extern crate crossterm; /// use crossterm::terminal; + /// use crossterm::Context; /// - /// let mut term = terminal::terminal(); + /// let context = Context::new(); + /// let mut term = terminal::terminal(&context); /// /// let size = term.terminal_size(); /// println!("{:?}", size); @@ -70,7 +76,7 @@ impl<'terminal> Terminal<'terminal> { /// ``` pub fn terminal_size(&mut self) -> (u16, u16) { if let Some(ref terminal) = self.terminal { - return terminal.terminal_size(&self.term) + return terminal.terminal_size(&self.context) } (0,0) } @@ -83,8 +89,10 @@ impl<'terminal> Terminal<'terminal> { /// /// extern crate crossterm; /// use crossterm::terminal; + /// use crossterm::Context; /// - /// let mut term = terminal::terminal(); + /// let context = Context::new(); + /// let mut term = terminal::terminal(&context); /// /// // scroll up by 5 lines /// let size = term.scroll_up(5); @@ -92,7 +100,7 @@ impl<'terminal> Terminal<'terminal> { /// ``` pub fn scroll_up(&mut self, count: i16) { if let Some(ref terminal) = self.terminal { - terminal.scroll_up(count,&self.term); + terminal.scroll_up(count,&self.context); } } @@ -104,8 +112,10 @@ impl<'terminal> Terminal<'terminal> { /// /// extern crate crossterm; /// use crossterm::terminal; + /// use crossterm::Context; /// - /// let mut term = terminal::terminal(); + /// let context = Context::new(); + /// let mut term = terminal::terminal(&context); /// /// // scroll down by 5 lines /// let size = term.scroll_down(5); @@ -113,7 +123,7 @@ impl<'terminal> Terminal<'terminal> { /// ``` pub fn scroll_down(&mut self, count: i16) { if let Some(ref terminal) = self.terminal { - terminal.scroll_down(count, &self.term); + terminal.scroll_down(count, &self.context); } } @@ -125,9 +135,11 @@ impl<'terminal> Terminal<'terminal> { /// /// extern crate crossterm; /// use crossterm::terminal; + /// use crossterm::Context; + /// + /// let context = Context::new(); + /// let mut term = terminal::terminal(&context); /// - /// let mut term = terminal::terminal(); - /// /// // Set of the size to X: 10 and Y: 10 /// let size = term.set_size(10,10); /// @@ -135,14 +147,48 @@ impl<'terminal> Terminal<'terminal> { pub fn set_size(&mut self, width: i16, height: i16) { if let Some (ref terminal) = self.terminal { - terminal.set_size(width,height,&self.term); + terminal.set_size(width,height,&self.context); } } + + /// Wraps an displayable object so it can be formatted with colors and attributes. + /// + /// Check `/examples/color` in the libary for more spesific examples. + /// + /// #Example + /// + /// ```rust + /// extern crate crossterm; + /// + /// use self::crossterm::style::{paint,Color}; + /// + /// fn main() + /// { + /// // Create an styledobject object from the text 'Unstyled font' + /// // Currently it has the default foregroundcolor and backgroundcolor. + /// println!("{}",paint("Unstyled font")); + /// + /// // Create an displayable object from the text 'Colored font', + /// // Paint this with the `Red` foreground color and `Blue` backgroundcolor. + /// // Print the result. + /// let styledobject = paint("Colored font").with(Color::Red).on(Color::Blue); + /// println!("{}", styledobject); + /// + /// // Or all in one line + /// println!("{}", paint("Colored font").with(Color::Red).on(Color::Blue)); + /// } + /// ``` + pub fn paint(&self, val: D) -> style::StyledObject + where + D: fmt::Display, + { + style::ObjectStyle::new().apply_to(val, self.context.screen_manager.clone()) + } } /// Get an Terminal implementation whereon terminal related actions can be performed. /// -/// Check `/examples/terminal` in the libary for more spesific examples. +/// Check `/examples/version/terminal` in the libary for more spesific examples. /// /// #Example /// @@ -150,16 +196,17 @@ impl<'terminal> Terminal<'terminal> { /// /// extern crate crossterm; /// use crossterm::terminal; +/// use crossterm::Context; /// -/// let mut term = terminal::terminal(); +/// let context = Context::new(); +/// +/// let mut term = terminal::terminal(&context); /// /// // scroll down by 5 lines /// let size = term.scroll_down(5); /// /// ``` /// -/// - -pub fn terminal<'terminal>(terminal: &'terminal terminal::Terminal) -> Box> { - Box::from(Terminal::new(&terminal)) +pub fn terminal<'context>(context: &'context Context) -> Box> { + Box::from(Terminal::new(&context)) } diff --git a/src/terminal/winapi_terminal.rs b/src/terminal/winapi_terminal.rs index c4ffcb0..f2a1e80 100644 --- a/src/terminal/winapi_terminal.rs +++ b/src/terminal/winapi_terminal.rs @@ -1,5 +1,5 @@ //! This is an `WINAPI` specific implementation for terminal related action. -//! This module is used for windows 10 terminals and unix terminals by default. +//! This module is used for non supporting `ANSI` windows terminals. use {Construct}; use cursor::cursor;