Added Sync markers
This commit is contained in:
parent
b98f549a73
commit
c848beb721
@ -12,7 +12,7 @@ readme = "README.md"
|
|||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
[target.'cfg(windows)'.dependencies]
|
[target.'cfg(windows)'.dependencies]
|
||||||
winapi = { version = "0.3.5", features = ["winbase","winuser","consoleapi","processenv","wincon", "handleapi"] }
|
winapi = { version = "0.3.5", features = ["winbase","winuser","consoleapi","processenv","wincon", "handleapi","errhandlingapi"] }
|
||||||
|
|
||||||
[target.'cfg(unix)'.dependencies]
|
[target.'cfg(unix)'.dependencies]
|
||||||
libc = "0.2.37"
|
libc = "0.2.37"
|
||||||
|
@ -16,18 +16,22 @@ mod some_types;
|
|||||||
mod input;
|
mod input;
|
||||||
|
|
||||||
use std::io::Write;
|
use std::io::Write;
|
||||||
|
use std::{thread,time};
|
||||||
fn main()
|
fn main()
|
||||||
{
|
{
|
||||||
// use crossterm::screen::RawScreen;
|
use crossterm::screen::RawScreen;
|
||||||
// use crossterm::Screen;
|
use crossterm::Screen;
|
||||||
//
|
|
||||||
// let mut screen = Screen::new(true);
|
let mut screen = Screen::new(true);
|
||||||
//
|
|
||||||
|
cursor::goto();
|
||||||
|
|
||||||
// write!(screen, "text \n\r");
|
// write!(screen, "text \n\r");
|
||||||
// let a = screen.enable_alternate_modes(true).unwrap();
|
let a = screen.enable_alternate_modes(true).unwrap();
|
||||||
|
// cursor::goto();
|
||||||
|
thread::sleep(time::Duration::from_millis(2000));
|
||||||
|
drop(a);
|
||||||
|
cursor::goto();
|
||||||
//
|
//
|
||||||
// write!(a, "text \n\r");
|
// write!(a, "text \n\r");
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -23,13 +23,13 @@ pub trait IEnableAnsiCommand {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// This trait provides an interface for switching to alternate screen and back.
|
// This trait provides an interface for switching to alternate screen and back.
|
||||||
pub trait IAlternateScreenCommand: Send {
|
pub trait IAlternateScreenCommand: Sync + Send {
|
||||||
fn enable(&self, stdout: &mut TerminalOutput) -> io::Result<()>;
|
fn enable(&self, stdout: &mut TerminalOutput) -> io::Result<()>;
|
||||||
fn disable(&self, stdout: &TerminalOutput) -> io::Result<()>;
|
fn disable(&self, stdout: &TerminalOutput) -> io::Result<()>;
|
||||||
}
|
}
|
||||||
|
|
||||||
// This trait provides an interface for switching to raw mode and back.
|
// This trait provides an interface for switching to raw mode and back.
|
||||||
pub trait IRawScreenCommand: Send{
|
pub trait IRawScreenCommand: Sync + Send{
|
||||||
fn enable(&mut self) -> io::Result<()>;
|
fn enable(&mut self) -> io::Result<()>;
|
||||||
fn disable(&self) -> io::Result<()>;
|
fn disable(&self) -> io::Result<()>;
|
||||||
}
|
}
|
||||||
|
@ -87,9 +87,8 @@ impl RawModeCommand
|
|||||||
impl RawModeCommand {
|
impl RawModeCommand {
|
||||||
/// Enables raw mode.
|
/// Enables raw mode.
|
||||||
pub fn enable(&mut self) -> Result<()> {
|
pub fn enable(&mut self) -> Result<()> {
|
||||||
|
|
||||||
let mut dw_mode: DWORD = 0;
|
let mut dw_mode: DWORD = 0;
|
||||||
let stdout = handle::get_output_handle().unwrap();
|
let stdout = handle::get_current_handle_1().unwrap();
|
||||||
|
|
||||||
if !kernel::get_console_mode(&stdout, &mut dw_mode) {
|
if !kernel::get_console_mode(&stdout, &mut dw_mode) {
|
||||||
return Err(Error::new(
|
return Err(Error::new(
|
||||||
@ -112,7 +111,7 @@ impl RawModeCommand {
|
|||||||
|
|
||||||
/// Disables raw mode.
|
/// Disables raw mode.
|
||||||
pub fn disable(&self) -> Result<()> {
|
pub fn disable(&self) -> Result<()> {
|
||||||
let stdout = handle::get_output_handle().unwrap();
|
let stdout = handle::get_current_handle_1().unwrap();
|
||||||
|
|
||||||
let mut dw_mode: DWORD = 0;
|
let mut dw_mode: DWORD = 0;
|
||||||
if !kernel::get_console_mode(&stdout, &mut dw_mode) {
|
if !kernel::get_console_mode(&stdout, &mut dw_mode) {
|
||||||
|
@ -41,10 +41,10 @@ pub fn get_module<T>(winapi_impl: T, unix_impl: T) -> Option<T> {
|
|||||||
if !windows_supportable()
|
if !windows_supportable()
|
||||||
{
|
{
|
||||||
// Try to enable ansi on windows if not than use WINAPI.
|
// Try to enable ansi on windows if not than use WINAPI.
|
||||||
does_support = try_enable_ansi_support();
|
// does_support = try_enable_ansi_support();
|
||||||
|
|
||||||
// uncomment this line when you want to use the winapi implementation.
|
// uncomment this line when you want to use the winapi implementation.
|
||||||
does_support = true;
|
does_support = false;
|
||||||
if !does_support {
|
if !does_support {
|
||||||
term = Some(winapi_impl);
|
term = Some(winapi_impl);
|
||||||
}
|
}
|
||||||
|
@ -15,14 +15,14 @@ use std::convert::From;
|
|||||||
/// With this type you will be able to switch to alternate screen and back to main screen.
|
/// With this type you will be able to switch to alternate screen and back to main screen.
|
||||||
pub struct AlternateScreen
|
pub struct AlternateScreen
|
||||||
{
|
{
|
||||||
command: Box<IAlternateScreenCommand + Send>,
|
command: Box<IAlternateScreenCommand + Sync + Send>,
|
||||||
pub screen: Screen,
|
pub screen: Screen,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AlternateScreen {
|
impl AlternateScreen {
|
||||||
|
|
||||||
/// Create new instance of alternate screen.
|
/// Create new instance of alternate screen.
|
||||||
pub fn new(command: Box<IAlternateScreenCommand + Send>, screen: Screen) -> Self
|
pub fn new(command: Box<IAlternateScreenCommand + Sync + Send>, screen: Screen) -> Self
|
||||||
{
|
{
|
||||||
return AlternateScreen { command, screen }
|
return AlternateScreen { command, screen }
|
||||||
}
|
}
|
||||||
@ -37,7 +37,7 @@ impl AlternateScreen {
|
|||||||
pub fn to_alternate_screen(stdout: TerminalOutput, raw_mode: bool) -> io::Result<AlternateScreen> {
|
pub fn to_alternate_screen(stdout: TerminalOutput, raw_mode: bool) -> io::Result<AlternateScreen> {
|
||||||
|
|
||||||
#[cfg(target_os = "windows")]
|
#[cfg(target_os = "windows")]
|
||||||
let command = functions::get_module::<Box<commands::IAlternateScreenCommand + Send>>(
|
let command = 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();
|
||||||
|
@ -3,27 +3,76 @@
|
|||||||
use winapi::um::handleapi::INVALID_HANDLE_VALUE;
|
use winapi::um::handleapi::INVALID_HANDLE_VALUE;
|
||||||
use winapi::um::processenv::GetStdHandle;
|
use winapi::um::processenv::GetStdHandle;
|
||||||
use winapi::um::winbase::{STD_INPUT_HANDLE, STD_OUTPUT_HANDLE};
|
use winapi::um::winbase::{STD_INPUT_HANDLE, STD_OUTPUT_HANDLE};
|
||||||
|
use winapi::um::winnt::{GENERIC_READ, GENERIC_WRITE, GENERIC_ALL, FILE_SHARE_WRITE};
|
||||||
|
use winapi::um::fileapi::{OPEN_EXISTING, CreateFileW};
|
||||||
|
use winapi::shared::minwindef::DWORD;
|
||||||
|
use winapi::um::errhandlingapi::GetLastError;
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use std::io::{self, Result};
|
use std::io::{self, Result};
|
||||||
|
use std::ptr::null_mut;
|
||||||
|
|
||||||
|
use winapi::ctypes::c_void;
|
||||||
|
|
||||||
/// Get the global stored handle whits provides access to the current screen.
|
/// Get the global stored handle whits provides access to the current screen.
|
||||||
pub fn get_current_handle(stdout: &Arc<TerminalOutput>) -> Result<HANDLE> {
|
pub fn get_current_handle(stdout: &Arc<TerminalOutput>) -> Result<HANDLE> {
|
||||||
|
// let handle: Result<HANDLE>;
|
||||||
|
//
|
||||||
|
// let winapi_stdout: &WinApiOutput = match stdout
|
||||||
|
// .as_any()
|
||||||
|
// .downcast_ref::<WinApiOutput>()
|
||||||
|
// {
|
||||||
|
// Some(win_api) => win_api,
|
||||||
|
// None => return Err(io::Error::new(io::ErrorKind::Other,"Could not convert to winapi screen write, this could happen when the user has an ANSI screen write and is calling the platform specific operations 'get_cursor_pos' or 'get_terminal_size'"))
|
||||||
|
// };
|
||||||
|
|
||||||
|
let dw: DWORD = 0;
|
||||||
|
unsafe {
|
||||||
|
|
||||||
|
let utf16: Vec<u16> = "CONOUT$".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());
|
||||||
|
|
||||||
|
if !is_valid_handle(&handle) {
|
||||||
|
|
||||||
|
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(),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(handle)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_current_handle_1() -> Result<HANDLE>
|
||||||
|
{
|
||||||
let handle: Result<HANDLE>;
|
let handle: Result<HANDLE>;
|
||||||
|
use std::str;
|
||||||
|
unsafe
|
||||||
|
{
|
||||||
|
let dw: DWORD = 0;
|
||||||
|
|
||||||
let winapi_stdout: &WinApiOutput = match stdout
|
let utf16: Vec<u16> = "CONOUT$".encode_utf16().collect();
|
||||||
.as_any()
|
let utf16_ptr: *const u16 = utf16.as_ptr();
|
||||||
.downcast_ref::<WinApiOutput>()
|
|
||||||
{
|
|
||||||
Some(win_api) => win_api,
|
|
||||||
None => return Err(io::Error::new(io::ErrorKind::Other,"Could not convert to winapi screen write, this could happen when the user has an ANSI screen write and is calling the platform specific operations 'get_cursor_pos' or 'get_terminal_size'"))
|
|
||||||
};
|
|
||||||
|
|
||||||
|
let handle = CreateFileW(utf16_ptr, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_WRITE, null_mut(), OPEN_EXISTING,dw, null_mut());
|
||||||
|
|
||||||
handle = Ok(winapi_stdout.get_handle());
|
if !is_valid_handle(&handle) {
|
||||||
|
return Err(io::Error::new(
|
||||||
|
io::ErrorKind::Other,
|
||||||
|
"Could not get output handle 1 !",
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
return handle;
|
Ok(handle)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the std_output_handle of the console
|
/// Get the std_output_handle of the console
|
||||||
|
@ -28,7 +28,7 @@ use Screen;
|
|||||||
/// ```
|
/// ```
|
||||||
pub struct TerminalCursor<'stdout> {
|
pub struct TerminalCursor<'stdout> {
|
||||||
screen: &'stdout Arc<TerminalOutput>,
|
screen: &'stdout Arc<TerminalOutput>,
|
||||||
terminal_cursor: Box<ITerminalCursor>,
|
terminal_cursor: Box<ITerminalCursor + Sync + Send>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'stdout> TerminalCursor<'stdout> {
|
impl<'stdout> TerminalCursor<'stdout> {
|
||||||
@ -36,11 +36,11 @@ impl<'stdout> TerminalCursor<'stdout> {
|
|||||||
pub fn new(screen: &'stdout Arc<TerminalOutput>) -> TerminalCursor<'stdout> {
|
pub fn new(screen: &'stdout Arc<TerminalOutput>) -> TerminalCursor<'stdout> {
|
||||||
#[cfg(target_os = "windows")]
|
#[cfg(target_os = "windows")]
|
||||||
let cursor =
|
let cursor =
|
||||||
functions::get_module::<Box<ITerminalCursor>>(WinApiCursor::new(), AnsiCursor::new())
|
functions::get_module::<Box<ITerminalCursor + Sync + Send>>(WinApiCursor::new(), AnsiCursor::new())
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
#[cfg(not(target_os = "windows"))]
|
#[cfg(not(target_os = "windows"))]
|
||||||
let cursor = AnsiCursor::new() as Box<ITerminalCursor>;
|
let cursor = AnsiCursor::new() as Box<ITerminalCursor + Sync + Send>;
|
||||||
|
|
||||||
TerminalCursor {
|
TerminalCursor {
|
||||||
terminal_cursor: cursor,
|
terminal_cursor: cursor,
|
||||||
|
@ -25,7 +25,7 @@ use std::sync::Arc;
|
|||||||
///!
|
///!
|
||||||
///! This trait is implemented for `WINAPI` (Windows specific) and `ANSI` (Unix specific),
|
///! This trait is implemented for `WINAPI` (Windows specific) and `ANSI` (Unix specific),
|
||||||
///! so that cursor related actions can be preformed on both unix and windows systems.
|
///! so that cursor related actions can be preformed on both unix and windows systems.
|
||||||
trait ITerminalCursor {
|
trait ITerminalCursor : Sync + Send {
|
||||||
/// Goto some location (x,y) in the context.
|
/// Goto some location (x,y) in the context.
|
||||||
fn goto(&self, x: u16, y: u16, stdout: &Arc<TerminalOutput>);
|
fn goto(&self, x: u16, y: u16, stdout: &Arc<TerminalOutput>);
|
||||||
/// Get the location (x,y) of the current cusror in the context
|
/// Get the location (x,y) of the current cusror in the context
|
||||||
|
@ -20,7 +20,7 @@ use Screen;
|
|||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
pub struct TerminalInput<'stdout> {
|
pub struct TerminalInput<'stdout> {
|
||||||
terminal_input: Box<ITerminalInput>,
|
terminal_input: Box<ITerminalInput + Sync + Send>,
|
||||||
stdout: &'stdout Arc<TerminalOutput>,
|
stdout: &'stdout Arc<TerminalOutput>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -27,7 +27,7 @@ use Screen;
|
|||||||
/// colored_terminal.reset();
|
/// colored_terminal.reset();
|
||||||
/// ```
|
/// ```
|
||||||
pub struct TerminalColor<'stdout> {
|
pub struct TerminalColor<'stdout> {
|
||||||
color: Box<ITerminalColor>,
|
color: Box<ITerminalColor + Sync + Send>,
|
||||||
stdout: &'stdout Arc<TerminalOutput>,
|
stdout: &'stdout Arc<TerminalOutput>,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -35,13 +35,13 @@ impl<'stdout> TerminalColor<'stdout> {
|
|||||||
/// Create new instance whereon color related actions can be performed.
|
/// Create new instance whereon color related actions can be performed.
|
||||||
pub fn new(stdout: &'stdout Arc<TerminalOutput>) -> TerminalColor<'stdout> {
|
pub fn new(stdout: &'stdout Arc<TerminalOutput>) -> TerminalColor<'stdout> {
|
||||||
#[cfg(target_os = "windows")]
|
#[cfg(target_os = "windows")]
|
||||||
let color = functions::get_module::<Box<ITerminalColor>>(
|
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>;
|
let color = Box::from(AnsiColor::new()) as Box<ITerminalColor + Sync + Send>;
|
||||||
|
|
||||||
TerminalColor {
|
TerminalColor {
|
||||||
color,
|
color,
|
||||||
|
@ -21,7 +21,7 @@ use std::fmt;
|
|||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
pub struct Terminal<'stdout> {
|
pub struct Terminal<'stdout> {
|
||||||
terminal: Box<ITerminal>,
|
terminal: Box<ITerminal + Sync + Send>,
|
||||||
screen: &'stdout Arc<TerminalOutput>,
|
screen: &'stdout Arc<TerminalOutput>,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -29,13 +29,13 @@ impl<'stdout> Terminal<'stdout> {
|
|||||||
/// Create new terminal instance whereon terminal related actions can be performed.
|
/// Create new terminal instance whereon terminal related actions can be performed.
|
||||||
pub fn new(screen: &'stdout Arc<TerminalOutput>) -> Terminal<'stdout> {
|
pub fn new(screen: &'stdout Arc<TerminalOutput>) -> Terminal<'stdout> {
|
||||||
#[cfg(target_os = "windows")]
|
#[cfg(target_os = "windows")]
|
||||||
let terminal = functions::get_module::<Box<ITerminal>>(
|
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>;
|
let terminal = Box::from(AnsiTerminal::new()) as Box<ITerminal + Sync + Send>;
|
||||||
|
|
||||||
Terminal {
|
Terminal {
|
||||||
terminal,
|
terminal,
|
||||||
|
Loading…
Reference in New Issue
Block a user