Fixed readline bug (#65)

* Fixed `read_line()` bug Windows
This commit is contained in:
Timon 2018-12-28 05:58:09 -08:00 committed by GitHub
parent e0136891e7
commit ddcda09602
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
27 changed files with 201 additions and 219 deletions

View File

@ -14,12 +14,4 @@ extern crate crossterm;
//mod some_types; //mod some_types;
//mod terminal; //mod terminal;
use crossterm::style::{style, Color}; fn main() { }
fn main() {
let styled_object = style("'Red' text on 'White' background")
.with(Color::Rgb { r: 0xFF, g: 0, b: 0 })
.on(Color::Rgb { r: 0xFF, g: 0xFF, b: 0xFF });
println!("{}", styled_object);
}

View File

@ -42,7 +42,8 @@ fn main() {
thread::sleep(time::Duration::from_millis(100)); thread::sleep(time::Duration::from_millis(100));
count += 1; count += 1;
} }
}).join(); })
.join();
for thread in threads { for thread in threads {
thread.join(); thread.join();

View File

@ -121,7 +121,8 @@ fn handle_incoming_logs(more_jobs_rx: SyncFlagRx, queue: WorkQueue<String>) {
} }
std::thread::yield_now(); std::thread::yield_now();
} }
}).join(); })
.join();
} }
// start different threads that log contiguously. // start different threads that log contiguously.

View File

