* 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;
use self::crossterm::style::{Color, style, color};
use self::crossterm::style::{color, style, Color};
use self::crossterm::{terminal, Screen};
/// print some red font | demonstration.
@ -16,7 +16,10 @@ pub fn paint_foreground() {
println!("Colored text: {}", styledobject);
// 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.
@ -34,85 +37,185 @@ pub fn paint_background() {
/// Print all available foreground colors | demonstration.
pub fn print_all_foreground_colors() {
println!("{}", style(format!("Black : \t\t {} \n", "")).with(Color::Black));
println!("{}", style(format!("Red : \t\t {} \n", "")).with(Color::Red));
println!("{}", style(format!("Cyan : \t\t {} \n", "")).with(Color::Cyan));
println!("{}", 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));
println!(
"{}",
style(format!("Black : \t\t {} \n", "")).with(Color::Black)
);
println!(
"{}",
style(format!("Red : \t\t {} \n", "")).with(Color::Red)
);
println!(
"{}",
style(format!("Cyan : \t\t {} \n", "")).with(Color::Cyan)
);
println!(
"{}",
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)]
println!("{}", style("RGB color (10,10,10) ").with(Color::Rgb {
r: 10,
g: 10,
b: 10
}));
println!(
"{}",
style("RGB color (10,10,10) ").with(Color::Rgb {
r: 10,
g: 10,
b: 10
})
);
#[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.
pub fn print_all_background_colors() {
println!("{}", style(format!("Black : \t {} \n", "")).on(Color::Black));
println!("{}", style(format!("Red : \t\t {} \n", "")).on(Color::Red));
println!("{}", style(format!("Cyan : \t\t {} \n", "")).on(Color::Cyan));
println!("{}", style(format!("DarkCyan : \t {} \n", "")).on(Color::DarkCyan));
println!("{}", style(format!("DarkRed : \t {} \n", "")).on(Color::DarkRed));
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)]
println!("{}", style("RGB color (10,10,10) ").on(Color::Rgb {
r: 10,
g: 10,
b: 10
}));
println!(
"{}",
style(format!("Black : \t {} \n", "")).on(Color::Black)
);
println!(
"{}",
style(format!("Red : \t\t {} \n", "")).on(Color::Red)
);
println!(
"{}",
style(format!("Cyan : \t\t {} \n", "")).on(Color::Cyan)
);
println!(
"{}",
style(format!("DarkCyan : \t {} \n", "")).on(Color::DarkCyan)
);
println!(
"{}",
style(format!("DarkRed : \t {} \n", "")).on(Color::DarkRed)
);
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)]
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..
#[cfg(unix)]
pub fn print_font_with_attributes() {
println!("{}",style("Normal text"));
println!("{}",style("Bold text").bold());
println!("{}",style("Italic text").italic());
println!("{}",style("Slow blinking text").slow_blink());
println!("{}",style("Rapid blinking text").rapid_blink());
println!("{}",style("Hidden text").hidden());
println!("{}",style("Underlined text").underlined());
println!("{}",style("Reversed text").reverse());
println!("{}",style("Dim text").dim());
println!("{}",style("Crossed out font").crossed_out());
println!("{}", style("Normal text"));
println!("{}", style("Bold text").bold());
println!("{}", style("Italic text").italic());
println!("{}", style("Slow blinking text").slow_blink());
println!("{}", style("Rapid blinking text").rapid_blink());
println!("{}", style("Hidden text").hidden());
println!("{}", style("Underlined text").underlined());
println!("{}", style("Reversed text").reverse());
println!("{}", style("Dim text").dim());
println!("{}", style("Crossed out font").crossed_out());
}
/// Print all supported RGB colors | demonstration.
#[cfg(unix)]
pub fn print_supported_colors() {
let count = color()
.get_available_color_count()
.unwrap();
let count = color().get_available_color_count().unwrap();
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.
//!
//! All you need to do is:
@ -9,12 +8,10 @@
extern crate crossterm;
// modules that could be test
mod terminal;
mod color;
mod cursor;
mod some_types;
mod input;
mod some_types;
mod terminal;
fn main()
{
}
fn main() {}

View File

@ -1,12 +1,12 @@
extern crate crossterm;
use self::crossterm::{Crossterm, Screen};
use self::crossterm::terminal::ClearType;
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::time::Duration;
use std::{thread, time};
/// this will capture the input until the given key.
pub fn read_async_until() {
@ -100,8 +100,7 @@ pub fn async_reading_on_alternate_screen() {
let screen = Screen::new(false);
// 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);
// init some modules we use for this demo
let input = crossterm.input();

View File

@ -1,12 +1,12 @@
extern crate crossterm;
use crossterm::{Screen, Crossterm};
use crossterm::terminal::{from_screen,Terminal, ClearType};
use crossterm::cursor::{TerminalCursor, cursor};
use crossterm::cursor::{cursor, TerminalCursor};
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::{thread,time};
use std::sync::{Arc, Mutex};
use std::{thread, time};
fn main() {
use crossterm::color;
@ -18,7 +18,7 @@ fn main() {
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;
@ -26,19 +26,16 @@ fn main() {
let input = input();
let mut stdin = input.read_async().bytes();
loop
{
loop {
let a = stdin.next();
match a {
Some(Ok(13)) =>
{
input_buf.lock().unwrap().clear();
}
Some(Ok(val)) =>
{
input_buf.lock().unwrap().push(val as char);
}
Some(Ok(13)) => {
input_buf.lock().unwrap().clear();
}
Some(Ok(val)) => {
input_buf.lock().unwrap().push(val as char);
}
_ => {}
}
@ -47,35 +44,36 @@ fn main() {
}
}).join();
for thread in threads
{
for thread in threads {
thread.join();
}
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 (_, term_height) = from_screen(screen).terminal_size();
for i in 0..1
{
for i in 0..1 {
let input_buffer = input_buf.clone();
let clone_stdout = 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 terminal = crossterm.terminal();
for j in 0..1000
{
swap_write(format!("Some output: {} from thread: {}", j, i).as_ref(), &input_buffer.lock().unwrap(), &terminal, &cursor, term_height);
for j in 0..1000 {
swap_write(
format!("Some output: {} from thread: {}", j, i).as_ref(),
&input_buffer.lock().unwrap(),
&terminal,
&cursor,
term_height,
);
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;
}
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);
terminal.clear(ClearType::CurrentLine);
terminal.write(format!("{}\r\n", msg));
terminal.write(format!(">{}", input_buf));
}
}

View File

@ -1,12 +1,12 @@
extern crate crossterm;
use crossterm::Screen;
use std::sync::Mutex;
use std::collections::VecDeque;
use std::sync::Arc;
use std::io::Write;
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.
#[derive(Clone)]
@ -16,7 +16,9 @@ struct WorkQueue<T: Send + Clone> {
impl<T: Send + Clone> WorkQueue<T> {
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
@ -74,14 +76,17 @@ impl SyncFlagRx {
fn new_sync_flag(initial_state: bool) -> (SyncFlagTx, SyncFlagRx) {
let state = Arc::new(Mutex::new(initial_state));
let tx = SyncFlagTx { inner: state.clone() };
let rx = SyncFlagRx { inner: state.clone() };
let tx = SyncFlagTx {
inner: state.clone(),
};
let rx = SyncFlagRx {
inner: state.clone(),
};
return (tx, rx);
}
fn main()
{
fn main() {
let (_results_tx, _results_rx): (Sender<String>, Receiver<String>) = mpsc::channel();
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.
handle_incoming_logs(more_jobs_rx.clone(), queue.clone());
// for handle in thread_handles
// {
// handle.join();
// }
// for handle in thread_handles
// {
// handle.join();
// }
}
fn handle_incoming_logs(more_jobs_rx: SyncFlagRx, queue: WorkQueue<String>)
{
thread::spawn( move || {
fn handle_incoming_logs(more_jobs_rx: SyncFlagRx, queue: WorkQueue<String>) {
thread::spawn(move || {
let mut screen: Screen = Screen::default();
// 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.
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.
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 thread_queue = queue.clone();
// create new thread
let thread = thread::spawn(move || {
// log 400 messages
for log_entry_count in 1..400
{
thread_queue.add_work(format!("Log {} from thread {} ",log_entry_count, thread_num));
for log_entry_count in 1..400 {
thread_queue.add_work(format!(
"Log {} from thread {} ",
log_entry_count, thread_num
));
more_jobs.set(true);
}
});

View File

@ -1,11 +1,10 @@
extern crate crossterm;
use crossterm::{Crossterm, Screen};
use crossterm::style::Color;
use crossterm::{Crossterm, Screen};
/// 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.
let crossterm = Crossterm::new();

View File

@ -1,6 +1,6 @@
extern crate crossterm;
use crossterm::style::{Color, style};
use crossterm::style::{style, Color};
use crossterm::terminal::{self, ClearType};
use crossterm::{Crossterm, Screen};
@ -26,7 +26,10 @@ fn print_wait_screen(screen: &Screen) {
for i in 1..5 {
// print the current counter at the line of `Seconds to Go: {counter}`
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
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.
pub fn print_wait_screen_on_alternate_window() {
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);
}
}

View File

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

View File

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

View File

@ -23,13 +23,13 @@ pub trait IEnableAnsiCommand {
}
// 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 disable(&self, stdout: &TerminalOutput) -> io::Result<()>;
}
// 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 disable(&self) -> io::Result<()>;
}

View File

@ -2,28 +2,27 @@
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.
pub struct ToAlternateScreenCommand;
impl ToAlternateScreenCommand {
pub fn new() -> ToAlternateScreenCommand {
return ToAlternateScreenCommand;
ToAlternateScreenCommand
}
}
impl IAlternateScreenCommand for ToAlternateScreenCommand {
/// enable alternate screen.
fn enable(&self, stdout: &mut TerminalOutput) -> Result<()> {
stdout.write_str(csi!("?1049h"));
stdout.write_str(csi!("?1049h"))?;
Ok(())
}
/// disable alternate screen.
fn disable(&self, stdout: &TerminalOutput) -> Result<()> {
stdout.write_str(csi!("?1049l"));
stdout.write_str(csi!("?1049l"))?;
Ok(())
}
}

View File

@ -1,67 +1,7 @@
//! This module contains the commands that can be used for unix systems.
use super::{ IStateCommand};
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::{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(())
}
}
use std::io::Result;
// 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 {
pub fn new() -> Self {
return RawModeCommand {}
RawModeCommand
}
/// Enables raw mode.
pub fn enable(&mut self) -> Result<()> {
terminal::into_raw_mode();
terminal::into_raw_mode()?;
unsafe { terminal::RAW_MODE_ENABLED_BY_USER = true }
Ok(())
@ -82,10 +22,9 @@ impl RawModeCommand {
/// Disables raw mode.
pub fn disable(&mut self) -> Result<()> {
terminal::disable_raw_mode();
terminal::disable_raw_mode()?;
unsafe { terminal::RAW_MODE_ENABLED_BY_USER = false }
Ok(())
}
}

View File

@ -3,13 +3,13 @@
use super::{IAlternateScreenCommand, IEnableAnsiCommand, TerminalOutput};
use kernel::windows_kernel::{ansi_support, csbi, handle, kernel};
use winapi::um::wincon;
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::sync::Arc;
use winapi::um::winnt::HANDLE;
/// 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.
@ -74,12 +74,11 @@ impl IEnableAnsiCommand for EnableAnsiCommand {
pub struct RawModeCommand {
mask: DWORD,
}
use self::wincon::{ ENABLE_LINE_INPUT, ENABLE_WRAP_AT_EOL_OUTPUT};
impl RawModeCommand
{
use self::wincon::{ENABLE_LINE_INPUT, ENABLE_WRAP_AT_EOL_OUTPUT};
impl RawModeCommand {
pub fn new() -> Self {
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<()> {
let handle = handle::get_output_handle()?;
// create a new screen buffer to copy to.

View File

@ -36,7 +36,7 @@ use std::sync::Arc;
/// }
/// ```
pub struct Crossterm {
stdout: Option<Arc<TerminalOutput>>
stdout: Option<Arc<TerminalOutput>>,
}
impl<'crossterm> Crossterm {
@ -47,7 +47,9 @@ impl<'crossterm> Crossterm {
/// Create a new instance of `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.
@ -61,8 +63,8 @@ impl<'crossterm> Crossterm {
/// ```
pub fn cursor(&self) -> cursor::TerminalCursor {
match &self.stdout {
None => { cursor::TerminalCursor::new()},
Some(stdout) => { cursor::TerminalCursor::on_screen(&stdout) },
None => cursor::TerminalCursor::new(),
Some(stdout) => cursor::TerminalCursor::on_screen(&stdout),
}
}
@ -91,12 +93,12 @@ impl<'crossterm> Crossterm {
/// let crossterm = Crossterm::new();
/// let mut terminal = crossterm.terminal();
/// ```
pub fn terminal(&self) -> terminal::Terminal {
pub fn terminal(&self) -> terminal::Terminal {
match &self.stdout {
None => terminal::Terminal::new(),
Some(stdout) => terminal::Terminal::on_screen(&stdout),
}
}
}
/// 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>
where
D: Display, {
D: Display,
{
style::ObjectStyle::new().apply_to(val)
}
}
impl From<Arc<TerminalOutput>> for Crossterm
{
impl From<Arc<TerminalOutput>> for Crossterm {
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 {
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`.
use super::TerminalOutput;
use std::sync::Arc;
use std::io::{self, Write};
use std::sync::Arc;
#[cfg(windows)]
use kernel::windows_kernel::ansi_support::{try_enable_ansi_support, windows_supportable};
#[cfg(windows)]
use kernel::windows_kernel::terminal::{ exit, terminal_size};
use kernel::windows_kernel::terminal::{exit, terminal_size};
#[cfg(windows)]
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.
pub fn get_terminal_size() -> (u16, u16) {
return terminal_size();
terminal_size()
}
/// Get the cursor position based on the current platform.
pub fn get_cursor_position() -> (u16, u16) {
#[cfg(unix)]
return pos().expect("Valide position");
// return pos().unwrap_or_else(|x| { return (0,0) });
return pos().expect("Valide position");
#[cfg(windows)]
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 does_support = true;
if !windows_supportable()
{
// Try to enable ansi on windows if not than use WINAPI.
does_support = try_enable_ansi_support();
if !windows_supportable() {
// Try to enable ansi on windows if not than use WINAPI.
does_support = try_enable_ansi_support();
// uncomment this line when you want to use the winapi implementation.
// does_support = false;
if !does_support {
term = Some(winapi_impl);
}
// uncomment this line when you want to use the winapi implementation.
// does_support = false;
if !does_support {
term = Some(winapi_impl);
}
}
if does_support {
term = Some(unix_impl);
@ -62,16 +60,26 @@ pub fn get_module<T>(winapi_impl: T, unix_impl: T) -> Option<T> {
term
}
pub fn write(stdout: &Option<&Arc<TerminalOutput>>, string: String) {
pub fn write(stdout: &Option<&Arc<TerminalOutput>>, string: String) -> io::Result<usize> {
match stdout {
None => { print!("{}", string.as_str()); io::stdout().flush(); },
Some(output) => { output.write_string(string); },
None => {
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 {
None => { print!("{}", string); io::stdout().flush(); },
Some(output) => { output.write_str(string); },
None => match io::stdout().flush() {
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;
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.
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::io;
/// 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.
///
/// 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>,
pub screen: Screen,
}
impl AlternateScreen {
/// Create new instance of alternate screen.
pub fn new(command: Box<IAlternateScreenCommand + Sync + Send>, screen: Screen) -> Self
{
return AlternateScreen { command, screen }
pub fn new(command: Box<IAlternateScreenCommand + Sync + Send>, screen: Screen) -> Self {
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`.
@ -38,13 +35,16 @@ impl AlternateScreen {
/// 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.
/// 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")]
let command = functions::get_module::<Box<commands::IAlternateScreenCommand + Sync + Send>>(
Box::from(commands::win_commands::ToAlternateScreenCommand::new()),
Box::from(commands::shared_commands::ToAlternateScreenCommand::new()),
).unwrap();
let command =
functions::get_module::<Box<commands::IAlternateScreenCommand + Sync + Send>>(
Box::from(commands::win_commands::ToAlternateScreenCommand::new()),
Box::from(commands::shared_commands::ToAlternateScreenCommand::new()),
).unwrap();
#[cfg(not(target_os = "windows"))]
let command = Box::from(commands::shared_commands::ToAlternateScreenCommand::new());
@ -54,12 +54,11 @@ impl AlternateScreen {
let screen = Screen::from(stdout);
if raw_mode
{
RawScreen::into_raw_mode();
if 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.
@ -69,8 +68,7 @@ impl AlternateScreen {
}
}
impl Drop for AlternateScreen
{
impl Drop for AlternateScreen {
/// This will switch back to main screen on drop.
fn drop(&mut self) {
self.to_main_screen();

View File

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

View File

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

View File

@ -1,10 +1,9 @@
use super::{AlternateScreen,RawScreen};
use super::{AlternateScreen, RawScreen};
use TerminalOutput;
use std::io::Write;
use std::io::Result;
use std::io::Write;
use std::sync::Arc;
use std::sync::atomic::AtomicBool;
/// 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>,
pub stdout: Arc<TerminalOutput>,
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.
/// 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
{
if raw_mode
{
let screen = Screen { stdout: Arc::new(TerminalOutput::new(true)), buffer: Vec::new(), drop: true };
RawScreen::into_raw_mode().unwrap();
return screen;
}
pub fn new(raw_mode: bool) -> Screen {
if raw_mode {
let screen = Screen {
stdout: Arc::new(TerminalOutput::new(true)),
buffer: Vec::new(),
drop: true,
};
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`.
@ -96,7 +95,7 @@ impl Screen
let stdout = TerminalOutput::new(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()`.
@ -112,8 +111,7 @@ impl Screen
/// screen.write_buf(b"Some more text");
/// ```
pub fn write_buf(&mut self, buf: &[u8]) -> Result<usize> {
self.buffer.write(buf)?;
Ok(buf.len())
self.buffer.write(buf)
}
/// 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`.
pub fn disable_drop(&mut self)
{
pub fn disable_drop(&mut self) {
self.drop = false;
}
}
impl From<TerminalOutput> for Screen
{
impl From<TerminalOutput> for Screen {
/// Create an screen with the given `Stdout`
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>'
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.
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.
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();
}
}
}
impl Write for Screen
{
impl Write for Screen {
fn write(&mut self, buf: &[u8]) -> Result<usize> {
self.stdout.write_buf(buf)
}
@ -175,4 +178,4 @@ impl Write for Screen
fn flush(&mut self) -> Result<()> {
self.stdout.flush()
}
}
}

View File

@ -1,22 +1,14 @@
//! 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;
use {libc, Screen};
use std::sync::Arc;
use std::fs;
use std::io::{self, Error, ErrorKind, Read, Write};
use std::os::unix::io::AsRawFd;
use std::time::{Duration, SystemTime};
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;
use termios::{tcsetattr, Termios};
/// A representation of the size of the current terminal.
#[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.
(us.cols, us.rows)
} 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);
// 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 {
// set this boolean so that we know that the systems has enabled raw mode.
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();
// Write command
stdout.write(b"\x1B[6n")?;
stdout.write_all(b"\x1B[6n")?;
stdout.flush()?;
let mut buf = [0u8; 2];
@ -133,7 +124,7 @@ pub fn pos() -> io::Result<(u16, u16)>
// Expect `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 {
return Err(Error::new(ErrorKind::Other, "test"));
};
@ -143,20 +134,16 @@ pub fn pos() -> io::Result<(u16, u16)>
unsafe {
if RAW_MODE_ENABLED_BY_SYSTEM && !RAW_MODE_ENABLED_BY_USER {
RAW_MODE_ENABLED_BY_SYSTEM = false;
disable_raw_mode();
disable_raw_mode()?;
}
}
return res
res
}
/// Set the terminal mode to the given mode.
pub fn set_terminal_mode(termios: &Termios) -> io::Result<()> {
extern "C" {
pub fn tcsetattr(fd: c_int, opt: c_int, termptr: *const Termios) -> c_int;
}
is_true(unsafe { tcsetattr(0, 0, termios) }).and(Ok(()))
}
static mut ORIGINAL_TERMINAL_MODE: Option<Termios> = None;
static mut RAW_MODE_ENABLED_BY_SYSTEM: bool = false;
pub static mut RAW_MODE_ENABLED_BY_USER: bool = false;
/// Transform the given mode into an raw mode (non-canonical) mode.
pub fn make_raw(termios: &mut Termios) {
@ -166,12 +153,7 @@ pub fn make_raw(termios: &mut Termios) {
unsafe { cfmakeraw(termios) }
}
static mut ORIGINAL_TERMINAL_MODE: Option<Termios> = None;
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<()>
{
pub fn into_raw_mode() -> io::Result<()> {
let tty_f;
let fd = unsafe {
@ -187,8 +169,7 @@ pub fn into_raw_mode() -> io::Result<()>
let original = termios.clone();
unsafe {
if let None = ORIGINAL_TERMINAL_MODE
{
if ORIGINAL_TERMINAL_MODE.is_none() {
ORIGINAL_TERMINAL_MODE = Some(original.clone())
}
}
@ -196,12 +177,10 @@ pub fn into_raw_mode() -> io::Result<()>
make_raw(&mut termios);
tcsetattr(fd, TCSADRAIN, &termios)?;
Ok(())
}
pub fn disable_raw_mode() -> io::Result<()>
{
pub fn disable_raw_mode() -> io::Result<()> {
let tty_f;
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)?;
}
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> {
@ -254,7 +232,7 @@ pub fn read_char() -> io::Result<char> {
};
let mut termios = Termios::from_fd(fd)?;
let original = termios.clone();
let original = termios;
make_raw(&mut termios);
tcsetattr(fd, TCSADRAIN, &termios)?;
@ -305,12 +283,3 @@ pub fn read_char() -> io::Result<char> {
pub fn exit() {
::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 std::io::{self, Result};
use std::sync::{Once, ONCE_INIT};
use std::mem::size_of;
use std::sync::Arc;
use std::sync::{Once, ONCE_INIT};
/// Create a new console screen buffer info struct.
pub fn get_csbi() -> Result<CONSOLE_SCREEN_BUFFER_INFO> {
let mut csbi = CONSOLE_SCREEN_BUFFER_INFO::empty();
let success;
unsafe {
success = GetConsoleScreenBufferInfo(handle::get_current_handle()?, &mut csbi)
}
unsafe { success = GetConsoleScreenBufferInfo(handle::get_current_handle()?, &mut csbi) }
if success == 0 {
return Err(io::Error::new(

View File

@ -7,19 +7,16 @@ use winapi::um::wincon::{
use super::{csbi, handle, kernel, TerminalOutput};
use kernel::windows_kernel::kernel::get_largest_console_window_size;
use std::io;
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.
static mut SAVED_CURSOR_POS: (u16, u16) = (0, 0);
/// Reset to saved cursor position
pub fn reset_to_saved_position() {
unsafe {
set_console_cursor_position(
SAVED_CURSOR_POS.0 as i16,
SAVED_CURSOR_POS.1 as i16,
);
set_console_cursor_position(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.
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::processenv::GetStdHandle;
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::fileapi::{OPEN_EXISTING, CreateFileW};
use winapi::shared::minwindef::DWORD;
use winapi::um::errhandlingapi::GetLastError;
use super::*;
use winapi::um::winnt::{FILE_SHARE_WRITE, GENERIC_ALL, GENERIC_READ, GENERIC_WRITE};
use std::sync::Arc;
use std::io::{self, Result};
use std::io::{self, Result};
use std::ptr::null_mut;
use std::sync::Arc;
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_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) {
unsafe
{
unsafe {
let error = GetLastError();
return Err(io::Error::new(
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;
impl Empty for COORD {
fn empty() -> COORD {
COORD { X: 0, Y: 0 }

View File

@ -7,9 +7,9 @@ use std::sync::Arc;
pub fn terminal_size() -> (u16, u16) {
let handle = handle::get_output_handle().unwrap();
// 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);
// }
// 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);
// }
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::um::consoleapi::WriteConsoleW;
use winapi::um::wincon::{
FillConsoleOutputAttribute, FillConsoleOutputCharacterA, WriteConsoleOutputA, CHAR_INFO,
COORD, PSMALL_RECT,
FillConsoleOutputAttribute, FillConsoleOutputCharacterA, WriteConsoleOutputA, CHAR_INFO, COORD,
PSMALL_RECT,
};
use super::{csbi, handle, kernel, TerminalOutput, HANDLE};
@ -18,7 +18,7 @@ use std::sync::Arc;
pub fn fill_console_output_character(
cells_written: &mut u32,
start_location: COORD,
cells_to_write: u32
cells_to_write: u32,
) -> bool {
let handle = handle::get_current_handle().unwrap();
@ -39,7 +39,7 @@ pub fn fill_console_output_character(
pub fn fill_console_output_attribute(
cells_written: &mut u32,
start_location: COORD,
cells_to_write: u32
cells_to_write: u32,
) -> bool {
// Get the position of the current console window

View File

@ -9,22 +9,19 @@ mod common;
mod kernel;
mod modules;
use common::screen;
pub use modules::cursor;
pub use modules::input;
pub use modules::output;
pub use modules::style;
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::input::*;
pub use self::output::*;
pub use self::style::*;
use common::functions;
pub use common::screen::{AlternateScreen, Screen};
pub use common::Crossterm;
pub use output::TerminalOutput;
#[cfg(unix)]
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.
use super::*;
use std::io::Write;
/// 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> {
Box::from(AnsiCursor { })
Box::from(AnsiCursor {})
}
}

View File

@ -33,13 +33,14 @@ pub struct TerminalCursor<'stdout> {
stdout: Option<&'stdout Arc<TerminalOutput>>,
}
impl<'stdout> TerminalCursor <'stdout>{
impl<'stdout> TerminalCursor<'stdout> {
/// Create new cursor instance whereon cursor related actions can be performed.
pub fn new() -> TerminalCursor<'stdout> {
#[cfg(target_os = "windows")]
let cursor =
functions::get_module::<Box<ITerminalCursor + Sync + Send>>(WinApiCursor::new(), AnsiCursor::new())
.unwrap();
let cursor = functions::get_module::<Box<ITerminalCursor + Sync + Send>>(
WinApiCursor::new(),
AnsiCursor::new(),
).unwrap();
#[cfg(not(target_os = "windows"))]
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> {
#[cfg(target_os = "windows")]
let cursor =
functions::get_module::<Box<ITerminalCursor + Sync + Send>>(WinApiCursor::new(), AnsiCursor::new())
.unwrap();
let cursor = functions::get_module::<Box<ITerminalCursor + Sync + Send>>(
WinApiCursor::new(),
AnsiCursor::new(),
).unwrap();
#[cfg(not(target_os = "windows"))]
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.
/// 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)
}

View File

@ -17,8 +17,8 @@ use self::winapi_cursor::WinApiCursor;
pub use self::cursor::{cursor, from_screen, TerminalCursor};
use super::functions;
use TerminalOutput;
use std::sync::Arc;
use TerminalOutput;
///! 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
@ -28,27 +28,27 @@ use std::sync::Arc;
///!
///! 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.
trait ITerminalCursor : Sync + Send {
trait ITerminalCursor: Sync + Send {
/// Goto some location (x,y) in the context.
fn goto(&self, x: u16, y: u16, stdout: &Option<&Arc<TerminalOutput>>);
/// Get the location (x,y) of the current cusror in the context
fn pos(&self) -> (u16, u16);
/// 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.
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.
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.
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.
fn save_position(&self,stdout: &Option<&Arc<TerminalOutput>>);
fn save_position(&self, stdout: &Option<&Arc<TerminalOutput>>);
/// 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.
fn hide(&self,stdout: &Option<&Arc<TerminalOutput>>);
fn hide(&self, stdout: &Option<&Arc<TerminalOutput>>);
/// 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.
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 =========================== */
#[cfg(windows)]
mod winapi_tests {
use modules::cursor::winapi_cursor::WinApiCursor;
use super::*;
use modules::cursor::winapi_cursor::WinApiCursor;
#[test]
fn goto_winapi()
{
fn goto_winapi() {
let screen = Screen::default();
let stdout = Some(&screen.stdout);
let cursor = WinApiCursor::new();
cursor.goto(5, 5,&stdout);
cursor.goto(5, 5, &stdout);
let (x, y) = cursor.pos();
assert_eq!(x, 5);
@ -25,15 +24,14 @@ mod winapi_tests {
}
#[test]
fn reset_safe_winapi()
{
fn reset_safe_winapi() {
let screen = Screen::default();
let stdout = Some(&screen.stdout);
let cursor = WinApiCursor::new();
let (x, y) = cursor.pos();
cursor.save_position(&stdout);
cursor.goto(5, 5,&stdout);
cursor.goto(5, 5, &stdout);
cursor.reset_position(&stdout);
let (x_saved, y_saved) = cursor.pos();
@ -45,8 +43,7 @@ mod winapi_tests {
/* ======================== ANSI =========================== */
#[test]
fn reset_safe_ansi()
{
fn reset_safe_ansi() {
if try_enable_ansi() {
let screen = Screen::default();
let stdout = Some(&screen.stdout);
@ -54,7 +51,7 @@ fn reset_safe_ansi()
let (x, y) = cursor.pos();
cursor.save_position(&stdout);
cursor.goto(5, 5,&stdout);
cursor.goto(5, 5, &stdout);
cursor.reset_position(&stdout);
let (x_saved, y_saved) = cursor.pos();
@ -65,14 +62,13 @@ fn reset_safe_ansi()
}
#[test]
fn goto_ansi()
{
fn goto_ansi() {
if try_enable_ansi() {
let screen = Screen::default();
let stdout = Some(&screen.stdout);
let cursor = AnsiCursor::new();
cursor.goto(5, 5,&stdout);
cursor.goto(5, 5, &stdout);
let (x, y) = cursor.pos();
assert_eq!(x, 5);
@ -80,16 +76,15 @@ fn goto_ansi()
}
}
fn try_enable_ansi() -> bool
{
fn try_enable_ansi() -> bool {
#[cfg(windows)]
{
if cfg!(target_os = "windows") {
use kernel::windows_kernel::ansi_support::try_enable_ansi_support;
if !try_enable_ansi_support()
{ return false; }
if !try_enable_ansi_support() {
return false;
}
}
}

View File

@ -16,7 +16,7 @@ impl 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);
}
@ -24,41 +24,41 @@ impl ITerminalCursor for WinApiCursor {
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();
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();
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();
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();
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();
}
fn reset_position(&self,_stdout: &Option<&Arc<TerminalOutput>>) {
fn reset_position(&self, _stdout: &Option<&Arc<TerminalOutput>>) {
cursor::reset_to_saved_position();
}
fn hide(&self,_stdout: &Option<&Arc<TerminalOutput>>) {
fn hide(&self, _stdout: &Option<&Arc<TerminalOutput>>) {
cursor::cursor_visibility(false);
}
fn show(&self,_stdout: &Option<&Arc<TerminalOutput>>) {
fn show(&self, _stdout: &Option<&Arc<TerminalOutput>>) {
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> {
return self.terminal_input.read_char(&self.stdout);
self.terminal_input.read_char(&self.stdout)
}
/// 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.
pub fn input<'stdout>() -> TerminalInput<'stdout> {
return TerminalInput::new();
TerminalInput::new()
}
/// 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.
pub fn from_screen<'stdout>(screen: &'stdout Screen) -> TerminalInput<'stdout> {
pub fn from_screen(screen: &Screen) -> TerminalInput {
TerminalInput::on_screen(&screen.stdout)
}

View File

@ -15,7 +15,7 @@ use self::windows_input::WindowsInput;
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 TerminalOutput;
@ -36,7 +36,8 @@ trait ITerminalInput {
/// Read the input asynchronously from the user.
fn read_async(&self, stdout: &Option<&Arc<TerminalOutput>>) -> AsyncReader;
/// 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.
@ -64,7 +65,7 @@ impl Read for AsyncReader {
Some(Ok(value)) => {
buf[total] = value;
total += 1;
},
}
_ => 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();
thread::spawn(move || {
for i in get_tty().unwrap().bytes() {
match i {
Ok(byte) => {
let end_of_stream = &byte == &delimiter;
let end_of_stream = byte == delimiter;
let send_error = send.send(Ok(byte)).is_err();
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 {
let is_raw_screen = match stdout {
Some(output) => output.is_in_raw_mode,
None => false
None => false,
};
// _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> {
let is_raw_screen = match stdout {
Some(output) => output.is_in_raw_mode,
None => false
None => false,
};
// _getwch is without echo and _getwche is with echo
@ -91,7 +91,7 @@ impl ITerminalInput for WindowsInput {
let is_raw_screen = match stdout {
Some(output) => output.is_in_raw_mode,
None => false
None => false,
};
thread::spawn(move || {
@ -117,12 +117,16 @@ impl ITerminalInput for WindowsInput {
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 is_raw_screen = match stdout {
Some(output) => output.is_in_raw_mode,
None => false
None => false,
};
thread::spawn(move || {

View File

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

View File

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

View File

@ -15,11 +15,8 @@ use self::winapi_output::WinApiOutput;
pub use self::output::TerminalOutput;
use std::any::Any;
use std::io;
use super::{functions};
/// This trait defines represents an stdout of an screen.
/// This trait can be implemented so that an concrete implementation of the IStdout can forfill
/// 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.
trait IStdout {
/// 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.
fn write(&self, buf: &[u8]) -> io::Result<usize>;
/// Flush the current output.

View File

@ -20,10 +20,8 @@
use super::*;
use std::any::Any;
use std::default::Default;
use std::io::Write;
use screen::RawScreen;
/// Struct that is an handle to an terminal 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.
pub struct TerminalOutput {
stdout: Box<IStdout + Send + Sync>,
pub is_in_raw_mode:bool,
pub is_in_raw_mode: bool,
}
impl TerminalOutput {
/// Create new screen write instance whereon screen related actions can be performed.
pub fn new(raw_mode: bool) -> Self {
#[cfg(target_os = "windows")]
let stdout: Box<IStdout + Send + Sync> = functions::get_module::<Box<IStdout + Send + Sync>>(
Box::from(WinApiOutput::new()),
Box::from(AnsiOutput::new()),
).unwrap();
let stdout: Box<IStdout + Send + Sync> =
functions::get_module::<Box<IStdout + Send + Sync>>(
Box::from(WinApiOutput::new()),
Box::from(AnsiOutput::new()),
).unwrap();
#[cfg(not(target_os = "windows"))]
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.
@ -76,12 +78,11 @@ impl Write for TerminalOutput {
}
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.
fn default() -> Self {
#[cfg(target_os = "windows")]
@ -93,6 +94,9 @@ impl Default for TerminalOutput
#[cfg(not(target_os = "windows"))]
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)]
mod winapi_tests {
use modules::output::winapi_output::WinApiOutput;
use super::*;
use modules::output::winapi_output::WinApiOutput;
/* ======================== WinApi =========================== */
#[test]
fn write_winapi()
{
fn write_winapi() {
let screen = Screen::default();
let output = WinApiOutput::new();
@ -21,8 +20,7 @@ mod winapi_tests {
}
#[test]
fn write_str_winapi()
{
fn write_str_winapi() {
let screen = Screen::default();
let output = WinApiOutput::new();
@ -34,8 +32,7 @@ mod winapi_tests {
/* ======================== ANSI =========================== */
#[test]
fn write_ansi()
{
fn write_ansi() {
let _screen = Screen::default();
let output = AnsiOutput::new();
@ -45,8 +42,7 @@ fn write_ansi()
}
#[test]
fn write_str_ansi()
{
fn write_str_ansi() {
let _screen = Screen::default();
let output = AnsiOutput::new();
@ -55,25 +51,28 @@ fn write_str_ansi()
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 {
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)]
{
if cfg!(target_os = "windows") {
use kernel::windows_kernel::ansi_support::try_enable_ansi_support;
{
if cfg!(target_os = "windows") {
use kernel::windows_kernel::ansi_support::try_enable_ansi_support;
if !try_enable_ansi_support()
{ return false; }
if !try_enable_ansi_support() {
return false;
}
}
}
return true;
}
}

View File

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

View File

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

View File

@ -63,7 +63,7 @@ impl<'stdout> TerminalColor<'stdout> {
TerminalColor {
color,
stdout: Some(stdout)
stdout: Some(stdout),
}
}
@ -128,9 +128,8 @@ pub fn color<'stdout>() -> TerminalColor<'stdout> {
TerminalColor::new()
}
/// 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.
pub fn from_screen<'stdout>(screen: &'stdout Screen) -> TerminalColor<'stdout> {
pub fn from_screen(screen: &Screen) -> TerminalColor {
TerminalColor::on_screen(&screen.stdout)
}

View File

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

View File

@ -30,10 +30,7 @@ impl Default for ObjectStyle {
impl ObjectStyle {
/// Apply an `StyledObject` to the passed displayable object.
pub fn apply_to<D: Display>(
&self,
val: D,
) -> StyledObject<D> {
pub fn apply_to<D: Display>(&self, val: D) -> StyledObject<D> {
StyledObject {
object_style: self.clone(),
content: val,
@ -42,12 +39,12 @@ impl ObjectStyle {
/// Get an new instance of `ObjectStyle`
pub fn new() -> ObjectStyle {
return ObjectStyle {
ObjectStyle {
fg_color: None,
bg_color: None,
#[cfg(unix)]
attrs: Vec::new(),
};
}
}
/// 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)]
pub fn attr(mut self, attr: Attribute) -> StyledObject<D> {
&self.object_style.add_attr(attr);
self.object_style.add_attr(attr);
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.
/// 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 mut reset = true;
@ -161,7 +160,9 @@ impl<'a, D: Display + 'a> StyledObject<D> {
#[cfg(unix)]
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;
}
@ -190,15 +191,14 @@ impl<'a, D: Display + 'a> StyledObject<D> {
/// let display_object = styled_object.into_displayable(&screen);
/// println!("Colored text: {}. Default color", display_object);
/// ```
pub fn into_displayable(self, screen: &'a Screen) -> DisplayableObject<'a, D>
{
return DisplayableObject::new(screen, self)
pub fn into_displayable(self, screen: &'a Screen) -> DisplayableObject<'a, D> {
DisplayableObject::new(screen, self)
}
}
impl<D: Display> Display for StyledObject<D> {
fn fmt(&self, f: &mut Formatter) -> Result<(), fmt::Error> {
let mut colored_terminal = color();
let colored_terminal = color();
let mut reset = true;
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.
///
/// ```
/// write! ("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>,
screen: &'a Screen,
}
impl <'a, D: Display + 'a> DisplayableObject<'a, D>
{
pub fn new(screen: &'a Screen, styled_object: StyledObject<D>) -> DisplayableObject<'a, D>
{
DisplayableObject { screen, styled_object }
impl<'a, D: Display + 'a> DisplayableObject<'a, D> {
pub fn new(screen: &'a Screen, styled_object: StyledObject<D>) -> DisplayableObject<'a, D> {
DisplayableObject {
screen,
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> {
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;
/// This struct is an windows implementation for color related actions.
pub struct WinApiColor
{
original_color: u16
pub struct WinApiColor {
original_color: u16,
}
impl 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;
use cursor::TerminalCursor;
impl AnsiTerminal {
pub fn new() -> AnsiTerminal {
AnsiTerminal {}
@ -18,20 +17,20 @@ impl ITerminal for AnsiTerminal {
fn clear(&self, clear_type: ClearType, stdout: &Option<&Arc<TerminalOutput>>) {
match clear_type {
ClearType::All => {
functions::write_str(&stdout,csi!("2J"));
TerminalCursor::new().goto(0,0);
functions::write_str(&stdout, csi!("2J"));
TerminalCursor::new().goto(0, 0);
}
ClearType::FromCursorDown => {
functions::write_str(&stdout,csi!("J"));
functions::write_str(&stdout, csi!("J"));
}
ClearType::FromCursorUp => {
functions::write_str(&stdout,csi!("1J"));
functions::write_str(&stdout, csi!("1J"));
}
ClearType::CurrentLine => {
functions::write_str(&stdout,csi!("2K"));
functions::write_str(&stdout, csi!("2K"));
}
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>>) {
functions::write(&stdout,format!(csi!("{}S"), count));
functions::write(&stdout, format!(csi!("{}S"), count));
}
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>>) {
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 {
// 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());

View File

@ -13,10 +13,10 @@ use self::ansi_terminal::AnsiTerminal;
#[cfg(target_os = "windows")]
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 std::sync::Arc;
use {Screen, TerminalOutput};
/// Enum that specifies a way of clearing.
@ -48,5 +48,5 @@ trait ITerminal {
/// Resize terminal to the given width and height.
fn set_size(&self, width: i16, height: i16, stdout: &Option<&Arc<TerminalOutput>>);
/// 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);
/// ```
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.

View File

@ -7,12 +7,11 @@ use Screen;
/* ======================== WinApi =========================== */
#[cfg(windows)]
mod winapi_tests {
use modules::terminal::winapi_terminal::WinApiTerminal;
use super::*;
use modules::terminal::winapi_terminal::WinApiTerminal;
#[test]
fn resize_winapi()
{
fn resize_winapi() {
let screen = Screen::default();
let stdout = Some(&screen.stdout);
let terminal = WinApiTerminal::new();
@ -28,15 +27,14 @@ mod winapi_tests {
/* ======================== ANSI =========================== */
#[test]
fn resize_ansi()
{
fn resize_ansi() {
use std::{thread, time};
if try_enable_ansi() {
let screen = Screen::default();
let stdout = Some(&screen.stdout);
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
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)]
{
if cfg!(target_os = "windows") {
use kernel::windows_kernel::ansi_support::try_enable_ansi_support;
{
if cfg!(target_os = "windows") {
use kernel::windows_kernel::ansi_support::try_enable_ansi_support;
if !try_enable_ansi_support()
{ return false; }
if !try_enable_ansi_support() {
return false;
}
}
}
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.
use cursor::TerminalCursor;
use super::*;
use cursor::TerminalCursor;
use kernel::windows_kernel::{csbi, kernel, terminal, writing};
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>>) {
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.
let mut screen = Screen::from(output.to_owned().clone());
drop(screen);
@ -208,7 +207,10 @@ pub fn clear_before_cursor(
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
let x = 0;
// position y at start
@ -305,11 +307,8 @@ fn clear(start_loaction: COORD, cells_to_write: u32) {
let mut cells_written = 0;
let mut success = false;
success = writing::fill_console_output_character(
&mut cells_written,
start_loaction,
cells_to_write,
);
success =
writing::fill_console_output_character(&mut cells_written, start_loaction, cells_to_write);
if !success {
panic!("Could not clear screen after cursor");
@ -317,11 +316,8 @@ fn clear(start_loaction: COORD, cells_to_write: u32) {
cells_written = 0;
success = writing::fill_console_output_attribute(
&mut cells_written,
start_loaction,
cells_to_write,
);
success =
writing::fill_console_output_attribute(&mut cells_written, start_loaction, cells_to_write);
if !success {
panic!("Could not reset attributes after cursor");