Windows done with RC refactor unix yet to be tested

This commit is contained in:
TimonPost 2018-07-29 21:46:15 +02:00
commit 3a02d9b7c0
13 changed files with 95 additions and 105 deletions

View File

@ -5,23 +5,23 @@ use std::io::Result;
pub mod shared_commands; pub mod shared_commands;
#[cfg(target_os = "unix")] #[cfg(not(target_os = "windows"))]
pub mod unix_command; pub mod unix_command;
#[cfg(target_os = "windows")] #[cfg(target_os = "windows")]
pub mod win_commands; pub mod win_commands;
#[cfg(target_os = "windows")]
pub use self::win_commands::*;
#[cfg(target_os = "unix")]
pub use self::unix_commands::*;
pub use self::shared_commands::*;
/// This trait provides a way to execute some state changing commands. /// This trait provides a way to execute some state changing commands.
pub trait IStateCommand { pub trait IStateCommand {
fn execute(&mut self) -> bool; fn execute(&mut self) -> Result<()>;
fn undo(&mut self) -> bool; fn undo(&mut self) -> Result<()>;
}
pub trait IEnableAnsiCommand
{
fn enable(&mut self) -> bool;
fn disable(&mut self) -> bool;
} }
/// This trait provides an interface for switching to alternate screen and back. /// This trait provides an interface for switching to alternate screen and back.

View File

@ -8,8 +8,8 @@ use std::io::Result;
pub struct ToAlternateScreenCommand; pub struct ToAlternateScreenCommand;
impl ToAlternateScreenCommand { impl ToAlternateScreenCommand {
pub fn new() -> Box<ToAlternateScreenCommand> { pub fn new() -> ToAlternateScreenCommand {
return Box::new(ToAlternateScreenCommand {}); return ToAlternateScreenCommand {};
} }
} }

View File

