diff --git a/Cargo.toml b/Cargo.toml index ea652db..0997ec6 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -28,8 +28,8 @@ path = "src/lib.rs" # path = "./examples/Crossterm 0.3.1/bin.rs" [[example]] -name = "simple" -path = "examples/simple.rs" +name = "examples" +path = "examples/examples.rs" [[example]] name = "logging" diff --git a/changes.md b/changes.md new file mode 100644 index 0000000..b55b5d8 --- /dev/null +++ b/changes.md @@ -0,0 +1,10 @@ +1. improved performance: removed mutexes, removed state manager, removed unceasingly RC types. +2. This create supports multithreading by implementing `Send` +2. nicer looking coloring module. +4. Added input functionality. +4. Able to have different screens to write to. + +2. cursor, color, terminal functions have other parameters. +3. bug fix resetting console color +6. Added Screen type +8. removed paint from Crossterm type. \ No newline at end of file diff --git a/examples/README.md b/examples/README.md index 91151bd..cb319b0 100644 --- a/examples/README.md +++ b/examples/README.md @@ -6,6 +6,4 @@ It has 4 modules: - terminal (this is about all the actions you can perform on the terminal) - input (this is about all input actions you can perform on with terminal) - crossterm_type (this is about the struct `Crossterm`) -- program examples (this folder will contain some real life examples) - -To run any example where there is a `main()` you could run `cargo run --example simple`. \ No newline at end of file +- program examples (this folder will contain some real life examples) \ No newline at end of file diff --git a/examples/color/mod.rs b/examples/color/mod.rs index 548c9ec..091958c 100644 --- a/examples/color/mod.rs +++ b/examples/color/mod.rs @@ -1,206 +1,130 @@ //! //! Examples of coloring the terminal. //! - extern crate crossterm; -use self::crossterm::style::Color; -use self::crossterm::terminal; -use self::crossterm::Context; +use self::crossterm::style::{Color, style, color}; +use self::crossterm::{terminal, Screen}; /// print some red font | demonstration. pub fn paint_foreground() { - let context = Context::new(); - let terminal = terminal::terminal(&context); - + let screen = Screen::default(); // 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 = 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); + // Call the method `with()` on the object given by `style()` and pass in any Color from the Color enum. + let mut styledobject = style("Red foreground").with(Color::Red); - // Crossterm provides method chaining so that the above points can be inlined. - println!("{}", terminal.paint("Red font").with(Color::Red)); + // Print the object to the given screen and. + styledobject.paint(&screen); + + style("Some colored text").with(Color::Blue).on(Color::Black).paint(&screen); + + // Crossterm provides method chaining for coloring so that the above points can be inlined. + style(format!("Red foreground color : \t {}", "■")).with(Color::Red).paint(&screen); } /// print some font on red background | demonstration. pub fn paint_background() { - let context = Context::new(); - let terminal = terminal::terminal(&context); - + let screen = Screen::default(); // 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 = 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); + // Call the method `on()` on the object given by `style()` and pass in any Color from the Color enum. + let mut styledobject = style("Red background color").on(Color::Red); - // Crossterm provides method chaining so that the above points can be inlined. - println!("{}", terminal.paint("Red background color").on(Color::Red)); -} + // Print the object to the given screen and. + styledobject.paint(&screen); -/// 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 = 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. - */ - styledobject = styledobject.with(Color::Red); - /* Background color: - Call the method `on()` on the object given by `paint()` - Pass in an Color from the Color enum. - */ - styledobject = styledobject.on(Color::Blue); - // 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!( - "{}", - terminal - .paint("Red font on blue background color") - .with(Color::Red) - .on(Color::Blue) - ); + // Crossterm provides method chaining for coloring so that the above points can be inlined. + style(format!("Red background color : \t {}", "■")).with(Color::Red).paint(&screen); } /// Print all available foreground colors | demonstration. pub fn print_all_foreground_colors() { - let context = Context::new(); - let terminal = terminal::terminal(&context); + let screen = Screen::default(); - 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)); + style(format!("Black : \t\t {} \n", "■")).with(Color::Black).paint(&screen); + style(format!("Red : \t\t {} \n", "■")).with(Color::Red).paint(&screen); + style(format!("Cyan : \t\t {} \n", "■")).with(Color::Cyan).paint(&screen); + style(format!("DarkCyan : \t {} \n", "■")).with(Color::DarkCyan).paint(&screen); + style(format!("DarkRed : \t {} \n", "■")).with(Color::DarkRed).paint(&screen); + style(format!("Green : \t {} \n", "■")).with(Color::Green).paint(&screen); + style(format!("DarkGreen : \t {} \n", "■")).with(Color::DarkGreen).paint(&screen); + style(format!("Blue : \t\t {} \n", "■")).with(Color::Blue).paint(&screen); + style(format!("DarkBlue : \t {} \n", "■")).with(Color::DarkBlue).paint(&screen); + style(format!("Magenta : \t {} \n", "■")).with(Color::Magenta).paint(&screen); + style(format!("DarkMagenta : \t {} \n", "■")).with(Color::DarkMagenta).paint(&screen); + style(format!("Yellow : \t {} \n", "■")).with(Color::Yellow).paint(&screen); + style(format!("DarkYellow : \t {} \n", "■")).with(Color::DarkYellow).paint(&screen); + style(format!("Grey : \t\t {} \n", "■")).with(Color::Grey).paint(&screen); + style(format!("White : \t {} \n", "■")).with(Color::White).paint(&screen); + + #[cfg(unix)] + style("RGB color (10,10,10) ").with(Color::Rgb { + r: 10, + g: 10, + b: 10 + }).paint(&screen); + + #[cfg(unix)] + style("RGB color (10,10,10) ").with(Color::AnsiValue(50)).paint(&screen); } /// Print all available foreground colors | demonstration. pub fn print_all_background_colors() { - let context = Context::new(); - let terminal = terminal::terminal(&context); + let screen = Screen::default(); - 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)); + style(format!("Black : \t {} \n", "■")).on(Color::Black).paint(&screen); + style(format!("Red : \t\t {} \n", "■")).on(Color::Red).paint(&screen); + style(format!("Cyan : \t\t {} \n", "■")).on(Color::Cyan).paint(&screen); + style(format!("DarkCyan : \t {} \n", "■")).on(Color::DarkCyan).paint(&screen); + style(format!("DarkRed : \t {} \n", "■")).on(Color::DarkRed).paint(&screen); + style(format!("Green : \t {} \n", "■")).on(Color::Green).paint(&screen); + style(format!("DarkGreen : \t {} \n", "■")).on(Color::DarkGreen).paint(&screen); + style(format!("Blue : \t\t {} \n", "■")).on(Color::Blue).paint(&screen); + style(format!("DarkBlue : \t {} \n", "■")).on(Color::DarkBlue).paint(&screen); + style(format!("Magenta : \t {} \n", "■")).on(Color::Magenta).paint(&screen); + style(format!("DarkMagenta : \t {} \n", "■")).on(Color::DarkMagenta).paint(&screen); + style(format!("Yellow : \t {} \n", "■")).on(Color::Yellow).paint(&screen); + style(format!("DarkYellow : \t {} \n", "■")).on(Color::DarkYellow).paint(&screen); + style(format!("Grey : \t\t {} \n", "■")).on(Color::Grey).paint(&screen); + style(format!("White : \t {} \n", "■")).on(Color::White).paint(&screen); + #[cfg(unix)] - println!( - "RGB (10,10,10): \t {}", - terminal.paint(" ").on(Color::Rgb { - r: 10, - g: 10, - b: 10 - }) - ); + style("RGB color (10,10,10) ").on(Color::Rgb { + r: 10, + g: 10, + b: 10 + }).paint(&screen); + #[cfg(unix)] - println!( - "RGB (10,10,10): \t {}", - terminal.paint(" ").on(Color::AnsiValue(50)) - ); + style("RGB color (10,10,10) ").on(Color::AnsiValue(50)).paint(&screen); } /// 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() { - 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()); + let screen = Screen::default(); + style("Normal text").paint(&screen); + style("Bold text").bold().paint(&screen); + style("Italic text").italic().paint(&screen); + style("Slow blinking text").slow().paint(&screen); + style("Rapid blinking text").rapid().paint(&screen); + style("Hidden text").hidden().paint(&screen); + style("Underlined text").underlined().paint(&screen); + style("Reversed text").reverse().paint(&screen); + style("Dim text").dim().paint(&screen); + style("Crossed out font").crossed_out().paint(&screen); } -/// Print all supported rgb colors | demonstration. +/// Print all supported RGB colors | demonstration. #[cfg(unix)] pub fn print_supported_colors() { - let context = Context::new(); - let terminal = terminal::terminal(&context); - - let count = crossterm::style::color(&context) + let screen = Screen::default(); + let count = color(&screen) .get_available_color_count() .unwrap(); for i in 0..count { - println!( - "{}", - terminal - .paint(format!("Color: {}", i)) - .with(Color::AnsiValue(i as u8)) - ); + style(format!("White : \t {}", i)).on(Color::AnsiValue(i as u8)).paint(&screen); } } diff --git a/examples/crossterm_type/mod.rs b/examples/crossterm_type/mod.rs deleted file mode 100644 index 9a7671b..0000000 --- a/examples/crossterm_type/mod.rs +++ /dev/null @@ -1,67 +0,0 @@ -extern crate crossterm; - -use crossterm::Crossterm; - -/// use the `Crossterm` to get an instance to the cursor module | demonstration. -pub fn use_crossterm_cursor() -{ - let crossterm = Crossterm::new(); - let mut cursor = crossterm.cursor(); - cursor.goto(5,5).print("test"); -} - -use crossterm::style::Color; - -/// use the `Crossterm` to get an instance to the color module | demonstration. -pub fn use_crossterm_color() -{ - let crossterm = Crossterm::new(); - let mut color = crossterm.color(); - color.set_bg(Color::Red); - color.set_fg(Color::Green); -} - -use crossterm::terminal::ClearType; - -/// use the `Crossterm` to get an instance to the terminal module | demonstration. -pub fn use_crossterm_terminal() -{ - let crossterm = Crossterm::new(); - let mut terminal = crossterm.terminal(); - terminal.clear(ClearType::All); - terminal.set_size(40,40); -} - -/// paint text with colors using `Crossterm` | demonstration. -pub fn use_crossterm_paint() -{ - let crossterm = Crossterm::new(); - crossterm.paint("Black on BLUE").with(Color::Black).on(Color::Blue); -} - -/// write text to terminal using `Crossterm` | demonstration. -pub fn use_crossterm_write() -{ - let crossterm = Crossterm::new(); - crossterm.write("some text \nsome text on new line"); -} - -/// Switch to alternate screen using the `Context` of `Crossterm` | demonstration. -pub fn create_alternate_screen_from_crossterm() -{ - use crossterm::screen::*; - use std::convert::From; - - let crossterm = Crossterm::new(); - - { - // move into alternate screen - let alternate_screen = AlternateScreen::from(crossterm.context()); - - // this will move the cursor and print `some text` on the alternate screen. - crossterm.cursor().goto(10, 10).print("Some text"); - } // <- alternate screen ends here an will be switched back to main screen. - - // print "Some other text" on the mainscreen at x: 0, y: 10 - crossterm.cursor().goto(0,10).print("Some other text"); -} \ No newline at end of file diff --git a/examples/cursor/mod.rs b/examples/cursor/mod.rs index 2345778..504ac7c 100644 --- a/examples/cursor/mod.rs +++ b/examples/cursor/mod.rs @@ -4,34 +4,28 @@ extern crate crossterm; use self::crossterm::cursor::{cursor, TerminalCursor}; -use self::crossterm::Context; +use self::crossterm::Screen; /// 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(&context); + let mut cursor = cursor(&Screen::default()); // 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); + let mut cursor = cursor(&Screen::default()); // 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(&context); + let mut cursor = cursor(&Screen::default()); // Move the cursor to position 3 times to the up in the terminal cursor.move_up(10); @@ -39,66 +33,55 @@ 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(&context); + let mut cursor = cursor(&Screen::default()); // Move the cursor to position 3 times to the right in the terminal cursor.move_right(3); } /// Move the cursor 3 down | demonstration. pub fn move_down() { - let context = Context::new(); - - // Get the cursor - let mut cursor = cursor(&context); + let mut cursor = cursor(&Screen::default()); // Move the cursor to position 3 times to the down in the terminal cursor.move_down(3); } /// Move the cursor 3 to the left | demonstration. pub fn move_left() { - let context = Context::new(); + let mut cursor = cursor(&Screen::default()); - // 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); } -/// 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(&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 - print!("@"); - // Rust is line buffered inorder to print at an certain position we need to clear the buffer first. - use std; - use std::io::Write; - std::io::stdout().flush(); - - /* Because the above method is a little to much code, - you can use the `print()` method for printing an value at an certain position in the terminal. - - Crossterm provides method chaining so that the above points can be inlined. - */ - - cursor.goto(10, 5).print("@"); -} +///// 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(&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 +// print!("@"); +// // Rust is line buffered inorder to print at an certain position we need to clear the buffer first. +// use std; +// use std::io::Write; +// std::io::stdout().flush(); +// +// /* Because the above method is a little to much code, +// you can use the `print()` method for printing an value at an certain position in the terminal. +// +// Crossterm provides method chaining so that the above points can be inlined. +// */ +// +// cursor.goto(10, 5).print("@"); +//} /// Save and reset cursor position | demonstration.. pub fn safe_and_reset_position() { - let context = Context::new(); - - let mut cursor = cursor(&context); - + let mut cursor = cursor(&Screen::default()); // Goto X: 5 Y: 5 cursor.goto(5, 5); // Safe cursor position: X: 5 Y: 5 @@ -117,25 +100,19 @@ pub fn safe_and_reset_position() { /// Hide cursor display | demonstration. pub fn hide_cursor() { - let context = Context::new(); - - let cursor = cursor(&context); + let mut cursor = cursor(&Screen::default()); cursor.hide(); } /// Show cursor display | demonstration. pub fn show_cursor() { - let context = Context::new(); - - let cursor = cursor(&context); + let mut cursor = cursor(&Screen::default()); cursor.show(); } /// Show cursor display, only works on certain terminals.| demonstration pub fn blink_cursor() { - let context = Context::new(); - - let cursor = cursor(&context); + let mut cursor = cursor(&Screen::default()); cursor.blink(false); cursor.blink(false); } diff --git a/examples/examples.rs b/examples/examples.rs new file mode 100644 index 0000000..a8f512d --- /dev/null +++ b/examples/examples.rs @@ -0,0 +1,20 @@ + +//! This bin folder can be used to try the examples out located in the examples directory. +//! +//! All you need to do is: +//! +//! - Download the crossterm source code. +//! - Run program with: `cargo run --example examples` + +extern crate crossterm; + +// modules that could be test + mod terminal; + mod color; + mod cursor; + mod some_types; + mod input; + +fn main() { + // call some test module function +} diff --git a/examples/input/keyboard/async_input.rs b/examples/input/keyboard/async_input.rs index 9221c37..9d00495 100644 --- a/examples/input/keyboard/async_input.rs +++ b/examples/input/keyboard/async_input.rs @@ -10,44 +10,41 @@ use std::time::Duration; /// this will capture the input until the given key. pub fn read_async_until() { - let screen = Screen::new(); + // create raw screen + let screen = Screen::new(true); let crossterm = Crossterm::new(); - if let Ok(raw) = screen.enable_raw_modes() - { - // init some modules we use for this demo - let input = crossterm.input(&raw.screen); - let terminal = crossterm.terminal(&raw.screen); - let mut cursor = crossterm.cursor(&raw.screen); + // init some modules we use for this demo + let input = crossterm.input(&screen); + let terminal = crossterm.terminal(&screen); + let mut cursor = crossterm.cursor(&screen); + let mut stdin = input.read_until_async(b'\r').bytes(); - let mut stdin = input.read_until_async(b'\r').bytes(); + for i in 0..100 { + terminal.clear(ClearType::All); + cursor.goto(1, 1); + let a = stdin.next(); - for i in 0..100 { - terminal.clear(ClearType::All); - cursor.goto(1, 1); - let a = stdin.next(); + println!("pressed key: {:?}", a); - println!("pressed key: {:?}", a); - - if let Some(Ok(b'\r')) = a { - println!("The enter key is hit and program is not listening to input anymore."); - break; - } - - if let Some(Ok(b'x')) = a { - println!("The key: x was pressed and program is terminated."); - break; - } - - thread::sleep(time::Duration::from_millis(100)); + if let Some(Ok(b'\r')) = a { + println!("The enter key is hit and program is not listening to input anymore."); + break; } + + if let Some(Ok(b'x')) = a { + println!("The key: x was pressed and program is terminated."); + break; + } + + thread::sleep(time::Duration::from_millis(100)); } } /// this will read pressed characters async until `x` is typed . pub fn read_async() { - let input = input(&Screen::new()); + let input = input(&Screen::default()); let mut stdin = input.read_async().bytes(); @@ -66,16 +63,13 @@ pub fn read_async() { } pub fn read_async_demo() { - let screen = Screen::new(); + let screen = Screen::new(true); let crossterm = Crossterm::new(); - // put stdout in raw mode so that characters wil not be outputted. - let raw = screen.enable_raw_modes().unwrap(); - // init some modules we use for this demo - let input = crossterm.input(&raw.screen); - let terminal = crossterm.terminal(&raw.screen); - let mut cursor = crossterm.cursor(&raw.screen); + let input = crossterm.input(&screen); + let terminal = crossterm.terminal(&screen); + let mut cursor = crossterm.cursor(&screen); // this will setup the async reading. let mut stdin = input.read_async().bytes(); @@ -106,41 +100,37 @@ pub fn read_async_demo() { pub fn async_reading_on_alternate_screen() { use crossterm::screen::AlternateScreen; - let screen = Screen::new(); + let screen = Screen::new(false); let crossterm = Crossterm::new(); // switch to alternate screen - if let Ok(alternate) = screen.enable_alternate_modes() + if let Ok(alternate) = screen.enable_alternate_modes(true) { - // put alternate screen in raw mode so that characters wil not be outputted. - if let Ok(raw) = alternate.enable_raw_modes() - { - // init some modules we use for this demo - let input = crossterm.input(&raw.screen); - let terminal = crossterm.terminal(&raw.screen); - let mut cursor = crossterm.cursor(&raw.screen); + // init some modules we use for this demo + let input = crossterm.input(&alternate.screen); + let terminal = crossterm.terminal(&alternate.screen); + let mut cursor = crossterm.cursor(&alternate.screen); - // this will setup the async reading. - let mut stdin = input.read_async().bytes(); + // this will setup the async reading. + let mut stdin = input.read_async().bytes(); - // loop until the enter key (\r) is pressed. - loop { - terminal.clear(ClearType::All); - cursor.goto(1, 1); + // loop until the enter key (\r) is pressed. + loop { + terminal.clear(ClearType::All); + cursor.goto(1, 1); - // get the next pressed key - let pressed_key = stdin.next(); + // get the next pressed key + let pressed_key = stdin.next(); - terminal.write(format!("\r{:?} <- Character pressed", pressed_key)); + terminal.write(format!("\r{:?} <- Character pressed", pressed_key)); - // check if pressed key is enter (\r) - if let Some(Ok(b'\r')) = pressed_key { - break; - } - - // wait 200 ms and reset cursor write - thread::sleep(Duration::from_millis(200)); + // check if pressed key is enter (\r) + if let Some(Ok(b'\r')) = pressed_key { + break; } + + // wait 200 ms and reset cursor write + thread::sleep(Duration::from_millis(200)); } } } diff --git a/examples/input/keyboard/input.rs b/examples/input/keyboard/input.rs index df8dd8f..979344f 100644 --- a/examples/input/keyboard/input.rs +++ b/examples/input/keyboard/input.rs @@ -4,7 +4,7 @@ use self::crossterm::input::input; use self::crossterm::Screen; pub fn read_char() { - let input = input(&Screen::new()); + let input = input(&Screen::default()); match input.read_char() { Ok(s) => println!("char typed: {}", s), @@ -13,7 +13,7 @@ pub fn read_char() { } pub fn read_line() { - let input = input(&Screen::new()); + let input = input(&Screen::default()); match input.read_line() { Ok(s) => println!("string typed: {}", s), diff --git a/examples/program_examples/README.md b/examples/program_examples/README.md index d8e0a7a..0d34259 100644 --- a/examples/program_examples/README.md +++ b/examples/program_examples/README.md @@ -6,4 +6,5 @@ The programs are: - First depth search: This is an search algorithm implemented visually. This program uses the following functionalities: cursor movement, coloring, alternate screen and terminal clearing. -- Duplex: This is a terminal application where there is some kind of conterminous output and with async input. So you could type an command while text is being outputted. \ No newline at end of file +- Duplex: This is a terminal application where there is some kind of conterminous output and with async input. So you could type an command while text is being outputted. +- This is an async logging program to demonstrate asynchronous working with crossterm. \ No newline at end of file diff --git a/examples/program_examples/first_depth_search/src/main.rs b/examples/program_examples/first_depth_search/src/main.rs index cfbde4c..ed07566 100644 --- a/examples/program_examples/first_depth_search/src/main.rs +++ b/examples/program_examples/first_depth_search/src/main.rs @@ -26,10 +26,10 @@ fn main() pub fn run() { // This is represents the current screen. - let screen = Screen::new(); + let screen = Screen::new(true); // set size of terminal so the map we are going to draw is fitting the screen. - terminal(&screen).set_size(110,50); + terminal(&screen).set_size(60,110); print_welcome_screen(&screen); @@ -39,7 +39,7 @@ pub fn run() fn start_algorithm(screen: &Screen) { // we first want to switch to alternate screen. On the alternate screen we are going to run or firstdepthsearch algorithm - if let Ok(ref alternate_screen) = screen.enable_alternate_modes() + if let Ok(ref alternate_screen) = screen.enable_alternate_modes(true) { // setup the map size and the position to start searching for a path. let map_size = Size::new(100, 40); @@ -58,41 +58,38 @@ fn start_algorithm(screen: &Screen) fn print_welcome_screen(screen: &Screen) { // create the handle for the cursor and terminal. - if let Ok(raw) = screen.enable_raw_modes() - { - let crossterm = Crossterm::new(); - let terminal = crossterm.terminal(&screen); - let cursor = crossterm.cursor(&raw.screen); - let input = crossterm.input(&raw.screen); + let crossterm = Crossterm::new(); + let terminal = crossterm.terminal(&screen); + let cursor = crossterm.cursor(&screen); + let input = crossterm.input(&screen); - // clear the screen and print the welcome message. - terminal.clear(ClearType::All); - cursor.goto(0, 0); - terminal.write(WELCOME_MESSAGE.join("\n")); + // clear the screen and print the welcome message. + terminal.clear(ClearType::All); + cursor.goto(0, 0); + terminal.write(WELCOME_MESSAGE.join("\n")); - cursor.hide(); - cursor.goto(0, 10); - terminal.write( - "The first depth search algorithm will start in: Seconds\n\ + cursor.hide(); + cursor.goto(0, 10); + terminal.write( + "The first depth search algorithm will start in: Seconds\n\ Press `q` to abort the program" - ); + ); - let mut stdin = input.read_async().bytes(); + let mut stdin = input.read_async().bytes(); - // print some progress example. - for i in (1..5).rev() { - let a = stdin.next(); + // print some progress example. + for i in (1..5).rev() { + let a = stdin.next(); - if let Some(Ok(b'q')) = a { - terminal.exit(); - } - - // print the current counter at the line of `Seconds to Go: {counter}` - cursor.goto(48, 10); - crossterm.style(format!("{}", i)).with(Color::Red).on(Color::Blue).paint(&screen); - - // 1 second delay - thread::sleep(time::Duration::from_secs(1)); - } + if let Some(Ok(b'q')) = a { + terminal.exit(); } + + // print the current counter at the line of `Seconds to Go: {counter}` + cursor.goto(48, 10); + crossterm.style(format!("{}", i)).with(Color::Red).on(Color::Blue).paint(&screen); + + // 1 second delay + thread::sleep(time::Duration::from_secs(1)); + } } \ No newline at end of file diff --git a/examples/simple.rs b/examples/simple.rs deleted file mode 100644 index b8611a1..0000000 --- a/examples/simple.rs +++ /dev/null @@ -1,35 +0,0 @@ - -//! This bin folder can be used to try the examples out located in the examples directory. -//! -//! All you need to do is: -//! -//! - Download the crossterm source code. -//! -//! - Add this in the Cargo.toml file: -//! ``` [[bin]] -//! name = "example_bin" -//! path = "./examples/bin.rs" -//! ``` -//! -//! - Run program with: `cargo run` -extern crate crossterm; - -use crossterm::style::Color; -use crossterm::Crossterm; -use crossterm::write::Stdout; -use crossterm::common::screen::Screen; -use std::io::Write; -// mod terminal; -// mod color; -// mod cursor; -// mod crossterm_type; - mod input; - -//use input::keyboard::{async_input, input as stdin}; - -use std::{thread, time, }; -use std::sync::mpsc; - -fn main() { - input::keyboard::async_input::async_reading_on_alternate_screen(); -} diff --git a/examples/some_types/mod.rs b/examples/some_types/mod.rs new file mode 100644 index 0000000..43aa23a --- /dev/null +++ b/examples/some_types/mod.rs @@ -0,0 +1,20 @@ +extern crate crossterm; + +use crossterm::{Crossterm, Screen}; + +#[test] +/// use the `Crossterm` to get an instance to the cursor module | demonstration. +pub fn use_crossterm_cursor() +{ + let screen = Screen::new(); + + // Create the crossterm type to access different modules. + let crossterm = Crossterm::new(); + + // pass a reference to the current screen. + let cursor = crossterm.cursor(&screen); + let color = crossterm.color(&screen); + let terminal = crossterm.terminal(&screen); + + // perform some actions with the instances above. +} diff --git a/examples/terminal/alternate_screen.rs b/examples/terminal/alternate_screen.rs index dbbb7c9..1a6132a 100644 --- a/examples/terminal/alternate_screen.rs +++ b/examples/terminal/alternate_screen.rs @@ -1,18 +1,18 @@ extern crate crossterm; -use crossterm::style::Color; +use crossterm::style::{Color, style}; use crossterm::terminal::{self, ClearType}; -use crossterm::Crossterm; +use crossterm::{Crossterm, Screen}; use std::io::{stdout, Write}; use std::{thread, time}; -fn print_wait_screen(crossterm: &mut Crossterm) { - let mut terminal = crossterm.terminal(); - let mut cursor = crossterm.cursor(); +fn print_wait_screen(screen: &Screen) { + let crossterm = Crossterm::new(); + let terminal = crossterm.terminal(&screen); + let cursor = crossterm.cursor(&screen); terminal.clear(ClearType::All); - cursor.goto(0, 0); cursor.hide(); @@ -25,49 +25,21 @@ fn print_wait_screen(crossterm: &mut Crossterm) { // 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(crossterm.paint(format!("{} of the 5 items processed", i)).with(Color::Red).on(Color::Blue)); + cursor.goto(10, 2); + style(format!("{} of the 5 items processed", i)).with(Color::Red).on(Color::Blue).paint(&screen); // 1 second delay thread::sleep(time::Duration::from_secs(1)); } - - stdout().flush(); } /// print wait screen on alternate screen, then swich back. pub fn print_wait_screen_on_alternate_window() { - let mut term = Crossterm::new(); - term.to_alternate_screen(); - - term.write(b"test"); - print_wait_screen(&mut term); -} - -/// some stress test switch from and to alternate screen. -pub fn switch_between_main_and_alternate_screen() { + let screen = Screen::default(); + if let Ok(alternate) = screen.enable_alternate_modes(false) { - let mut term = Crossterm::new(); - let mut cursor = term.cursor(); - - // create new alternate screen instance and switch to the alternate screen. - let alternate = term.to_alternate_screen(); - - { cursor.goto(0, 0); } - write!(term, "we are at the alternate screen!"); - thread::sleep(time::Duration::from_secs(3)); - - term.to_main_screen(); - write!(term, "we are at the alternate screen!"); - thread::sleep(time::Duration::from_secs(3)); - - term.to_alternate_screen(); - write!(term, "we are at the alternate screen!"); - thread::sleep(time::Duration::from_secs(3)); - } // <- Crossterm goes out of scope. - - println!("Whe are back at the main screen"); + print_wait_screen(&alternate.screen); + } } diff --git a/examples/terminal/raw_mode.rs b/examples/terminal/raw_mode.rs index 5bc1ce2..e3db954 100644 --- a/examples/terminal/raw_mode.rs +++ b/examples/terminal/raw_mode.rs @@ -1,31 +1,33 @@ extern crate crossterm; -use crossterm::Crossterm; - +use crossterm::{Crossterm, Screen}; use crossterm::terminal::{self, ClearType}; +use crossterm::style::{style, Color}; use std::io::{stdout, Write}; use std::{thread, time}; -// raw screen is not working correctly currently -fn print_wait_screen(crossterm: &mut Crossterm) { - let terminal = crossterm.terminal(); - let mut cursor = crossterm.cursor(); +fn print_wait_screen(screen: &Screen) { + let crossterm = Crossterm::new(); + let terminal = crossterm.terminal(&screen); + let cursor = crossterm.cursor(&screen); terminal.clear(ClearType::All); + cursor.goto(0, 0); + cursor.hide(); - 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: "); + terminal.write( + "Welcome to the wait screen.\n\ + Please wait a few seconds until we arrive back at the main screen.\n\ + Progress: ", + ); // print some progress example. 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)); + cursor.goto(10, 2); + style(format!("{} of the 5 items processed", i)).with(Color::Red).on(Color::Blue).paint(&screen); + screen.stdout.flush(); // 1 second delay thread::sleep(time::Duration::from_secs(1)); @@ -33,21 +35,11 @@ fn print_wait_screen(crossterm: &mut Crossterm) { } pub fn print_wait_screen_on_alternate_window() { - let mut term = Crossterm::new(); + let screen = Screen::default(); - // create scope. If this scope ends the screen will be switched back to mainscreen. - // because `AlternateScreen` switches back to main screen when going out of scope. + if let Ok(alternate) = screen.enable_alternate_modes(true) { - // 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. - term.to_alternate_screen(); - term.enable_raw_mode(); - - // Print the wait screen. - print_wait_screen(&mut term); - - term.flush(); + print_wait_screen(&alternate.screen); } println!("Whe are back at the main screen"); diff --git a/examples/terminal/terminal.rs b/examples/terminal/terminal.rs index 5ca260f..3ed9eae 100644 --- a/examples/terminal/terminal.rs +++ b/examples/terminal/terminal.rs @@ -4,8 +4,8 @@ extern crate crossterm; -use crossterm::terminal::ClearType; -use crossterm::Crossterm; +use crossterm::terminal::{ClearType, terminal}; +use crossterm::{Crossterm, Screen}; fn print_test_data() { for i in 0..100 { @@ -15,8 +15,7 @@ fn print_test_data() { /// Clear all lines in terminal | demonstration pub fn clear_all_lines() { - let term = Crossterm::new(); - let mut terminal = term.terminal(); + let mut terminal = terminal(&Screen::default()); print_test_data(); @@ -26,13 +25,14 @@ 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 = Crossterm::new(); - let mut terminal = term.terminal(); + let screen = Screen::default(); + let crossterm = Crossterm::new(); + let mut terminal = crossterm.terminal(&screen); print_test_data(); // Set terminal cursor position (see example for more info). - term.cursor().goto(4, 8); + crossterm.cursor(&screen).goto(4, 8); // Clear all cells from current cursor position down. terminal.clear(ClearType::FromCursorDown); @@ -40,13 +40,14 @@ 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 = Crossterm::new(); - let mut terminal = term.terminal(); + let screen = Screen::default(); + let crossterm = Crossterm::new(); + let mut terminal = crossterm.terminal(&screen); print_test_data(); // Set terminal cursor position (see example for more info). - term.cursor().goto(4, 4); + crossterm.cursor(&screen).goto(4, 4); // Clear all cells from current cursor position down. terminal.clear(ClearType::FromCursorUp); @@ -54,13 +55,14 @@ 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 = Crossterm::new(); - let mut terminal = term.terminal(); + let screen = Screen::default(); + let crossterm = Crossterm::new(); + let mut terminal = crossterm.terminal(&screen); print_test_data(); // Set terminal cursor position (see example for more info). - term.cursor().goto(4, 4); + crossterm.cursor(&screen).goto(4, 4); // Clear current line cells. terminal.clear(ClearType::CurrentLine); @@ -68,13 +70,14 @@ 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 = Crossterm::new(); - let mut terminal = term.terminal(); + let screen = Screen::default(); + let crossterm = Crossterm::new(); + let mut terminal = crossterm.terminal(&screen); print_test_data(); // Set terminal cursor position (see example for more info). - term.cursor().goto(4, 20); + crossterm.cursor(&screen).goto(4, 20); // Clear all the cells until next line. terminal.clear(ClearType::UntilNewLine); @@ -82,8 +85,7 @@ pub fn clear_until_new_line() { /// Print the the current terminal size | demonstration. pub fn print_terminal_size() { - let term = Crossterm::new(); - let mut terminal = term.terminal(); + let mut terminal = terminal(&Screen::default()); // Get terminal size let (width, height) = terminal.terminal_size(); @@ -94,16 +96,14 @@ pub fn print_terminal_size() { /// Set the terminal size to width 10, height: 10 | demonstration. pub fn set_terminal_size() { - let term = Crossterm::new(); - let mut terminal = term.terminal(); + let mut terminal = terminal(&Screen::default()); terminal.set_size(10, 10); } /// Scroll down 10 lines | demonstration. pub fn scroll_down() { - let term = Crossterm::new(); - let mut terminal = term.terminal(); + let mut terminal = terminal(&Screen::default()); print_test_data(); @@ -113,8 +113,7 @@ pub fn scroll_down() { /// Scroll down 10 lines | demonstration. pub fn scroll_up() { - let term = Crossterm::new(); - let mut terminal = term.terminal(); + let mut terminal = terminal(&Screen::default()); print_test_data(); @@ -124,8 +123,7 @@ pub fn scroll_up() { /// Resize the terminal to X: 10, Y: 10 | demonstration. pub fn resize_terminal() { - let term = Crossterm::new(); - let mut terminal = term.terminal(); + let mut terminal = terminal(&Screen::default()); // Get terminal size terminal.set_size(10, 10); @@ -133,7 +131,6 @@ pub fn resize_terminal() { /// exit the current proccess. pub fn exit() { - let term = Crossterm::new(); - let mut terminal = term.terminal(); + let mut terminal = terminal(&Screen::default()); terminal.exit(); } diff --git a/src/common/functions.rs b/src/common/functions.rs index 18faa50..1198be9 100644 --- a/src/common/functions.rs +++ b/src/common/functions.rs @@ -54,7 +54,8 @@ pub fn get_module(winapi_impl: T, unix_impl: T) -> Option { // Try to enable ansi on windows if not than use WINAPI. does_support = try_enable_ansi_support(); -// does_support = false; + // uncomment this line when you want to use the winapi implementation. + does_support = false; if !does_support { term = Some(winapi_impl); } diff --git a/src/common/screen/alternate.rs b/src/common/screen/alternate.rs index 78d9f0b..b6eadbe 100644 --- a/src/common/screen/alternate.rs +++ b/src/common/screen/alternate.rs @@ -61,11 +61,6 @@ impl AlternateScreen { self.command.disable(&self.screen.stdout)?; Ok(()) } - - pub fn enable_raw_modes(&self) -> io::Result - { - return self.screen.enable_raw_modes(); - } } impl Drop for AlternateScreen diff --git a/src/common/screen/raw.rs b/src/common/screen/raw.rs index 8eca969..023008a 100644 --- a/src/common/screen/raw.rs +++ b/src/common/screen/raw.rs @@ -13,48 +13,34 @@ //! With these modes you can easier design the terminal screen. use super::commands::*; -use super::{functions, Screen}; +use super::{functions, Screen, Stdout}; use std::io::{self, Write}; /// A wrapper for the raw terminal state. Which can be used to write to. -pub struct RawScreen -{ - #[cfg(not(target_os = "windows"))] - command: unix_command::RawModeCommand, - #[cfg(target_os = "windows")] - command: win_commands::RawModeCommand, - - pub screen: Screen, -} +pub struct RawScreen; impl RawScreen { - pub fn into_raw_mode(screen: Screen) -> io::Result + pub fn into_raw_mode() -> io::Result<()> { #[cfg(not(target_os = "windows"))] - let command = unix_command::RawModeCommand::new(); + let mut command = unix_command::RawModeCommand::new(); #[cfg(target_os = "windows")] - let command = win_commands::RawModeCommand::new(); + let mut command = win_commands::RawModeCommand::new(); - Ok(RawScreen { command: command, screen}) + command.enable()?; + + Ok(()) } - pub fn disable_raw_modes(&self) -> io::Result<()> + pub fn disable_raw_modes() -> io::Result<()> { - self.command.disable()?; + #[cfg(not(target_os = "windows"))] + let mut command = unix_command::RawModeCommand::new(); + #[cfg(target_os = "windows")] + let mut command = win_commands::RawModeCommand::new(); + + command.disable()?; return Ok(()) } } - -impl Drop for RawScreen -{ - fn drop(&mut self) { - self.disable_raw_modes(); - } -} - -// -/////// Trait withs contains a method for switching into raw mode. -////pub trait IntoRawMode: Write + Sized { -//// fn into_raw_mode(&self, context: Rc) -> io::Result; -////} diff --git a/src/common/screen/screen.rs b/src/common/screen/screen.rs index bab2b98..1580609 100644 --- a/src/common/screen/screen.rs +++ b/src/common/screen/screen.rs @@ -21,9 +21,15 @@ pub struct Screen impl Screen { - pub fn new() -> Screen + pub fn new(raw_mode: bool) -> Screen { - return Screen { stdout: Arc::new(Stdout::new(false)), buffer: Vec::new() }; + if raw_mode + { + RawScreen::into_raw_mode();; + return Screen { stdout: Arc::new(Stdout::new(true)), buffer: Vec::new() }; + } + + return Screen::default(); } pub fn from(stdout: Stdout) -> Screen @@ -31,19 +37,41 @@ impl Screen return Screen { stdout: Arc::new(stdout), buffer: Vec::new() }; } - pub fn enable_raw_modes(&self) -> Result { - let mut screen = Screen::from(Stdout::new(true)); - let raw_screen = RawScreen::into_raw_mode(screen)?; - return Ok(raw_screen) + pub fn enable_raw_modes(&self) -> Result<()> { + RawScreen::into_raw_mode()?; + return Ok(()) } - pub fn enable_alternate_modes(&self) -> Result { - let mut stdout = Stdout::new(true); + pub fn enable_alternate_modes(&self, raw_mode: bool) -> Result { + let mut stdout = Stdout::new(raw_mode); + + if raw_mode + { + RawScreen::into_raw_mode(); + } + let alternate_screen = AlternateScreen::to_alternate_screen(stdout)?; return Ok(alternate_screen); } } +impl Default for Screen +{ + fn default() -> Self { + return Screen { stdout: Arc::new(Stdout::new(false)), buffer: Vec::new() }; + } +} + +impl Drop for Screen +{ + fn drop(&mut self) { + if self.stdout.is_in_raw_mode + { + RawScreen::disable_raw_modes(); + } + } +} + impl Write for Screen { fn write(&mut self, buf: &[u8]) -> Result { diff --git a/src/kernel/windows_kernel/csbi.rs b/src/kernel/windows_kernel/csbi.rs index 26f4434..72c3d1a 100644 --- a/src/kernel/windows_kernel/csbi.rs +++ b/src/kernel/windows_kernel/csbi.rs @@ -11,6 +11,8 @@ use winapi::um::winnt::HANDLE; use winapi::um::winnt::{FILE_SHARE_READ, FILE_SHARE_WRITE, GENERIC_READ, GENERIC_WRITE}; use super::{handle, kernel, Empty, Stdout}; + +use std::sync::{Once, ONCE_INIT}; use std::io::{self, ErrorKind, Result}; use std::mem::size_of; use std::sync::Arc; @@ -106,3 +108,15 @@ pub fn set_active_screen_buffer(new_buffer: HANDLE) -> Result<()> { } Ok(()) } + +static GET_ORIGINAL_CONSOLE_COLOR: Once = ONCE_INIT; +static mut original_console_color: u16 = 0; + +pub fn get_original_console_color() -> u16 { + GET_ORIGINAL_CONSOLE_COLOR.call_once(|| { + let handle = handle::get_output_handle().unwrap(); + let csbi = get_csbi_by_handle(&handle).unwrap(); + unsafe { original_console_color = csbi.wAttributes as u16 }; + }); + return unsafe { original_console_color }; +} diff --git a/src/modules/cursor/cursor.rs b/src/modules/cursor/cursor.rs index 87e7391..ecb01b3 100644 --- a/src/modules/cursor/cursor.rs +++ b/src/modules/cursor/cursor.rs @@ -160,53 +160,6 @@ impl TerminalCursor { self } - /// Print an value at the current cursor position. - /// - /// This method prints an value with `print!()` and clears the buffer afterwards. - /// Rust's standard output is line-buffered. So your text gets sent to the console one line at a time. - /// If you set the curosr position and try to `print!()` at that position and do not clear the buffer, than the character will not be printed at that position. - /// But will be printed when the next `println()` will be done. - /// - /// With this method you can print any displayable value at a certain position and the output buffer will be cleared afterwards. - /// - /// For more information see the cursor example in /examples/cursor - /// - /// #Example - /// - /// ```rust - /// - /// extern crate crossterm; - /// - /// use self::crossterm::Context; - /// use self::crossterm::cursor; - /// - /// use std; - /// use std::io::Write; - /// - /// let crossterm = Crossterm::new(); - /// let cursor = crossterm.cursor(); - /// - /// // of course we can just do this. - /// cursor.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(&context) - /// .goto(10,10) - /// .print("@"); - /// - /// ``` - pub fn print(&mut self, value: D) -> &mut TerminalCursor { - use std::fmt::Write; - let mut string = String::new(); - write!(string, "{}", value).unwrap(); - - &self.screen.write_string(string); - &self.screen.flush(); - self - } - /// Save cursor position for recall later. /// /// Note that this position is stored program based not per instance of the `Cursor` struct. diff --git a/src/modules/style/mod.rs b/src/modules/style/mod.rs index 30fc4df..a002922 100644 --- a/src/modules/style/mod.rs +++ b/src/modules/style/mod.rs @@ -15,6 +15,7 @@ use self::winapi_color::WinApiColor; use std::convert::From; use std::str::FromStr; use std::sync::Arc; +use std::fmt::Display; pub use self::color::TerminalColor; pub use self::objectstyle::ObjectStyle; @@ -40,6 +41,12 @@ pub trait ITerminalColor { fn color_value(&self, color: Color, color_type: ColorType) -> String; } +pub fn style(val: D) -> StyledObject + where + D: Display, { + ObjectStyle::new().apply_to(val) +} + /// Attributes that could be applied on some text. #[derive(Copy, Clone, Debug, PartialEq, Eq, Ord, PartialOrd)] pub enum Attribute { diff --git a/src/modules/style/winapi_color.rs b/src/modules/style/winapi_color.rs index d2da9c4..8b4d936 100644 --- a/src/modules/style/winapi_color.rs +++ b/src/modules/style/winapi_color.rs @@ -11,11 +11,14 @@ use winapi::um::wincon; use std::sync::Arc; /// This struct is an windows implementation for color related actions. -pub struct WinApiColor; +pub struct WinApiColor +{ + original_color: u16 +} impl WinApiColor { pub fn new() -> WinApiColor { - WinApiColor {} + WinApiColor { original_color: csbi::get_original_console_color()} } } @@ -63,8 +66,7 @@ impl ITerminalColor for WinApiColor { } fn reset(&self, stdout: &Arc) { - self.set_bg(Color::Black, stdout); - self.set_fg(Color::White, stdout); + kernel::set_console_text_attribute(self.original_color, stdout); } /// This will get the winapi color value from the Color and ColorType struct diff --git a/src/modules/write/stdout.rs b/src/modules/write/stdout.rs index 1410327..7d6ce30 100644 --- a/src/modules/write/stdout.rs +++ b/src/modules/write/stdout.rs @@ -52,7 +52,6 @@ impl Stdout { Stdout { screen_manager , is_in_raw_mode} } - /// Write String to the current screen. pub fn write_string(&self, string: String) -> io::Result { self.screen_manager.write_str(string.as_str())