Windows done with RC refactor unix yet to be tested
This commit is contained in:
commit
3a02d9b7c0
@ -5,23 +5,23 @@ use std::io::Result;
|
||||
|
||||
pub mod shared_commands;
|
||||
|
||||
#[cfg(target_os = "unix")]
|
||||
#[cfg(not(target_os = "windows"))]
|
||||
pub mod unix_command;
|
||||
|
||||
#[cfg(target_os = "windows")]
|
||||
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.
|
||||
pub trait IStateCommand {
|
||||
fn execute(&mut self) -> bool;
|
||||
fn undo(&mut self) -> bool;
|
||||
fn execute(&mut self) -> Result<()>;
|
||||
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.
|
||||
|
@ -8,8 +8,8 @@ use std::io::Result;
|
||||
pub struct ToAlternateScreenCommand;
|
||||
|
||||
impl ToAlternateScreenCommand {
|
||||
pub fn new() -> Box<ToAlternateScreenCommand> {
|
||||
return Box::new(ToAlternateScreenCommand {});
|
||||
pub fn new() -> ToAlternateScreenCommand {
|
||||
return ToAlternateScreenCommand {};
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -10,41 +10,30 @@ use std::io::{Result,Error, ErrorKind};
|
||||
|
||||
/// This command is used for switching to NoncanonicalMode.
|
||||
#[derive(Copy, Clone)]
|
||||
pub struct NoncanonicalModeCommand {
|
||||
key: u16,
|
||||
}
|
||||
pub struct NoncanonicalModeCommand;
|
||||
|
||||
impl NoncanonicalModeCommand {
|
||||
pub fn new(state_manager: &Mutex<StateManager>) -> u16 {
|
||||
let mut state = state_manager.lock().unwrap();
|
||||
{
|
||||
let key = state.get_changes_count();
|
||||
let command = NoncanonicalModeCommand { key: key };
|
||||
|
||||
state.register_change(Box::from(command), key);
|
||||
key
|
||||
}
|
||||
pub fn new() -> NoncanonicalModeCommand {
|
||||
NoncanonicalModeCommand { }
|
||||
}
|
||||
}
|
||||
|
||||
impl IStateCommand for NoncanonicalModeCommand {
|
||||
fn execute(&mut self) -> bool {
|
||||
fn execute(&mut self) -> Result<()> {
|
||||
// Set noncanonical mode
|
||||
if let Ok(orig) = Termios::from_fd(FD_STDIN) {
|
||||
let mut noncan = orig.clone();
|
||||
noncan.c_lflag &= !ICANON;
|
||||
noncan.c_lflag &= !ECHO;
|
||||
noncan.c_lflag &= !CREAD;
|
||||
match tcsetattr(FD_STDIN, TCSAFLUSH, &noncan) {
|
||||
Ok(_) => return true,
|
||||
Err(_) => return false,
|
||||
};
|
||||
tcsetattr(FD_STDIN, TCSAFLUSH, &noncan)?;
|
||||
} 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
|
||||
if let Ok(orig) = Termios::from_fd(FD_STDIN) {
|
||||
let mut noncan = orig.clone();
|
||||
@ -52,13 +41,11 @@ impl IStateCommand for NoncanonicalModeCommand {
|
||||
noncan.c_lflag &= ECHO;
|
||||
noncan.c_lflag &= CREAD;
|
||||
|
||||
match tcsetattr(FD_STDIN, TCSAFLUSH, &noncan) {
|
||||
Ok(_) => return true,
|
||||
Err(_) => return false,
|
||||
};
|
||||
tcsetattr(FD_STDIN, TCSAFLUSH, &noncan)?;
|
||||
} else {
|
||||
return false;
|
||||
return Err(Error::new(ErrorKind::Other,"Could not set console mode when enabling raw mode"))
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
//! 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 std::mem;
|
||||
@ -18,16 +18,16 @@ pub struct EnableAnsiCommand {
|
||||
}
|
||||
|
||||
impl EnableAnsiCommand {
|
||||
pub fn new() -> Box<EnableAnsiCommand> {
|
||||
pub fn new() -> EnableAnsiCommand {
|
||||
let command = EnableAnsiCommand {
|
||||
mask: ENABLE_VIRTUAL_TERMINAL_PROCESSING,
|
||||
};
|
||||
Box::from(command)
|
||||
command
|
||||
}
|
||||
}
|
||||
|
||||
impl IStateCommand for EnableAnsiCommand {
|
||||
fn execute(&mut self) -> bool {
|
||||
impl IEnableAnsiCommand for EnableAnsiCommand {
|
||||
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.
|
||||
if ansi_support::has_been_tried_to_enable_ansi() && ansi_support::ansi_enabled() {
|
||||
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() {
|
||||
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.
|
||||
/// 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 {
|
||||
pub fn new() -> Box<ToAlternateScreenBufferCommand>{
|
||||
return Box::from(ToAlternateScreenBufferCommand {});
|
||||
impl ToAlternateScreenCommand {
|
||||
pub fn new() -> ToAlternateScreenCommand{
|
||||
return ToAlternateScreenCommand {};
|
||||
}
|
||||
}
|
||||
|
||||
impl IAlternateScreenCommand for ToAlternateScreenBufferCommand {
|
||||
fn to_alternate_screen(&self, screen_manager: &mut ScreenManager) -> Result<()>{
|
||||
impl IAlternateScreenCommand for ToAlternateScreenCommand {
|
||||
fn enable(&self, screen_manager: &mut ScreenManager) -> Result<()>{
|
||||
use super::super::super::manager::WinApiScreenManager;
|
||||
|
||||
let handle = handle::get_output_handle()?;
|
||||
@ -163,7 +163,7 @@ impl IAlternateScreenCommand for ToAlternateScreenBufferCommand {
|
||||
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()?;
|
||||
csbi::set_active_screen_buffer(handle);
|
||||
|
||||
|
@ -75,7 +75,7 @@ impl<'crossterm> Crossterm
|
||||
return self.enable_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;
|
||||
},
|
||||
}
|
||||
@ -92,7 +92,7 @@ impl<'crossterm> Crossterm
|
||||
return self.disable_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;
|
||||
},
|
||||
}
|
||||
@ -122,7 +122,7 @@ impl Drop for Crossterm
|
||||
fn drop(&mut self) {
|
||||
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
|
||||
{
|
||||
@ -133,34 +133,34 @@ impl Drop for Crossterm
|
||||
|
||||
|
||||
|
||||
/// Wraps an displayable object so it can be formatted with colors and attributes.
|
||||
///
|
||||
/// Check `/examples/color` in the libary for more spesific examples.
|
||||
///
|
||||
/// #Example
|
||||
///
|
||||
/// ```rust
|
||||
/// extern crate crossterm;
|
||||
///
|
||||
/// use self::crossterm::style::{paint,Color};
|
||||
///
|
||||
/// fn main()
|
||||
/// {
|
||||
/// // Create an styledobject object from the text 'Unstyled font'
|
||||
/// // Currently it has the default foregroundcolor and backgroundcolor.
|
||||
/// println!("{}",paint("Unstyled font"));
|
||||
///
|
||||
/// // Create an displayable object from the text 'Colored font',
|
||||
/// // Paint this with the `Red` foreground color and `Blue` backgroundcolor.
|
||||
/// // Print the result.
|
||||
/// let styledobject = paint("Colored font").with(Color::Red).on(Color::Blue);
|
||||
/// println!("{}", styledobject);
|
||||
///
|
||||
/// // Or all in one line
|
||||
/// println!("{}", paint("Colored font").with(Color::Red).on(Color::Blue));
|
||||
/// }
|
||||
///
|
||||
/// ```
|
||||
// Wraps an displayable object so it can be formatted with colors and attributes.
|
||||
//
|
||||
// Check `/examples/color` in the libary for more spesific examples.
|
||||
//
|
||||
// #Example
|
||||
//
|
||||
// ```rust
|
||||
// extern crate crossterm;
|
||||
//
|
||||
// use self::crossterm::style::{paint,Color};
|
||||
//
|
||||
// fn main()
|
||||
// {
|
||||
// // Create an styledobject object from the text 'Unstyled font'
|
||||
// // Currently it has the default foregroundcolor and backgroundcolor.
|
||||
// println!("{}",paint("Unstyled font"));
|
||||
//
|
||||
// // Create an displayable object from the text 'Colored font',
|
||||
// // Paint this with the `Red` foreground color and `Blue` backgroundcolor.
|
||||
// // Print the result.
|
||||
// let styledobject = paint("Colored font").with(Color::Red).on(Color::Blue);
|
||||
// println!("{}", styledobject);
|
||||
//
|
||||
// // Or all in one line
|
||||
// println!("{}", paint("Colored font").with(Color::Red).on(Color::Blue));
|
||||
// }
|
||||
//
|
||||
// ```
|
||||
// pub fn paint<D>(&self, val: D) -> style::StyledObject<D>
|
||||
// where
|
||||
// D: fmt::Display,
|
||||
|
@ -35,8 +35,8 @@ impl AlternateScreen {
|
||||
pub fn new() -> Box<commands::IAlternateScreenCommand> {
|
||||
#[cfg(target_os = "windows")]
|
||||
let command = functions::get_module::<Box<commands::IAlternateScreenCommand>>(
|
||||
commands::win_commands::ToAlternateScreenBufferCommand::new(),
|
||||
commands::shared_commands::ToAlternateScreenBufferCommand::new(),
|
||||
Box::from(commands::win_commands::ToAlternateScreenCommand::new()),
|
||||
Box::from(commands::shared_commands::ToAlternateScreenCommand::new()),
|
||||
).unwrap();
|
||||
|
||||
#[cfg(not(target_os = "windows"))]
|
||||
|
@ -13,9 +13,10 @@
|
||||
//! With these modes you can easier design the terminal screen.
|
||||
|
||||
#[cfg(not(windows))]
|
||||
use common::commands::EnableRawModeCommand;
|
||||
use common::commands::unix_command::EnableRawModeCommand;
|
||||
|
||||
#[cfg(windows)]
|
||||
use common::commands::EnableRawModeCommand;
|
||||
use common::commands::win_commands::EnableRawModeCommand;
|
||||
|
||||
use super::{functions, ScreenManager};
|
||||
use super::commands;
|
||||
|
@ -3,12 +3,18 @@
|
||||
use libc;
|
||||
pub use libc::termios;
|
||||
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::os::unix::io::AsRawFd;
|
||||
use std::{fs, io, mem};
|
||||
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.
|
||||
#[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.
|
||||
pub fn pos() -> (u16, u16) {
|
||||
let crossterm = Terminal::new();
|
||||
let crossterm = Crossterm::new();
|
||||
let input = crossterm.input();
|
||||
|
||||
let delimiter = b'R';
|
||||
|
@ -7,14 +7,15 @@ static mut IS_ANSI_ON_WINDOWS_ENABLED: Option<bool> = None;
|
||||
static mut DOES_WINDOWS_SUPPORT_ANSI: Option<bool> = None;
|
||||
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.
|
||||
pub fn try_enable_ansi_support() -> bool {
|
||||
ENABLE_ANSI.call_once(|| {
|
||||
|
||||
let mut command = EnableAnsiCommand::new();
|
||||
let success = command.execute();
|
||||
let success = command.enable();
|
||||
|
||||
set_is_windows_ansi_supportable(success);
|
||||
set_ansi_enabled(success);
|
||||
|
@ -38,7 +38,7 @@ impl<'terminal> TerminalColor<'terminal> {
|
||||
).unwrap();
|
||||
|
||||
#[cfg(not(target_os = "windows"))]
|
||||
let color = AnsiColor::new() as Box<ITerminalColor>;
|
||||
let color = Box::from(AnsiColor::new()) as Box<ITerminalColor>;
|
||||
|
||||
TerminalColor {
|
||||
color,
|
||||
|
@ -5,7 +5,7 @@ use super::{ScreenManager, Color, StyledObject};
|
||||
use std::fmt::Display;
|
||||
|
||||
#[cfg(unix)]
|
||||
use super::super::Attribute;
|
||||
use super::Attribute;
|
||||
|
||||
/// Struct that contains the style properties that can be applied to an displayable object.
|
||||
#[derive(Clone)]
|
||||
|
@ -6,7 +6,7 @@ use std::fmt::{self, Display};
|
||||
use std::io::Write;
|
||||
|
||||
#[cfg(unix)]
|
||||
use super::super::Attribute;
|
||||
use super::Attribute;
|
||||
|
||||
#[cfg(windows)]
|
||||
use super::super::super::manager::WinApiScreenManager;
|
||||
@ -90,55 +90,55 @@ impl<'terminal,D: Display> StyledObject<'terminal,D> {
|
||||
/// Increase the font intensity.
|
||||
#[cfg(unix)]
|
||||
#[inline(always)]
|
||||
pub fn bold(self) -> StyledObject<D> {
|
||||
pub fn bold(self) -> StyledObject<'terminal,D> {
|
||||
self.attr(Attribute::Bold)
|
||||
}
|
||||
/// Faint (decreased intensity) (Not widely supported).
|
||||
#[cfg(unix)]
|
||||
#[inline(always)]
|
||||
pub fn dim(self) -> StyledObject<D> {
|
||||
pub fn dim(self) -> StyledObject<'terminal,D> {
|
||||
self.attr(Attribute::Dim)
|
||||
}
|
||||
/// Make the font italic (Not widely supported; Sometimes treated as inverse).
|
||||
#[cfg(unix)]
|
||||
#[inline(always)]
|
||||
pub fn italic(self) -> StyledObject<D> {
|
||||
pub fn italic(self) -> StyledObject<'terminal,D> {
|
||||
self.attr(Attribute::Italic)
|
||||
}
|
||||
/// Underline font.
|
||||
#[cfg(unix)]
|
||||
#[inline(always)]
|
||||
pub fn underlined(self) -> StyledObject<D> {
|
||||
pub fn underlined(self) -> StyledObject<'terminal,D> {
|
||||
self.attr(Attribute::Underlined)
|
||||
}
|
||||
/// Slow Blink (less than 150 per minute; not widely supported).
|
||||
#[cfg(unix)]
|
||||
#[inline(always)]
|
||||
pub fn slow_blink(self) -> StyledObject<D> {
|
||||
pub fn slow_blink(self) -> StyledObject<'terminal,D> {
|
||||
self.attr(Attribute::SlowBlink)
|
||||
}
|
||||
/// Rapid Blink (MS-DOS ANSI.SYS; 150+ per minute; not widely supported).
|
||||
#[cfg(unix)]
|
||||
#[inline(always)]
|
||||
pub fn rapid_blink(self) -> StyledObject<D> {
|
||||
pub fn rapid_blink(self) -> StyledObject<'terminal,D> {
|
||||
self.attr(Attribute::RapidBlink)
|
||||
}
|
||||
/// Swap foreground and background colors.
|
||||
#[cfg(unix)]
|
||||
#[inline(always)]
|
||||
pub fn reverse(self) -> StyledObject<D> {
|
||||
pub fn reverse(self) -> StyledObject<'terminal,D> {
|
||||
self.attr(Attribute::Reverse)
|
||||
}
|
||||
/// Hide text (Not widely supported).
|
||||
#[cfg(unix)]
|
||||
#[inline(always)]
|
||||
pub fn hidden(self) -> StyledObject<D> {
|
||||
pub fn hidden(self) -> StyledObject<'terminal,D> {
|
||||
self.attr(Attribute::Hidden)
|
||||
}
|
||||
/// Characters legible, but marked for deletion. Not widely supported.
|
||||
#[cfg(unix)]
|
||||
#[inline(always)]
|
||||
pub fn crossed_out(self) -> StyledObject<D> {
|
||||
pub fn crossed_out(self) -> StyledObject<'terminal,D> {
|
||||
self.attr(Attribute::CrossedOut)
|
||||
}
|
||||
}
|
||||
|
@ -37,7 +37,7 @@ impl<'terminal> Terminal<'terminal> {
|
||||
).unwrap();
|
||||
|
||||
#[cfg(not(target_os = "windows"))]
|
||||
let terminal = AnsiTerminal::new() as Box<ITerminal>;
|
||||
let terminal = Box::from(AnsiTerminal::new()) as Box<ITerminal>;
|
||||
|
||||
Terminal {
|
||||
terminal,
|
||||
|
Loading…
Reference in New Issue
Block a user