* Removed lots of Clippy warnings and `ran cargo fmt`
This commit is contained in:
Timon 2018-11-21 17:48:22 +01:00 committed by GitHub
parent 8ac61db3c1
commit f068ae69b1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
54 changed files with 630 additions and 616 deletions

View File

@ -3,7 +3,7 @@
//! //!
extern crate crossterm; extern crate crossterm;
use self::crossterm::style::{Color, style, color}; use self::crossterm::style::{color, style, Color};
use self::crossterm::{terminal, Screen}; use self::crossterm::{terminal, Screen};
/// print some red font | demonstration. /// print some red font | demonstration.
@ -16,7 +16,10 @@ pub fn paint_foreground() {
println!("Colored text: {}", styledobject); println!("Colored text: {}", styledobject);
// Or print inline // Or print inline
println!("Colored text: {}", style("Red foreground").with(Color::Blue)); println!(
"Colored text: {}",
style("Red foreground").with(Color::Blue)
);
} }
/// print some font on red background | demonstration. /// print some font on red background | demonstration.
@ -34,85 +37,185 @@ pub fn paint_background() {
/// Print all available foreground colors | demonstration. /// Print all available foreground colors | demonstration.
pub fn print_all_foreground_colors() { pub fn print_all_foreground_colors() {
println!("{}", style(format!("Black : \t\t {} \n", "")).with(Color::Black)); println!(
println!("{}", style(format!("Red : \t\t {} \n", "")).with(Color::Red)); "{}",
println!("{}", style(format!("Cyan : \t\t {} \n", "")).with(Color::Cyan)); style(format!("Black : \t\t {} \n", "")).with(Color::Black)
println!("{}", style(format!("DarkCyan : \t {} \n", "")).with(Color::DarkCyan)); );
println!("{}", style(format!("DarkRed : \t {} \n", "")).with(Color::DarkRed)); println!(
println!("{}", style(format!("Green : \t {} \n", "")).with(Color::Green)); "{}",
println!("{}", style(format!("DarkGreen : \t {} \n", "")).with(Color::DarkGreen)); style(format!("Red : \t\t {} \n", "")).with(Color::Red)
println!("{}", style(format!("Blue : \t\t {} \n", "")).with(Color::Blue)); );
println!("{}", style(format!("DarkBlue : \t {} \n", "")).with(Color::DarkBlue)); println!(
println!("{}", style(format!("Magenta : \t {} \n", "")).with(Color::Magenta)); "{}",
println!("{}", style(format!("DarkMagenta : \t {} \n", "")).with(Color::DarkMagenta)); style(format!("Cyan : \t\t {} \n", "")).with(Color::Cyan)
println!("{}", style(format!("Yellow : \t {} \n", "")).with(Color::Yellow)); );
println!("{}", style(format!("DarkYellow : \t {} \n", "")).with(Color::DarkYellow)); println!(
println!("{}", style(format!("Grey : \t\t {} \n", "")).with(Color::Grey)); "{}",
println!("{}", style(format!("White : \t {} \n", "")).with(Color::White)); style(format!("DarkCyan : \t {} \n", "")).with(Color::DarkCyan)
);
println!(
"{}",
style(format!("DarkRed : \t {} \n", "")).with(Color::DarkRed)
);
println!(
"{}",
style(format!("Green : \t {} \n", "")).with(Color::Green)
);
println!(
"{}",
style(format!("DarkGreen : \t {} \n", "")).with(Color::DarkGreen)
);
println!(
"{}",
style(format!("Blue : \t\t {} \n", "")).with(Color::Blue)
);
println!(
"{}",
style(format!("DarkBlue : \t {} \n", "")).with(Color::DarkBlue)
);
println!(
"{}",
style(format!("Magenta : \t {} \n", "")).with(Color::Magenta)
);
println!(
"{}",
style(format!("DarkMagenta : \t {} \n", "")).with(Color::DarkMagenta)
);
println!(
"{}",
style(format!("Yellow : \t {} \n", "")).with(Color::Yellow)
);
println!(
"{}",
style(format!("DarkYellow : \t {} \n", "")).with(Color::DarkYellow)
);
println!(
"{}",
style(format!("Grey : \t\t {} \n", "")).with(Color::Grey)
);
println!(
"{}",
style(format!("White : \t {} \n", "")).with(Color::White)
);
#[cfg(unix)] #[cfg(unix)]
println!("{}", style("RGB color (10,10,10) ").with(Color::Rgb { println!(
r: 10, "{}",
g: 10, style("RGB color (10,10,10) ").with(Color::Rgb {
b: 10 r: 10,
})); g: 10,
b: 10
})
);
#[cfg(unix)] #[cfg(unix)]
println!("{}",style("RGB color (10,10,10) ")).with(Color::AnsiValue(50)); println!("{}", style("RGB color (10,10,10) ")).with(Color::AnsiValue(50));
} }
/// Print all available foreground colors | demonstration. /// Print all available foreground colors | demonstration.
pub fn print_all_background_colors() { pub fn print_all_background_colors() {
println!("{}", style(format!("Black : \t {} \n", "")).on(Color::Black)); println!(
println!("{}", style(format!("Red : \t\t {} \n", "")).on(Color::Red)); "{}",
println!("{}", style(format!("Cyan : \t\t {} \n", "")).on(Color::Cyan)); style(format!("Black : \t {} \n", "")).on(Color::Black)
println!("{}", style(format!("DarkCyan : \t {} \n", "")).on(Color::DarkCyan)); );
println!("{}", style(format!("DarkRed : \t {} \n", "")).on(Color::DarkRed)); println!(
println!("{}", style(format!("Green : \t {} \n", "")).on(Color::Green)); "{}",
println!("{}", style(format!("DarkGreen : \t {} \n", "")).on(Color::DarkGreen)); style(format!("Red : \t\t {} \n", "")).on(Color::Red)
println!("{}", style(format!("Blue : \t\t {} \n", "")).on(Color::Blue)); );
println!("{}", style(format!("DarkBlue : \t {} \n", "")).on(Color::DarkBlue)); println!(
println!("{}", style(format!("Magenta : \t {} \n", "")).on(Color::Magenta)); "{}",
println!("{}", style(format!("DarkMagenta : \t {} \n", "")).on(Color::DarkMagenta)); style(format!("Cyan : \t\t {} \n", "")).on(Color::Cyan)
println!("{}", style(format!("Yellow : \t {} \n", "")).on(Color::Yellow)); );
println!("{}", style(format!("DarkYellow : \t {} \n", "")).on(Color::DarkYellow)); println!(
println!("{}", style(format!("Grey : \t\t {} \n", "")).on(Color::Grey)); "{}",
println!("{}", style(format!("White : \t {} \n", "")).on(Color::White)); style(format!("DarkCyan : \t {} \n", "")).on(Color::DarkCyan)
);
#[cfg(unix)] println!(
println!("{}", style("RGB color (10,10,10) ").on(Color::Rgb { "{}",
r: 10, style(format!("DarkRed : \t {} \n", "")).on(Color::DarkRed)
g: 10, );
b: 10 println!(
})); "{}",
style(format!("Green : \t {} \n", "")).on(Color::Green)
);
println!(
"{}",
style(format!("DarkGreen : \t {} \n", "")).on(Color::DarkGreen)
);
println!(
"{}",
style(format!("Blue : \t\t {} \n", "")).on(Color::Blue)
);
println!(
"{}",
style(format!("DarkBlue : \t {} \n", "")).on(Color::DarkBlue)
);
println!(
"{}",
style(format!("Magenta : \t {} \n", "")).on(Color::Magenta)
);
println!(
"{}",
style(format!("DarkMagenta : \t {} \n", "")).on(Color::DarkMagenta)
);
println!(
"{}",
style(format!("Yellow : \t {} \n", "")).on(Color::Yellow)
);
println!(
"{}",
style(format!("DarkYellow : \t {} \n", "")).on(Color::DarkYellow)
);
println!(
"{}",
style(format!("Grey : \t\t {} \n", "")).on(Color::Grey)
);
println!(
"{}",
style(format!("White : \t {} \n", "")).on(Color::White)
);
#[cfg(unix)] #[cfg(unix)]
println!("{}",style("RGB color (10,10,10) ").on(Color::AnsiValue(50))); println!(
"{}",
style("RGB color (10,10,10) ").on(Color::Rgb {
r: 10,
g: 10,
b: 10
})
);
#[cfg(unix)]
println!(
"{}",
style("RGB color (10,10,10) ").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.. /// 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)] #[cfg(unix)]
pub fn print_font_with_attributes() { pub fn print_font_with_attributes() {
println!("{}",style("Normal text")); println!("{}", style("Normal text"));
println!("{}",style("Bold text").bold()); println!("{}", style("Bold text").bold());
println!("{}",style("Italic text").italic()); println!("{}", style("Italic text").italic());
println!("{}",style("Slow blinking text").slow_blink()); println!("{}", style("Slow blinking text").slow_blink());
println!("{}",style("Rapid blinking text").rapid_blink()); println!("{}", style("Rapid blinking text").rapid_blink());
println!("{}",style("Hidden text").hidden()); println!("{}", style("Hidden text").hidden());
println!("{}",style("Underlined text").underlined()); println!("{}", style("Underlined text").underlined());
println!("{}",style("Reversed text").reverse()); println!("{}", style("Reversed text").reverse());
println!("{}",style("Dim text").dim()); println!("{}", style("Dim text").dim());
println!("{}",style("Crossed out font").crossed_out()); println!("{}", style("Crossed out font").crossed_out());
} }
/// Print all supported RGB colors | demonstration. /// Print all supported RGB colors | demonstration.
#[cfg(unix)] #[cfg(unix)]
pub fn print_supported_colors() { pub fn print_supported_colors() {
let count = color() let count = color().get_available_color_count().unwrap();
.get_available_color_count()
.unwrap();
for i in 0..count { for i in 0..count {
println!("{}", style(format!("White : \t {}", i)).on(Color::AnsiValue(i as u8))); println!(
"{}",
style(format!("White : \t {}", i)).on(Color::AnsiValue(i as u8))
);
} }
} }

View File

@ -1,4 +1,3 @@
//! This bin folder can be used to try the examples out located in the examples directory. //! This bin folder can be used to try the examples out located in the examples directory.
//! //!
//! All you need to do is: //! All you need to do is:
@ -9,12 +8,10 @@
extern crate crossterm; extern crate crossterm;
// modules that could be test // modules that could be test
mod terminal;
mod color; mod color;
mod cursor; mod cursor;
mod some_types;
mod input; mod input;
mod some_types;
mod terminal;
fn main() fn main() {}
{
}

View File

@ -1,12 +1,12 @@
extern crate crossterm; extern crate crossterm;
use self::crossterm::{Crossterm, Screen};
use self::crossterm::terminal::ClearType;
use self::crossterm::input::input; use self::crossterm::input::input;
use self::crossterm::terminal::ClearType;
use self::crossterm::{Crossterm, Screen};
use std::{thread, time};
use std::io::{stdout, Read, Write}; use std::io::{stdout, Read, Write};
use std::time::Duration; use std::time::Duration;
use std::{thread, time};
/// this will capture the input until the given key. /// this will capture the input until the given key.
pub fn read_async_until() { pub fn read_async_until() {
@ -100,8 +100,7 @@ pub fn async_reading_on_alternate_screen() {
let screen = Screen::new(false); let screen = Screen::new(false);
// switch to alternate screen // switch to alternate screen
if let Ok(alternate) = screen.enable_alternate_modes(true) if let Ok(alternate) = screen.enable_alternate_modes(true) {
{
let crossterm = Crossterm::from_screen(&alternate.screen); let crossterm = Crossterm::from_screen(&alternate.screen);
// init some modules we use for this demo // init some modules we use for this demo
let input = crossterm.input(); let input = crossterm.input();

View File

@ -1,12 +1,12 @@
extern crate crossterm; extern crate crossterm;
use crossterm::{Screen, Crossterm}; use crossterm::cursor::{cursor, TerminalCursor};
use crossterm::terminal::{from_screen,Terminal, ClearType};
use crossterm::cursor::{TerminalCursor, cursor};
use crossterm::input::input; use crossterm::input::input;
use std::sync::{Arc,Mutex}; use crossterm::terminal::{from_screen, ClearType, Terminal};
use crossterm::{Crossterm, Screen};
use std::io::Read; use std::io::Read;
use std::{thread,time}; use std::sync::{Arc, Mutex};
use std::{thread, time};
fn main() { fn main() {
use crossterm::color; use crossterm::color;
@ -18,7 +18,7 @@ fn main() {
let mut input_buf = Arc::new(Mutex::new(String::new())); let mut input_buf = Arc::new(Mutex::new(String::new()));
let threads = log(input_buf.clone(),&screen); let threads = log(input_buf.clone(), &screen);
let mut count = 0; let mut count = 0;
@ -26,19 +26,16 @@ fn main() {
let input = input(); let input = input();
let mut stdin = input.read_async().bytes(); let mut stdin = input.read_async().bytes();
loop loop {
{
let a = stdin.next(); let a = stdin.next();
match a { match a {
Some(Ok(13)) => Some(Ok(13)) => {
{ input_buf.lock().unwrap().clear();
input_buf.lock().unwrap().clear(); }
} Some(Ok(val)) => {
Some(Ok(val)) => input_buf.lock().unwrap().push(val as char);
{ }
input_buf.lock().unwrap().push(val as char);
}
_ => {} _ => {}
} }
@ -47,35 +44,36 @@ fn main() {
} }
}).join(); }).join();
for thread in threads {
for thread in threads
{
thread.join(); thread.join();
} }
cursor.show(); cursor.show();
} }
fn log(input_buf: Arc<Mutex<String>>, screen: &Screen) -> Vec<thread::JoinHandle<()>> fn log(input_buf: Arc<Mutex<String>>, screen: &Screen) -> Vec<thread::JoinHandle<()>> {
{
let mut threads = Vec::with_capacity(10); let mut threads = Vec::with_capacity(10);
let (_, term_height) = from_screen(screen).terminal_size(); let (_, term_height) = from_screen(screen).terminal_size();
for i in 0..1 for i in 0..1 {
{
let input_buffer = input_buf.clone(); let input_buffer = input_buf.clone();
let clone_stdout = screen.stdout.clone(); let clone_stdout = screen.stdout.clone();
let crossterm = Crossterm::from(screen.stdout.clone()); let crossterm = Crossterm::from(screen.stdout.clone());
let join = thread::spawn( move || { let join = thread::spawn(move || {
let cursor = crossterm.cursor(); let cursor = crossterm.cursor();
let terminal = crossterm.terminal(); let terminal = crossterm.terminal();
for j in 0..1000 for j in 0..1000 {
{ swap_write(
swap_write(format!("Some output: {} from thread: {}", j, i).as_ref(), &input_buffer.lock().unwrap(), &terminal, &cursor, term_height); format!("Some output: {} from thread: {}", j, i).as_ref(),
&input_buffer.lock().unwrap(),
&terminal,
&cursor,
term_height,
);
thread::sleep(time::Duration::from_millis(300)); thread::sleep(time::Duration::from_millis(300));
} }
}); });
@ -86,9 +84,15 @@ fn log(input_buf: Arc<Mutex<String>>, screen: &Screen) -> Vec<thread::JoinHandle
return threads; return threads;
} }
pub fn swap_write(msg: &str, input_buf: &String, terminal: &Terminal, cursor: &TerminalCursor, term_height: u16) { pub fn swap_write(
msg: &str,
input_buf: &String,
terminal: &Terminal,
cursor: &TerminalCursor,
term_height: u16,
) {
cursor.goto(0, term_height); cursor.goto(0, term_height);
terminal.clear(ClearType::CurrentLine); terminal.clear(ClearType::CurrentLine);
terminal.write(format!("{}\r\n", msg)); terminal.write(format!("{}\r\n", msg));
terminal.write(format!(">{}", input_buf)); terminal.write(format!(">{}", input_buf));
} }

View File

@ -1,12 +1,12 @@
extern crate crossterm; extern crate crossterm;
use crossterm::Screen; use crossterm::Screen;
use std::sync::Mutex;
use std::collections::VecDeque; use std::collections::VecDeque;
use std::sync::Arc;
use std::io::Write; use std::io::Write;
use std::sync::mpsc::{self, Receiver, Sender}; use std::sync::mpsc::{self, Receiver, Sender};
use std::thread::{JoinHandle, self}; use std::sync::Arc;
use std::sync::Mutex;
use std::thread::{self, JoinHandle};
/// This is an que that could be shared between threads safely. /// This is an que that could be shared between threads safely.
#[derive(Clone)] #[derive(Clone)]
@ -16,7 +16,9 @@ struct WorkQueue<T: Send + Clone> {
impl<T: Send + Clone> WorkQueue<T> { impl<T: Send + Clone> WorkQueue<T> {
fn new() -> Self { fn new() -> Self {
Self { inner: Arc::new(Mutex::new(VecDeque::new())) } Self {
inner: Arc::new(Mutex::new(VecDeque::new())),
}
} }
// get an item from the que if exists // get an item from the que if exists
@ -74,14 +76,17 @@ impl SyncFlagRx {
fn new_sync_flag(initial_state: bool) -> (SyncFlagTx, SyncFlagRx) { fn new_sync_flag(initial_state: bool) -> (SyncFlagTx, SyncFlagRx) {
let state = Arc::new(Mutex::new(initial_state)); let state = Arc::new(Mutex::new(initial_state));
let tx = SyncFlagTx { inner: state.clone() }; let tx = SyncFlagTx {
let rx = SyncFlagRx { inner: state.clone() }; inner: state.clone(),
};
let rx = SyncFlagRx {
inner: state.clone(),
};
return (tx, rx); return (tx, rx);
} }
fn main() fn main() {
{
let (_results_tx, _results_rx): (Sender<String>, Receiver<String>) = mpsc::channel(); let (_results_tx, _results_rx): (Sender<String>, Receiver<String>) = mpsc::channel();
let (mut more_jobs_tx, more_jobs_rx) = new_sync_flag(true); let (mut more_jobs_tx, more_jobs_rx) = new_sync_flag(true);
@ -94,15 +99,14 @@ fn main()
// a thread that will log all logs in the queue. // a thread that will log all logs in the queue.
handle_incoming_logs(more_jobs_rx.clone(), queue.clone()); handle_incoming_logs(more_jobs_rx.clone(), queue.clone());
// for handle in thread_handles // for handle in thread_handles
// { // {
// handle.join(); // handle.join();
// } // }
} }
fn handle_incoming_logs(more_jobs_rx: SyncFlagRx, queue: WorkQueue<String>) fn handle_incoming_logs(more_jobs_rx: SyncFlagRx, queue: WorkQueue<String>) {
{ thread::spawn(move || {
thread::spawn( move || {
let mut screen: Screen = Screen::default(); let mut screen: Screen = Screen::default();
// Loop while there's expected to be work, looking for work. // Loop while there's expected to be work, looking for work.
@ -121,23 +125,25 @@ fn handle_incoming_logs(more_jobs_rx: SyncFlagRx, queue: WorkQueue<String>)
} }
// start different threads that log contiguously. // start different threads that log contiguously.
fn log_with_different_threads(more_jobs_tx: SyncFlagTx, queue: WorkQueue<String>) -> Vec<JoinHandle<()>> fn log_with_different_threads(
{ more_jobs_tx: SyncFlagTx,
queue: WorkQueue<String>,
) -> Vec<JoinHandle<()>> {
// one vector that will have the thread handles in it. // one vector that will have the thread handles in it.
let mut threads = Vec::new(); let mut threads = Vec::new();
for thread_num in 1..5 for thread_num in 1..5 {
{
let mut more_jobs = more_jobs_tx.clone(); let mut more_jobs = more_jobs_tx.clone();
let thread_queue = queue.clone(); let thread_queue = queue.clone();
// create new thread // create new thread
let thread = thread::spawn(move || { let thread = thread::spawn(move || {
// log 400 messages // log 400 messages
for log_entry_count in 1..400 for log_entry_count in 1..400 {
{ thread_queue.add_work(format!(
thread_queue.add_work(format!("Log {} from thread {} ",log_entry_count, thread_num)); "Log {} from thread {} ",
log_entry_count, thread_num
));
more_jobs.set(true); more_jobs.set(true);
} }
}); });

View File

@ -1,11 +1,10 @@
extern crate crossterm; extern crate crossterm;
use crossterm::{Crossterm, Screen};
use crossterm::style::Color; use crossterm::style::Color;
use crossterm::{Crossterm, Screen};
/// use the `Crossterm` to get an instance to the cursor module | demonstration. /// use the `Crossterm` to get an instance to the cursor module | demonstration.
pub fn crossterm() pub fn crossterm() {
{
// Create the crossterm type to access different modules. // Create the crossterm type to access different modules.
let crossterm = Crossterm::new(); let crossterm = Crossterm::new();

View File

@ -1,6 +1,6 @@
extern crate crossterm; extern crate crossterm;
use crossterm::style::{Color, style}; use crossterm::style::{style, Color};
use crossterm::terminal::{self, ClearType}; use crossterm::terminal::{self, ClearType};
use crossterm::{Crossterm, Screen}; use crossterm::{Crossterm, Screen};
@ -26,7 +26,10 @@ fn print_wait_screen(screen: &Screen) {
for i in 1..5 { for i in 1..5 {
// print the current counter at the line of `Seconds to Go: {counter}` // print the current counter at the line of `Seconds to Go: {counter}`
cursor.goto(10, 2); cursor.goto(10, 2);
style(format!("{} of the 5 items processed", i)).with(Color::Red).on(Color::Blue).paint(&screen); style(format!("{} of the 5 items processed", i))
.with(Color::Red)
.on(Color::Blue)
.paint(&screen);
// 1 second delay // 1 second delay
thread::sleep(time::Duration::from_secs(1)); thread::sleep(time::Duration::from_secs(1));
@ -35,11 +38,9 @@ fn print_wait_screen(screen: &Screen) {
/// print wait screen on alternate screen, then switch back. /// print wait screen on alternate screen, then switch back.
pub fn print_wait_screen_on_alternate_window() { pub fn print_wait_screen_on_alternate_window() {
let screen = Screen::default(); let screen = Screen::default();
if let Ok(alternate) = screen.enable_alternate_modes(false) if let Ok(alternate) = screen.enable_alternate_modes(false) {
{
print_wait_screen(&alternate.screen); print_wait_screen(&alternate.screen);
} }
} }

View File

@ -1,8 +1,8 @@
extern crate crossterm; extern crate crossterm;
use crossterm::{Crossterm, Screen};
use crossterm::terminal::{self, ClearType};
use crossterm::style::{style, Color}; use crossterm::style::{style, Color};
use crossterm::terminal::{self, ClearType};
use crossterm::{Crossterm, Screen};
use std::io::{stdout, Write}; use std::io::{stdout, Write};
use std::{thread, time}; use std::{thread, time};
@ -27,7 +27,10 @@ fn print_wait_screen(screen: &mut Screen) {
for i in 1..5 { for i in 1..5 {
// print the current counter at the line of `Seconds to Go: {counter}` // print the current counter at the line of `Seconds to Go: {counter}`
cursor.goto(10, 2); cursor.goto(10, 2);
style(format!("{} of the 5 items processed", i)).with(Color::Red).on(Color::Blue).paint(&screen); style(format!("{} of the 5 items processed", i))
.with(Color::Red)
.on(Color::Blue)
.paint(&screen);
screen.stdout.flush(); screen.stdout.flush();
// 1 second delay // 1 second delay
@ -38,9 +41,8 @@ fn print_wait_screen(screen: &mut Screen) {
pub fn print_wait_screen_on_alternate_window() { pub fn print_wait_screen_on_alternate_window() {
let screen = Screen::default(); let screen = Screen::default();
if let Ok(ref mut alternate) = screen.enable_alternate_modes(true) if let Ok(ref mut alternate) = screen.enable_alternate_modes(true) {
{ print_wait_screen(&mut alternate.screen);
print_wait_screen(&mut alternate.screen);
} }
drop(screen); drop(screen);
println!("Whe are back at the main screen"); println!("Whe are back at the main screen");

View File

@ -4,8 +4,8 @@
extern crate crossterm; extern crate crossterm;
use crossterm::terminal::{ClearType, terminal};
use crossterm::cursor; use crossterm::cursor;
use crossterm::terminal::{terminal, ClearType};
fn print_test_data() { fn print_test_data() {
for i in 0..100 { for i in 0..100 {
println!("Test data to test terminal: {}", i); println!("Test data to test terminal: {}", i);
@ -25,7 +25,7 @@ pub fn clear_all_lines() {
/// Clear all lines from cursor position X:4, Y:4 down | demonstration /// Clear all lines from cursor position X:4, Y:4 down | demonstration
pub fn clear_from_cursor_down() { pub fn clear_from_cursor_down() {
let mut terminal = terminal(); let mut terminal = terminal();
print_test_data(); print_test_data();
// Set terminal cursor position (see example for more info). // Set terminal cursor position (see example for more info).
@ -55,7 +55,7 @@ pub fn clear_current_line() {
print_test_data(); print_test_data();
// Set terminal cursor position (see example for more info). // Set terminal cursor position (see example for more info).
cursor().goto(4, 4); cursor().goto(4, 4);
// Clear current line cells. // Clear current line cells.
terminal.clear(ClearType::CurrentLine); terminal.clear(ClearType::CurrentLine);
@ -87,7 +87,6 @@ pub fn print_terminal_size() {
/// Set the terminal size to width 10, height: 10 | demonstration. /// Set the terminal size to width 10, height: 10 | demonstration.
pub fn set_terminal_size() { pub fn set_terminal_size() {
let mut terminal = terminal(); let mut terminal = terminal();
terminal.set_size(10, 10); terminal.set_size(10, 10);
@ -95,7 +94,6 @@ pub fn set_terminal_size() {
/// Scroll down 10 lines | demonstration. /// Scroll down 10 lines | demonstration.
pub fn scroll_down() { pub fn scroll_down() {
let mut terminal = terminal(); let mut terminal = terminal();
print_test_data(); print_test_data();
@ -106,7 +104,6 @@ pub fn scroll_down() {
/// Scroll down 10 lines | demonstration. /// Scroll down 10 lines | demonstration.
pub fn scroll_up() { pub fn scroll_up() {
let mut terminal = terminal(); let mut terminal = terminal();
print_test_data(); print_test_data();
@ -117,7 +114,6 @@ pub fn scroll_up() {
/// Resize the terminal to X: 10, Y: 10 | demonstration. /// Resize the terminal to X: 10, Y: 10 | demonstration.
pub fn resize_terminal() { pub fn resize_terminal() {
let mut terminal = terminal(); let mut terminal = terminal();
// Get terminal size // Get terminal size
@ -126,7 +122,6 @@ pub fn resize_terminal() {
/// exit the current proccess. /// exit the current proccess.
pub fn exit() { pub fn exit() {
let mut terminal = terminal(); let mut terminal = terminal();
terminal.exit(); terminal.exit();
} }

View File

@ -23,13 +23,13 @@ pub trait IEnableAnsiCommand {
} }
// This trait provides an interface for switching to alternate screen and back. // This trait provides an interface for switching to alternate screen and back.
pub trait IAlternateScreenCommand: Sync + Send { pub trait IAlternateScreenCommand: Sync + Send {
fn enable(&self, stdout: &mut TerminalOutput) -> io::Result<()>; fn enable(&self, stdout: &mut TerminalOutput) -> io::Result<()>;
fn disable(&self, stdout: &TerminalOutput) -> io::Result<()>; fn disable(&self, stdout: &TerminalOutput) -> io::Result<()>;
} }
// This trait provides an interface for switching to raw mode and back. // This trait provides an interface for switching to raw mode and back.
pub trait IRawScreenCommand: Sync + Send{ pub trait IRawScreenCommand: Sync + Send {
fn enable(&mut self) -> io::Result<()>; fn enable(&mut self) -> io::Result<()>;
fn disable(&self) -> io::Result<()>; fn disable(&self) -> io::Result<()>;
} }

View File

@ -2,28 +2,27 @@
use super::{IAlternateScreenCommand, TerminalOutput}; use super::{IAlternateScreenCommand, TerminalOutput};
use std::io::{ Result}; use std::io::Result;
/// This command is used for switching to alternate screen and back to main screen. /// This command is used for switching to alternate screen and back to main screen.
pub struct ToAlternateScreenCommand; pub struct ToAlternateScreenCommand;
impl ToAlternateScreenCommand { impl ToAlternateScreenCommand {
pub fn new() -> ToAlternateScreenCommand { pub fn new() -> ToAlternateScreenCommand {
return ToAlternateScreenCommand; ToAlternateScreenCommand
} }
} }
impl IAlternateScreenCommand for ToAlternateScreenCommand { impl IAlternateScreenCommand for ToAlternateScreenCommand {
/// enable alternate screen. /// enable alternate screen.
fn enable(&self, stdout: &mut TerminalOutput) -> Result<()> { fn enable(&self, stdout: &mut TerminalOutput) -> Result<()> {
stdout.write_str(csi!("?1049h")); stdout.write_str(csi!("?1049h"))?;
Ok(()) Ok(())
} }
/// disable alternate screen. /// disable alternate screen.
fn disable(&self, stdout: &TerminalOutput) -> Result<()> { fn disable(&self, stdout: &TerminalOutput) -> Result<()> {
stdout.write_str(csi!("?1049l")); stdout.write_str(csi!("?1049l"))?;
Ok(()) Ok(())
} }
} }

View File

@ -1,67 +1,7 @@
//! This module contains the commands that can be used for unix systems. //! This module contains the commands that can be used for unix systems.
use super::{ IStateCommand};
use kernel::unix_kernel::terminal; use kernel::unix_kernel::terminal;
use termios::{tcsetattr, Termios, CREAD, ECHO, ICANON, TCSAFLUSH, BRKINT, ICRNL, INPCK, ISTRIP, IXON, OPOST, CS8, IEXTEN, ISIG,VTIME, VMIN};
use libc::STDIN_FILENO;
use std::sync::{Once, ONCE_INIT};
static TERMINAL_MODE: Once = ONCE_INIT;
use std::io::Result;
use std::io::{Error, ErrorKind, Result};
/// This command is used for switching to NoncanonicalMode.
#[derive(Copy, Clone)]
pub struct NoncanonicalModeCommand;
impl NoncanonicalModeCommand {
pub fn new() -> NoncanonicalModeCommand {
NoncanonicalModeCommand {}
}
}
static mut ORIGINAL: Option<Termios> = None;
impl NoncanonicalModeCommand {
pub fn enable(&mut self) -> Result<()> {
// Set noncanonical mode
if let Ok(orig) = Termios::from_fd(STDIN_FILENO) {
TERMINAL_MODE.call_once(|| {
unsafe { ORIGINAL = Some(orig.clone()); }
});
let mut noncan = orig.clone();
noncan.c_iflag &= !(BRKINT | ICRNL | INPCK | ISTRIP | IXON);
noncan.c_oflag &= !(OPOST);
noncan.c_cflag |= (CS8);
noncan.c_lflag &= !(ECHO | ICANON | IEXTEN | ISIG);
noncan.c_cc[VMIN] = 0;
noncan.c_cc[VTIME] = 1;
tcsetattr(STDIN_FILENO, TCSAFLUSH, &noncan)?;
} else {
return Err(Error::new(
ErrorKind::Other,
"Could not set console mode when enabling raw mode",
));
}
unsafe { terminal::RAW_MODE_ENABLED_BY_USER = true }
Ok(())
}
pub fn disable(&self) -> Result<()> {
unsafe {
if let Some(original) = ORIGINAL
{
tcsetattr(STDIN_FILENO, TCSAFLUSH, &original)?;
}
}
unsafe { terminal::RAW_MODE_ENABLED_BY_USER = false }
Ok(())
}
}
// This command is used for enabling and disabling raw mode for the terminal. // This command is used for enabling and disabling raw mode for the terminal.
/// This command is used for enabling and disabling raw mode for the terminal. /// This command is used for enabling and disabling raw mode for the terminal.
@ -69,12 +9,12 @@ pub struct RawModeCommand;
impl RawModeCommand { impl RawModeCommand {
pub fn new() -> Self { pub fn new() -> Self {
return RawModeCommand {} RawModeCommand
} }
/// Enables raw mode. /// Enables raw mode.
pub fn enable(&mut self) -> Result<()> { pub fn enable(&mut self) -> Result<()> {
terminal::into_raw_mode(); terminal::into_raw_mode()?;
unsafe { terminal::RAW_MODE_ENABLED_BY_USER = true } unsafe { terminal::RAW_MODE_ENABLED_BY_USER = true }
Ok(()) Ok(())
@ -82,10 +22,9 @@ impl RawModeCommand {
/// Disables raw mode. /// Disables raw mode.
pub fn disable(&mut self) -> Result<()> { pub fn disable(&mut self) -> Result<()> {
terminal::disable_raw_mode(); terminal::disable_raw_mode()?;
unsafe { terminal::RAW_MODE_ENABLED_BY_USER = false } unsafe { terminal::RAW_MODE_ENABLED_BY_USER = false }
Ok(()) Ok(())
} }
} }

View File

@ -3,13 +3,13 @@
use super::{IAlternateScreenCommand, IEnableAnsiCommand, TerminalOutput}; use super::{IAlternateScreenCommand, IEnableAnsiCommand, TerminalOutput};
use kernel::windows_kernel::{ansi_support, csbi, handle, kernel}; use kernel::windows_kernel::{ansi_support, csbi, handle, kernel};
use winapi::um::wincon;
use winapi::shared::minwindef::DWORD; use winapi::shared::minwindef::DWORD;
use winapi::um::wincon::{ENABLE_VIRTUAL_TERMINAL_PROCESSING}; use winapi::um::wincon;
use winapi::um::wincon::ENABLE_VIRTUAL_TERMINAL_PROCESSING;
use winapi::um::winnt::HANDLE;
use std::io::{Error, ErrorKind, Result}; use std::io::{Error, ErrorKind, Result};
use std::sync::Arc; use std::sync::Arc;
use winapi::um::winnt::HANDLE;
/// This command is used for enabling and disabling ANSI code support for windows systems, /// This command is used for enabling and disabling ANSI code support for windows systems,
/// For more info check: https://docs.microsoft.com/en-us/windows/console/console-virtual-terminal-sequences. /// For more info check: https://docs.microsoft.com/en-us/windows/console/console-virtual-terminal-sequences.
@ -74,12 +74,11 @@ impl IEnableAnsiCommand for EnableAnsiCommand {
pub struct RawModeCommand { pub struct RawModeCommand {
mask: DWORD, mask: DWORD,
} }
use self::wincon::{ ENABLE_LINE_INPUT, ENABLE_WRAP_AT_EOL_OUTPUT}; use self::wincon::{ENABLE_LINE_INPUT, ENABLE_WRAP_AT_EOL_OUTPUT};
impl RawModeCommand impl RawModeCommand {
{
pub fn new() -> Self { pub fn new() -> Self {
RawModeCommand { RawModeCommand {
mask: ENABLE_WRAP_AT_EOL_OUTPUT | ENABLE_LINE_INPUT mask: ENABLE_WRAP_AT_EOL_OUTPUT | ENABLE_LINE_INPUT,
} }
} }
} }
@ -144,9 +143,8 @@ impl ToAlternateScreenCommand {
} }
} }
impl IAlternateScreenCommand for ToAlternateScreenCommand { impl IAlternateScreenCommand for ToAlternateScreenCommand {
fn enable(&self, stdout: &mut TerminalOutput) -> Result<()> { fn enable(&self, stdout: &mut TerminalOutput) -> Result<()> {
let handle = handle::get_output_handle()?; let handle = handle::get_output_handle()?;
// create a new screen buffer to copy to. // create a new screen buffer to copy to.

View File

@ -36,7 +36,7 @@ use std::sync::Arc;
/// } /// }
/// ``` /// ```
pub struct Crossterm { pub struct Crossterm {
stdout: Option<Arc<TerminalOutput>> stdout: Option<Arc<TerminalOutput>>,
} }
impl<'crossterm> Crossterm { impl<'crossterm> Crossterm {
@ -47,7 +47,9 @@ impl<'crossterm> Crossterm {
/// Create a new instance of `Crossterm` /// Create a new instance of `Crossterm`
pub fn from_screen(screen: &Screen) -> Crossterm { pub fn from_screen(screen: &Screen) -> Crossterm {
Crossterm { stdout: Some(screen.stdout.clone()) } Crossterm {
stdout: Some(screen.stdout.clone()),
}
} }
/// Get an `TerminalCursor` implementation whereon cursor related actions can be performed. /// Get an `TerminalCursor` implementation whereon cursor related actions can be performed.
@ -61,8 +63,8 @@ impl<'crossterm> Crossterm {
/// ``` /// ```
pub fn cursor(&self) -> cursor::TerminalCursor { pub fn cursor(&self) -> cursor::TerminalCursor {
match &self.stdout { match &self.stdout {
None => { cursor::TerminalCursor::new()}, None => cursor::TerminalCursor::new(),
Some(stdout) => { cursor::TerminalCursor::on_screen(&stdout) }, Some(stdout) => cursor::TerminalCursor::on_screen(&stdout),
} }
} }
@ -91,12 +93,12 @@ impl<'crossterm> Crossterm {
/// let crossterm = Crossterm::new(); /// let crossterm = Crossterm::new();
/// let mut terminal = crossterm.terminal(); /// let mut terminal = crossterm.terminal();
/// ``` /// ```
pub fn terminal(&self) -> terminal::Terminal { pub fn terminal(&self) -> terminal::Terminal {
match &self.stdout { match &self.stdout {
None => terminal::Terminal::new(), None => terminal::Terminal::new(),
Some(stdout) => terminal::Terminal::on_screen(&stdout), Some(stdout) => terminal::Terminal::on_screen(&stdout),
} }
} }
/// Get an `TerminalColor` implementation whereon color related actions can be performed. /// Get an `TerminalColor` implementation whereon color related actions can be performed.
/// ///
@ -135,21 +137,24 @@ impl<'crossterm> Crossterm {
/// ``` /// ```
pub fn style<D>(&self, val: D) -> style::StyledObject<D> pub fn style<D>(&self, val: D) -> style::StyledObject<D>
where where
D: Display, { D: Display,
{
style::ObjectStyle::new().apply_to(val) style::ObjectStyle::new().apply_to(val)
} }
} }
impl From<Arc<TerminalOutput>> for Crossterm impl From<Arc<TerminalOutput>> for Crossterm {
{
fn from(stdout: Arc<TerminalOutput>) -> Self { fn from(stdout: Arc<TerminalOutput>) -> Self {
Crossterm { stdout: Some(stdout) } Crossterm {
stdout: Some(stdout),
}
} }
} }
impl From<Screen> for Crossterm impl From<Screen> for Crossterm {
{
fn from(screen: Screen) -> Self { fn from(screen: Screen) -> Self {
Crossterm { stdout: Some(screen.stdout.clone()) } Crossterm {
stdout: Some(screen.stdout.clone()),
}
} }
} }

View File

@ -1,14 +1,14 @@
//! Some actions need to preformed platform independently since they can not be solved `ANSI escape codes`. //! Some actions need to preformed platform independently since they can not be solved `ANSI escape codes`.
use super::TerminalOutput; use super::TerminalOutput;
use std::sync::Arc;
use std::io::{self, Write}; use std::io::{self, Write};
use std::sync::Arc;
#[cfg(windows)] #[cfg(windows)]
use kernel::windows_kernel::ansi_support::{try_enable_ansi_support, windows_supportable}; use kernel::windows_kernel::ansi_support::{try_enable_ansi_support, windows_supportable};
#[cfg(windows)] #[cfg(windows)]
use kernel::windows_kernel::terminal::{ exit, terminal_size}; use kernel::windows_kernel::terminal::{exit, terminal_size};
#[cfg(windows)] #[cfg(windows)]
use kernel::windows_kernel::cursor::pos; use kernel::windows_kernel::cursor::pos;
@ -18,14 +18,13 @@ use kernel::unix_kernel::terminal::{exit, pos, terminal_size};
/// Get the terminal size based on the current platform. /// Get the terminal size based on the current platform.
pub fn get_terminal_size() -> (u16, u16) { pub fn get_terminal_size() -> (u16, u16) {
return terminal_size(); terminal_size()
} }
/// Get the cursor position based on the current platform. /// Get the cursor position based on the current platform.
pub fn get_cursor_position() -> (u16, u16) { pub fn get_cursor_position() -> (u16, u16) {
#[cfg(unix)] #[cfg(unix)]
return pos().expect("Valide position"); return pos().expect("Valide position");
// return pos().unwrap_or_else(|x| { return (0,0) });
#[cfg(windows)] #[cfg(windows)]
return pos(); return pos();
} }
@ -43,17 +42,16 @@ pub fn get_module<T>(winapi_impl: T, unix_impl: T) -> Option<T> {
let mut term: Option<T> = None; let mut term: Option<T> = None;
let mut does_support = true; let mut does_support = true;
if !windows_supportable() if !windows_supportable() {
{ // Try to enable ansi on windows if not than use WINAPI.
// Try to enable ansi on windows if not than use WINAPI. does_support = try_enable_ansi_support();
does_support = try_enable_ansi_support();
// uncomment this line when you want to use the winapi implementation. // uncomment this line when you want to use the winapi implementation.
// does_support = false; // does_support = false;
if !does_support { if !does_support {
term = Some(winapi_impl); term = Some(winapi_impl);
}
} }
}
if does_support { if does_support {
term = Some(unix_impl); term = Some(unix_impl);
@ -62,16 +60,26 @@ pub fn get_module<T>(winapi_impl: T, unix_impl: T) -> Option<T> {
term term
} }
pub fn write(stdout: &Option<&Arc<TerminalOutput>>, string: String) { pub fn write(stdout: &Option<&Arc<TerminalOutput>>, string: String) -> io::Result<usize> {
match stdout { match stdout {
None => { print!("{}", string.as_str()); io::stdout().flush(); }, None => {
Some(output) => { output.write_string(string); }, print!("{}", string.as_str());
match io::stdout().flush() {
Ok(_) => Ok(string.len()),
Err(e) => Err(e),
}
}
Some(output) => output.write_string(string),
} }
} }
pub fn write_str(stdout: &Option<&Arc<TerminalOutput>>, string: &str) { pub fn write_str(stdout: &Option<&Arc<TerminalOutput>>, string: &str) -> io::Result<usize> {
match stdout { match stdout {
None => { print!("{}", string); io::stdout().flush(); }, None => match io::stdout().flush() {
Some(output) => { output.write_str(string); }, Ok(_) => Ok(string.len()),
Err(e) => Err(e),
},
Some(output) => output.write_str(string),
} }
} }

View File

@ -10,4 +10,4 @@ pub mod traits;
mod crossterm; mod crossterm;
pub use self::crossterm::Crossterm; pub use self::crossterm::Crossterm;
use {Screen, TerminalOutput}; use TerminalOutput;

View File

@ -6,27 +6,24 @@
//! Vim uses the entirety of the screen to edit the file, then returning to bash leaves the original buffer unchanged. //! Vim uses the entirety of the screen to edit the file, then returning to bash leaves the original buffer unchanged.
use super::commands::{self, IAlternateScreenCommand}; use super::commands::{self, IAlternateScreenCommand};
use super::{functions, Screen, TerminalOutput,RawScreen}; use super::{RawScreen, Screen, TerminalOutput};
use std::io;
use std::convert::From; use std::convert::From;
use std::io;
/// With this type you will be able to switch to alternate screen and back to main screen. /// With this type you will be able to switch to alternate screen and back to main screen.
/// Check also the Screen type for swishing to alternate mode. /// Check also the Screen type for swishing to alternate mode.
/// ///
/// Although this type is available for you to use I would recommend using `Screen` instead. /// Although this type is available for you to use I would recommend using `Screen` instead.
pub struct AlternateScreen pub struct AlternateScreen {
{
command: Box<IAlternateScreenCommand + Sync + Send>, command: Box<IAlternateScreenCommand + Sync + Send>,
pub screen: Screen, pub screen: Screen,
} }
impl AlternateScreen { impl AlternateScreen {
/// Create new instance of alternate screen. /// Create new instance of alternate screen.
pub fn new(command: Box<IAlternateScreenCommand + Sync + Send>, screen: Screen) -> Self pub fn new(command: Box<IAlternateScreenCommand + Sync + Send>, screen: Screen) -> Self {
{ AlternateScreen { command, screen }
return AlternateScreen { command, screen }
} }
/// Switch to alternate screen. This function will return an `AlternateScreen` instance if everything went well this type will give you control over the `AlternateScreen`. /// Switch to alternate screen. This function will return an `AlternateScreen` instance if everything went well this type will give you control over the `AlternateScreen`.
@ -38,13 +35,16 @@ impl AlternateScreen {
/// The alternate buffer is exactly the dimensions of the window, without any scrollback region. /// The alternate buffer is exactly the dimensions of the window, without any scrollback region.
/// For an example of this behavior, consider when vim is launched from bash. /// For an example of this behavior, consider when vim is launched from bash.
/// Vim uses the entirety of the screen to edit the file, then returning to bash leaves the original buffer unchanged. /// Vim uses the entirety of the screen to edit the file, then returning to bash leaves the original buffer unchanged.
pub fn to_alternate_screen(stdout: TerminalOutput, raw_mode: bool) -> io::Result<AlternateScreen> { pub fn to_alternate_screen(
stdout: TerminalOutput,
raw_mode: bool,
) -> io::Result<AlternateScreen> {
#[cfg(target_os = "windows")] #[cfg(target_os = "windows")]
let command = functions::get_module::<Box<commands::IAlternateScreenCommand + Sync + Send>>( let command =
Box::from(commands::win_commands::ToAlternateScreenCommand::new()), functions::get_module::<Box<commands::IAlternateScreenCommand + Sync + Send>>(
Box::from(commands::shared_commands::ToAlternateScreenCommand::new()), Box::from(commands::win_commands::ToAlternateScreenCommand::new()),
).unwrap(); Box::from(commands::shared_commands::ToAlternateScreenCommand::new()),
).unwrap();
#[cfg(not(target_os = "windows"))] #[cfg(not(target_os = "windows"))]
let command = Box::from(commands::shared_commands::ToAlternateScreenCommand::new()); let command = Box::from(commands::shared_commands::ToAlternateScreenCommand::new());
@ -54,12 +54,11 @@ impl AlternateScreen {
let screen = Screen::from(stdout); let screen = Screen::from(stdout);
if raw_mode if raw_mode {
{ RawScreen::into_raw_mode()?;
RawScreen::into_raw_mode();
} }
return Ok(AlternateScreen::new(command, screen)); Ok(AlternateScreen::new(command, screen))
} }
/// Switch the alternate screen back to main screen. /// Switch the alternate screen back to main screen.
@ -69,8 +68,7 @@ impl AlternateScreen {
} }
} }
impl Drop for AlternateScreen impl Drop for AlternateScreen {
{
/// This will switch back to main screen on drop. /// This will switch back to main screen on drop.
fn drop(&mut self) { fn drop(&mut self) {
self.to_main_screen(); self.to_main_screen();

View File

@ -5,8 +5,8 @@ mod alternate;
mod raw; mod raw;
mod screen; mod screen;
use super::{commands, functions, TerminalOutput}; use super::{commands, TerminalOutput};
pub use self::raw::RawScreen;
pub use self::alternate::AlternateScreen; pub use self::alternate::AlternateScreen;
pub use self::raw::RawScreen;
pub use self::screen::Screen; pub use self::screen::Screen;

View File

@ -15,10 +15,8 @@
//! With these modes you can easier design the terminal screen. //! With these modes you can easier design the terminal screen.
use super::commands::*; use super::commands::*;
use TerminalOutput;
use std::io; use std::io;
use std::sync::Arc;
/// A wrapper for the raw terminal state. Which can be used to write to. /// A wrapper for the raw terminal state. Which can be used to write to.
/// ///
@ -28,8 +26,7 @@ pub struct RawScreen;
impl RawScreen { impl RawScreen {
/// Put terminal in raw mode. /// Put terminal in raw mode.
pub fn into_raw_mode() -> io::Result<()> pub fn into_raw_mode() -> io::Result<()> {
{
#[cfg(not(target_os = "windows"))] #[cfg(not(target_os = "windows"))]
let mut command = unix_command::RawModeCommand::new(); let mut command = unix_command::RawModeCommand::new();
#[cfg(target_os = "windows")] #[cfg(target_os = "windows")]
@ -41,14 +38,13 @@ impl RawScreen {
} }
/// Put terminal back in original modes. /// Put terminal back in original modes.
pub fn disable_raw_modes() -> io::Result<()> pub fn disable_raw_modes() -> io::Result<()> {
{
#[cfg(not(target_os = "windows"))] #[cfg(not(target_os = "windows"))]
let mut command = unix_command::RawModeCommand::new(); let mut command = unix_command::RawModeCommand::new();
#[cfg(target_os = "windows")] #[cfg(target_os = "windows")]
let mut command = win_commands::RawModeCommand::new(); let mut command = win_commands::RawModeCommand::new();
command.disable()?; command.disable()?;
return Ok(()) Ok(())
} }
} }

View File

@ -1,10 +1,9 @@
use super::{AlternateScreen,RawScreen}; use super::{AlternateScreen, RawScreen};
use TerminalOutput; use TerminalOutput;
use std::io::Write;
use std::io::Result; use std::io::Result;
use std::io::Write;
use std::sync::Arc; use std::sync::Arc;
use std::sync::atomic::AtomicBool;
/// This type represents an screen which could be in normal, raw and alternate modes. /// This type represents an screen which could be in normal, raw and alternate modes.
/// ///
@ -60,27 +59,27 @@ use std::sync::atomic::AtomicBool;
/// } /// }
/// ``` /// ```
/// ///
pub struct Screen pub struct Screen {
{
buffer: Vec<u8>, buffer: Vec<u8>,
pub stdout: Arc<TerminalOutput>, pub stdout: Arc<TerminalOutput>,
drop: bool, drop: bool,
} }
impl Screen impl Screen {
{
/// Create new instance of the Screen also specify if the current screen should be in raw mode or normal mode. /// Create new instance of the Screen also specify if the current screen should be in raw mode or normal mode.
/// If you are not sure what raw mode is then pass false or use the `Screen::default()` to create an instance. /// If you are not sure what raw mode is then pass false or use the `Screen::default()` to create an instance.
pub fn new(raw_mode: bool) -> Screen pub fn new(raw_mode: bool) -> Screen {
{ if raw_mode {
if raw_mode let screen = Screen {
{ stdout: Arc::new(TerminalOutput::new(true)),
let screen = Screen { stdout: Arc::new(TerminalOutput::new(true)), buffer: Vec::new(), drop: true }; buffer: Vec::new(),
RawScreen::into_raw_mode().unwrap(); drop: true,
return screen; };
} RawScreen::into_raw_mode().unwrap();
return screen;
}
return Screen::default(); Screen::default()
} }
/// Switch to alternate screen. This function will return an `AlternateScreen` instance. If everything went well this type will give you control over the `AlternateScreen`. /// Switch to alternate screen. This function will return an `AlternateScreen` instance. If everything went well this type will give you control over the `AlternateScreen`.
@ -96,7 +95,7 @@ impl Screen
let stdout = TerminalOutput::new(raw_mode); let stdout = TerminalOutput::new(raw_mode);
let alternate_screen = AlternateScreen::to_alternate_screen(stdout, raw_mode)?; let alternate_screen = AlternateScreen::to_alternate_screen(stdout, raw_mode)?;
return Ok(alternate_screen); Ok(alternate_screen)
} }
/// Write buffer to an internal buffer. When you want to write the buffer to screen use `flush_buf()`. /// Write buffer to an internal buffer. When you want to write the buffer to screen use `flush_buf()`.
@ -112,8 +111,7 @@ impl Screen
/// screen.write_buf(b"Some more text"); /// screen.write_buf(b"Some more text");
/// ``` /// ```
pub fn write_buf(&mut self, buf: &[u8]) -> Result<usize> { pub fn write_buf(&mut self, buf: &[u8]) -> Result<usize> {
self.buffer.write(buf)?; self.buffer.write(buf)
Ok(buf.len())
} }
/// Flush the internal buffer to the screen. /// Flush the internal buffer to the screen.
@ -125,49 +123,54 @@ impl Screen
} }
/// This will disable the drop which will cause raw modes not to be undone on drop of `Screen`. /// This will disable the drop which will cause raw modes not to be undone on drop of `Screen`.
pub fn disable_drop(&mut self) pub fn disable_drop(&mut self) {
{
self.drop = false; self.drop = false;
} }
} }
impl From<TerminalOutput> for Screen impl From<TerminalOutput> for Screen {
{
/// Create an screen with the given `Stdout` /// Create an screen with the given `Stdout`
fn from(stdout: TerminalOutput) -> Self { fn from(stdout: TerminalOutput) -> Self {
return Screen { stdout: Arc::new(stdout), buffer: Vec::new(), drop: true}; Screen {
stdout: Arc::new(stdout),
buffer: Vec::new(),
drop: true,
}
} }
} }
impl From<Arc<TerminalOutput>> for Screen impl From<Arc<TerminalOutput>> for Screen {
{
/// Create an screen with the given 'Arc<Stdout>' /// Create an screen with the given 'Arc<Stdout>'
fn from(stdout: Arc<TerminalOutput>) -> Self { fn from(stdout: Arc<TerminalOutput>) -> Self {
return Screen { stdout: stdout, buffer: Vec::new(), drop: true}; Screen {
stdout,
buffer: Vec::new(),
drop: true,
}
} }
} }
impl Default for Screen impl Default for Screen {
{
/// Create an new screen which will not be in raw mode or alternate mode. /// Create an new screen which will not be in raw mode or alternate mode.
fn default() -> Self { fn default() -> Self {
return Screen { stdout: Arc::new(TerminalOutput::new(false)), buffer: Vec::new(), drop: true}; Screen {
stdout: Arc::new(TerminalOutput::new(false)),
buffer: Vec::new(),
drop: true,
}
} }
} }
impl Drop for Screen impl Drop for Screen {
{
/// If the current screen is in raw mode whe need to disable it when the instance goes out of scope. /// If the current screen is in raw mode whe need to disable it when the instance goes out of scope.
fn drop(&mut self) { fn drop(&mut self) {
if self.stdout.is_in_raw_mode && self.drop if self.stdout.is_in_raw_mode && self.drop {
{
RawScreen::disable_raw_modes(); RawScreen::disable_raw_modes();
} }
} }
} }
impl Write for Screen impl Write for Screen {
{
fn write(&mut self, buf: &[u8]) -> Result<usize> { fn write(&mut self, buf: &[u8]) -> Result<usize> {
self.stdout.write_buf(buf) self.stdout.write_buf(buf)
} }
@ -175,4 +178,4 @@ impl Write for Screen
fn flush(&mut self) -> Result<()> { fn flush(&mut self) -> Result<()> {
self.stdout.flush() self.stdout.flush()
} }
} }

View File

@ -1,22 +1,14 @@
//! This module contains all `unix` specific terminal related logic. //! This module contains all `unix` specific terminal related logic.
use self::libc::{c_int, c_ushort, ioctl, STDOUT_FILENO, TIOCGWINSZ, TIOCSWINSZ, signal, SIG_IGN, SIGWINCH}; use self::libc::{c_ushort, ioctl, STDOUT_FILENO, TCSADRAIN, TIOCGWINSZ};
use common::commands::unix_command::RawModeCommand;
use {libc, TerminalOutput, Screen};
pub use libc::termios; pub use libc::termios;
use {libc, Screen};
use std::sync::Arc; use std::fs;
use std::io::{self, Error, ErrorKind, Read, Write}; use std::io::{self, Error, ErrorKind, Read, Write};
use std::os::unix::io::AsRawFd; use std::os::unix::io::AsRawFd;
use std::time::{Duration, SystemTime}; use termios::{tcsetattr, Termios};
use std::{fs, mem};
use termios::{cfmakeraw, tcsetattr, Termios, TCSADRAIN, CREAD, ECHO, ICANON, TCSAFLUSH};
const FD_STDIN: ::std::os::unix::io::RawFd = 1;
use Crossterm;
use input::input;
/// A representation of the size of the current terminal. /// A representation of the size of the current terminal.
#[repr(C)] #[repr(C)]
@ -46,7 +38,7 @@ pub fn terminal_size() -> (u16, u16) {
// because crossterm works starts counting at 0 and unix terminal starts at cell 1 you have subtract one to get 0-based results. // because crossterm works starts counting at 0 and unix terminal starts at cell 1 you have subtract one to get 0-based results.
(us.cols, us.rows) (us.cols, us.rows)
} else { } else {
(0,0) (0, 0)
} }
} }
@ -71,8 +63,7 @@ pub fn terminal_size() -> (u16, u16) {
// } // }
//} //}
pub fn pos() -> io::Result<(u16, u16)> pub fn pos() -> io::Result<(u16, u16)> {
{
let _screen = Screen::new(false); let _screen = Screen::new(false);
// if we enable raw modes with screen, this could cause problems if raw mode is already enabled in applicaition. // if we enable raw modes with screen, this could cause problems if raw mode is already enabled in applicaition.
@ -82,7 +73,7 @@ pub fn pos() -> io::Result<(u16, u16)>
if !RAW_MODE_ENABLED_BY_USER || !RAW_MODE_ENABLED_BY_SYSTEM { if !RAW_MODE_ENABLED_BY_USER || !RAW_MODE_ENABLED_BY_SYSTEM {
// set this boolean so that we know that the systems has enabled raw mode. // set this boolean so that we know that the systems has enabled raw mode.
RAW_MODE_ENABLED_BY_SYSTEM = true; RAW_MODE_ENABLED_BY_SYSTEM = true;
into_raw_mode(); into_raw_mode()?;
} }
} }
@ -91,7 +82,7 @@ pub fn pos() -> io::Result<(u16, u16)>
let mut stdout = io::stdout(); let mut stdout = io::stdout();
// Write command // Write command
stdout.write(b"\x1B[6n")?; stdout.write_all(b"\x1B[6n")?;
stdout.flush()?; stdout.flush()?;
let mut buf = [0u8; 2]; let mut buf = [0u8; 2];
@ -133,7 +124,7 @@ pub fn pos() -> io::Result<(u16, u16)>
// Expect `R` // Expect `R`
let res = if c == 'R' { let res = if c == 'R' {
Ok(((cols -1) as u16, (rows -1) as u16)) Ok(((cols - 1) as u16, (rows - 1) as u16))
} else { } else {
return Err(Error::new(ErrorKind::Other, "test")); return Err(Error::new(ErrorKind::Other, "test"));
}; };
@ -143,20 +134,16 @@ pub fn pos() -> io::Result<(u16, u16)>
unsafe { unsafe {
if RAW_MODE_ENABLED_BY_SYSTEM && !RAW_MODE_ENABLED_BY_USER { if RAW_MODE_ENABLED_BY_SYSTEM && !RAW_MODE_ENABLED_BY_USER {
RAW_MODE_ENABLED_BY_SYSTEM = false; RAW_MODE_ENABLED_BY_SYSTEM = false;
disable_raw_mode(); disable_raw_mode()?;
} }
} }
return res res
} }
/// Set the terminal mode to the given mode. static mut ORIGINAL_TERMINAL_MODE: Option<Termios> = None;
pub fn set_terminal_mode(termios: &Termios) -> io::Result<()> { static mut RAW_MODE_ENABLED_BY_SYSTEM: bool = false;
extern "C" { pub static mut RAW_MODE_ENABLED_BY_USER: bool = false;
pub fn tcsetattr(fd: c_int, opt: c_int, termptr: *const Termios) -> c_int;
}
is_true(unsafe { tcsetattr(0, 0, termios) }).and(Ok(()))
}
/// Transform the given mode into an raw mode (non-canonical) mode. /// Transform the given mode into an raw mode (non-canonical) mode.
pub fn make_raw(termios: &mut Termios) { pub fn make_raw(termios: &mut Termios) {
@ -166,12 +153,7 @@ pub fn make_raw(termios: &mut Termios) {
unsafe { cfmakeraw(termios) } unsafe { cfmakeraw(termios) }
} }
static mut ORIGINAL_TERMINAL_MODE: Option<Termios> = None; pub fn into_raw_mode() -> io::Result<()> {
static mut RAW_MODE_ENABLED_BY_SYSTEM: bool = false;
pub static mut RAW_MODE_ENABLED_BY_USER: bool = false;
pub fn into_raw_mode() -> io::Result<()>
{
let tty_f; let tty_f;
let fd = unsafe { let fd = unsafe {
@ -187,8 +169,7 @@ pub fn into_raw_mode() -> io::Result<()>
let original = termios.clone(); let original = termios.clone();
unsafe { unsafe {
if let None = ORIGINAL_TERMINAL_MODE if ORIGINAL_TERMINAL_MODE.is_none() {
{
ORIGINAL_TERMINAL_MODE = Some(original.clone()) ORIGINAL_TERMINAL_MODE = Some(original.clone())
} }
} }
@ -196,12 +177,10 @@ pub fn into_raw_mode() -> io::Result<()>
make_raw(&mut termios); make_raw(&mut termios);
tcsetattr(fd, TCSADRAIN, &termios)?; tcsetattr(fd, TCSADRAIN, &termios)?;
Ok(()) Ok(())
} }
pub fn disable_raw_mode() -> io::Result<()> pub fn disable_raw_mode() -> io::Result<()> {
{
let tty_f; let tty_f;
let fd = unsafe { let fd = unsafe {
@ -213,8 +192,7 @@ pub fn disable_raw_mode() -> io::Result<()>
} }
}; };
if let Some(original) = unsafe { ORIGINAL_TERMINAL_MODE } if let Some(original) = unsafe { ORIGINAL_TERMINAL_MODE } {
{
tcsetattr(fd, TCSADRAIN, &original)?; tcsetattr(fd, TCSADRAIN, &original)?;
} }
Ok(()) Ok(())
@ -235,7 +213,7 @@ pub fn get_tty() -> io::Result<fs::File> {
} }
}; };
return Ok(tty_f); Ok(tty_f)
} }
pub fn read_char() -> io::Result<char> { pub fn read_char() -> io::Result<char> {
@ -254,7 +232,7 @@ pub fn read_char() -> io::Result<char> {
}; };
let mut termios = Termios::from_fd(fd)?; let mut termios = Termios::from_fd(fd)?;
let original = termios.clone(); let original = termios;
make_raw(&mut termios); make_raw(&mut termios);
tcsetattr(fd, TCSADRAIN, &termios)?; tcsetattr(fd, TCSADRAIN, &termios)?;
@ -305,12 +283,3 @@ pub fn read_char() -> io::Result<char> {
pub fn exit() { pub fn exit() {
::std::process::exit(0); ::std::process::exit(0);
} }
/// Is the return value true?
fn is_true(value: i32) -> Result<(), Error> {
match value {
-1 => Err(io::Error::last_os_error()),
0 => Ok(()),
_ => Err(io::Error::last_os_error()),
}
}

View File

@ -13,18 +13,16 @@ use winapi::um::winnt::{FILE_SHARE_READ, FILE_SHARE_WRITE, GENERIC_READ, GENERIC
use super::{handle, kernel, Empty, TerminalOutput, HANDLE}; use super::{handle, kernel, Empty, TerminalOutput, HANDLE};
use std::io::{self, Result}; use std::io::{self, Result};
use std::sync::{Once, ONCE_INIT};
use std::mem::size_of; use std::mem::size_of;
use std::sync::Arc; use std::sync::Arc;
use std::sync::{Once, ONCE_INIT};
/// Create a new console screen buffer info struct. /// Create a new console screen buffer info struct.
pub fn get_csbi() -> Result<CONSOLE_SCREEN_BUFFER_INFO> { pub fn get_csbi() -> Result<CONSOLE_SCREEN_BUFFER_INFO> {
let mut csbi = CONSOLE_SCREEN_BUFFER_INFO::empty(); let mut csbi = CONSOLE_SCREEN_BUFFER_INFO::empty();
let success; let success;
unsafe { unsafe { success = GetConsoleScreenBufferInfo(handle::get_current_handle()?, &mut csbi) }
success = GetConsoleScreenBufferInfo(handle::get_current_handle()?, &mut csbi)
}
if success == 0 { if success == 0 {
return Err(io::Error::new( return Err(io::Error::new(

View File

@ -7,19 +7,16 @@ use winapi::um::wincon::{
use super::{csbi, handle, kernel, TerminalOutput}; use super::{csbi, handle, kernel, TerminalOutput};
use kernel::windows_kernel::kernel::get_largest_console_window_size;
use std::io; use std::io;
use std::sync::Arc; use std::sync::Arc;
use kernel::windows_kernel::kernel::get_largest_console_window_size;
/// This stores the cursor pos, at program level. So it can be recalled later. /// 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 /// Reset to saved cursor position
pub fn reset_to_saved_position() { pub fn reset_to_saved_position() {
unsafe { unsafe {
set_console_cursor_position( set_console_cursor_position(SAVED_CURSOR_POS.0 as i16, SAVED_CURSOR_POS.1 as i16);
SAVED_CURSOR_POS.0 as i16,
SAVED_CURSOR_POS.1 as i16,
);
} }
} }

View File

@ -1,17 +1,17 @@
//! This module contains some logic for working with the console handle. //! This module contains some logic for working with the console handle.
use super::*;
use winapi::shared::minwindef::DWORD;
use winapi::um::errhandlingapi::GetLastError;
use winapi::um::fileapi::{CreateFileW, OPEN_EXISTING};
use winapi::um::handleapi::INVALID_HANDLE_VALUE; use winapi::um::handleapi::INVALID_HANDLE_VALUE;
use winapi::um::processenv::GetStdHandle; use winapi::um::processenv::GetStdHandle;
use winapi::um::winbase::{STD_INPUT_HANDLE, STD_OUTPUT_HANDLE}; use winapi::um::winbase::{STD_INPUT_HANDLE, STD_OUTPUT_HANDLE};
use winapi::um::winnt::{GENERIC_READ, GENERIC_WRITE, GENERIC_ALL, FILE_SHARE_WRITE}; use winapi::um::winnt::{FILE_SHARE_WRITE, GENERIC_ALL, GENERIC_READ, GENERIC_WRITE};
use winapi::um::fileapi::{OPEN_EXISTING, CreateFileW};
use winapi::shared::minwindef::DWORD;
use winapi::um::errhandlingapi::GetLastError;
use super::*;
use std::sync::Arc; use std::io::{self, Result};
use std::io::{self, Result};
use std::ptr::null_mut; use std::ptr::null_mut;
use std::sync::Arc;
use winapi::ctypes::c_void; use winapi::ctypes::c_void;
@ -22,16 +22,25 @@ pub fn get_current_handle() -> Result<HANDLE> {
let utf16: Vec<u16> = "CONOUT$\0".encode_utf16().collect(); let utf16: Vec<u16> = "CONOUT$\0".encode_utf16().collect();
let utf16_ptr: *const u16 = utf16.as_ptr(); let utf16_ptr: *const u16 = utf16.as_ptr();
let handle = CreateFileW(utf16_ptr, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_WRITE, null_mut(), OPEN_EXISTING, dw, null_mut()); let handle = CreateFileW(
utf16_ptr,
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_WRITE,
null_mut(),
OPEN_EXISTING,
dw,
null_mut(),
);
if !is_valid_handle(&handle) { if !is_valid_handle(&handle) {
unsafe {
unsafe
{
let error = GetLastError(); let error = GetLastError();
return Err(io::Error::new( return Err(io::Error::new(
io::ErrorKind::Other, io::ErrorKind::Other,
format!("Could not get output handle current handle!, error code: {}", error).as_ref(), format!(
"Could not get output handle current handle!, error code: {}",
error
).as_ref(),
)); ));
} }
} }

View File

@ -15,7 +15,6 @@ use TerminalOutput;
use common::traits::Empty; use common::traits::Empty;
impl Empty for COORD { impl Empty for COORD {
fn empty() -> COORD { fn empty() -> COORD {
COORD { X: 0, Y: 0 } COORD { X: 0, Y: 0 }

View File

@ -7,9 +7,9 @@ use std::sync::Arc;
pub fn terminal_size() -> (u16, u16) { pub fn terminal_size() -> (u16, u16) {
let handle = handle::get_output_handle().unwrap(); let handle = handle::get_output_handle().unwrap();
// if let Ok(csbi) = csbi::get_csbi_by_handle(&handle) { // if let Ok(csbi) = csbi::get_csbi_by_handle(&handle) {
// println!("right: {} left: {} bottom: {}, top: {} window top {} windows width {} csbi.dwCursorPosition.X {} csbi.dwCursorPosition.Y {}", csbi.srWindow.Right, csbi.srWindow.Left, csbi.srWindow.Bottom, csbi.srWindow.Top, csbi.dwSize.X,csbi.dwSize.Y, csbi.dwCursorPosition.X, csbi.dwCursorPosition.Y); // println!("right: {} left: {} bottom: {}, top: {} window top {} windows width {} csbi.dwCursorPosition.X {} csbi.dwCursorPosition.Y {}", csbi.srWindow.Right, csbi.srWindow.Left, csbi.srWindow.Bottom, csbi.srWindow.Top, csbi.dwSize.X,csbi.dwSize.Y, csbi.dwCursorPosition.X, csbi.dwCursorPosition.Y);
// } // }
if let Ok(csbi) = csbi::get_csbi_by_handle(&handle) { if let Ok(csbi) = csbi::get_csbi_by_handle(&handle) {
( (

View File

@ -4,8 +4,8 @@ use winapi::ctypes::c_void;
use winapi::shared::ntdef::NULL; use winapi::shared::ntdef::NULL;
use winapi::um::consoleapi::WriteConsoleW; use winapi::um::consoleapi::WriteConsoleW;
use winapi::um::wincon::{ use winapi::um::wincon::{
FillConsoleOutputAttribute, FillConsoleOutputCharacterA, WriteConsoleOutputA, CHAR_INFO, FillConsoleOutputAttribute, FillConsoleOutputCharacterA, WriteConsoleOutputA, CHAR_INFO, COORD,
COORD, PSMALL_RECT, PSMALL_RECT,
}; };
use super::{csbi, handle, kernel, TerminalOutput, HANDLE}; use super::{csbi, handle, kernel, TerminalOutput, HANDLE};
@ -18,7 +18,7 @@ use std::sync::Arc;
pub fn fill_console_output_character( pub fn fill_console_output_character(
cells_written: &mut u32, cells_written: &mut u32,
start_location: COORD, start_location: COORD,
cells_to_write: u32 cells_to_write: u32,
) -> bool { ) -> bool {
let handle = handle::get_current_handle().unwrap(); let handle = handle::get_current_handle().unwrap();
@ -39,7 +39,7 @@ pub fn fill_console_output_character(
pub fn fill_console_output_attribute( pub fn fill_console_output_attribute(
cells_written: &mut u32, cells_written: &mut u32,
start_location: COORD, start_location: COORD,
cells_to_write: u32 cells_to_write: u32,
) -> bool { ) -> bool {
// Get the position of the current console window // Get the position of the current console window

View File

@ -9,22 +9,19 @@ mod common;
mod kernel; mod kernel;
mod modules; mod modules;
use common::screen;
pub use modules::cursor; pub use modules::cursor;
pub use modules::input; pub use modules::input;
pub use modules::output; pub use modules::output;
pub use modules::style; pub use modules::style;
pub use modules::terminal; pub use modules::terminal;
pub use common::screen::{Screen, AlternateScreen};
pub use common::Crossterm;
pub use output::TerminalOutput;
pub use self::cursor::*; pub use self::cursor::*;
pub use self::input::*; pub use self::input::*;
pub use self::output::*; pub use self::output::*;
pub use self::style::*; pub use self::style::*;
pub use common::screen::{AlternateScreen, Screen};
use common::functions; pub use common::Crossterm;
pub use output::TerminalOutput;
#[cfg(unix)] #[cfg(unix)]
extern crate libc; extern crate libc;

View File

@ -3,16 +3,13 @@
//! Note that the cursor position is 0 based. This means that we start counting at 0 when setting the cursor position ect. //! Note that the cursor position is 0 based. This means that we start counting at 0 when setting the cursor position ect.
use super::*; use super::*;
use std::io::Write;
/// This struct is an ansi implementation for cursor related actions. /// This struct is an ansi implementation for cursor related actions.
pub struct AnsiCursor { } pub struct AnsiCursor {}
impl AnsiCursor impl AnsiCursor {
{
pub fn new() -> Box<AnsiCursor> { pub fn new() -> Box<AnsiCursor> {
Box::from(AnsiCursor { }) Box::from(AnsiCursor {})
} }
} }

View File

@ -33,13 +33,14 @@ pub struct TerminalCursor<'stdout> {
stdout: Option<&'stdout Arc<TerminalOutput>>, stdout: Option<&'stdout Arc<TerminalOutput>>,
} }
impl<'stdout> TerminalCursor <'stdout>{ impl<'stdout> TerminalCursor<'stdout> {
/// Create new cursor instance whereon cursor related actions can be performed. /// Create new cursor instance whereon cursor related actions can be performed.
pub fn new() -> TerminalCursor<'stdout> { pub fn new() -> TerminalCursor<'stdout> {
#[cfg(target_os = "windows")] #[cfg(target_os = "windows")]
let cursor = let cursor = functions::get_module::<Box<ITerminalCursor + Sync + Send>>(
functions::get_module::<Box<ITerminalCursor + Sync + Send>>(WinApiCursor::new(), AnsiCursor::new()) WinApiCursor::new(),
.unwrap(); AnsiCursor::new(),
).unwrap();
#[cfg(not(target_os = "windows"))] #[cfg(not(target_os = "windows"))]
let cursor = AnsiCursor::new() as Box<ITerminalCursor + Sync + Send>; let cursor = AnsiCursor::new() as Box<ITerminalCursor + Sync + Send>;
@ -52,9 +53,10 @@ impl<'stdout> TerminalCursor <'stdout>{
pub fn on_screen(stdout: &'stdout Arc<TerminalOutput>) -> TerminalCursor<'stdout> { pub fn on_screen(stdout: &'stdout Arc<TerminalOutput>) -> TerminalCursor<'stdout> {
#[cfg(target_os = "windows")] #[cfg(target_os = "windows")]
let cursor = let cursor = functions::get_module::<Box<ITerminalCursor + Sync + Send>>(
functions::get_module::<Box<ITerminalCursor + Sync + Send>>(WinApiCursor::new(), AnsiCursor::new()) WinApiCursor::new(),
.unwrap(); AnsiCursor::new(),
).unwrap();
#[cfg(not(target_os = "windows"))] #[cfg(not(target_os = "windows"))]
let cursor = AnsiCursor::new() as Box<ITerminalCursor + Sync + Send>; let cursor = AnsiCursor::new() as Box<ITerminalCursor + Sync + Send>;
@ -211,6 +213,6 @@ pub fn cursor() -> TerminalCursor<'static> {
/// Get an TerminalCursor implementation whereon cursor related actions can be performed. /// Get an TerminalCursor implementation whereon cursor related actions can be performed.
/// Pass the reference to any screen you want this type to perform actions on. /// Pass the reference to any screen you want this type to perform actions on.
pub fn from_screen<'stdout>(screen: &'stdout Screen) -> TerminalCursor<'stdout> { pub fn from_screen(screen: &Screen) -> TerminalCursor {
TerminalCursor::on_screen(&screen.stdout) TerminalCursor::on_screen(&screen.stdout)
} }

View File

@ -17,8 +17,8 @@ use self::winapi_cursor::WinApiCursor;
pub use self::cursor::{cursor, from_screen, TerminalCursor}; pub use self::cursor::{cursor, from_screen, TerminalCursor};
use super::functions; use super::functions;
use TerminalOutput;
use std::sync::Arc; use std::sync::Arc;
use TerminalOutput;
///! This trait defines the actions that can be preformed with the terminal cursor. ///! This trait defines the actions that can be preformed with the terminal cursor.
///! This trait can be implemented so that an concrete implementation of the ITerminalCursor can forfill ///! This trait can be implemented so that an concrete implementation of the ITerminalCursor can forfill
@ -28,27 +28,27 @@ use std::sync::Arc;
///! ///!
///! This trait is implemented for `WINAPI` (Windows specific) and `ANSI` (Unix specific), ///! 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. ///! so that cursor related actions can be preformed on both unix and windows systems.
trait ITerminalCursor : Sync + Send { trait ITerminalCursor: Sync + Send {
/// Goto some location (x,y) in the context. /// Goto some location (x,y) in the context.
fn goto(&self, x: u16, y: u16, stdout: &Option<&Arc<TerminalOutput>>); fn goto(&self, x: u16, y: u16, stdout: &Option<&Arc<TerminalOutput>>);
/// Get the location (x,y) of the current cusror in the context /// Get the location (x,y) of the current cusror in the context
fn pos(&self) -> (u16, u16); fn pos(&self) -> (u16, u16);
/// Move cursor n times up /// Move cursor n times up
fn move_up(&self, count: u16,stdout: &Option<&Arc<TerminalOutput>>); fn move_up(&self, count: u16, stdout: &Option<&Arc<TerminalOutput>>);
/// Move the cursor `n` times to the right. /// Move the cursor `n` times to the right.
fn move_right(&self, count: u16,stdout: &Option<&Arc<TerminalOutput>>); fn move_right(&self, count: u16, stdout: &Option<&Arc<TerminalOutput>>);
/// Move the cursor `n` times down. /// Move the cursor `n` times down.
fn move_down(&self, count: u16,stdout: &Option<&Arc<TerminalOutput>>); fn move_down(&self, count: u16, stdout: &Option<&Arc<TerminalOutput>>);
/// Move the cursor `n` times left. /// Move the cursor `n` times left.
fn move_left(&self, count: u16,stdout: &Option<&Arc<TerminalOutput>>); fn move_left(&self, count: u16, stdout: &Option<&Arc<TerminalOutput>>);
/// Save cursor position so that its saved position can be recalled later. Note that this position is stored program based not per instance of the cursor struct. /// Save cursor position so that its saved position can be recalled later. Note that this position is stored program based not per instance of the cursor struct.
fn save_position(&self,stdout: &Option<&Arc<TerminalOutput>>); fn save_position(&self, stdout: &Option<&Arc<TerminalOutput>>);
/// Return to saved cursor position /// Return to saved cursor position
fn reset_position(&self,stdout: &Option<&Arc<TerminalOutput>>); fn reset_position(&self, stdout: &Option<&Arc<TerminalOutput>>);
/// Hide the terminal cursor. /// Hide the terminal cursor.
fn hide(&self,stdout: &Option<&Arc<TerminalOutput>>); fn hide(&self, stdout: &Option<&Arc<TerminalOutput>>);
/// Show the terminal cursor /// Show the terminal cursor
fn show(&self,stdout: &Option<&Arc<TerminalOutput>>); fn show(&self, stdout: &Option<&Arc<TerminalOutput>>);
/// Enable or disable the blinking of the cursor. /// Enable or disable the blinking of the cursor.
fn blink(&self, blink: bool,stdout: &Option<&Arc<TerminalOutput>>); fn blink(&self, blink: bool, stdout: &Option<&Arc<TerminalOutput>>);
} }

View File

@ -7,17 +7,16 @@ use Screen;
/* ======================== WinApi =========================== */ /* ======================== WinApi =========================== */
#[cfg(windows)] #[cfg(windows)]
mod winapi_tests { mod winapi_tests {
use modules::cursor::winapi_cursor::WinApiCursor;
use super::*; use super::*;
use modules::cursor::winapi_cursor::WinApiCursor;
#[test] #[test]
fn goto_winapi() fn goto_winapi() {
{
let screen = Screen::default(); let screen = Screen::default();
let stdout = Some(&screen.stdout); let stdout = Some(&screen.stdout);
let cursor = WinApiCursor::new(); let cursor = WinApiCursor::new();
cursor.goto(5, 5,&stdout); cursor.goto(5, 5, &stdout);
let (x, y) = cursor.pos(); let (x, y) = cursor.pos();
assert_eq!(x, 5); assert_eq!(x, 5);
@ -25,15 +24,14 @@ mod winapi_tests {
} }
#[test] #[test]
fn reset_safe_winapi() fn reset_safe_winapi() {
{
let screen = Screen::default(); let screen = Screen::default();
let stdout = Some(&screen.stdout); let stdout = Some(&screen.stdout);
let cursor = WinApiCursor::new(); let cursor = WinApiCursor::new();
let (x, y) = cursor.pos(); let (x, y) = cursor.pos();
cursor.save_position(&stdout); cursor.save_position(&stdout);
cursor.goto(5, 5,&stdout); cursor.goto(5, 5, &stdout);
cursor.reset_position(&stdout); cursor.reset_position(&stdout);
let (x_saved, y_saved) = cursor.pos(); let (x_saved, y_saved) = cursor.pos();
@ -45,8 +43,7 @@ mod winapi_tests {
/* ======================== ANSI =========================== */ /* ======================== ANSI =========================== */
#[test] #[test]
fn reset_safe_ansi() fn reset_safe_ansi() {
{
if try_enable_ansi() { if try_enable_ansi() {
let screen = Screen::default(); let screen = Screen::default();
let stdout = Some(&screen.stdout); let stdout = Some(&screen.stdout);
@ -54,7 +51,7 @@ fn reset_safe_ansi()
let (x, y) = cursor.pos(); let (x, y) = cursor.pos();
cursor.save_position(&stdout); cursor.save_position(&stdout);
cursor.goto(5, 5,&stdout); cursor.goto(5, 5, &stdout);
cursor.reset_position(&stdout); cursor.reset_position(&stdout);
let (x_saved, y_saved) = cursor.pos(); let (x_saved, y_saved) = cursor.pos();
@ -65,14 +62,13 @@ fn reset_safe_ansi()
} }
#[test] #[test]
fn goto_ansi() fn goto_ansi() {
{
if try_enable_ansi() { if try_enable_ansi() {
let screen = Screen::default(); let screen = Screen::default();
let stdout = Some(&screen.stdout); let stdout = Some(&screen.stdout);
let cursor = AnsiCursor::new(); let cursor = AnsiCursor::new();
cursor.goto(5, 5,&stdout); cursor.goto(5, 5, &stdout);
let (x, y) = cursor.pos(); let (x, y) = cursor.pos();
assert_eq!(x, 5); assert_eq!(x, 5);
@ -80,16 +76,15 @@ fn goto_ansi()
} }
} }
fn try_enable_ansi() -> bool {
fn try_enable_ansi() -> bool
{
#[cfg(windows)] #[cfg(windows)]
{ {
if cfg!(target_os = "windows") { if cfg!(target_os = "windows") {
use kernel::windows_kernel::ansi_support::try_enable_ansi_support; use kernel::windows_kernel::ansi_support::try_enable_ansi_support;
if !try_enable_ansi_support() if !try_enable_ansi_support() {
{ return false; } return false;
}
} }
} }

View File

@ -16,7 +16,7 @@ impl WinApiCursor {
} }
impl ITerminalCursor for WinApiCursor { impl ITerminalCursor for WinApiCursor {
fn goto(&self, x: u16, y: u16,_stdout: &Option<&Arc<TerminalOutput>>) { fn goto(&self, x: u16, y: u16, _stdout: &Option<&Arc<TerminalOutput>>) {
cursor::set_console_cursor_position(x as i16, y as i16); cursor::set_console_cursor_position(x as i16, y as i16);
} }
@ -24,41 +24,41 @@ impl ITerminalCursor for WinApiCursor {
cursor::pos() cursor::pos()
} }
fn move_up(&self, count: u16,_stdout: &Option<&Arc<TerminalOutput>>) { fn move_up(&self, count: u16, _stdout: &Option<&Arc<TerminalOutput>>) {
let (xpos, ypos) = self.pos(); let (xpos, ypos) = self.pos();
self.goto(xpos, ypos - count, _stdout); self.goto(xpos, ypos - count, _stdout);
} }
fn move_right(&self, count: u16,_stdout: &Option<&Arc<TerminalOutput>>) { fn move_right(&self, count: u16, _stdout: &Option<&Arc<TerminalOutput>>) {
let (xpos, ypos) = self.pos(); let (xpos, ypos) = self.pos();
self.goto(xpos + count, ypos, _stdout); self.goto(xpos + count, ypos, _stdout);
} }
fn move_down(&self, count: u16,_stdout: &Option<&Arc<TerminalOutput>>) { fn move_down(&self, count: u16, _stdout: &Option<&Arc<TerminalOutput>>) {
let (xpos, ypos) = self.pos(); let (xpos, ypos) = self.pos();
self.goto(xpos, ypos + count, _stdout); self.goto(xpos, ypos + count, _stdout);
} }
fn move_left(&self, count: u16,_stdout: &Option<&Arc<TerminalOutput>>) { fn move_left(&self, count: u16, _stdout: &Option<&Arc<TerminalOutput>>) {
let (xpos, ypos) = self.pos(); let (xpos, ypos) = self.pos();
self.goto(xpos - count, ypos, _stdout); self.goto(xpos - count, ypos, _stdout);
} }
fn save_position(&self,_stdout: &Option<&Arc<TerminalOutput>>) { fn save_position(&self, _stdout: &Option<&Arc<TerminalOutput>>) {
cursor::save_cursor_pos(); cursor::save_cursor_pos();
} }
fn reset_position(&self,_stdout: &Option<&Arc<TerminalOutput>>) { fn reset_position(&self, _stdout: &Option<&Arc<TerminalOutput>>) {
cursor::reset_to_saved_position(); cursor::reset_to_saved_position();
} }
fn hide(&self,_stdout: &Option<&Arc<TerminalOutput>>) { fn hide(&self, _stdout: &Option<&Arc<TerminalOutput>>) {
cursor::cursor_visibility(false); cursor::cursor_visibility(false);
} }
fn show(&self,_stdout: &Option<&Arc<TerminalOutput>>) { fn show(&self, _stdout: &Option<&Arc<TerminalOutput>>) {
cursor::cursor_visibility(true); cursor::cursor_visibility(true);
} }
fn blink(&self, blink: bool,_stdout: &Option<&Arc<TerminalOutput>>) {} fn blink(&self, blink: bool, _stdout: &Option<&Arc<TerminalOutput>>) {}
} }

View File

@ -83,7 +83,7 @@ impl<'stdout> TerminalInput<'stdout> {
/// } /// }
/// ``` /// ```
pub fn read_char(&self) -> io::Result<char> { pub fn read_char(&self) -> io::Result<char> {
return self.terminal_input.read_char(&self.stdout); self.terminal_input.read_char(&self.stdout)
} }
/// Read the input asynchronously from the user. /// Read the input asynchronously from the user.
@ -162,11 +162,11 @@ impl<'stdout> TerminalInput<'stdout> {
/// Get an Terminal Input implementation whereon input related actions can be performed. /// Get an Terminal Input implementation whereon input related actions can be performed.
pub fn input<'stdout>() -> TerminalInput<'stdout> { pub fn input<'stdout>() -> TerminalInput<'stdout> {
return TerminalInput::new(); TerminalInput::new()
} }
/// Get an Terminal Input implementation whereon input related actions can be performed. /// Get an Terminal Input implementation whereon input related actions can be performed.
/// Pass the reference to any screen you want this type to perform actions on. /// Pass the reference to any screen you want this type to perform actions on.
pub fn from_screen<'stdout>(screen: &'stdout Screen) -> TerminalInput<'stdout> { pub fn from_screen(screen: &Screen) -> TerminalInput {
TerminalInput::on_screen(&screen.stdout) TerminalInput::on_screen(&screen.stdout)
} }

View File

@ -15,7 +15,7 @@ use self::windows_input::WindowsInput;
pub use self::input::{input, TerminalInput}; pub use self::input::{input, TerminalInput};
use std::io::{self, Read, Error, ErrorKind}; use std::io::{self, Error, ErrorKind, Read};
use std::sync::{mpsc, Arc}; use std::sync::{mpsc, Arc};
use TerminalOutput; use TerminalOutput;
@ -36,7 +36,8 @@ trait ITerminalInput {
/// Read the input asynchronously from the user. /// Read the input asynchronously from the user.
fn read_async(&self, stdout: &Option<&Arc<TerminalOutput>>) -> AsyncReader; fn read_async(&self, stdout: &Option<&Arc<TerminalOutput>>) -> AsyncReader;
/// Read the input asynchronously until a certain character is hit. /// Read the input asynchronously until a certain character is hit.
fn read_until_async(&self, delimiter: u8, stdout: &Option<&Arc<TerminalOutput>>) -> AsyncReader; fn read_until_async(&self, delimiter: u8, stdout: &Option<&Arc<TerminalOutput>>)
-> AsyncReader;
} }
/// This is a wrapper for reading from the input asynchronously. /// This is a wrapper for reading from the input asynchronously.
@ -64,7 +65,7 @@ impl Read for AsyncReader {
Some(Ok(value)) => { Some(Ok(value)) => {
buf[total] = value; buf[total] = value;
total += 1; total += 1;
}, }
_ => return Err(Error::new(ErrorKind::Other, "No characters pressed.")), _ => return Err(Error::new(ErrorKind::Other, "No characters pressed.")),
} }
} }

View File

@ -38,17 +38,21 @@ impl ITerminalInput for UnixInput {
} }
}); });
AsyncReader { recv: recv } AsyncReader { recv }
} }
fn read_until_async(&self, delimiter: u8, __stdout: &Option<&Arc<TerminalOutput>>) -> AsyncReader { fn read_until_async(
&self,
delimiter: u8,
__stdout: &Option<&Arc<TerminalOutput>>,
) -> AsyncReader {
let (send, recv) = mpsc::channel(); let (send, recv) = mpsc::channel();
thread::spawn(move || { thread::spawn(move || {
for i in get_tty().unwrap().bytes() { for i in get_tty().unwrap().bytes() {
match i { match i {
Ok(byte) => { Ok(byte) => {
let end_of_stream = &byte == &delimiter; let end_of_stream = byte == delimiter;
let send_error = send.send(Ok(byte)).is_err(); let send_error = send.send(Ok(byte)).is_err();
if end_of_stream || send_error { if end_of_stream || send_error {
@ -62,6 +66,6 @@ impl ITerminalInput for UnixInput {
} }
}); });
AsyncReader { recv: recv } AsyncReader { recv }
} }
} }

View File

@ -22,7 +22,7 @@ impl ITerminalInput for WindowsInput {
loop { loop {
let is_raw_screen = match stdout { let is_raw_screen = match stdout {
Some(output) => output.is_in_raw_mode, Some(output) => output.is_in_raw_mode,
None => false None => false,
}; };
// _getwch is without echo and _getwche is with echo // _getwch is without echo and _getwche is with echo
@ -55,7 +55,7 @@ impl ITerminalInput for WindowsInput {
fn read_char(&self, stdout: &Option<&Arc<TerminalOutput>>) -> io::Result<char> { fn read_char(&self, stdout: &Option<&Arc<TerminalOutput>>) -> io::Result<char> {
let is_raw_screen = match stdout { let is_raw_screen = match stdout {
Some(output) => output.is_in_raw_mode, Some(output) => output.is_in_raw_mode,
None => false None => false,
}; };
// _getwch is without echo and _getwche is with echo // _getwch is without echo and _getwche is with echo
@ -91,7 +91,7 @@ impl ITerminalInput for WindowsInput {
let is_raw_screen = match stdout { let is_raw_screen = match stdout {
Some(output) => output.is_in_raw_mode, Some(output) => output.is_in_raw_mode,
None => false None => false,
}; };
thread::spawn(move || { thread::spawn(move || {
@ -117,12 +117,16 @@ impl ITerminalInput for WindowsInput {
AsyncReader { recv: rx } AsyncReader { recv: rx }
} }
fn read_until_async(&self, delimiter: u8, stdout: &Option<&Arc<TerminalOutput>>) -> AsyncReader { fn read_until_async(
&self,
delimiter: u8,
stdout: &Option<&Arc<TerminalOutput>>,
) -> AsyncReader {
let (tx, rx) = mpsc::channel(); let (tx, rx) = mpsc::channel();
let is_raw_screen = match stdout { let is_raw_screen = match stdout {
Some(output) => output.is_in_raw_mode, Some(output) => output.is_in_raw_mode,
None => false None => false,
}; };
thread::spawn(move || { thread::spawn(move || {

View File

@ -4,5 +4,4 @@ pub mod output;
pub mod style; pub mod style;
pub mod terminal; pub mod terminal;
use super::common::commands;
use super::common::functions; use super::common::functions;

View File

@ -4,8 +4,7 @@
use super::IStdout; use super::IStdout;
use std::any::Any; use std::io::{self, stdout, Stdout, Write};
use std::io::{self, Write,Stdout, stdout};
/// This struct is a wrapper for `Stdout` /// This struct is a wrapper for `Stdout`
pub struct AnsiOutput { pub struct AnsiOutput {

View File

@ -15,11 +15,8 @@ use self::winapi_output::WinApiOutput;
pub use self::output::TerminalOutput; pub use self::output::TerminalOutput;
use std::any::Any;
use std::io; use std::io;
use super::{functions};
/// This trait defines represents an stdout of an screen. /// This trait defines represents an stdout of an screen.
/// This trait can be implemented so that an concrete implementation of the IStdout can forfill /// This trait can be implemented so that an concrete implementation of the IStdout can forfill
/// the wishes to work on an specific platform. /// the wishes to work on an specific platform.
@ -30,7 +27,7 @@ use super::{functions};
/// so that color related actions can be preformed on both unix and windows systems. /// so that color related actions can be preformed on both unix and windows systems.
trait IStdout { trait IStdout {
/// Write an &str to the current stdout and flush the screen. /// Write an &str to the current stdout and flush the screen.
fn write_str(&self, string: &str ) -> io::Result<usize>; fn write_str(&self, string: &str) -> io::Result<usize>;
/// Write [u8] buffer to console. /// Write [u8] buffer to console.
fn write(&self, buf: &[u8]) -> io::Result<usize>; fn write(&self, buf: &[u8]) -> io::Result<usize>;
/// Flush the current output. /// Flush the current output.

View File

@ -20,10 +20,8 @@
use super::*; use super::*;
use std::any::Any;
use std::default::Default; use std::default::Default;
use std::io::Write; use std::io::Write;
use screen::RawScreen;
/// Struct that is an handle to an terminal screen. /// Struct that is an handle to an terminal screen.
/// This handle could be used to write to the current screen /// This handle could be used to write to the current screen
@ -31,22 +29,26 @@ use screen::RawScreen;
/// For unix and windows 10 `stdout()` will be used for handle when on windows systems with versions lower than 10 WinApi `HANDLE` will be used. /// For unix and windows 10 `stdout()` will be used for handle when on windows systems with versions lower than 10 WinApi `HANDLE` will be used.
pub struct TerminalOutput { pub struct TerminalOutput {
stdout: Box<IStdout + Send + Sync>, stdout: Box<IStdout + Send + Sync>,
pub is_in_raw_mode:bool, pub is_in_raw_mode: bool,
} }
impl TerminalOutput { impl TerminalOutput {
/// Create new screen write instance whereon screen related actions can be performed. /// Create new screen write instance whereon screen related actions can be performed.
pub fn new(raw_mode: bool) -> Self { pub fn new(raw_mode: bool) -> Self {
#[cfg(target_os = "windows")] #[cfg(target_os = "windows")]
let stdout: Box<IStdout + Send + Sync> = functions::get_module::<Box<IStdout + Send + Sync>>( let stdout: Box<IStdout + Send + Sync> =
Box::from(WinApiOutput::new()), functions::get_module::<Box<IStdout + Send + Sync>>(
Box::from(AnsiOutput::new()), Box::from(WinApiOutput::new()),
).unwrap(); Box::from(AnsiOutput::new()),
).unwrap();
#[cfg(not(target_os = "windows"))] #[cfg(not(target_os = "windows"))]
let stdout = Box::from(AnsiOutput::new()) as Box<IStdout + Send + Sync>; let stdout = Box::from(AnsiOutput::new()) as Box<IStdout + Send + Sync>;
TerminalOutput { stdout , is_in_raw_mode: raw_mode} TerminalOutput {
stdout,
is_in_raw_mode: raw_mode,
}
} }
/// Write String to the current screen. /// Write String to the current screen.
@ -76,12 +78,11 @@ impl Write for TerminalOutput {
} }
fn flush(&mut self) -> io::Result<()> { fn flush(&mut self) -> io::Result<()> {
self.flush() self.stdout.flush()
} }
} }
impl Default for TerminalOutput impl Default for TerminalOutput {
{
/// Get the default handle to the current screen. /// Get the default handle to the current screen.
fn default() -> Self { fn default() -> Self {
#[cfg(target_os = "windows")] #[cfg(target_os = "windows")]
@ -93,6 +94,9 @@ impl Default for TerminalOutput
#[cfg(not(target_os = "windows"))] #[cfg(not(target_os = "windows"))]
let stdout = Box::from(AnsiOutput::new()) as Box<IStdout + Send + Sync>; let stdout = Box::from(AnsiOutput::new()) as Box<IStdout + Send + Sync>;
TerminalOutput { stdout , is_in_raw_mode: false} TerminalOutput {
stdout,
is_in_raw_mode: false,
}
} }
} }

View File

@ -6,12 +6,11 @@ use Screen;
#[cfg(windows)] #[cfg(windows)]
mod winapi_tests { mod winapi_tests {
use modules::output::winapi_output::WinApiOutput;
use super::*; use super::*;
use modules::output::winapi_output::WinApiOutput;
/* ======================== WinApi =========================== */ /* ======================== WinApi =========================== */
#[test] #[test]
fn write_winapi() fn write_winapi() {
{
let screen = Screen::default(); let screen = Screen::default();
let output = WinApiOutput::new(); let output = WinApiOutput::new();
@ -21,8 +20,7 @@ mod winapi_tests {
} }
#[test] #[test]
fn write_str_winapi() fn write_str_winapi() {
{
let screen = Screen::default(); let screen = Screen::default();
let output = WinApiOutput::new(); let output = WinApiOutput::new();
@ -34,8 +32,7 @@ mod winapi_tests {
/* ======================== ANSI =========================== */ /* ======================== ANSI =========================== */
#[test] #[test]
fn write_ansi() fn write_ansi() {
{
let _screen = Screen::default(); let _screen = Screen::default();
let output = AnsiOutput::new(); let output = AnsiOutput::new();
@ -45,8 +42,7 @@ fn write_ansi()
} }
#[test] #[test]
fn write_str_ansi() fn write_str_ansi() {
{
let _screen = Screen::default(); let _screen = Screen::default();
let output = AnsiOutput::new(); let output = AnsiOutput::new();
@ -55,25 +51,28 @@ fn write_str_ansi()
is_valid_write(result, bytes.len()); is_valid_write(result, bytes.len());
} }
fn is_valid_write(result: ::std::io::Result<usize>, str_length: usize) fn is_valid_write(result: ::std::io::Result<usize>, str_length: usize) {
{
match result { match result {
Err(_) => assert!(false), Err(_) => assert!(false),
Ok(length) => if str_length == length { assert!(true) } else { assert!(false) } Ok(length) => if str_length == length {
assert!(true)
} else {
assert!(false)
},
}; };
} }
fn try_enable_ansi() -> bool fn try_enable_ansi() -> bool {
{
#[cfg(windows)] #[cfg(windows)]
{ {
if cfg!(target_os = "windows") { if cfg!(target_os = "windows") {
use kernel::windows_kernel::ansi_support::try_enable_ansi_support; use kernel::windows_kernel::ansi_support::try_enable_ansi_support;
if !try_enable_ansi_support() if !try_enable_ansi_support() {
{ return false; } return false;
} }
} }
}
return true; return true;
} }

View File

@ -1,26 +1,23 @@
use super::IStdout; use super::IStdout;
use screen::RawScreen;
use common::commands::win_commands::RawModeCommand; use common::commands::win_commands::RawModeCommand;
use kernel::windows_kernel::{handle, writing}; use kernel::windows_kernel::{handle, writing};
use screen::RawScreen;
use winapi::um::winnt::HANDLE; use winapi::um::winnt::HANDLE;
use std::sync::Mutex;
use std::any::Any; use std::any::Any;
use std::io; use std::io;
use std::sync::Mutex;
/// This struct is a wrapper for WINAPI `HANDLE` /// This struct is a wrapper for WINAPI `HANDLE`
pub struct WinApiOutput; pub struct WinApiOutput;
impl WinApiOutput impl WinApiOutput {
{ pub fn new() -> WinApiOutput {
pub fn new() -> WinApiOutput
{
WinApiOutput WinApiOutput
} }
} }
impl IStdout for WinApiOutput { impl IStdout for WinApiOutput {
fn write_str(&self, string: &str) -> io::Result<usize> { fn write_str(&self, string: &str) -> io::Result<usize> {
self.write(string.as_bytes()) self.write(string.as_bytes())
} }

View File

@ -14,17 +14,23 @@ impl AnsiColor {
impl ITerminalColor for AnsiColor { impl ITerminalColor for AnsiColor {
fn set_fg(&self, fg_color: Color, stdout: &Option<&Arc<TerminalOutput>>) { fn set_fg(&self, fg_color: Color, stdout: &Option<&Arc<TerminalOutput>>) {
functions::write(stdout,format!( functions::write(
csi!("{}m"), stdout,
self.color_value(fg_color, ColorType::Foreground) format!(
)); csi!("{}m"),
self.color_value(fg_color, ColorType::Foreground)
),
);
} }
fn set_bg(&self, bg_color: Color, stdout: &Option<&Arc<TerminalOutput>>) { fn set_bg(&self, bg_color: Color, stdout: &Option<&Arc<TerminalOutput>>) {
functions::write(stdout,format!( functions::write(
csi!("{}m"), stdout,
self.color_value(bg_color, ColorType::Background) format!(
)); csi!("{}m"),
self.color_value(bg_color, ColorType::Background)
),
);
} }
fn reset(&self, stdout: &Option<&Arc<TerminalOutput>>) { fn reset(&self, stdout: &Option<&Arc<TerminalOutput>>) {

View File

@ -63,7 +63,7 @@ impl<'stdout> TerminalColor<'stdout> {
TerminalColor { TerminalColor {
color, color,
stdout: Some(stdout) stdout: Some(stdout),
} }
} }
@ -128,9 +128,8 @@ pub fn color<'stdout>() -> TerminalColor<'stdout> {
TerminalColor::new() TerminalColor::new()
} }
/// Get an Terminal Color implementation whereon color related actions can be performed. /// Get an Terminal Color implementation whereon color related actions can be performed.
/// Pass the reference to any screen you want this type to perform actions on. /// Pass the reference to any screen you want this type to perform actions on.
pub fn from_screen<'stdout>(screen: &'stdout Screen) -> TerminalColor<'stdout> { pub fn from_screen(screen: &Screen) -> TerminalColor {
TerminalColor::on_screen(&screen.stdout) TerminalColor::on_screen(&screen.stdout)
} }

View File

@ -13,14 +13,14 @@ use self::ansi_color::AnsiColor;
use self::winapi_color::WinApiColor; use self::winapi_color::WinApiColor;
use std::convert::From; use std::convert::From;
use std::fmt::Display;
use std::str::FromStr; use std::str::FromStr;
use std::sync::Arc; use std::sync::Arc;
use std::fmt::Display;
pub use self::color::{TerminalColor, color, from_screen}; pub use self::color::{color, from_screen, TerminalColor};
pub use self::objectstyle::ObjectStyle; pub use self::objectstyle::ObjectStyle;
pub use self::styledobject::StyledObject;
pub use self::styledobject::DisplayableObject; pub use self::styledobject::DisplayableObject;
pub use self::styledobject::StyledObject;
use super::functions; use super::functions;
use TerminalOutput; use TerminalOutput;
@ -63,10 +63,11 @@ trait ITerminalColor {
/// println!("{}", styled_object); /// println!("{}", styled_object);
/// } /// }
/// ``` /// ```
pub fn style<'a,D: 'a>(val: D) -> StyledObject<D> pub fn style<'a, D: 'a>(val: D) -> StyledObject<D>
where where
D: Display, { D: Display,
ObjectStyle::new().apply_to(val) {
ObjectStyle::new().apply_to(val)
} }
/// Attributes that could be applied on some text. /// Attributes that could be applied on some text.

View File

@ -30,10 +30,7 @@ impl Default for ObjectStyle {
impl ObjectStyle { impl ObjectStyle {
/// Apply an `StyledObject` to the passed displayable object. /// Apply an `StyledObject` to the passed displayable object.
pub fn apply_to<D: Display>( pub fn apply_to<D: Display>(&self, val: D) -> StyledObject<D> {
&self,
val: D,
) -> StyledObject<D> {
StyledObject { StyledObject {
object_style: self.clone(), object_style: self.clone(),
content: val, content: val,
@ -42,12 +39,12 @@ impl ObjectStyle {
/// Get an new instance of `ObjectStyle` /// Get an new instance of `ObjectStyle`
pub fn new() -> ObjectStyle { pub fn new() -> ObjectStyle {
return ObjectStyle { ObjectStyle {
fg_color: None, fg_color: None,
bg_color: None, bg_color: None,
#[cfg(unix)] #[cfg(unix)]
attrs: Vec::new(), attrs: Vec::new(),
}; }
} }
/// Set the background color of `ObjectStyle` to the passed color. /// Set the background color of `ObjectStyle` to the passed color.

View File

@ -74,7 +74,7 @@ impl<'a, D: Display + 'a> StyledObject<D> {
/// ``` /// ```
#[cfg(unix)] #[cfg(unix)]
pub fn attr(mut self, attr: Attribute) -> StyledObject<D> { pub fn attr(mut self, attr: Attribute) -> StyledObject<D> {
&self.object_style.add_attr(attr); self.object_style.add_attr(attr);
self self
} }
@ -144,8 +144,7 @@ impl<'a, D: Display + 'a> StyledObject<D> {
/// ///
/// You should take not that `StyledObject` implements `Display`. You don't need to call paint unless you are on alternate screen. /// You should take not that `StyledObject` implements `Display`. You don't need to call paint unless you are on alternate screen.
/// Checkout `into_displayable()` for more information about this. /// Checkout `into_displayable()` for more information about this.
pub fn paint(&self, screen: &Screen) pub fn paint(&self, screen: &Screen) {
{
let colored_terminal = from_screen(&screen); let colored_terminal = from_screen(&screen);
let mut reset = true; let mut reset = true;
@ -161,7 +160,9 @@ impl<'a, D: Display + 'a> StyledObject<D> {
#[cfg(unix)] #[cfg(unix)]
for attr in self.object_style.attrs.iter() { for attr in self.object_style.attrs.iter() {
screen.stdout.write_string(format!(csi!("{}m"), *attr as i16)); screen
.stdout
.write_string(format!(csi!("{}m"), *attr as i16));
reset = true; reset = true;
} }
@ -190,15 +191,14 @@ impl<'a, D: Display + 'a> StyledObject<D> {
/// let display_object = styled_object.into_displayable(&screen); /// let display_object = styled_object.into_displayable(&screen);
/// println!("Colored text: {}. Default color", display_object); /// println!("Colored text: {}. Default color", display_object);
/// ``` /// ```
pub fn into_displayable(self, screen: &'a Screen) -> DisplayableObject<'a, D> pub fn into_displayable(self, screen: &'a Screen) -> DisplayableObject<'a, D> {
{ DisplayableObject::new(screen, self)
return DisplayableObject::new(screen, self)
} }
} }
impl<D: Display> Display for StyledObject<D> { impl<D: Display> Display for StyledObject<D> {
fn fmt(&self, f: &mut Formatter) -> Result<(), fmt::Error> { fn fmt(&self, f: &mut Formatter) -> Result<(), fmt::Error> {
let mut colored_terminal = color(); let colored_terminal = color();
let mut reset = true; let mut reset = true;
if let Some(bg) = self.object_style.bg_color { if let Some(bg) = self.object_style.bg_color {
@ -221,31 +221,29 @@ impl<D: Display> Display for StyledObject<D> {
} }
} }
/// This is a wrapper for a styled object on alternate screen so that the styled object could be printed on the alternate screen with the standard write functions in rust. /// This is a wrapper for a styled object on alternate screen so that the styled object could be printed on the alternate screen with the standard write functions in rust.
/// ///
/// ``` /// ```
/// write! ("some normal text, {} <- some colored text", DisplayableObject::new(&screen, styled_object)); /// write! ("some normal text, {} <- some colored text", DisplayableObject::new(&screen, styled_object));
/// println! ("some normal text, {} <- some colored text", DisplayableObject::new(&screen, styled_object)); /// println! ("some normal text, {} <- some colored text", DisplayableObject::new(&screen, styled_object));
/// ``` /// ```
pub struct DisplayableObject<'a, D:Display + 'a> pub struct DisplayableObject<'a, D: Display + 'a> {
{
styled_object: StyledObject<D>, styled_object: StyledObject<D>,
screen: &'a Screen, screen: &'a Screen,
} }
impl <'a, D: Display + 'a> DisplayableObject<'a, D> impl<'a, D: Display + 'a> DisplayableObject<'a, D> {
{ pub fn new(screen: &'a Screen, styled_object: StyledObject<D>) -> DisplayableObject<'a, D> {
pub fn new(screen: &'a Screen, styled_object: StyledObject<D>) -> DisplayableObject<'a, D> DisplayableObject {
{ screen,
DisplayableObject { screen, styled_object } styled_object,
}
} }
} }
impl<'a, D: Display + 'a> Display for DisplayableObject<'a, D> impl<'a, D: Display + 'a> Display for DisplayableObject<'a, D> {
{
fn fmt(&self, _f: &mut Formatter) -> Result<(), fmt::Error> { fn fmt(&self, _f: &mut Formatter) -> Result<(), fmt::Error> {
self.styled_object.paint(&self.screen); self.styled_object.paint(&self.screen);
return Ok(()) Ok(())
} }
} }

View File

@ -8,14 +8,15 @@ use kernel::windows_kernel::{csbi, kernel};
use winapi::um::wincon; use winapi::um::wincon;
/// This struct is an windows implementation for color related actions. /// This struct is an windows implementation for color related actions.
pub struct WinApiColor pub struct WinApiColor {
{ original_color: u16,
original_color: u16
} }
impl WinApiColor { impl WinApiColor {
pub fn new() -> WinApiColor { pub fn new() -> WinApiColor {
WinApiColor { original_color: csbi::get_original_console_color()} WinApiColor {
original_color: csbi::get_original_console_color(),
}
} }
} }

View File

@ -7,7 +7,6 @@ use super::*;
pub struct AnsiTerminal; pub struct AnsiTerminal;
use cursor::TerminalCursor; use cursor::TerminalCursor;
impl AnsiTerminal { impl AnsiTerminal {
pub fn new() -> AnsiTerminal { pub fn new() -> AnsiTerminal {
AnsiTerminal {} AnsiTerminal {}
@ -18,20 +17,20 @@ impl ITerminal for AnsiTerminal {
fn clear(&self, clear_type: ClearType, stdout: &Option<&Arc<TerminalOutput>>) { fn clear(&self, clear_type: ClearType, stdout: &Option<&Arc<TerminalOutput>>) {
match clear_type { match clear_type {
ClearType::All => { ClearType::All => {
functions::write_str(&stdout,csi!("2J")); functions::write_str(&stdout, csi!("2J"));
TerminalCursor::new().goto(0,0); TerminalCursor::new().goto(0, 0);
} }
ClearType::FromCursorDown => { ClearType::FromCursorDown => {
functions::write_str(&stdout,csi!("J")); functions::write_str(&stdout, csi!("J"));
} }
ClearType::FromCursorUp => { ClearType::FromCursorUp => {
functions::write_str(&stdout,csi!("1J")); functions::write_str(&stdout, csi!("1J"));
} }
ClearType::CurrentLine => { ClearType::CurrentLine => {
functions::write_str(&stdout,csi!("2K")); functions::write_str(&stdout, csi!("2K"));
} }
ClearType::UntilNewLine => { ClearType::UntilNewLine => {
functions::write_str(&stdout,csi!("K")); functions::write_str(&stdout, csi!("K"));
} }
}; };
} }
@ -41,18 +40,18 @@ impl ITerminal for AnsiTerminal {
} }
fn scroll_up(&self, count: i16, stdout: &Option<&Arc<TerminalOutput>>) { fn scroll_up(&self, count: i16, stdout: &Option<&Arc<TerminalOutput>>) {
functions::write(&stdout,format!(csi!("{}S"), count)); functions::write(&stdout, format!(csi!("{}S"), count));
} }
fn scroll_down(&self, count: i16, stdout: &Option<&Arc<TerminalOutput>>) { fn scroll_down(&self, count: i16, stdout: &Option<&Arc<TerminalOutput>>) {
functions::write(&stdout,format!(csi!("{}T"), count)); functions::write(&stdout, format!(csi!("{}T"), count));
} }
fn set_size(&self, width: i16, height: i16, stdout: &Option<&Arc<TerminalOutput>>) { fn set_size(&self, width: i16, height: i16, stdout: &Option<&Arc<TerminalOutput>>) {
functions::write(&stdout,format!(csi!("8;{};{}t"), height, width)); functions::write(&stdout, format!(csi!("8;{};{}t"), height, width));
} }
fn exit(&self,stdout: &Option<&Arc<TerminalOutput>>) { fn exit(&self, stdout: &Option<&Arc<TerminalOutput>>) {
if let Some(output) = stdout { if let Some(output) = stdout {
// drop the screen with the current stdout. This will make sure when in raw mode this will be disabled first. // drop the screen with the current stdout. This will make sure when in raw mode this will be disabled first.
let screen = Screen::from(output.to_owned().clone()); let screen = Screen::from(output.to_owned().clone());

View File

@ -13,10 +13,10 @@ use self::ansi_terminal::AnsiTerminal;
#[cfg(target_os = "windows")] #[cfg(target_os = "windows")]
use self::winapi_terminal::WinApiTerminal; use self::winapi_terminal::WinApiTerminal;
pub use self::terminal::{terminal, from_screen, Terminal}; pub use self::terminal::{from_screen, terminal, Terminal};
use std::sync::Arc;
use super::functions; use super::functions;
use std::sync::Arc;
use {Screen, TerminalOutput}; use {Screen, TerminalOutput};
/// Enum that specifies a way of clearing. /// Enum that specifies a way of clearing.
@ -48,5 +48,5 @@ trait ITerminal {
/// Resize terminal to the given width and height. /// Resize terminal to the given width and height.
fn set_size(&self, width: i16, height: i16, stdout: &Option<&Arc<TerminalOutput>>); fn set_size(&self, width: i16, height: i16, stdout: &Option<&Arc<TerminalOutput>>);
/// Close the current terminal /// Close the current terminal
fn exit(&self,stdout: &Option<&Arc<TerminalOutput>>); fn exit(&self, stdout: &Option<&Arc<TerminalOutput>>);
} }

View File

@ -90,7 +90,7 @@ impl<'stdout> Terminal<'stdout> {
/// println!("{:?}", size); /// println!("{:?}", size);
/// ``` /// ```
pub fn terminal_size(&self) -> (u16, u16) { pub fn terminal_size(&self) -> (u16, u16) {
return self.terminal.terminal_size(&self.screen); self.terminal.terminal_size(&self.screen)
} }
/// Scroll `n` lines up in the current terminal. /// Scroll `n` lines up in the current terminal.

View File

@ -7,12 +7,11 @@ use Screen;
/* ======================== WinApi =========================== */ /* ======================== WinApi =========================== */
#[cfg(windows)] #[cfg(windows)]
mod winapi_tests { mod winapi_tests {
use modules::terminal::winapi_terminal::WinApiTerminal;
use super::*; use super::*;
use modules::terminal::winapi_terminal::WinApiTerminal;
#[test] #[test]
fn resize_winapi() fn resize_winapi() {
{
let screen = Screen::default(); let screen = Screen::default();
let stdout = Some(&screen.stdout); let stdout = Some(&screen.stdout);
let terminal = WinApiTerminal::new(); let terminal = WinApiTerminal::new();
@ -28,15 +27,14 @@ mod winapi_tests {
/* ======================== ANSI =========================== */ /* ======================== ANSI =========================== */
#[test] #[test]
fn resize_ansi() fn resize_ansi() {
{
use std::{thread, time}; use std::{thread, time};
if try_enable_ansi() { if try_enable_ansi() {
let screen = Screen::default(); let screen = Screen::default();
let stdout = Some(&screen.stdout); let stdout = Some(&screen.stdout);
let terminal = AnsiTerminal::new(); let terminal = AnsiTerminal::new();
terminal.set_size(50,50, &stdout); terminal.set_size(50, 50, &stdout);
// see issue: https://github.com/eminence/terminal-size/issues/11 // see issue: https://github.com/eminence/terminal-size/issues/11
thread::sleep(time::Duration::from_millis(30)); thread::sleep(time::Duration::from_millis(30));
@ -48,17 +46,17 @@ fn resize_ansi()
} }
} }
fn try_enable_ansi() -> bool fn try_enable_ansi() -> bool {
{
#[cfg(windows)] #[cfg(windows)]
{ {
if cfg!(target_os = "windows") { if cfg!(target_os = "windows") {
use kernel::windows_kernel::ansi_support::try_enable_ansi_support; use kernel::windows_kernel::ansi_support::try_enable_ansi_support;
if !try_enable_ansi_support() if !try_enable_ansi_support() {
{ return false; } return false;
} }
} }
}
return true; return true;
} }

View File

@ -3,8 +3,8 @@
//! //!
//! Windows versions lower then windows 10 are not supporting ANSI codes. Those versions will use this implementation instead. //! Windows versions lower then windows 10 are not supporting ANSI codes. Those versions will use this implementation instead.
use cursor::TerminalCursor;
use super::*; use super::*;
use cursor::TerminalCursor;
use kernel::windows_kernel::{csbi, kernel, terminal, writing}; use kernel::windows_kernel::{csbi, kernel, terminal, writing};
use winapi::um::wincon::{CONSOLE_SCREEN_BUFFER_INFO, COORD, SMALL_RECT}; use winapi::um::wincon::{CONSOLE_SCREEN_BUFFER_INFO, COORD, SMALL_RECT};
@ -151,8 +151,7 @@ impl ITerminal for WinApiTerminal {
} }
fn exit(&self, stdout: &Option<&Arc<TerminalOutput>>) { fn exit(&self, stdout: &Option<&Arc<TerminalOutput>>) {
if let Some(output) = stdout if let Some(output) = stdout {
{
// drop the screen with the current stdout. This will make sure when in raw mode this will be disabled first. // drop the screen with the current stdout. This will make sure when in raw mode this will be disabled first.
let mut screen = Screen::from(output.to_owned().clone()); let mut screen = Screen::from(output.to_owned().clone());
drop(screen); drop(screen);
@ -208,7 +207,10 @@ pub fn clear_before_cursor(
clear(start_location, cells_to_write); clear(start_location, cells_to_write);
} }
pub fn clear_entire_screen(csbi: CONSOLE_SCREEN_BUFFER_INFO, stdout: &Option<&Arc<TerminalOutput>>) { pub fn clear_entire_screen(
csbi: CONSOLE_SCREEN_BUFFER_INFO,
stdout: &Option<&Arc<TerminalOutput>>,
) {
// position x at start // position x at start
let x = 0; let x = 0;
// position y at start // position y at start
@ -305,11 +307,8 @@ fn clear(start_loaction: COORD, cells_to_write: u32) {
let mut cells_written = 0; let mut cells_written = 0;
let mut success = false; let mut success = false;
success = writing::fill_console_output_character( success =
&mut cells_written, writing::fill_console_output_character(&mut cells_written, start_loaction, cells_to_write);
start_loaction,
cells_to_write,
);
if !success { if !success {
panic!("Could not clear screen after cursor"); panic!("Could not clear screen after cursor");
@ -317,11 +316,8 @@ fn clear(start_loaction: COORD, cells_to_write: u32) {
cells_written = 0; cells_written = 0;
success = writing::fill_console_output_attribute( success =
&mut cells_written, writing::fill_console_output_attribute(&mut cells_written, start_loaction, cells_to_write);
start_loaction,
cells_to_write,
);
if !success { if !success {
panic!("Could not reset attributes after cursor"); panic!("Could not reset attributes after cursor");