@ -87,7 +87,10 @@ pub fn write(stdout: &Option<&Arc<TerminalOutput>>, string: String) -> io::Resul
pub fn write_str(stdout: &Option<&Arc<TerminalOutput>>, string: &str) -> io::Result<usize> { pub fn write_str(stdout: &Option<&Arc<TerminalOutput>>, string: &str) -> io::Result<usize> {
match stdout { match stdout {
None => match io::stdout().flush() { None => match io::stdout().flush() {
Ok(_) => { write!(io::stdout(), "{}", string)?; Ok(string.len()) }, Ok(_) => {
write!(io::stdout(), "{}", string)?;
Ok(string.len())
}
Err(e) => Err(e), Err(e) => Err(e),
}, },
Some(output) => output.write_str(string), Some(output) => output.write_str(string),

View File

@ -44,7 +44,8 @@ impl AlternateScreen {
functions::get_module::<Box<commands::IAlternateScreenCommand + Sync + Send>>( functions::get_module::<Box<commands::IAlternateScreenCommand + Sync + Send>>(
Box::from(commands::win_commands::ToAlternateScreenCommand::new()), Box::from(commands::win_commands::ToAlternateScreenCommand::new()),
Box::from(commands::shared_commands::ToAlternateScreenCommand::new()), Box::from(commands::shared_commands::ToAlternateScreenCommand::new()),
).unwrap(); )
.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());

View File

@ -21,7 +21,7 @@ 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 { success = GetConsoleScreenBufferInfo(handle::get_current_handle()?, &mut csbi) } unsafe { success = GetConsoleScreenBufferInfo(handle::get_current_out_handle()?, &mut csbi) }
if success == 0 { if success == 0 {
return Err(io::Error::new( return Err(io::Error::new(
@ -35,7 +35,7 @@ pub fn get_csbi() -> Result<CONSOLE_SCREEN_BUFFER_INFO> {
/// Get buffer info and handle of the current screen. /// Get buffer info and handle of the current screen.
pub fn get_csbi_and_handle() -> Result<(CONSOLE_SCREEN_BUFFER_INFO, HANDLE)> { pub fn get_csbi_and_handle() -> Result<(CONSOLE_SCREEN_BUFFER_INFO, HANDLE)> {
let handle = handle::get_current_handle()?; let handle = handle::get_current_out_handle()?;
let csbi = get_csbi_by_handle(&handle)?; let csbi = get_csbi_by_handle(&handle)?;
return Ok((csbi, handle)); return Ok((csbi, handle));
@ -59,7 +59,7 @@ pub fn get_csbi_by_handle(handle: &HANDLE) -> Result<CONSOLE_SCREEN_BUFFER_INFO>
/// Set the console screen buffer size /// Set the console screen buffer size
pub fn set_console_screen_buffer_size(size: COORD) -> bool { pub fn set_console_screen_buffer_size(size: COORD) -> bool {
let handle = handle::get_current_handle().unwrap(); let handle = handle::get_current_out_handle().unwrap();
unsafe { unsafe {
if !kernel::is_true(SetConsoleScreenBufferSize(handle, size)) { if !kernel::is_true(SetConsoleScreenBufferSize(handle, size)) {

View File

@ -29,7 +29,7 @@ pub fn save_cursor_pos() {
/// get the current cursor position. /// get the current cursor position.
pub fn pos() -> (u16, u16) { pub fn pos() -> (u16, u16) {
let handle = handle::get_current_handle().unwrap(); let handle = handle::get_current_out_handle().unwrap();
if let Ok(csbi) = csbi::get_csbi_by_handle(&handle) { if let Ok(csbi) = csbi::get_csbi_by_handle(&handle) {
( (
@ -57,7 +57,7 @@ pub fn set_console_cursor_position(x: i16, y: i16) {
); );
} }
let handle = handle::get_current_handle().unwrap(); let handle = handle::get_current_out_handle().unwrap();
let position = COORD { X: x, Y: y }; let position = COORD { X: x, Y: y };
@ -80,7 +80,7 @@ pub fn set_console_cursor_position(x: i16, y: i16) {
/// change the cursor visibility. /// change the cursor visibility.
pub fn cursor_visibility(visable: bool) -> io::Result<()> { pub fn cursor_visibility(visable: bool) -> io::Result<()> {
let handle = handle::get_current_handle().unwrap(); let handle = handle::get_current_out_handle().unwrap();
let cursor_info = CONSOLE_CURSOR_INFO { let cursor_info = CONSOLE_CURSOR_INFO {
dwSize: 100, dwSize: 100,

View File

@ -1,49 +1,61 @@
//! 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 super::*;
use winapi::shared::minwindef::DWORD;
use winapi::um::errhandlingapi::GetLastError;
use winapi::um::fileapi::{CreateFileW, OPEN_EXISTING}; 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::{FILE_SHARE_WRITE, GENERIC_READ, GENERIC_WRITE}; use winapi::um::winnt::{FILE_SHARE_READ, FILE_SHARE_WRITE, GENERIC_READ, GENERIC_WRITE};
use std::io::{self, Result}; use std::io::{self, Result};
use std::ptr::null_mut; use std::ptr::null_mut;
/// Get the handle of the active screen. /// Get the handle of the active screen.
pub fn get_current_handle() -> Result<HANDLE> { pub fn get_current_out_handle() -> Result<HANDLE> {
let dw: DWORD = 0;
unsafe {
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( let handle = unsafe {
CreateFileW(
utf16_ptr, utf16_ptr,
GENERIC_READ | GENERIC_WRITE, GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE,
null_mut(), null_mut(),
OPEN_EXISTING, OPEN_EXISTING,
dw, 0,
null_mut(), null_mut(),
); )
};
if !is_valid_handle(&handle) { if !is_valid_handle(&handle) {
unsafe { return Err(io::Error::last_os_error());
let error = GetLastError();
return Err(io::Error::new(
io::ErrorKind::Other,
format!(
"Could not get output handle current handle!, error code: {}",
error
).as_ref(),
));
}
} }
Ok(handle) Ok(handle)
} }
/// Get the handle of the active screen.
pub fn get_current_in_handle() -> Result<HANDLE> {
let utf16: Vec<u16> = "CONIN$\0".encode_utf16().collect();
let utf16_ptr: *const u16 = utf16.as_ptr();
let handle = unsafe {
CreateFileW(
utf16_ptr,
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE,
null_mut(),
OPEN_EXISTING,
0,
null_mut(),
)
};
if !is_valid_handle(&handle) {
return Err(io::Error::last_os_error());
}
Ok(handle)
} }
/// Get the std_output_handle of the console /// Get the std_output_handle of the console

View File

@ -30,7 +30,7 @@ pub fn get_console_mode(handle: &HANDLE, current_mode: &mut u32) -> bool {
/// Change the console text attribute. /// Change the console text attribute.
pub fn set_console_text_attribute(value: u16) -> bool { pub fn set_console_text_attribute(value: u16) -> bool {
let handle = handle::get_current_handle().unwrap(); let handle = handle::get_current_out_handle().unwrap();
unsafe { unsafe {
return is_true(SetConsoleTextAttribute(handle, value)); return is_true(SetConsoleTextAttribute(handle, value));
@ -39,7 +39,7 @@ pub fn set_console_text_attribute(value: u16) -> bool {
/// Change console info. /// Change console info.
pub fn set_console_info(absolute: bool, rect: &SMALL_RECT) -> bool { pub fn set_console_info(absolute: bool, rect: &SMALL_RECT) -> bool {
let handle = handle::get_current_handle().unwrap(); let handle = handle::get_current_out_handle().unwrap();
let absolute = match absolute { let absolute = match absolute {
true => 1, true => 1,

View File

@ -5,6 +5,7 @@ pub mod csbi;
pub mod cursor; pub mod cursor;
pub mod handle; pub mod handle;
pub mod kernel; pub mod kernel;
pub mod reading;
pub mod terminal; pub mod terminal;
pub mod writing; pub mod writing;

View File

@ -1,84 +1,73 @@
//use { Context, ScreenManager }; use super::handle::get_current_in_handle;
//use std::rc::Rc; use std::io::{self, Error, Result};
//use std::sync::Mutex;
// use std::{
//use winapi::um::consoleapi::ReadConsoleW; mem::{self, zeroed},
//use winapi::um::winnt::HANDLE; ptr::{null, null_mut},
//use winapi::um::wincon::{ COORD, PSMALL_RECT, ReadConsoleOutputA, CHAR_INFO, }; };
//use winapi::shared::minwindef::{ DWORD, LPDWORD, LPVOID };
//use winapi::shared::ntdef::NULL; use winapi::{
// shared::minwindef::{LPVOID, ULONG},
//use super::kernel; um::consoleapi::{ReadConsoleInputW, ReadConsoleW},
//use winapi::ctypes::c_void; um::wincon::CONSOLE_READCONSOLE_CONTROL,
// um::wincon::{CHAR_INFO, CONSOLE_FONT_INFOEX, INPUT_RECORD, PCONSOLE_READCONSOLE_CONTROL},
//pub fn read(buf: &mut [u8], stdout: &Rc<Mutex<ScreenManager>>) { };
//// // Read more if the buffer is empty
//// let mut utf16: Vec<u16> = Vec::new(); use std::io::Write;
//// let mut num: DWORD = 0;
//// /// Could be used to read a line from the stdin.
//// let handle = kernel::get_current_handle(&stdout); /// Note that this is a blocking call and it continues when user pressed enter.
//// pub fn read_line(buf: &mut Vec<u8>) -> io::Result<usize> {
//// unsafe { let handle = get_current_in_handle()?;
//// ReadConsoleW(handle,
//// utf16.as_mut_ptr() as LPVOID, let mut utf16 = vec![0u16; 0x1000];
//// utf16.len() as u32, let mut num = 0;
//// &mut num as LPDWORD, let mut input_control = readconsole_input_control(CTRL_Z_MASK);
//// ptr::mut_null())
//// }; unsafe {
//// ReadConsoleW(
//// utf16.truncate(num as uint); handle,
//// let utf8 = match from_utf16(utf16.as_slice()) { utf16.as_mut_ptr() as LPVOID,
//// Some(utf8) => utf8.into_bytes(), utf16.len() as u32,
//// None => {} &mut num,
//// }; &mut input_control as PCONSOLE_READCONSOLE_CONTROL,
//// )
//// panic!(utf8); };
//
//} utf16.truncate(num as usize);
//
//pub fn read_line(stdout: &Rc<Mutex<ScreenManager>>) -> ::std::io::Result<String> let mut data = match String::from_utf16(&utf16) {
//{ Ok(utf8) => utf8.into_bytes(),
// const BUFFER_LENGHT: u32 = 1024; Err(..) => return Err(invalid_encoding()),
// let mut buffer: &mut [CHAR_INFO; BUFFER_LENGHT as usize] = unsafe {::std::mem::zeroed() }; };
//
// let handle = kernel::get_current_handle(&stdout); if let Some(&last_byte) = data.last() {
// if last_byte == CTRL_Z {
// let mut dw_mode: DWORD = 0; data.pop();
// let console_mode = kernel::get_console_mode(&handle, &mut dw_mode); }
// };
// let ptr = buffer.as_ptr() as *const _ as *mut c_void;
// let mut chars_read: u32 = 0; let a = &data
// .into_iter()
// panic!(); .filter(|&x| x != 10 || x != 13)
// unsafe .collect::<Vec<u8>>();
// {
// ReadConsoleW(handle, ptr, BUFFER_LENGHT , &mut chars_read, unsafe {::std::mem::zeroed() }); buf.write(a);
// } Ok(num as usize)
// }
// Ok(String::new())
//} pub fn readconsole_input_control(wakeup_mask: ULONG) -> CONSOLE_READCONSOLE_CONTROL {
// CONSOLE_READCONSOLE_CONTROL {
///// Read the console outptut. nLength: mem::size_of::<CONSOLE_READCONSOLE_CONTROL>() as ULONG,
//pub fn read_console_output( nInitialChars: 0,
// read_buffer: &HANDLE, dwCtrlWakeupMask: wakeup_mask,
// copy_buffer: &mut [CHAR_INFO; 160], dwControlKeyState: 0,
// buffer_size: COORD, }
// buffer_coord: COORD, }
// source_buffer: PSMALL_RECT,
//) { fn invalid_encoding() -> io::Error {
// io::Error::new(io::ErrorKind::InvalidData, "text was not valid unicode")
// }
// unsafe {
// if !kernel::is_true( const CTRL_Z: u8 = 0x1A;
// ReadConsoleOutputA( const CTRL_Z_MASK: ULONG = 0x4000000; //1 << 0x1A
// *read_buffer, // screen buffer to read from
// copy_buffer.as_mut_ptr(), // buffer to copy into
// buffer_size, // col-row size of chiBuffer
// buffer_coord, // top left dest. cell in chiBuffer
// source_buffer,
// ), // screen buffer source rectangle
// ) {
// panic!("Cannot read console output");
// }
// }
//}

View File

@ -19,7 +19,7 @@ pub fn fill_console_output_character(
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_out_handle().unwrap();
unsafe { unsafe {
// fill the cells in console with blanks // fill the cells in console with blanks

View File

@ -12,17 +12,20 @@ mod common;
mod kernel; mod kernel;
mod modules; mod modules;
pub use modules::terminal;
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 self::style::{color, style, Color, ColorType, Attribute, TerminalColor, ObjectStyle, StyledObject, DisplayableObject};
pub use self::cursor::{cursor, TerminalCursor}; pub use self::cursor::{cursor, TerminalCursor};
pub use self::input::{input, TerminalInput, AsyncReader, KeyEvent}; pub use self::input::{input, AsyncReader, KeyEvent, TerminalInput};
pub use self::terminal::{terminal, Terminal};
pub use self::output::TerminalOutput; pub use self::output::TerminalOutput;
pub use self::style::{
color, style, Attribute, Color, ColorType, DisplayableObject, ObjectStyle, StyledObject,
TerminalColor,
};
pub use self::terminal::{terminal, Terminal};
pub use common::screen::{AlternateScreen, Screen}; pub use common::screen::{AlternateScreen, Screen};
pub use common::Crossterm; pub use common::Crossterm;

View File

@ -40,7 +40,8 @@ impl<'stdout> TerminalCursor<'stdout> {
let cursor = functions::get_module::<Box<ITerminalCursor + Sync + Send>>( let cursor = functions::get_module::<Box<ITerminalCursor + Sync + Send>>(
WinApiCursor::new(), WinApiCursor::new(),
AnsiCursor::new(), AnsiCursor::new(),
).unwrap(); )
.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>;
@ -72,7 +73,8 @@ impl<'stdout> TerminalCursor<'stdout> {
let cursor = functions::get_module::<Box<ITerminalCursor + Sync + Send>>( let cursor = functions::get_module::<Box<ITerminalCursor + Sync + Send>>(
WinApiCursor::new(), WinApiCursor::new(),
AnsiCursor::new(), AnsiCursor::new(),
).unwrap(); )
.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>;

View File

@ -2,8 +2,8 @@
//! Like reading a line, reading a character and reading asynchronously. //! Like reading a line, reading a character and reading asynchronously.
use super::*; use super::*;
use Screen;
use std::{thread, time::Duration}; use std::{thread, time::Duration};
use Screen;
/// Struct that stores a platform-specific implementation for input related actions. /// Struct that stores a platform-specific implementation for input related actions.
/// ///
@ -78,6 +78,9 @@ impl<'stdout> TerminalInput<'stdout> {
/// Read one line from the user input. /// Read one line from the user input.
/// ///
/// Note that this function only works when rawscreen is not turned on.
/// When you do want to read a line in raw mode please checkout `read_async` or `read_async_until`.
///
/// ```rust /// ```rust
/// let input = input(); /// let input = input();
/// match input.read_line() { /// match input.read_line() {
@ -86,7 +89,17 @@ impl<'stdout> TerminalInput<'stdout> {
/// } /// }
/// ``` /// ```
pub fn read_line(&self) -> io::Result<String> { pub fn read_line(&self) -> io::Result<String> {
self.terminal_input.read_line(&self.stdout) if let Some(stdout) = self.stdout {
if stdout.is_in_raw_mode {
return Err(Error::new(ErrorKind::Other, "Crossterm does not support readline in raw mode this should be done instead whit `read_async` or `read_async_until`"));
}
}
let mut rv = String::new();
io::stdin().read_line(&mut rv)?;
let len = rv.trim_right_matches(&['\r', '\n'][..]).len();
rv.truncate(len);
Ok(rv)
} }
/// Read one character from the user input /// Read one character from the user input
@ -198,15 +211,21 @@ impl<'stdout> TerminalInput<'stdout> {
let pressed_key: Option<Result<u8, Error>> = stdin.next(); let pressed_key: Option<Result<u8, Error>> = stdin.next();
match pressed_key { match pressed_key {
Some(Ok(value)) => { Some(Ok(value)) => match key_event {
match key_event { KeyEvent::OnKeyPress(ascii_code) => {
KeyEvent::OnKeyPress(ascii_code) => if value == ascii_code { break; }, if value == ascii_code {
KeyEvent::OnEnter => if value == b'\r' { break; },
KeyEvent::OnAnyKeyPress => {
break; break;
} }
} }
KeyEvent::OnEnter => {
if value == b'\r' {
break;
} }
}
KeyEvent::OnAnyKeyPress => {
break;
}
},
_ => {} _ => {}
} }

View File

@ -13,7 +13,7 @@ use self::unix_input::UnixInput;
#[cfg(target_os = "windows")] #[cfg(target_os = "windows")]
use self::windows_input::WindowsInput; use self::windows_input::WindowsInput;
pub use self::input::{input, from_screen, TerminalInput}; pub use self::input::{from_screen, input, TerminalInput};
use std::io::{self, Error, ErrorKind, Read}; use std::io::{self, Error, ErrorKind, Read};
use std::sync::{mpsc, Arc}; use std::sync::{mpsc, Arc};
@ -29,8 +29,6 @@ use TerminalOutput;
/// This trait is implemented for Windows and UNIX systems. /// This trait is implemented for Windows and UNIX systems.
/// Unix is using the 'TTY' and windows is using 'libc' C functions to read the input. /// Unix is using the 'TTY' and windows is using 'libc' C functions to read the input.
trait ITerminalInput { trait ITerminalInput {
/// Read one line from the user input
fn read_line(&self, stdout: &Option<&Arc<TerminalOutput>>) -> io::Result<String>;
/// Read one character from the user input /// Read one character from the user input
fn read_char(&self, stdout: &Option<&Arc<TerminalOutput>>) -> io::Result<char>; fn read_char(&self, stdout: &Option<&Arc<TerminalOutput>>) -> io::Result<char>;
/// Read the input asynchronously from the user. /// Read the input asynchronously from the user.

View File

@ -15,14 +15,6 @@ impl UnixInput {
} }
impl ITerminalInput for UnixInput { impl ITerminalInput for UnixInput {
fn read_line(&self, __stdout: &Option<&Arc<TerminalOutput>>) -> io::Result<String> {
let mut rv = String::new();
io::stdin().read_line(&mut rv)?;
let len = rv.trim_right_matches(&['\r', '\n'][..]).len();
rv.truncate(len);
Ok(rv)
}
fn read_char(&self, __stdout: &Option<&Arc<TerminalOutput>>) -> io::Result<char> { fn read_char(&self, __stdout: &Option<&Arc<TerminalOutput>>) -> io::Result<char> {
read_char() read_char()
} }

View File

@ -2,56 +2,20 @@
use super::*; use super::*;
use winapi::um::winnt::INT; use kernel::windows_kernel::reading::read_line;
use std::char; use std::char;
use std::thread; use std::thread;
use winapi::um::winnt::INT;
pub struct WindowsInput; pub struct WindowsInput;
impl WindowsInput { impl WindowsInput {
pub fn new() -> WindowsInput { pub fn new() -> WindowsInput {
WindowsInput {} WindowsInput
} }
} }
impl ITerminalInput for WindowsInput { impl ITerminalInput for WindowsInput {
fn read_line(&self, stdout: &Option<&Arc<TerminalOutput>>) -> io::Result<String> {
let mut chars: Vec<char> = Vec::new();
loop {
let is_raw_screen = match stdout {
Some(output) => output.is_in_raw_mode,
None => false,
};
// _getwch is without echo and _getwche is with echo
let pressed_char = unsafe {
if is_raw_screen {
_getwch()
} else {
_getwche()
}
};
// if 0 or 0xe0 we need to listen again because the next key will be an special key
if pressed_char != 0 || pressed_char != 0xe0 {
match char::from_u32(pressed_char as u32) {
Some(c) => {
if is_line_end(c) {
break;
} else {
chars.push(c);
}
}
None => panic!("Some error needs to be returned"),
};
}
}
return Ok(chars.into_iter().collect());
}
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,

View File

@ -15,8 +15,8 @@ use self::winapi_output::WinApiOutput;
pub use self::output::TerminalOutput; pub use self::output::TerminalOutput;
use std::io;
use super::functions; use super::functions;
use std::io;
/// 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

View File

@ -37,7 +37,8 @@ impl TerminalOutput {
functions::get_module::<Box<IStdout + Send + Sync>>( functions::get_module::<Box<IStdout + Send + Sync>>(
Box::from(WinApiOutput::new()), Box::from(WinApiOutput::new()),
Box::from(AnsiOutput::new()), Box::from(AnsiOutput::new()),
).unwrap(); )
.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>;
@ -86,7 +87,8 @@ impl Default for TerminalOutput {
let stdout = functions::get_module::<Box<IStdout + Send + Sync>>( let stdout = functions::get_module::<Box<IStdout + Send + Sync>>(
Box::from(WinApiOutput::new()), Box::from(WinApiOutput::new()),
Box::from(AnsiOutput::new()), Box::from(AnsiOutput::new()),
).unwrap(); )
.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>;

View File

@ -54,11 +54,13 @@ fn write_str_ansi() {
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 { Ok(length) => {
if str_length == length {
assert!(true) assert!(true)
} else { } else {
assert!(false) assert!(false)
}, }
}
}; };
} }

View File

@ -18,7 +18,7 @@ impl IStdout for WinApiOutput {
} }
fn write(&self, buf: &[u8]) -> io::Result<usize> { fn write(&self, buf: &[u8]) -> io::Result<usize> {
let handle = handle::get_current_handle().unwrap(); let handle = handle::get_current_out_handle().unwrap();
writing::write_char_buffer(&handle, buf) writing::write_char_buffer(&handle, buf)
} }

View File

@ -39,7 +39,8 @@ impl<'stdout> TerminalColor<'stdout> {
let color = functions::get_module::<Box<ITerminalColor + Sync + Send>>( let color = functions::get_module::<Box<ITerminalColor + Sync + Send>>(
Box::from(WinApiColor::new()), Box::from(WinApiColor::new()),
Box::from(AnsiColor::new()), Box::from(AnsiColor::new()),
).unwrap(); )
.unwrap();
#[cfg(not(target_os = "windows"))] #[cfg(not(target_os = "windows"))]
let color = Box::from(AnsiColor::new()) as Box<ITerminalColor + Sync + Send>; let color = Box::from(AnsiColor::new()) as Box<ITerminalColor + Sync + Send>;
@ -71,7 +72,8 @@ impl<'stdout> TerminalColor<'stdout> {
let color = functions::get_module::<Box<ITerminalColor + Sync + Send>>( let color = functions::get_module::<Box<ITerminalColor + Sync + Send>>(
Box::from(WinApiColor::new()), Box::from(WinApiColor::new()),
Box::from(AnsiColor::new()), Box::from(AnsiColor::new()),
).unwrap(); )
.unwrap();
#[cfg(not(target_os = "windows"))] #[cfg(not(target_os = "windows"))]
let color = Box::from(AnsiColor::new()) as Box<ITerminalColor + Sync + Send>; let color = Box::from(AnsiColor::new()) as Box<ITerminalColor + Sync + Send>;

View File

@ -111,11 +111,7 @@ pub enum Color {
Grey, Grey,
White, White,
Rgb { Rgb { r: u8, g: u8, b: u8 },
r: u8,
g: u8,
b: u8,
},
AnsiValue(u8), AnsiValue(u8),
} }

View File

@ -101,8 +101,8 @@ impl ITerminalColor for WinApiColor {
Color::White => fg_intensity | fg_red | fg_green | fg_blue, Color::White => fg_intensity | fg_red | fg_green | fg_blue,
/* WinApi will be used for systems that do not support ANSI, those are windows version less then 10. RGB and 255 (AnsiBValue) colors are not supported in that case.*/ /* WinApi will be used for systems that do not support ANSI, those are windows version less then 10. RGB and 255 (AnsiBValue) colors are not supported in that case.*/
Color::Rgb{ r: _, g: _, b: _ } => { 0 } Color::Rgb { r: _, g: _, b: _ } => 0,
Color::AnsiValue(_val) => { 0 } Color::AnsiValue(_val) => 0,
}; };
} }
ColorType::Background => { ColorType::Background => {
@ -124,8 +124,8 @@ impl ITerminalColor for WinApiColor {
Color::White => bg_intensity | bg_red | bg_green | bg_blue, Color::White => bg_intensity | bg_red | bg_green | bg_blue,
/* WinApi will be used for systems that do not support ANSI, those are windows version less then 10. RGB and 255 (AnsiBValue) colors are not supported in that case.*/ /* WinApi will be used for systems that do not support ANSI, those are windows version less then 10. RGB and 255 (AnsiBValue) colors are not supported in that case.*/
Color::Rgb{ r: _, g: _, b: _ } => { 0 } Color::Rgb { r: _, g: _, b: _ } => 0,
Color::AnsiValue(_val) => { 0 } Color::AnsiValue(_val) => 0,
}; };
} }
}; };

View File

@ -13,7 +13,7 @@ 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 super::functions; use super::functions;
use std::sync::Arc; use std::sync::Arc;

View File

@ -32,7 +32,8 @@ impl<'stdout> Terminal<'stdout> {
let terminal = functions::get_module::<Box<ITerminal + Sync + Send>>( let terminal = functions::get_module::<Box<ITerminal + Sync + Send>>(
Box::new(WinApiTerminal::new()), Box::new(WinApiTerminal::new()),
Box::new(AnsiTerminal::new()), Box::new(AnsiTerminal::new()),
).unwrap(); )
.unwrap();
#[cfg(not(target_os = "windows"))] #[cfg(not(target_os = "windows"))]
let terminal = Box::from(AnsiTerminal::new()) as Box<ITerminal + Sync + Send>; let terminal = Box::from(AnsiTerminal::new()) as Box<ITerminal + Sync + Send>;
@ -64,7 +65,8 @@ impl<'stdout> Terminal<'stdout> {
let terminal = functions::get_module::<Box<ITerminal + Sync + Send>>( let terminal = functions::get_module::<Box<ITerminal + Sync + Send>>(
Box::new(WinApiTerminal::new()), Box::new(WinApiTerminal::new()),
Box::new(AnsiTerminal::new()), Box::new(AnsiTerminal::new()),
).unwrap(); )
.unwrap();
#[cfg(not(target_os = "windows"))] #[cfg(not(target_os = "windows"))]
let terminal = Box::from(AnsiTerminal::new()) as Box<ITerminal + Sync + Send>; let terminal = Box::from(AnsiTerminal::new()) as Box<ITerminal + Sync + Send>;