@ -10,41 +10,30 @@ use std::io::{Result,Error, ErrorKind};
/// This command is used for switching to NoncanonicalMode. /// This command is used for switching to NoncanonicalMode.
#[derive(Copy, Clone)] #[derive(Copy, Clone)]
pub struct NoncanonicalModeCommand { pub struct NoncanonicalModeCommand;
key: u16,
}
impl NoncanonicalModeCommand { impl NoncanonicalModeCommand {
pub fn new(state_manager: &Mutex<StateManager>) -> u16 { pub fn new() -> NoncanonicalModeCommand {
let mut state = state_manager.lock().unwrap(); NoncanonicalModeCommand { }
{
let key = state.get_changes_count();
let command = NoncanonicalModeCommand { key: key };
state.register_change(Box::from(command), key);
key
}
} }
} }
impl IStateCommand for NoncanonicalModeCommand { impl IStateCommand for NoncanonicalModeCommand {
fn execute(&mut self) -> bool { fn execute(&mut self) -> Result<()> {
// Set noncanonical mode // Set noncanonical mode
if let Ok(orig) = Termios::from_fd(FD_STDIN) { if let Ok(orig) = Termios::from_fd(FD_STDIN) {
let mut noncan = orig.clone(); let mut noncan = orig.clone();
noncan.c_lflag &= !ICANON; noncan.c_lflag &= !ICANON;
noncan.c_lflag &= !ECHO; noncan.c_lflag &= !ECHO;
noncan.c_lflag &= !CREAD; noncan.c_lflag &= !CREAD;
match tcsetattr(FD_STDIN, TCSAFLUSH, &noncan) { tcsetattr(FD_STDIN, TCSAFLUSH, &noncan)?;
Ok(_) => return true,
Err(_) => return false,
};
} else { } else {
return false; return Err(Error::new(ErrorKind::Other,"Could not set console mode when enabling raw mode"))
} }
Ok(())
} }
fn undo(&mut self) -> bool { fn undo(&mut self) -> Result<()> {
// Disable noncanonical mode // Disable noncanonical mode
if let Ok(orig) = Termios::from_fd(FD_STDIN) { if let Ok(orig) = Termios::from_fd(FD_STDIN) {
let mut noncan = orig.clone(); let mut noncan = orig.clone();
@ -52,13 +41,11 @@ impl IStateCommand for NoncanonicalModeCommand {
noncan.c_lflag &= ECHO; noncan.c_lflag &= ECHO;
noncan.c_lflag &= CREAD; noncan.c_lflag &= CREAD;
match tcsetattr(FD_STDIN, TCSAFLUSH, &noncan) { tcsetattr(FD_STDIN, TCSAFLUSH, &noncan)?;
Ok(_) => return true,
Err(_) => return false,
};
} else { } else {
return false; return Err(Error::new(ErrorKind::Other,"Could not set console mode when enabling raw mode"))
} }
Ok(())
} }
} }

View File

@ -1,6 +1,6 @@
//! This module contains the commands that can be used for windows systems. //! This module contains the commands that can be used for windows systems.
use super::{ ScreenManager, IStateCommand, IAlternateScreenCommand, IRawScreenCommand}; use super::{ ScreenManager, IEnableAnsiCommand, IAlternateScreenCommand, IRawScreenCommand};
use kernel::windows_kernel::{ansi_support, csbi, handle, kernel}; use kernel::windows_kernel::{ansi_support, csbi, handle, kernel};
use std::mem; use std::mem;
@ -18,16 +18,16 @@ pub struct EnableAnsiCommand {
} }
impl EnableAnsiCommand { impl EnableAnsiCommand {
pub fn new() -> Box<EnableAnsiCommand> { pub fn new() -> EnableAnsiCommand {
let command = EnableAnsiCommand { let command = EnableAnsiCommand {
mask: ENABLE_VIRTUAL_TERMINAL_PROCESSING, mask: ENABLE_VIRTUAL_TERMINAL_PROCESSING,
}; };
Box::from(command) command
} }
} }
impl IStateCommand for EnableAnsiCommand { impl IEnableAnsiCommand for EnableAnsiCommand {
fn execute(&mut self) -> bool { fn enable(&mut self) -> bool {
// we need to check whether we tried to enable ansi before. If we have we can just return if that had succeeded. // we need to check whether we tried to enable ansi before. If we have we can just return if that had succeeded.
if ansi_support::has_been_tried_to_enable_ansi() && ansi_support::ansi_enabled() { if ansi_support::has_been_tried_to_enable_ansi() && ansi_support::ansi_enabled() {
return ansi_support::windows_supportable(); return ansi_support::windows_supportable();
@ -47,7 +47,7 @@ impl IStateCommand for EnableAnsiCommand {
} }
} }
fn undo(&mut self) -> bool { fn disable(&mut self) -> bool {
if ansi_support::ansi_enabled() { if ansi_support::ansi_enabled() {
let output_handle = handle::get_output_handle().unwrap(); let output_handle = handle::get_output_handle().unwrap();
@ -122,16 +122,16 @@ impl IRawScreenCommand for EnableRawModeCommand {
/// This command is used for switching to alternate screen and back to main screen. /// This command is used for switching to alternate screen and back to main screen.
/// check https://docs.microsoft.com/en-us/windows/console/reading-and-writing-blocks-of-characters-and-attributes for more info /// check https://docs.microsoft.com/en-us/windows/console/reading-and-writing-blocks-of-characters-and-attributes for more info
pub struct ToAlternateScreenBufferCommand; pub struct ToAlternateScreenCommand;
impl ToAlternateScreenBufferCommand { impl ToAlternateScreenCommand {
pub fn new() -> Box<ToAlternateScreenBufferCommand>{ pub fn new() -> ToAlternateScreenCommand{
return Box::from(ToAlternateScreenBufferCommand {}); return ToAlternateScreenCommand {};
} }
} }
impl IAlternateScreenCommand for ToAlternateScreenBufferCommand { impl IAlternateScreenCommand for ToAlternateScreenCommand {
fn to_alternate_screen(&self, screen_manager: &mut ScreenManager) -> Result<()>{ fn enable(&self, screen_manager: &mut ScreenManager) -> Result<()>{
use super::super::super::manager::WinApiScreenManager; use super::super::super::manager::WinApiScreenManager;
let handle = handle::get_output_handle()?; let handle = handle::get_output_handle()?;
@ -163,7 +163,7 @@ impl IAlternateScreenCommand for ToAlternateScreenBufferCommand {
Ok(()) Ok(())
} }
fn to_main_screen(&self, screen_manager: &mut ScreenManager) -> Result<()>{ fn disable(&self, screen_manager: &mut ScreenManager) -> Result<()>{
let handle = handle::get_output_handle()?; let handle = handle::get_output_handle()?;
csbi::set_active_screen_buffer(handle); csbi::set_active_screen_buffer(handle);

View File

@ -75,7 +75,7 @@ impl<'crossterm> Crossterm
return self.enable_alternate_screen(); return self.enable_alternate_screen();
}, },
Some(ref mut alternate_screen) => { Some(ref mut alternate_screen) => {
alternate_screen.to_alternate_screen(&mut self.active_screen)?; alternate_screen.enable(&mut self.active_screen)?;
self.alternate_mode = true; self.alternate_mode = true;
}, },
} }
@ -92,7 +92,7 @@ impl<'crossterm> Crossterm
return self.disable_alternate_screen(); return self.disable_alternate_screen();
}, },
Some(ref mut alternate_screen) => { Some(ref mut alternate_screen) => {
alternate_screen.to_main_screen(&mut self.active_screen)?; alternate_screen.disable(&mut self.active_screen)?;
self.alternate_mode = false; self.alternate_mode = false;
}, },
} }
@ -122,7 +122,7 @@ impl Drop for Crossterm
fn drop(&mut self) { fn drop(&mut self) {
if let Some(ref mut screen) = self.alternate_screen if let Some(ref mut screen) = self.alternate_screen
{ {
screen.to_main_screen(&mut self.active_screen); screen.disable(&mut self.active_screen);
} }
if let Some(ref mut raw_terminal) = self.raw_terminal if let Some(ref mut raw_terminal) = self.raw_terminal
{ {
@ -133,34 +133,34 @@ impl Drop for Crossterm
/// Wraps an displayable object so it can be formatted with colors and attributes. // Wraps an displayable object so it can be formatted with colors and attributes.
/// //
/// Check `/examples/color` in the libary for more spesific examples. // Check `/examples/color` in the libary for more spesific examples.
/// //
/// #Example // #Example
/// //
/// ```rust // ```rust
/// extern crate crossterm; // extern crate crossterm;
/// //
/// use self::crossterm::style::{paint,Color}; // use self::crossterm::style::{paint,Color};
/// //
/// fn main() // fn main()
/// { // {
/// // Create an styledobject object from the text 'Unstyled font' // // Create an styledobject object from the text 'Unstyled font'
/// // Currently it has the default foregroundcolor and backgroundcolor. // // Currently it has the default foregroundcolor and backgroundcolor.
/// println!("{}",paint("Unstyled font")); // println!("{}",paint("Unstyled font"));
/// //
/// // Create an displayable object from the text 'Colored font', // // Create an displayable object from the text 'Colored font',
/// // Paint this with the `Red` foreground color and `Blue` backgroundcolor. // // Paint this with the `Red` foreground color and `Blue` backgroundcolor.
/// // Print the result. // // Print the result.
/// let styledobject = paint("Colored font").with(Color::Red).on(Color::Blue); // let styledobject = paint("Colored font").with(Color::Red).on(Color::Blue);
/// println!("{}", styledobject); // println!("{}", styledobject);
/// //
/// // Or all in one line // // Or all in one line
/// println!("{}", paint("Colored font").with(Color::Red).on(Color::Blue)); // println!("{}", paint("Colored font").with(Color::Red).on(Color::Blue));
/// } // }
/// //
/// ``` // ```
// pub fn paint<D>(&self, val: D) -> style::StyledObject<D> // pub fn paint<D>(&self, val: D) -> style::StyledObject<D>
// where // where
// D: fmt::Display, // D: fmt::Display,

View File

@ -35,8 +35,8 @@ impl AlternateScreen {
pub fn new() -> Box<commands::IAlternateScreenCommand> { pub fn new() -> Box<commands::IAlternateScreenCommand> {
#[cfg(target_os = "windows")] #[cfg(target_os = "windows")]
let command = functions::get_module::<Box<commands::IAlternateScreenCommand>>( let command = functions::get_module::<Box<commands::IAlternateScreenCommand>>(
commands::win_commands::ToAlternateScreenBufferCommand::new(), Box::from(commands::win_commands::ToAlternateScreenCommand::new()),
commands::shared_commands::ToAlternateScreenBufferCommand::new(), Box::from(commands::shared_commands::ToAlternateScreenCommand::new()),
).unwrap(); ).unwrap();
#[cfg(not(target_os = "windows"))] #[cfg(not(target_os = "windows"))]

View File

@ -13,9 +13,10 @@
//! With these modes you can easier design the terminal screen. //! With these modes you can easier design the terminal screen.
#[cfg(not(windows))] #[cfg(not(windows))]
use common::commands::EnableRawModeCommand; use common::commands::unix_command::EnableRawModeCommand;
#[cfg(windows)] #[cfg(windows)]
use common::commands::EnableRawModeCommand; use common::commands::win_commands::EnableRawModeCommand;
use super::{functions, ScreenManager}; use super::{functions, ScreenManager};
use super::commands; use super::commands;

View File

@ -3,12 +3,18 @@
use libc; use libc;
pub use libc::termios; pub use libc::termios;
use self::libc::{c_int, c_ushort, ioctl, STDOUT_FILENO, TIOCGWINSZ}; use self::libc::{c_int, c_ushort, ioctl, STDOUT_FILENO, TIOCGWINSZ};
use common::commands::{NoncanonicalModeCommand, EnableRawModeCommand}; use common::commands::unix_command::{NoncanonicalModeCommand, EnableRawModeCommand};
use std::io::Error; use std::io::Error;
use std::os::unix::io::AsRawFd; use std::os::unix::io::AsRawFd;
use std::{fs, io, mem}; use std::{fs, io, mem};
use termios::{cfmakeraw, tcsetattr, Termios, TCSADRAIN}; use termios::{cfmakeraw, tcsetattr, Termios, TCSADRAIN};
use std::io::ErrorKind;
use std::io::Read;
use std::time::{SystemTime, Duration};
use Crossterm;
/// A representation of the size of the current terminal. /// A representation of the size of the current terminal.
#[repr(C)] #[repr(C)]
@ -41,14 +47,9 @@ pub fn terminal_size() -> (u16, u16) {
} }
} }
use std::time::{SystemTime, Duration};
use std::io::ErrorKind;
use Terminal;
use std::io::Read;
/// Get the current cursor position. /// Get the current cursor position.
pub fn pos() -> (u16, u16) { pub fn pos() -> (u16, u16) {
let crossterm = Terminal::new(); let crossterm = Crossterm::new();
let input = crossterm.input(); let input = crossterm.input();
let delimiter = b'R'; let delimiter = b'R';

View File

@ -7,14 +7,15 @@ static mut IS_ANSI_ON_WINDOWS_ENABLED: Option<bool> = None;
static mut DOES_WINDOWS_SUPPORT_ANSI: Option<bool> = None; static mut DOES_WINDOWS_SUPPORT_ANSI: Option<bool> = None;
static ENABLE_ANSI: Once = ONCE_INIT; static ENABLE_ANSI: Once = ONCE_INIT;
use common::commands::{EnableAnsiCommand, IStateCommand}; use common::commands::win_commands::{EnableAnsiCommand};
use common::commands::IEnableAnsiCommand;
/// Try enable `ANSI escape codes` and return the result. /// Try enable `ANSI escape codes` and return the result.
pub fn try_enable_ansi_support() -> bool { pub fn try_enable_ansi_support() -> bool {
ENABLE_ANSI.call_once(|| { ENABLE_ANSI.call_once(|| {
let mut command = EnableAnsiCommand::new(); let mut command = EnableAnsiCommand::new();
let success = command.execute(); let success = command.enable();
set_is_windows_ansi_supportable(success); set_is_windows_ansi_supportable(success);
set_ansi_enabled(success); set_ansi_enabled(success);

View File

@ -38,7 +38,7 @@ impl<'terminal> TerminalColor<'terminal> {
).unwrap(); ).unwrap();
#[cfg(not(target_os = "windows"))] #[cfg(not(target_os = "windows"))]
let color = AnsiColor::new() as Box<ITerminalColor>; let color = Box::from(AnsiColor::new()) as Box<ITerminalColor>;
TerminalColor { TerminalColor {
color, color,

View File

@ -5,7 +5,7 @@ use super::{ScreenManager, Color, StyledObject};
use std::fmt::Display; use std::fmt::Display;
#[cfg(unix)] #[cfg(unix)]
use super::super::Attribute; use super::Attribute;
/// Struct that contains the style properties that can be applied to an displayable object. /// Struct that contains the style properties that can be applied to an displayable object.
#[derive(Clone)] #[derive(Clone)]

View File

@ -6,7 +6,7 @@ use std::fmt::{self, Display};
use std::io::Write; use std::io::Write;
#[cfg(unix)] #[cfg(unix)]
use super::super::Attribute; use super::Attribute;
#[cfg(windows)] #[cfg(windows)]
use super::super::super::manager::WinApiScreenManager; use super::super::super::manager::WinApiScreenManager;
@ -90,55 +90,55 @@ impl<'terminal,D: Display> StyledObject<'terminal,D> {
/// Increase the font intensity. /// Increase the font intensity.
#[cfg(unix)] #[cfg(unix)]
#[inline(always)] #[inline(always)]
pub fn bold(self) -> StyledObject<D> { pub fn bold(self) -> StyledObject<'terminal,D> {
self.attr(Attribute::Bold) self.attr(Attribute::Bold)
} }
/// Faint (decreased intensity) (Not widely supported). /// Faint (decreased intensity) (Not widely supported).
#[cfg(unix)] #[cfg(unix)]
#[inline(always)] #[inline(always)]
pub fn dim(self) -> StyledObject<D> { pub fn dim(self) -> StyledObject<'terminal,D> {
self.attr(Attribute::Dim) self.attr(Attribute::Dim)
} }
/// Make the font italic (Not widely supported; Sometimes treated as inverse). /// Make the font italic (Not widely supported; Sometimes treated as inverse).
#[cfg(unix)] #[cfg(unix)]
#[inline(always)] #[inline(always)]
pub fn italic(self) -> StyledObject<D> { pub fn italic(self) -> StyledObject<'terminal,D> {
self.attr(Attribute::Italic) self.attr(Attribute::Italic)
} }
/// Underline font. /// Underline font.
#[cfg(unix)] #[cfg(unix)]
#[inline(always)] #[inline(always)]
pub fn underlined(self) -> StyledObject<D> { pub fn underlined(self) -> StyledObject<'terminal,D> {
self.attr(Attribute::Underlined) self.attr(Attribute::Underlined)
} }
/// Slow Blink (less than 150 per minute; not widely supported). /// Slow Blink (less than 150 per minute; not widely supported).
#[cfg(unix)] #[cfg(unix)]
#[inline(always)] #[inline(always)]
pub fn slow_blink(self) -> StyledObject<D> { pub fn slow_blink(self) -> StyledObject<'terminal,D> {
self.attr(Attribute::SlowBlink) self.attr(Attribute::SlowBlink)
} }
/// Rapid Blink (MS-DOS ANSI.SYS; 150+ per minute; not widely supported). /// Rapid Blink (MS-DOS ANSI.SYS; 150+ per minute; not widely supported).
#[cfg(unix)] #[cfg(unix)]
#[inline(always)] #[inline(always)]
pub fn rapid_blink(self) -> StyledObject<D> { pub fn rapid_blink(self) -> StyledObject<'terminal,D> {
self.attr(Attribute::RapidBlink) self.attr(Attribute::RapidBlink)
} }
/// Swap foreground and background colors. /// Swap foreground and background colors.
#[cfg(unix)] #[cfg(unix)]
#[inline(always)] #[inline(always)]
pub fn reverse(self) -> StyledObject<D> { pub fn reverse(self) -> StyledObject<'terminal,D> {
self.attr(Attribute::Reverse) self.attr(Attribute::Reverse)
} }
/// Hide text (Not widely supported). /// Hide text (Not widely supported).
#[cfg(unix)] #[cfg(unix)]
#[inline(always)] #[inline(always)]
pub fn hidden(self) -> StyledObject<D> { pub fn hidden(self) -> StyledObject<'terminal,D> {
self.attr(Attribute::Hidden) self.attr(Attribute::Hidden)
} }
/// Characters legible, but marked for deletion. Not widely supported. /// Characters legible, but marked for deletion. Not widely supported.
#[cfg(unix)] #[cfg(unix)]
#[inline(always)] #[inline(always)]
pub fn crossed_out(self) -> StyledObject<D> { pub fn crossed_out(self) -> StyledObject<'terminal,D> {
self.attr(Attribute::CrossedOut) self.attr(Attribute::CrossedOut)
} }
} }

View File

@ -37,7 +37,7 @@ impl<'terminal> Terminal<'terminal> {
).unwrap(); ).unwrap();
#[cfg(not(target_os = "windows"))] #[cfg(not(target_os = "windows"))]
let terminal = AnsiTerminal::new() as Box<ITerminal>; let terminal = Box::from(AnsiTerminal::new()) as Box<ITerminal>;
Terminal { Terminal {
terminal, terminal,