maked crossterm sendable for threads
This commit is contained in:
parent
14ecd33f11
commit
406f2046f9
@ -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<()>;
|
||||
|
@ -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};
|
||||
|
||||
|
@ -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;
|
||||
@ -142,7 +142,7 @@ impl ToAlternateScreenCommand {
|
||||
}
|
||||
}
|
||||
|
||||
impl IAlternateScreenCommand for ToAlternateScreenCommand {
|
||||
impl IAlternateScreenCommand for ToAlternateScreenCommand {
|
||||
fn enable(&self, screen_manager: &mut ScreenManager) -> Result<()> {
|
||||
use super::super::super::manager::WinApiScreenManager;
|
||||
|
||||
|
@ -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) => {
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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();
|
||||
|
@ -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;
|
||||
|
@ -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>;
|
||||
////}
|
||||
|
@ -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;
|
||||
@ -16,18 +14,21 @@ pub fn get_current_handle(screen_manager: &ScreenManager) -> Result<HANDLE> {
|
||||
let handle: Result<HANDLE>;
|
||||
|
||||
let winapi_screen_manager: &WinApiScreenManager = match screen_manager
|
||||
.as_any()
|
||||
.downcast_ref::<WinApiScreenManager>()
|
||||
{
|
||||
Some(win_api) => win_api,
|
||||
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'"))
|
||||
};
|
||||
.as_any()
|
||||
.downcast_ref::<WinApiScreenManager>()
|
||||
{
|
||||
Some(win_api) => win_api,
|
||||
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 {
|
||||
|
@ -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,
|
||||
}
|
||||
|
@ -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 }
|
||||
}
|
||||
|
@ -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(),
|
||||
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 {}
|
||||
|
@ -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).
|
||||
|
Loading…
Reference in New Issue
Block a user