maked crossterm sendable for threads

This commit is contained in:
TimonPost 2018-07-31 23:05:45 +02:00
parent 14ecd33f11
commit 406f2046f9
13 changed files with 94 additions and 65 deletions

View File

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

View File

@ -1,6 +1,6 @@
//! This module contains the commands that can be used for unix systems.
use super::{IRawScreenCommand, IStateCommand};
use super::{ IStateCommand};
use kernel::unix_kernel::terminal;
use termios::{tcsetattr, Termios, CREAD, ECHO, ICANON, TCSAFLUSH};

View File

@ -1,6 +1,6 @@
//! This module contains the commands that can be used for windows systems.
use super::{IAlternateScreenCommand, IEnableAnsiCommand, IRawScreenCommand, ScreenManager};
use super::{IAlternateScreenCommand, IEnableAnsiCommand, ScreenManager};
use kernel::windows_kernel::{ansi_support, csbi, handle, kernel};
use std::mem;

View File

@ -1,7 +1,6 @@
use super::commands::{IAlternateScreenCommand, IRawScreenCommand};
use super::commands::{IAlternateScreenCommand};
use super::screen::AlternateScreen;
use super::screen::RawScreen;
use super::super::cursor;
use super::super::input;
@ -14,12 +13,23 @@ use std::io::Write;
use std::io::Result;
#[cfg(not(windows))]
use common::commands::unix_command;
#[cfg(windows)]
use common::commands::win_commands;
pub struct Crossterm {
pub active_screen: manager::ScreenManager,
raw_terminal: Option<RawScreenCommand>,
#[cfg(not(windows))]
raw_terminal: Option<unix_command::RawModeCommand>,
#[cfg(windows)]
raw_terminal: Option<win_commands::RawModeCommand>,
// Would be cool to figure out a way to have multiple screens instead of just only the main and alternate screen.
// For windows this would be easy but for unix I have no idea.
alternate_screen: Option<AlternateScreenCommand>,
alternate_screen: Option<Box<IAlternateScreenCommand + Send>>,
}
impl<'a> Crossterm {
@ -34,7 +44,13 @@ impl<'a> Crossterm {
pub fn enable_raw_mode(&mut self) -> Result<()> {
match self.raw_terminal {
None => {
self.raw_terminal = Some(RawScreen::new());
#[cfg(not(target_os = "windows"))]
let raw_terminal = Some(unix_command::RawModeCommand::new());
#[cfg(target_os = "windows")]
let raw_terminal = Some(win_commands::RawModeCommand::new());
self.raw_terminal = raw_terminal;
return self.enable_raw_mode();
}
Some(ref mut raw_terminal) => {
@ -48,7 +64,13 @@ impl<'a> Crossterm {
pub fn disable_raw_mode(&mut self) -> Result<()> {
match self.raw_terminal {
None => {
self.raw_terminal = Some(RawScreen::new());
#[cfg(not(target_os = "windows"))]
let raw_terminal = Some(unix_command::RawModeCommand::new());
#[cfg(target_os = "windows")]
let raw_terminal = Some(win_commands::RawModeCommand::new());
self.raw_terminal = raw_terminal;
return self.disable_raw_mode();
}
Some(ref mut raw_terminal) => {

View File

@ -53,7 +53,7 @@ pub fn get_module<T>(winapi_impl: T, unix_impl: T) -> Option<T> {
// Try to enable ansi on windows if not than use WINAPI.
does_support = try_enable_ansi_support();
// does_support = false;
// does_support = false;
if !does_support {
term = Some(winapi_impl);
}

View File

@ -32,9 +32,9 @@ pub struct AlternateScreen;
impl AlternateScreen {
/// Create an new alternate screen type.
pub fn new() -> Box<commands::IAlternateScreenCommand> {
pub fn new() -> Box<commands::IAlternateScreenCommand + Send> {
#[cfg(target_os = "windows")]
let command = functions::get_module::<Box<commands::IAlternateScreenCommand>>(
let command = functions::get_module::<Box<commands::IAlternateScreenCommand + Send>>(
Box::from(commands::win_commands::ToAlternateScreenCommand::new()),
Box::from(commands::shared_commands::ToAlternateScreenCommand::new()),
).unwrap();

View File

@ -6,4 +6,4 @@ mod raw;
use super::{commands, functions, ScreenManager};
pub use self::alternate::AlternateScreen;
pub use self::raw::RawScreen;
//pub use self::raw::RawScreen;

View File

@ -12,28 +12,23 @@
//!
//! With these modes you can easier design the terminal screen.
#[cfg(not(windows))]
use common::commands::unix_command::EnableRawModeCommand;
#[cfg(windows)]
use common::commands::win_commands::EnableRawModeCommand;
use super::commands;
use super::{functions, ScreenManager};
use std::io::{self, Write};
/// A wrapper for the raw terminal state. Which can be used to write to.
pub struct RawScreen;
impl RawScreen {
/// Create a new RawScreen type.
pub fn new() -> Box<commands::IRawScreenCommand> {
Box::from(EnableRawModeCommand::new())
}
}
///// Trait withs contains a method for switching into raw mode.
//pub trait IntoRawMode: Write + Sized {
// fn into_raw_mode(&self, context: Rc<Context>) -> io::Result<RawTerminal>;
//
//use super::commands;
//use super::{functions, ScreenManager};
//
//use std::io::{self, Write};
//
///// A wrapper for the raw terminal state. Which can be used to write to.
//pub struct RawScreen;
//
//impl RawScreen {
// /// Create a new RawScreen type.
// pub fn new() -> Box<commands::IRawScreenCommand> {
// Box::from(EnableRawModeCommand::new())
// }
//}
//
/////// Trait withs contains a method for switching into raw mode.
////pub trait IntoRawMode: Write + Sized {
//// fn into_raw_mode(&self, context: Rc<Context>) -> io::Result<RawTerminal>;
////}

View File

@ -4,11 +4,9 @@ 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::HANDLE;
use std::sync::Arc;
use super::super::super::manager::{ScreenManager, WinApiScreenManager};
use std::io::{self, ErrorKind, Result};
/// Get the global stored handle whits provides access to the current screen.
pub fn get_current_handle(screen_manager: &ScreenManager) -> Result<HANDLE> {
let mut mutex = screen_manager;
@ -23,11 +21,14 @@ pub fn get_current_handle(screen_manager: &ScreenManager) -> Result<HANDLE> {
None => return Err(io::Error::new(io::ErrorKind::Other,"Could not convert to winapi screen manager, this could happen when the user has an ANSI screen manager and is calling the platform specific operations 'get_cursor_pos' or 'get_terminal_size'"))
};
handle = Ok(*winapi_screen_manager.get_handle());
return handle;
}
use std::io::{self, ErrorKind, Result};
/// Get the std_output_handle of the console
pub fn get_output_handle() -> Result<HANDLE> {
unsafe {

View File

@ -6,14 +6,15 @@ use super::IScreenManager;
use std::any::Any;
use std::cell::RefCell;
use std::io::{self, Read, Write};
use std::sync::{Arc,Mutex};
use std::io::{self, Read, Write,Stdout};
use std::str::from_utf8;
/// This struct is an ANSI escape code implementation for screen related actions.
pub struct AnsiScreenManager {
is_alternate_screen: bool,
is_raw_screen: bool,
output: RefCell<Box<Write>>,
output: Box<Stdout>,
}
impl IScreenManager for AnsiScreenManager {
@ -34,22 +35,27 @@ impl IScreenManager for AnsiScreenManager {
}
fn write_str(&self, string: &str) -> io::Result<usize> {
let mut output = self.output.borrow_mut();
write!(output, "{}", string)?;
let out = &self.output;
let mut handle = out.lock();
write!(handle, "{}", string)?;
Ok(0)
}
fn write(&self, buf: &[u8]) -> io::Result<usize> {
{
let mut output = self.output.borrow_mut();
output.write(buf)?;
let out = &self.output;
let mut handle = out.lock();
handle.write(buf)?;
}
Ok(0)
}
fn flush(&self) -> io::Result<()> {
let mut output = self.output.borrow_mut();
output.flush()
let out = &self.output;
let mut handle = out.lock();
handle.flush();
Ok(())
}
fn as_any(&self) -> &Any {
@ -64,7 +70,7 @@ impl IScreenManager for AnsiScreenManager {
impl AnsiScreenManager {
pub fn new() -> Self {
AnsiScreenManager {
output: RefCell::new(Box::from(io::stdout()) as Box<Write>),
output: Box::from(io::stdout()),
is_alternate_screen: false,
is_raw_screen: false,
}

View File

@ -36,13 +36,13 @@ impl ScreenManager {
/// Create new screen manager instance whereon screen related actions can be performed.
pub fn new() -> ScreenManager {
#[cfg(target_os = "windows")]
let screen_manager = functions::get_module::<Box<IScreenManager>>(
let screen_manager = functions::get_module::<Box<IScreenManager + Send>>(
Box::from(WinApiScreenManager::new()),
Box::from(AnsiScreenManager::new()),
).unwrap();
#[cfg(not(target_os = "windows"))]
let screen_manager = Box::from(AnsiScreenManager::new()) as Box<IScreenManager>;
let screen_manager = Box::from(AnsiScreenManager::new()) as Box<IScreenManager + Send>;
ScreenManager { screen_manager }
}

View File

@ -3,8 +3,10 @@ use kernel::windows_kernel::{handle, kernel, writing};
use winapi::um::wincon::ENABLE_PROCESSED_OUTPUT;
use winapi::um::winnt::HANDLE;
use std::ptr::NonNull;
use std::any::Any;
use std::io::{self, Write};
use std::sync::Arc;
/// This struct is an WINAPI implementation for screen related actions.
pub struct WinApiScreenManager {
@ -59,11 +61,12 @@ impl IScreenManager for WinApiScreenManager {
impl WinApiScreenManager {
/// Create a new instance.
pub fn new() -> Self {
WinApiScreenManager {
output: handle::get_output_handle().unwrap(),
alternate_handle: handle::get_output_handle().unwrap(),
is_alternate_screen: false,
is_raw_screen: false,
alternate_handle: handle::get_output_handle().unwrap(),
}
}
@ -83,3 +86,5 @@ impl WinApiScreenManager {
}
}
}
unsafe impl Send for WinApiScreenManager {}

View File

@ -66,8 +66,8 @@ impl<'terminal> Terminal<'terminal> {
/// term.clear(terminal::ClearType::UntilNewLine);
///
/// ```
pub fn clear(&self, clear_type: ClearType) {
self.terminal.clear(clear_type, &self.screen_manager);
pub fn clear(&mut self, clear_type: ClearType) {
self.terminal.clear(clear_type, &mut self.screen_manager);
}
/// Get the terminal size (x,y).