fixed input and cursor with new implementation

This commit is contained in:
TimonPost 2018-07-27 22:28:30 +02:00
parent d7387ed227
commit 26472359bc
24 changed files with 424 additions and 517 deletions

View File

@ -25,4 +25,12 @@ use crossterm::Terminal;
use std::{thread, time}; use std::{thread, time};
fn main() { fn main() {
let term = Terminal::new();
let mut cursor = term.cursor();
cursor.goto(10,10);
cursor.print("test");
let stdin = term.input();
let line = stdin.read_line();
println!("{:?}", line)
} }

View File

@ -4,95 +4,63 @@
use super::*; use super::*;
use shared::functions; use shared::functions;
use Context; use {Context,ScreenManager};
/// This struct is an ansi implementation for cursor related actions. /// This struct is an ansi implementation for cursor related actions.
pub struct AnsiCursor { pub struct AnsiCursor;
context: Rc<Context>,
}
impl AnsiCursor { impl AnsiCursor {
pub fn new(context: Rc<Context>) -> Box<AnsiCursor> { pub fn new() -> Box<AnsiCursor> {
Box::from(AnsiCursor { context }) Box::from(AnsiCursor { })
} }
} }
impl ITerminalCursor for AnsiCursor { impl ITerminalCursor for AnsiCursor {
fn goto(&self, x: u16, y: u16) { fn goto(&self, x: u16, y: u16, screen_manager: &ScreenManager) {
let mut screen = self.context.screen_manager.lock().unwrap(); screen_manager.write_string(format!(csi!("{};{}H"), y + 1, x + 1));
{
screen.write_string(format!(csi!("{};{}H"), y + 1, x + 1));
}
} }
fn pos(&self) -> (u16, u16) { fn pos(&self, screen_manager: &ScreenManager) -> (u16, u16) {
functions::get_cursor_position(self.context.clone()) functions::get_cursor_position(screen_manager)
} }
fn move_up(&self, count: u16) { fn move_up(&self, count: u16, screen_manager: &ScreenManager) {
let mut screen = self.context.screen_manager.lock().unwrap(); screen_manager.write_string(format!(csi!("{}A"), count));
{
screen.write_string(format!(csi!("{}A"), count));
}
} }
fn move_right(&self, count: u16) { fn move_right(&self, count: u16, screen_manager: &ScreenManager) {
let mut screen = self.context.screen_manager.lock().unwrap(); screen_manager.write_string(format!(csi!("{}C"), count));
{
screen.write_string(format!(csi!("{}C"), count));
}
} }
fn move_down(&self, count: u16) { fn move_down(&self, count: u16, screen_manager: &ScreenManager) {
let mut screen = self.context.screen_manager.lock().unwrap(); screen_manager.write_string(format!(csi!("{}B"), count));
{
screen.write_string(format!(csi!("{}B"), count));
}
} }
fn move_left(&self, count: u16) { fn move_left(&self, count: u16, screen_manager: &ScreenManager) {
let mut screen = self.context.screen_manager.lock().unwrap(); screen_manager.write_string(format!(csi!("{}D"), count));
{
screen.write_string(format!(csi!("{}D"), count));
}
} }
fn save_position(&self) { fn save_position(&self, screen_manager: &ScreenManager) {
let mut screen = self.context.screen_manager.lock().unwrap(); screen_manager.write_str(csi!("s"));
{
screen.write_str(csi!("s"));
}
} }
fn reset_position(&self) { fn reset_position(&self, screen_manager: &ScreenManager) {
let mut screen = self.context.screen_manager.lock().unwrap(); screen_manager.write_str(csi!("u"));
{
screen.write_str(csi!("u"));
}
} }
fn hide(&self) { fn hide(&self, screen_manager: &ScreenManager) {
let mut screen = self.context.screen_manager.lock().unwrap(); screen_manager.write_str(csi!("?25l"));
{
screen.write_str(csi!("?25l"));
}
} }
fn show(&self) { fn show(&self, screen_manager: &ScreenManager) {
let mut screen = self.context.screen_manager.lock().unwrap(); screen_manager.write_str(csi!("?25h"));
{
screen.write_str(csi!("?25h"));
}
} }
fn blink(&self, blink: bool) { fn blink(&self, blink: bool, screen_manager: &ScreenManager) {
let mut screen = self.context.screen_manager.lock().unwrap();
{
if blink { if blink {
screen.write_str(csi!("?12h")); screen_manager.write_str(csi!("?12h"));
} else { } else {
screen.write_str(csi!("?12l")); screen_manager.write_str(csi!("?12l"));
}
} }
} }
} }

View File

@ -13,25 +13,25 @@ use std::rc::Rc;
/// Struct that stores an specific platform implementation for cursor related actions. /// Struct that stores an specific platform implementation for cursor related actions.
pub struct TerminalCursor<'cursor> { pub struct TerminalCursor<'cursor> {
context: &'cursor ScreenManager, screen_manager: &'cursor ScreenManager,
terminal_cursor: Box<ITerminalCursor>, terminal_cursor: Box<ITerminalCursor>,
} }
impl<'cursor> TerminalCursor<'cursor> { impl<'cursor> TerminalCursor<'cursor> {
/// Create new cursor instance whereon cursor related actions can be performed. /// Create new cursor instance whereon cursor related actions can be performed.
pub fn new(context: &'cursor ScreenManager) -> TerminalCursor<'cursor> { pub fn new(screen_manager: &'cursor ScreenManager) -> TerminalCursor<'cursor> {
#[cfg(target_os = "windows")] #[cfg(target_os = "windows")]
let cursor = functions::get_module::<Box<ITerminalCursor>>( let cursor = functions::get_module::<Box<ITerminalCursor>>(
WinApiCursor::new(context.screen_manager.clone()), WinApiCursor::new(),
AnsiCursor::new(context.clone()), AnsiCursor::new(),
).unwrap(); ).unwrap();
#[cfg(not(target_os = "windows"))] #[cfg(not(target_os = "windows"))]
let cursor = AnsiCursor::new(context.clone()) as Box<ITerminalCursor>; let cursor = AnsiCursor::new() as Box<ITerminalCursor>;
TerminalCursor { TerminalCursor {
terminal_cursor: cursor, terminal_cursor: cursor,
context, screen_manager: screen_manager,
} }
} }
@ -56,8 +56,8 @@ impl<'cursor> TerminalCursor<'cursor> {
/// } /// }
/// ///
/// ``` /// ```
pub fn goto(&mut self, x: u16, y: u16) -> &mut TerminalCursor { pub fn goto(&mut self, x: u16, y: u16) -> &mut TerminalCursor<'cursor> {
self.terminal_cursor.goto(x, y); self.terminal_cursor.goto(x, y, &self.screen_manager);
self self
} }
@ -83,7 +83,7 @@ impl<'cursor> TerminalCursor<'cursor> {
/// ///
/// ``` /// ```
pub fn pos(&self) -> (u16, u16) { pub fn pos(&self) -> (u16, u16) {
self.terminal_cursor.pos() self.terminal_cursor.pos(&self.screen_manager)
} }
/// Move the current cursor position `n` times up. /// Move the current cursor position `n` times up.
@ -107,8 +107,8 @@ impl<'cursor> TerminalCursor<'cursor> {
/// } /// }
/// ///
/// ``` /// ```
pub fn move_up(&mut self, count: u16) -> &mut TerminalCursor { pub fn move_up(&mut self, count: u16) -> &mut TerminalCursor<'cursor> {
self.terminal_cursor.move_up(count); self.terminal_cursor.move_up(count, &self.screen_manager);
self self
} }
@ -131,8 +131,8 @@ impl<'cursor> TerminalCursor<'cursor> {
/// cursor.move_right(3); /// cursor.move_right(3);
/// } /// }
/// ``` /// ```
pub fn move_right(&mut self, count: u16) -> &mut TerminalCursor { pub fn move_right(&mut self, count: u16) -> &mut TerminalCursor<'cursor> {
self.terminal_cursor.move_right(count); self.terminal_cursor.move_right(count, &self.screen_manager);
self self
} }
@ -157,8 +157,8 @@ impl<'cursor> TerminalCursor<'cursor> {
/// } /// }
/// ///
/// ``` /// ```
pub fn move_down(&mut self, count: u16) -> &mut TerminalCursor { pub fn move_down(&mut self, count: u16) -> &mut TerminalCursor<'cursor> {
self.terminal_cursor.move_down(count); self.terminal_cursor.move_down(count, &self.screen_manager);
self self
} }
@ -183,8 +183,8 @@ impl<'cursor> TerminalCursor<'cursor> {
/// } /// }
/// ///
/// ``` /// ```
pub fn move_left(&mut self, count: u16) -> &mut TerminalCursor { pub fn move_left(&mut self, count: u16) -> &mut TerminalCursor<'cursor> {
self.terminal_cursor.move_left(count); self.terminal_cursor.move_left(count, &self.screen_manager);
self self
} }
@ -224,19 +224,13 @@ impl<'cursor> TerminalCursor<'cursor> {
/// .print("@"); /// .print("@");
/// ///
/// ``` /// ```
pub fn print<D: Display>(&mut self, value: D) -> &mut TerminalCursor { pub fn print<D: Display>(&mut self, value: D) -> &mut TerminalCursor<'cursor> {
{
use std::fmt::Write; use std::fmt::Write;
let mut string = String::new(); let mut string = String::new();
write!(string, "{}", value).unwrap(); write!(string, "{}", value).unwrap();
let mut mutex = &self.context.screen_manager; &self.screen_manager.write_string(string);
{ &self.screen_manager.flush();
let mut screen_manager = mutex.lock().unwrap();
screen_manager.write_string(string);
screen_manager.flush();
}
}
self self
} }
@ -257,7 +251,7 @@ impl<'cursor> TerminalCursor<'cursor> {
/// ///
/// ``` /// ```
pub fn save_position(&self) { pub fn save_position(&self) {
self.terminal_cursor.save_position(); self.terminal_cursor.save_position(&self.screen_manager);
} }
/// Return to saved cursor position /// Return to saved cursor position
@ -277,7 +271,7 @@ impl<'cursor> TerminalCursor<'cursor> {
/// ///
/// ``` /// ```
pub fn reset_position(&self) { pub fn reset_position(&self) {
self.terminal_cursor.reset_position(); self.terminal_cursor.reset_position(&self.screen_manager);
} }
/// Hide de cursor in the console. /// Hide de cursor in the console.
@ -295,7 +289,7 @@ impl<'cursor> TerminalCursor<'cursor> {
/// ///
/// ``` /// ```
pub fn hide(&self) { pub fn hide(&self) {
self.terminal_cursor.hide(); self.terminal_cursor.hide(&self.screen_manager);
} }
/// Show the cursor in the console. /// Show the cursor in the console.
@ -313,7 +307,7 @@ impl<'cursor> TerminalCursor<'cursor> {
/// ///
/// ``` /// ```
pub fn show(&self) { pub fn show(&self) {
self.terminal_cursor.show(); self.terminal_cursor.show(&self.screen_manager);
} }
/// Enable or disable blinking of the terminal. /// Enable or disable blinking of the terminal.
@ -335,37 +329,37 @@ impl<'cursor> TerminalCursor<'cursor> {
/// ///
/// ``` /// ```
pub fn blink(&self, blink: bool) { pub fn blink(&self, blink: bool) {
self.terminal_cursor.blink(blink); self.terminal_cursor.blink(blink, &self.screen_manager);
} }
} }
/// Get an TerminalCursor implementation whereon cursor related actions can be performed. // Get an TerminalCursor implementation whereon cursor related actions can be performed.
/// //
/// Check `/examples/version/cursor` in the libary for more spesific examples. // Check `/examples/version/cursor` in the libary for more spesific examples.
/// //
/// #Example // #Example
/// //
/// ```rust // ```rust
/// //
/// extern crate crossterm; // extern crate crossterm;
/// use self::crossterm::Context; // use self::crossterm::Context;
/// use self::crossterm::cursor; // use self::crossterm::cursor;
/// //
/// let context = Context::new(); // let context = Context::new();
/// //
/// // Get cursor and goto pos X: 5, Y: 10 // // Get cursor and goto pos X: 5, Y: 10
/// let mut cursor = cursor::cursor(&context); // let mut cursor = cursor::cursor(&context);
/// cursor.goto(5,10); // cursor.goto(5,10);
/// //
/// cursor.show(); // cursor.show();
/// cursor.hide(); // cursor.hide();
/// cursor.blink(); // cursor.blink();
/// cursor.move_left(2); // cursor.move_left(2);
/// //
/// //Or you can do it in one line. // //Or you can do it in one line.
/// cursor::cursor(&context).goto(5,10); // cursor::cursor(&context).goto(5,10);
/// //
/// ``` // ```
pub fn cursor(context: &Rc<Context>) -> Box<TerminalCursor> { //pub fn cursor(context: &ScreenManager) -> Box<TerminalCursor> {
Box::from(TerminalCursor::new(context.clone())) // Box::from(TerminalCursor::new(context.clone()))
} //}

View File

@ -17,8 +17,8 @@ use self::ansi_cursor::AnsiCursor;
#[cfg(target_os = "windows")] #[cfg(target_os = "windows")]
use self::winapi_cursor::WinApiCursor; use self::winapi_cursor::WinApiCursor;
pub use self::cursor::{cursor, TerminalCursor}; pub use self::cursor::{TerminalCursor};
use ScreenManager;
use std::rc::Rc; use std::rc::Rc;
///! This trait defines the actions that can be preformed with the terminal cursor. ///! This trait defines the actions that can be preformed with the terminal cursor.

View File

@ -20,47 +20,47 @@ impl WinApiCursor {
impl ITerminalCursor for WinApiCursor { impl ITerminalCursor for WinApiCursor {
fn goto(&self, x: u16, y: u16, screen_manager: &ScreenManager) { fn goto(&self, x: u16, y: u16, screen_manager: &ScreenManager) {
cursor::set_console_cursor_position(x as i16, y as i16, &self.screen_manager); cursor::set_console_cursor_position(x as i16, y as i16, screen_manager);
} }
fn pos(&self, screen_manager: &ScreenManager) -> (u16, u16) { fn pos(&self, screen_manager: &ScreenManager) -> (u16, u16) {
cursor::pos(&self.screen_manager) cursor::pos(screen_manager)
} }
fn move_up(&self, count: u16, screen_manager: &ScreenManager) { fn move_up(&self, count: u16, screen_manager: &ScreenManager) {
let (xpos, ypos) = self.pos(); let (xpos, ypos) = self.pos(screen_manager);
self.goto(xpos, ypos - count); self.goto(xpos, ypos - count, screen_manager);
} }
fn move_right(&self, count: u16, screen_manager: &ScreenManager) { fn move_right(&self, count: u16, screen_manager: &ScreenManager) {
let (xpos, ypos) = self.pos(); let (xpos, ypos) = self.pos(screen_manager);
self.goto(xpos + count, ypos); self.goto(xpos + count, ypos, screen_manager);
} }
fn move_down(&self, count: u16, screen_manager: &ScreenManager) { fn move_down(&self, count: u16, screen_manager: &ScreenManager) {
let (xpos, ypos) = self.pos(); let (xpos, ypos) = self.pos(screen_manager);
self.goto(xpos, ypos + count); self.goto(xpos, ypos + count, screen_manager);
} }
fn move_left(&self, count: u16, screen_manager: &ScreenManager) { fn move_left(&self, count: u16, screen_manager: &ScreenManager) {
let (xpos, ypos) = self.pos(); let (xpos, ypos) = self.pos(screen_manager);
self.goto(xpos - count, ypos); self.goto(xpos - count, ypos, screen_manager);
} }
fn save_position(&self, screen_manager: &ScreenManager) { fn save_position(&self, screen_manager: &ScreenManager) {
cursor::save_cursor_pos(&self.screen_manager); cursor::save_cursor_pos(screen_manager);
} }
fn reset_position(&self, screen_manager: &ScreenManager) { fn reset_position(&self, screen_manager: &ScreenManager) {
cursor::reset_to_saved_position(&self.screen_manager); cursor::reset_to_saved_position(screen_manager);
} }
fn hide(&self, screen_manager: &ScreenManager) { fn hide(&self, screen_manager: &ScreenManager) {
cursor::cursor_visibility(false, &self.screen_manager); cursor::cursor_visibility(false, screen_manager);
} }
fn show(&self, screen_manager: &ScreenManager) { fn show(&self, screen_manager: &ScreenManager) {
cursor::cursor_visibility(true, &self.screen_manager); cursor::cursor_visibility(true, screen_manager);
} }
fn blink(&self, blink: bool, screen_manager: &ScreenManager) {} fn blink(&self, blink: bool, screen_manager: &ScreenManager) {}

View File

@ -2,48 +2,44 @@ use std::io;
use super::*; use super::*;
use std::rc::Rc; use std::rc::Rc;
use Context; use {Context, ScreenManager };
pub struct TerminalInput { pub struct TerminalInput<'terminal> {
context: Rc<Context>,
terminal_input: Box<ITerminalInput>, terminal_input: Box<ITerminalInput>,
screen_manager: &'terminal ScreenManager
} }
impl TerminalInput { impl<'terminal> TerminalInput<'terminal> {
pub fn new(context: Rc<Context>) -> TerminalInput { pub fn new(screen_manager: &'terminal ScreenManager) -> TerminalInput<'terminal> {
#[cfg(target_os = "windows")] #[cfg(target_os = "windows")]
let input = Box::from(WindowsInput::new(context.clone())); let input = Box::from(WindowsInput::new());
#[cfg(not(target_os = "windows"))] #[cfg(not(target_os = "windows"))]
let input = Box::from(UnixInput::new()); let input = Box::from(UnixInput::new());
TerminalInput { TerminalInput {
terminal_input: input, terminal_input: input,
context, screen_manager: screen_manager
} }
} }
pub fn read_line(&self) -> io::Result<String> { pub fn read_line(&self) -> io::Result<String> {
self.terminal_input.read_line() self.terminal_input.read_line(&self.screen_manager)
} }
pub fn read_char(&self) -> io::Result<char> { pub fn read_char(&self) -> io::Result<char> {
return self.terminal_input.read_char(); return self.terminal_input.read_char(&self.screen_manager);
}
pub fn read_key(&self) -> io::Result<Key> {
self.terminal_input.read_pressed_key()
} }
pub fn read_async(&self) -> AsyncReader { pub fn read_async(&self) -> AsyncReader {
self.terminal_input.read_async() self.terminal_input.read_async(&self.screen_manager)
} }
pub fn read_until_async(&self, delimiter: u8) -> AsyncReader { pub fn read_until_async(&self, delimiter: u8) -> AsyncReader {
self.terminal_input.read_until_async(delimiter) self.terminal_input.read_until_async(delimiter,&self.screen_manager)
} }
} }
pub fn input(context: &Rc<Context>) -> Box<TerminalInput> { pub fn input(screen_manager: &ScreenManager) -> TerminalInput {
return Box::from(TerminalInput::new(context.clone())); return TerminalInput::new(screen_manager)
} }

View File

@ -13,18 +13,18 @@ use self::unix_input::UnixInput;
mod unix_input; mod unix_input;
pub use self::input::{input, TerminalInput}; pub use self::input::{input, TerminalInput};
use ScreenManager;
use std::io::Read; use std::io::Read;
use std::sync::mpsc; use std::sync::mpsc;
trait ITerminalInput { trait ITerminalInput {
fn read_line(&self) -> io::Result<String>; fn read_line(&self, screen_manger: &ScreenManager) -> io::Result<String>;
fn read_char(&self) -> io::Result<char>; fn read_char(&self, screen_manger: &ScreenManager) -> io::Result<char>;
fn read_pressed_key(&self) -> io::Result<Key>;
fn read_async(&self) -> AsyncReader; fn read_async(&self, screen_manger: &ScreenManager) -> AsyncReader;
fn read_until_async(&self, delimiter: u8) -> AsyncReader; fn read_until_async(&self, delimiter: u8, screen_manger: &ScreenManager) -> AsyncReader;
} }
pub struct AsyncReader { pub struct AsyncReader {

View File

@ -8,7 +8,7 @@ use std::thread;
use super::super::kernel::unix_kernel::terminal::{get_tty, read_char}; use super::super::kernel::unix_kernel::terminal::{get_tty, read_char};
use super::super::terminal::terminal; use super::super::terminal::terminal;
use super::{AsyncReader, ITerminalInput, Key}; use super::{AsyncReader, ITerminalInput, Key};
use ScreenManager;
pub struct UnixInput; pub struct UnixInput;
impl UnixInput { impl UnixInput {
@ -18,7 +18,7 @@ impl UnixInput {
} }
impl ITerminalInput for UnixInput { impl ITerminalInput for UnixInput {
fn read_line(&self) -> io::Result<String> { fn read_line(&self, screen_manger: &ScreenManager) -> io::Result<String> {
let mut rv = String::new(); let mut rv = String::new();
io::stdin().read_line(&mut rv)?; io::stdin().read_line(&mut rv)?;
let len = rv.trim_right_matches(&['\r', '\n'][..]).len(); let len = rv.trim_right_matches(&['\r', '\n'][..]).len();
@ -26,15 +26,11 @@ impl ITerminalInput for UnixInput {
Ok(rv) Ok(rv)
} }
fn read_char(&self) -> io::Result<char> { fn read_char(&self, screen_manger: &ScreenManager) -> io::Result<char> {
read_char() read_char()
} }
fn read_pressed_key(&self) -> io::Result<Key> { fn read_async(&self, screen_manger: &ScreenManager) -> AsyncReader {
Ok(Key::Unknown)
}
fn read_async(&self) -> AsyncReader {
let (send, recv) = mpsc::channel(); let (send, recv) = mpsc::channel();
thread::spawn(move || for i in get_tty().unwrap().bytes() { thread::spawn(move || for i in get_tty().unwrap().bytes() {
@ -46,7 +42,7 @@ impl ITerminalInput for UnixInput {
AsyncReader { recv: recv } AsyncReader { recv: recv }
} }
fn read_until_async(&self, delimiter: u8) -> AsyncReader { fn read_until_async(&self, delimiter: u8, screen_manger: &ScreenManager) -> AsyncReader {
let (send, recv) = mpsc::channel(); let (send, recv) = mpsc::channel();
thread::spawn(move || for i in get_tty().unwrap().bytes() { thread::spawn(move || for i in get_tty().unwrap().bytes() {

View File

@ -9,36 +9,23 @@ use super::{AsyncReader, ITerminalInput, Key};
use winapi::um::winnt::INT; use winapi::um::winnt::INT;
use winapi::um::winuser; use winapi::um::winuser;
use super::super::terminal::terminal;
use std::rc::Rc; use std::rc::Rc;
use Context; use ScreenManager;
pub struct WindowsInput { pub struct WindowsInput;
context: Rc<Context>,
pub display_input: bool,
}
impl WindowsInput { impl WindowsInput {
pub fn new(context: Rc<Context>) -> WindowsInput { pub fn new() -> WindowsInput {
WindowsInput { WindowsInput {}
context,
display_input: false,
}
} }
} }
impl ITerminalInput for WindowsInput { impl ITerminalInput for WindowsInput {
fn read_line(&self) -> io::Result<String> { fn read_line(&self,screen_manger: &ScreenManager) -> io::Result<String> {
let term = terminal(&self.context);
let mut chars: Vec<char> = Vec::new(); let mut chars: Vec<char> = Vec::new();
loop { loop {
let mut is_raw_screen = false; let is_raw_screen = screen_manger.is_raw_screen();
{
let mutex = &self.context.screen_manager;
let screen = mutex.lock().unwrap();
is_raw_screen = screen.is_raw_screen();
}
// _getwch is without echo and _getwche is with echo // _getwch is without echo and _getwche is with echo
let pressed_char = unsafe { if is_raw_screen { _getwch() } else { _getwche() } }; let pressed_char = unsafe { if is_raw_screen { _getwch() } else { _getwche() } };
@ -63,15 +50,8 @@ impl ITerminalInput for WindowsInput {
return Ok(chars.into_iter().collect()); return Ok(chars.into_iter().collect());
} }
fn read_char(&self) -> io::Result<char> { fn read_char(&self, screen_manger: &ScreenManager) -> io::Result<char> {
let term = terminal(&self.context); let is_raw_screen = screen_manger.is_raw_screen();
let mut is_raw_screen = false;
{
let mutex = &self.context.screen_manager;
let screen = mutex.lock().unwrap();
is_raw_screen = screen.is_raw_screen();
}
// _getwch is without echo and _getwche is with echo // _getwch is without echo and _getwche is with echo
let pressed_char = unsafe { if is_raw_screen { _getwch() } else { _getwche() } }; let pressed_char = unsafe { if is_raw_screen { _getwch() } else { _getwche() } };
@ -86,9 +66,6 @@ impl ITerminalInput for WindowsInput {
match char::from_u32(pressed_char as u32) { match char::from_u32(pressed_char as u32) {
Some(c) => { Some(c) => {
if self.display_input {
term.write(c);
}
return Ok(c); return Ok(c);
} }
None => Err(io::Error::new( None => Err(io::Error::new(
@ -98,41 +75,11 @@ impl ITerminalInput for WindowsInput {
} }
} }
fn read_pressed_key(&self) -> io::Result<Key> { fn read_async(&self,screen_manger: &ScreenManager) -> AsyncReader {
use Context;
let context = Context::new();
let buf: [u8; 1024] = unsafe { ::std::mem::zeroed() };
// reading::read(&mut buf, &context.screen_manager);
Ok(Key::Unknown)
// let pressed_char = unsafe { _getwch() };
//
// // if 0 or 0xe0 we need to listen again because the next key will be an special key
// if pressed_char == 0 || pressed_char == 0xe0 {
// let special_key: i32 = unsafe { _getwch() };
// println!("spkey {}",special_key);
// return Ok(key_from_key_code(0x26));
// } else {
// match char::from_u32(pressed_char as u32)
// {
// Some(c) => return Ok(Key::Char(c)),
// None => { panic!("Some error needs to be returned") }
// }
// }
}
fn read_async(&self) -> AsyncReader {
let (tx, rx) = mpsc::channel(); let (tx, rx) = mpsc::channel();
let mut is_raw_screen = false; let is_raw_screen = screen_manger.is_raw_screen();
{
let mutex = &self.context.screen_manager;
let screen = mutex.lock().unwrap();
is_raw_screen = screen.is_raw_screen();
}
// panic!("is raw screen: {} ", is_raw_screen);
thread::spawn(move || { thread::spawn(move || {
loop { loop {
@ -155,15 +102,10 @@ impl ITerminalInput for WindowsInput {
AsyncReader { recv: rx } AsyncReader { recv: rx }
} }
fn read_until_async(&self, delimiter: u8) -> AsyncReader { fn read_until_async(&self, delimiter: u8,screen_manger: &ScreenManager) -> AsyncReader {
let (tx, rx) = mpsc::channel(); let (tx, rx) = mpsc::channel();
let mut is_raw_screen = false; let is_raw_screen = screen_manger.is_raw_screen();
{
let mutex =&self.context.screen_manager;
let screen = mutex.lock().unwrap();
is_raw_screen = screen.is_raw_screen();
}
thread::spawn(move || { thread::spawn(move || {
loop { loop {

View File

@ -16,7 +16,7 @@ use std::sync::Mutex;
use ScreenManager; use ScreenManager;
/// Create a new console screen buffer info struct. /// Create a new console screen buffer info struct.
pub fn get_csbi(screen_manager: &Rc<Mutex<ScreenManager>>) -> Result<CONSOLE_SCREEN_BUFFER_INFO> { pub fn get_csbi(screen_manager: &ScreenManager) -> Result<CONSOLE_SCREEN_BUFFER_INFO> {
let mut csbi = CONSOLE_SCREEN_BUFFER_INFO::empty(); let mut csbi = CONSOLE_SCREEN_BUFFER_INFO::empty();
let success; let success;
@ -36,7 +36,7 @@ pub fn get_csbi(screen_manager: &Rc<Mutex<ScreenManager>>) -> Result<CONSOLE_SCR
/// Get buffer info and handle of the current screen. /// Get buffer info and handle of the current screen.
pub fn get_csbi_and_handle( pub fn get_csbi_and_handle(
screen_manager: &Rc<Mutex<ScreenManager>>, screen_manager: &ScreenManager,
) -> Result<(CONSOLE_SCREEN_BUFFER_INFO, HANDLE)> { ) -> Result<(CONSOLE_SCREEN_BUFFER_INFO, HANDLE)> {
let handle = handle::get_current_handle(screen_manager)?; let handle = handle::get_current_handle(screen_manager)?;
let csbi = get_csbi_by_handle(&handle)?; let csbi = get_csbi_by_handle(&handle)?;
@ -63,7 +63,7 @@ pub fn get_csbi_by_handle(handle: &HANDLE) -> Result<CONSOLE_SCREEN_BUFFER_INFO>
/// Set the console screen buffer size /// Set the console screen buffer size
pub fn set_console_screen_buffer_size( pub fn set_console_screen_buffer_size(
size: COORD, size: COORD,
screen_manager: &Rc<Mutex<ScreenManager>>, screen_manager: &ScreenManager,
) -> bool { ) -> bool {
let handle = handle::get_current_handle(screen_manager).unwrap(); let handle = handle::get_current_handle(screen_manager).unwrap();

View File

@ -16,7 +16,7 @@ use std::sync::Mutex;
static mut SAVED_CURSOR_POS: (u16, u16) = (0, 0); static mut SAVED_CURSOR_POS: (u16, u16) = (0, 0);
/// Reset to saved cursor position /// Reset to saved cursor position
pub fn reset_to_saved_position(screen_manager: &Rc<Mutex<ScreenManager>>) { pub fn reset_to_saved_position(screen_manager: &ScreenManager) {
unsafe { unsafe {
set_console_cursor_position( set_console_cursor_position(
SAVED_CURSOR_POS.0 as i16, SAVED_CURSOR_POS.0 as i16,
@ -27,7 +27,7 @@ pub fn reset_to_saved_position(screen_manager: &Rc<Mutex<ScreenManager>>) {
} }
/// Save current cursor position to recall later. /// Save current cursor position to recall later.
pub fn save_cursor_pos(screen_manager: &Rc<Mutex<ScreenManager>>) { pub fn save_cursor_pos(screen_manager: &ScreenManager) {
let position = pos(screen_manager); let position = pos(screen_manager);
unsafe { unsafe {
@ -36,7 +36,7 @@ pub fn save_cursor_pos(screen_manager: &Rc<Mutex<ScreenManager>>) {
} }
/// get the current cursor position. /// get the current cursor position.
pub fn pos(screen_manager: &Rc<Mutex<ScreenManager>>) -> (u16, u16) { pub fn pos(screen_manager: &ScreenManager) -> (u16, u16) {
let handle = handle::get_output_handle().unwrap(); let handle = handle::get_output_handle().unwrap();
@ -47,7 +47,7 @@ pub fn pos(screen_manager: &Rc<Mutex<ScreenManager>>) -> (u16, u16) {
} }
} }
pub fn absolute_cursor_pos(screen_manager: &Rc<Mutex<ScreenManager>>) -> (u16, u16) { pub fn absolute_cursor_pos(screen_manager: &ScreenManager) -> (u16, u16) {
let handle = handle::get_output_handle().unwrap(); let handle = handle::get_output_handle().unwrap();
@ -62,7 +62,7 @@ pub fn absolute_cursor_pos(screen_manager: &Rc<Mutex<ScreenManager>>) -> (u16, u
} }
/// Set the cursor position to the given x and y. Note that this is 0 based. /// Set the cursor position to the given x and y. Note that this is 0 based.
pub fn set_console_cursor_position(x: i16, y: i16, screen_manager: &Rc<Mutex<ScreenManager>>) { pub fn set_console_cursor_position(x: i16, y: i16, screen_manager: &ScreenManager) {
if x < 0 || x >= <i16>::max_value() { if x < 0 || x >= <i16>::max_value() {
panic!( panic!(
"Argument Out of Range Exception when setting cursor position to X: {}", "Argument Out of Range Exception when setting cursor position to X: {}",
@ -91,7 +91,7 @@ pub fn set_console_cursor_position(x: i16, y: i16, screen_manager: &Rc<Mutex<Scr
} }
/// change the cursor visibility. /// change the cursor visibility.
pub fn cursor_visibility(visable: bool, screen_manager: &Rc<Mutex<ScreenManager>>) -> Result<()> { pub fn cursor_visibility(visable: bool, screen_manager: &ScreenManager) -> Result<()> {
let handle = handle::get_current_handle(screen_manager).unwrap(); let handle = handle::get_current_handle(screen_manager).unwrap();
let cursor_info = CONSOLE_CURSOR_INFO { let cursor_info = CONSOLE_CURSOR_INFO {

View File

@ -6,27 +6,23 @@ use winapi::um::winnt::HANDLE;
use std::io::{self, ErrorKind, Result}; use std::io::{self, ErrorKind, Result};
use std::rc::Rc; use std::rc::Rc;
use std::sync::Mutex; use std::sync::Mutex;
use super::super::super::manager::{ScreenManager, WinApiScreenManager}; use super::super::super::manager::{ScreenManager, WinApiScreenManager};
/// 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(screen_manager: &Rc<Mutex<ScreenManager>>) -> Result<HANDLE> { pub fn get_current_handle(screen_manager: &ScreenManager) -> Result<HANDLE> {
let mut mutex = screen_manager; let mut mutex = screen_manager;
let handle: Result<HANDLE>; let handle: Result<HANDLE>;
let mut screen_manager = mutex.lock().unwrap(); let winapi_screen_manager: &WinApiScreenManager = match screen_manager
{
let winapi_screen_manager: &mut WinApiScreenManager = match screen_manager
.as_any() .as_any()
.downcast_mut::<WinApiScreenManager>() .downcast_ref::<WinApiScreenManager>()
{ {
Some(win_api) => win_api, 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'")) 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()); handle = Ok(*winapi_screen_manager.get_handle());
}
return handle; return handle;
} }

View File

@ -37,7 +37,7 @@ pub fn get_console_mode(handle: &HANDLE, current_mode: &mut u32) -> bool {
} }
/// Change the console text attribute. /// Change the console text attribute.
pub fn set_console_text_attribute(value: u16, screen_manager: &Rc<Mutex<ScreenManager>>) -> bool { pub fn set_console_text_attribute(value: u16, screen_manager: &ScreenManager) -> bool {
let handle = handle::get_current_handle(screen_manager).unwrap(); let handle = handle::get_current_handle(screen_manager).unwrap();
unsafe { unsafe {
@ -49,7 +49,7 @@ pub fn set_console_text_attribute(value: u16, screen_manager: &Rc<Mutex<ScreenMa
pub fn set_console_info( pub fn set_console_info(
absolute: bool, absolute: bool,
rect: &SMALL_RECT, rect: &SMALL_RECT,
screen_manager: &Rc<Mutex<ScreenManager>>, screen_manager: &ScreenManager,
) -> bool { ) -> bool {
let handle = handle::get_current_handle(screen_manager).unwrap(); let handle = handle::get_current_handle(screen_manager).unwrap();
@ -72,7 +72,7 @@ pub fn is_true(value: i32) -> bool {
} }
///// Get the original color of the terminal. ///// Get the original color of the terminal.
//pub fn get_original_console_color(screen_manager: &Rc<Mutex<ScreenManager>>) -> u16 { //pub fn get_original_console_color(screen_manager: &ScreenManager) -> u16 {
// let console_buffer_info = csbi::get_console_screen_buffer_info(screen_manager); // let console_buffer_info = csbi::get_console_screen_buffer_info(screen_manager);
// console_buffer_info.wAttributes as u16 // console_buffer_info.wAttributes as u16
//} //}

View File

@ -5,7 +5,7 @@ use ScreenManager;
use super::{csbi, handle}; use super::{csbi, handle};
/// Get the terminal size /// Get the terminal size
pub fn terminal_size(screen_manager: &Rc<Mutex<ScreenManager>>) -> (u16, u16) { pub fn terminal_size(screen_manager: &ScreenManager) -> (u16, u16) {
let handle = handle::get_output_handle().unwrap(); let handle = handle::get_output_handle().unwrap();
@ -19,7 +19,7 @@ pub fn terminal_size(screen_manager: &Rc<Mutex<ScreenManager>>) -> (u16, u16) {
} }
} }
pub fn buffer_size(screen_manager: &Rc<Mutex<ScreenManager>>) -> (u16, u16) { pub fn buffer_size(screen_manager: &ScreenManager) -> (u16, u16) {
let handle = handle::get_output_handle().unwrap(); let handle = handle::get_output_handle().unwrap();

View File

@ -20,7 +20,7 @@ pub fn fill_console_output_character(
cells_written: &mut u32, cells_written: &mut u32,
start_location: COORD, start_location: COORD,
cells_to_write: u32, cells_to_write: u32,
screen_manager: &Rc<Mutex<ScreenManager>>, screen_manager: &ScreenManager,
) -> bool { ) -> bool {
let handle = handle::get_current_handle(screen_manager).unwrap(); let handle = handle::get_current_handle(screen_manager).unwrap();
@ -42,7 +42,7 @@ pub fn fill_console_output_attribute(
cells_written: &mut u32, cells_written: &mut u32,
start_location: COORD, start_location: COORD,
cells_to_write: u32, cells_to_write: u32,
screen_manager: &Rc<Mutex<ScreenManager>>, screen_manager: &ScreenManager,
) -> bool { ) -> bool {
// Get the position of the current console window // Get the position of the current console window

View File

@ -11,11 +11,11 @@ mod state;
pub mod cursor; pub mod cursor;
pub mod input; pub mod input;
pub mod manager; pub mod manager;
pub mod style; //pub mod style;
pub mod terminal; pub mod terminal;
pub use shared::Terminal::Terminal; pub use shared::Terminal::Terminal;
pub use shared::crossterm::Crossterm; //pub use shared::crossterm::Crossterm;
pub use shared::raw; pub use shared::raw;
pub use shared::screen; pub use shared::screen;
pub use state::context::Context; pub use state::context::Context;

View File

@ -4,14 +4,14 @@
use std::any::Any; use std::any::Any;
use std::io::{self, Read, Write}; use std::io::{self, Read, Write};
use std::sync::Mutex;
use super::IScreenManager; use super::IScreenManager;
use std::str::from_utf8;
pub struct AnsiScreenManager { pub struct AnsiScreenManager {
is_alternate_screen: bool, is_alternate_screen: bool,
is_raw_screen: bool, is_raw_screen: bool,
output: Box<Write>, output: Mutex<Box<Write>>
input: Box<Read>,
} }
impl IScreenManager for AnsiScreenManager { impl IScreenManager for AnsiScreenManager {
@ -31,41 +31,37 @@ impl IScreenManager for AnsiScreenManager {
self.is_alternate_screen self.is_alternate_screen
} }
fn write_string(&mut self, string: String) -> io::Result<usize> { fn write_str(&self, string: &str) -> io::Result<usize> {
write!(self.output, "{}", string)?; {
let mx = &self.output;
let mut output = mx.lock().unwrap();
write!(output, "{}", string)?;
}
self.flush(); self.flush();
Ok(0) Ok(0)
} }
fn write_str(&mut self, string: &str) -> io::Result<usize> { fn write(&self, buf: &[u8]) -> io::Result<usize> {
write!(self.output, "{}", string)?; {
self.flush(); let mx = &self.output;
let mut output = mx.lock().unwrap();
output.write(buf)?;
}
Ok(0) Ok(0)
} }
// fn read_line(&mut self) -> io::Result<String> fn flush(&self) -> io::Result<()> {
// { let mx = &self.output;
// let mut rv = String::new(); let mut output = mx.lock().unwrap();
// self.input.read_line(&mut rv)?; output.flush()
// let len = rv.trim_right_matches(&['\r', '\n'][..]).len();
// rv.truncate(len);
// Ok(rv)
// }
//
// fn read_char(&mut self) -> io::Result<String>
// {
//
// }
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
self.output.write(buf)
} }
fn flush(&mut self) -> io::Result<()> { fn as_any(&self) -> &Any {
self.output.flush() self
} }
fn as_any(&mut self) -> &mut Any { fn as_any_mut(&mut self) -> &mut Any {
self self
} }
} }
@ -73,8 +69,7 @@ impl IScreenManager for AnsiScreenManager {
impl AnsiScreenManager { impl AnsiScreenManager {
pub fn new() -> Self { pub fn new() -> Self {
AnsiScreenManager { AnsiScreenManager {
input: (Box::from(io::stdin()) as Box<Read>), output: Mutex::new(Box::from(io::stdout()) as Box<Write>),
output: (Box::from(io::stdout()) as Box<Write>),
is_alternate_screen: false, is_alternate_screen: false,
is_raw_screen: false, is_raw_screen: false,
} }

View File

@ -52,27 +52,26 @@ impl ScreenManager {
} }
/// Write an ANSI code as String. /// Write an ANSI code as String.
pub fn write_string(&mut self, string: String) -> io::Result<usize> { pub fn write_string(&self, string: String) -> io::Result<usize> {
self.screen_manager.write_string(string) self.screen_manager.write_str(string.as_str())
} }
pub fn flush(&self) -> io::Result<()>
{
self.screen_manager.flush()
}
/// Write an ANSI code as &str /// Write an ANSI code as &str
pub fn write_str(&mut self, string: &str) -> io::Result<usize> { pub fn write_str(&self, string: &str) -> io::Result<usize> {
self.screen_manager.write_str(string) self.screen_manager.write_str(string)
} }
/// Can be used to get an specific implementation used for the current platform. /// Can be used to get an specific implementation used for the current platform.
pub fn as_any(&mut self) -> &mut Any { pub fn as_any(&self) -> &Any {
self.screen_manager.as_any() self.screen_manager.as_any()
} }
}
impl Write for ScreenManager { /// Can be used to get an specific implementation used for the current platform.
fn write(&mut self, buf: &[u8]) -> io::Result<usize> { pub fn as_any_mut(&mut self) -> &mut Any {
self.screen_manager.write(buf) self.screen_manager.as_any_mut()
}
fn flush(&mut self) -> io::Result<()> {
self.screen_manager.flush()
} }
} }

View File

@ -39,14 +39,14 @@ pub trait IScreenManager {
fn is_raw_screen(&self) -> bool; fn is_raw_screen(&self) -> bool;
fn is_alternate_screen(&self) -> bool; fn is_alternate_screen(&self) -> bool;
/// Write ansi code as String to the current stdout.
fn write_string(&mut self, string: String) -> io::Result<usize>;
/// Write a &str to the current stdout. /// Write a &str to the current stdout.
fn write_str(&mut self, string: &str) -> io::Result<usize>; fn write_str(&self, string: &str) -> io::Result<usize>;
/// Write [u8] buffer to console. /// Write [u8] buffer to console.
fn write(&mut self, buf: &[u8]) -> io::Result<usize>; fn write(&self, buf: &[u8]) -> io::Result<usize>;
/// Flush the current output. /// Flush the current output.
fn flush(&mut self) -> io::Result<()>; fn flush(&self) -> io::Result<()>;
/// Can be used to convert to an specific IScreenManager implementation. /// Can be used to convert to an specific IScreenManager implementation.
fn as_any(&mut self) -> &mut Any; fn as_any(&self) -> &Any;
/// Can be used to convert to an specific mutable IScreenManager implementation.
fn as_any_mut(&mut self) -> &mut Any;
} }

View File

@ -15,7 +15,6 @@ pub struct WinApiScreenManager {
} }
impl IScreenManager for WinApiScreenManager { impl IScreenManager for WinApiScreenManager {
fn set_is_raw_screen(&mut self, value: bool) { fn set_is_raw_screen(&mut self, value: bool) {
self.is_raw_screen = value; self.is_raw_screen = value;
} }
@ -31,16 +30,11 @@ impl IScreenManager for WinApiScreenManager {
self.is_alternate_screen self.is_alternate_screen
} }
fn write_str(&self, string: &str) -> io::Result<usize> {
fn write_string(&mut self, string: String) -> io::Result<usize> {
self.write(string.as_bytes()) self.write(string.as_bytes())
} }
fn write_str(&mut self, string: &str) -> io::Result<usize> { fn write(&self, buf: &[u8]) -> io::Result<usize> {
self.write(string.as_bytes())
}
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
if self.is_alternate_screen { if self.is_alternate_screen {
writing::write_char_buffer(&self.alternate_handle, buf) writing::write_char_buffer(&self.alternate_handle, buf)
} else { } else {
@ -48,11 +42,15 @@ impl IScreenManager for WinApiScreenManager {
} }
} }
fn flush(&mut self) -> io::Result<()> { fn flush(&self) -> io::Result<()> {
Ok(()) Ok(())
} }
fn as_any(&mut self) -> &mut Any { fn as_any(&self) -> &Any {
self
}
fn as_any_mut(&mut self) -> &mut Any {
self self
} }
} }
@ -76,7 +74,7 @@ impl WinApiScreenManager {
} }
/// get the current screen handle. /// get the current screen handle.
pub fn get_handle(&mut self) -> &HANDLE { pub fn get_handle(&self) -> &HANDLE {
if self.is_alternate_screen { if self.is_alternate_screen {
return &self.alternate_handle; return &self.alternate_handle;
} else { } else {

View File

@ -2,6 +2,12 @@ use {StateManager, ScreenManager};
use super::super::state::commands::*; use super::super::state::commands::*;
use super::raw::RawTerminal; use super::raw::RawTerminal;
use super::screen::AlternateScreen; use super::screen::AlternateScreen;
use super::super::cursor;
use super::super::input;
use super::super::terminal;
use std::collections::HashMap; use std::collections::HashMap;
use std::io::Result; use std::io::Result;
@ -93,6 +99,18 @@ impl Terminal{
return Ok(()) return Ok(())
} }
pub fn cursor(&self) -> cursor::TerminalCursor {
cursor::TerminalCursor::new(&self.active_screen)
}
pub fn input(&self) -> input::TerminalInput {
return input::TerminalInput::new(&self.active_screen)
}
pub fn terminal(&self) -> input::TerminalInput {
return input::TerminalInput::new(&self.active_screen)
}
} }
impl Drop for Terminal impl Drop for Terminal

View File

@ -1,183 +1,183 @@
//! This module provides easy access to the functionalities of crossterm. ////! This module provides easy access to the functionalities of crossterm.
//! since `crossterm version 0.3.0` an `Context` type is introduced (check that documentation for more info why this type is introduced). ////! since `crossterm version 0.3.0` an `Context` type is introduced (check that documentation for more info why this type is introduced).
//! ////!
//! You have to provide this `Context` to the modules: `cursor::cursor(), color::color(), terminal::terminal()`. ////! You have to provide this `Context` to the modules: `cursor::cursor(), color::color(), terminal::terminal()`.
//! ////!
//! use crossterm::Context; ////! use crossterm::Context;
//! use crossterm::cursor; ////! use crossterm::cursor;
//! use crossterm::color; ////! use crossterm::color;
//! use crossterm::terminal; ////! use crossterm::terminal;
//! ////!
//! let context = Context::new(); ////! let context = Context::new();
//! let cursor = cursor::cursor(&context) ////! let cursor = cursor::cursor(&context)
//! let terminal = terminal::terminal(&context); ////! let terminal = terminal::terminal(&context);
//! let color = terminal::color(&context); ////! let color = terminal::color(&context);
//! ////!
//! Because it can seem a little odd to constantly create an Context and provide it to these modules. ////! Because it can seem a little odd to constantly create an Context and provide it to these modules.
//! You can better use `Crossterm` for accessing these modules. ////! You can better use `Crossterm` for accessing these modules.
//! `Crossterm` handles the Context internally so jo do not have to bother about it, for example: ////! `Crossterm` handles the Context internally so jo do not have to bother about it, for example:
//! ////!
//! let crossterm = Crossterm::new(); ////! let crossterm = Crossterm::new();
//! let color = crossterm.color(); ////! let color = crossterm.color();
//! let cursor = crossterm.cursor(); ////! let cursor = crossterm.cursor();
//! let terminal = crossterm.terminal(); ////! let terminal = crossterm.terminal();
//
use super::super::cursor; //use super::super::cursor;
use super::super::input::input; //use super::super::input::input;
use super::super::style; //use super::super::style;
use super::super::terminal::terminal; //use super::super::terminal::terminal;
//
use Context; //use Context;
//
use std::convert::From; //use std::convert::From;
use std::fmt::Display; //use std::fmt::Display;
use std::mem; //use std::mem;
use std::rc::Rc; //use std::rc::Rc;
use std::sync::Arc; //use std::sync::Arc;
//
/// Because it can seem a little odd to constantly create an `Context` and provide it to modules like: `cursor, color and terminal`. ///// Because it can seem a little odd to constantly create an `Context` and provide it to modules like: `cursor, color and terminal`.
/// You can better use `Crossterm` for accessing these modules. ///// You can better use `Crossterm` for accessing these modules.
/// `Crossterm` handles the Context internally so jo do not have to bother about it, for example: ///// `Crossterm` handles the Context internally so jo do not have to bother about it, for example:
/// /////
/// Check `/examples/Crossterm 0.3.0/program_examples/first_depth_search` in the library for more specific examples. ///// Check `/examples/Crossterm 0.3.0/program_examples/first_depth_search` in the library for more specific examples.
/// /////
/// let crossterm = Crossterm::new(); ///// let crossterm = Crossterm::new();
/// let color = crossterm.color(); ///// let color = crossterm.color();
/// let cursor = crossterm.cursor(); ///// let cursor = crossterm.cursor();
/// let terminal = crossterm.terminal(); ///// let terminal = crossterm.terminal();
pub struct Crossterm { pub struct Crossterm {
context: Rc<Context>, // context: Rc<Context>,
}
/// Create `Crossterm` instance from `Context`
impl From<Rc<Context>> for Crossterm {
fn from(context: Rc<Context>) -> Self {
return Crossterm { context: context };
}
}
impl Crossterm {
pub fn new() -> Crossterm {
return Crossterm {
context: Context::new(),
};
}
/// Get an Terminal implementation whereon terminal related actions can be performed.
///
/// #Example
///
/// ```rust
///
/// extern crate crossterm;
/// use crossterm::Crossterm;
/// use crossterm::terminal;
///
/// let crossterm = Crossterm::new();
/// let mut terminal = crossterm.terminal();
///
/// ```
pub fn terminal(&self) -> terminal::Terminal {
return terminal::Terminal::new(self.context.clone());
}
/// Get an TerminalCursor implementation whereon cursor related actions can be performed.
///
/// #Example
///
/// ```rust
///
/// extern crate crossterm;
/// use crossterm::Crossterm;
/// use crossterm::terminal;
///
/// let crossterm = Crossterm::new();
/// let mut cursor = crossterm.cursor();
///
/// // move cursor to x: 5 and y:10
/// cursor.goto(5,10);
///
/// ```
pub fn cursor(&self) -> cursor::TerminalCursor {
return cursor::TerminalCursor::new(self.context.clone());
}
/// Get an Color implementation whereon color related actions can be performed.
///
/// Check `/examples/version/color` in the library for more specific examples.
///
/// #Example
///
/// ```rust
///
/// extern crate crossterm;
/// use crossterm::Crossterm;
/// use crossterm::terminal;
///
/// let crossterm = Crossterm::new();
/// let mut terminal_color = crossterm.color();
///
/// ```
pub fn color(&self) -> style::TerminalColor {
return style::TerminalColor::new(self.context.clone());
}
pub fn input(&self) -> input::TerminalInput {
return input::TerminalInput::new(self.context.clone());
}
/// Wraps an displayable object so it can be formatted with colors and attributes.
///
/// Check `/examples/color` in the library for more specific examples.
///
/// #Example
///
/// ```rust
/// extern crate crossterm;
///
/// use self::crossterm::style::{paint,Color};
/// use self::crossterm::Crossterm;
///
/// fn main()
/// {
/// let crossterm = Crossterm::new();
/// // Create an styledobject object from the text 'Unstyled font'
/// // Currently it has the default foreground color and background color.
/// println!("{}",crossterm.paint("Unstyled font"));
///
/// // Create an displayable object from the text 'Colored font',
/// // Paint this with the `Red` foreground color and `Blue` background color.
/// // Print the result.
/// let styledobject = crossterm.paint("Colored font").with(Color::Red).on(Color::Blue);
/// println!("{}", styledobject);
///
/// // Or all in one line
/// println!("{}", crossterm.paint("Colored font").with(Color::Red).on(Color::Blue));
/// }
/// ```
pub fn paint<'a, D: Display>(&'a self, value: D) -> style::StyledObject<D> {
self.terminal().paint(value)
}
/// Write any displayable value to the current screen weather it will be the main screen or alternate screen.
///
/// #Example
///
/// ```rust
///
/// extern crate crossterm;
/// use crossterm::Crossterm;
///
/// let mut crossterm = Crossterm::new();
/// crossterm.write("Some text \n Some text on new line.");
///
/// ```
pub fn write<D: Display>(&self, value: D) {
self.terminal().write(value)
}
/// Get an copy of the context that `Crossterm` uses internally.
pub fn context(&self) -> Rc<Context> {
self.context.clone()
}
} }
//
///// Create `Crossterm` instance from `Context`
//impl From<Rc<Context>> for Crossterm {
// fn from(context: Rc<Context>) -> Self {
// return Crossterm { context: context };
// }
//}
//
//impl Crossterm {
// pub fn new() -> Crossterm {
// return Crossterm {
// context: Context::new(),
// };
// }
//
// /// Get an Terminal implementation whereon terminal related actions can be performed.
// ///
// /// #Example
// ///
// /// ```rust
// ///
// /// extern crate crossterm;
// /// use crossterm::Crossterm;
// /// use crossterm::terminal;
// ///
// /// let crossterm = Crossterm::new();
// /// let mut terminal = crossterm.terminal();
// ///
// /// ```
// pub fn terminal(&self) -> terminal::Terminal {
// return terminal::Terminal::new(self.context.clone());
// }
//
// /// Get an TerminalCursor implementation whereon cursor related actions can be performed.
// ///
// /// #Example
// ///
// /// ```rust
// ///
// /// extern crate crossterm;
// /// use crossterm::Crossterm;
// /// use crossterm::terminal;
// ///
// /// let crossterm = Crossterm::new();
// /// let mut cursor = crossterm.cursor();
// ///
// /// // move cursor to x: 5 and y:10
// /// cursor.goto(5,10);
// ///
// /// ```
// pub fn cursor(&self) -> cursor::TerminalCursor {
// return cursor::TerminalCursor::new(self.context.clone());
// }
//
// /// Get an Color implementation whereon color related actions can be performed.
// ///
// /// Check `/examples/version/color` in the library for more specific examples.
// ///
// /// #Example
// ///
// /// ```rust
// ///
// /// extern crate crossterm;
// /// use crossterm::Crossterm;
// /// use crossterm::terminal;
// ///
// /// let crossterm = Crossterm::new();
// /// let mut terminal_color = crossterm.color();
// ///
// /// ```
// pub fn color(&self) -> style::TerminalColor {
// return style::TerminalColor::new(self.context.clone());
// }
//
// pub fn input(&self) -> input::TerminalInput {
// return input::TerminalInput::new(self.context.clone());
// }
//
// /// Wraps an displayable object so it can be formatted with colors and attributes.
// ///
// /// Check `/examples/color` in the library for more specific examples.
// ///
// /// #Example
// ///
// /// ```rust
// /// extern crate crossterm;
// ///
// /// use self::crossterm::style::{paint,Color};
// /// use self::crossterm::Crossterm;
// ///
// /// fn main()
// /// {
// /// let crossterm = Crossterm::new();
// /// // Create an styledobject object from the text 'Unstyled font'
// /// // Currently it has the default foreground color and background color.
// /// println!("{}",crossterm.paint("Unstyled font"));
// ///
// /// // Create an displayable object from the text 'Colored font',
// /// // Paint this with the `Red` foreground color and `Blue` background color.
// /// // Print the result.
// /// let styledobject = crossterm.paint("Colored font").with(Color::Red).on(Color::Blue);
// /// println!("{}", styledobject);
// ///
// /// // Or all in one line
// /// println!("{}", crossterm.paint("Colored font").with(Color::Red).on(Color::Blue));
// /// }
// /// ```
// pub fn paint<'a, D: Display>(&'a self, value: D) -> style::StyledObject<D> {
// self.terminal().paint(value)
// }
//
// /// Write any displayable value to the current screen weather it will be the main screen or alternate screen.
// ///
// /// #Example
// ///
// /// ```rust
// ///
// /// extern crate crossterm;
// /// use crossterm::Crossterm;
// ///
// /// let mut crossterm = Crossterm::new();
// /// crossterm.write("Some text \n Some text on new line.");
// ///
// /// ```
// pub fn write<D: Display>(&self, value: D) {
// self.terminal().write(value)
// }
//
// /// Get an copy of the context that `Crossterm` uses internally.
// pub fn context(&self) -> Rc<Context> {
// self.context.clone()
// }
//}

View File

@ -15,7 +15,7 @@ use kernel::windows_kernel::cursor::{pos, absolute_cursor_pos};
use kernel::unix_kernel::terminal::{exit, pos, terminal_size}; use kernel::unix_kernel::terminal::{exit, pos, terminal_size};
/// Get the terminal size based on the current platform. /// Get the terminal size based on the current platform.
pub fn get_terminal_size(screen_manager: &Rc<Mutex<ScreenManager>>) -> (u16, u16) { pub fn get_terminal_size(screen_manager: &ScreenManager) -> (u16, u16) {
#[cfg(unix)] #[cfg(unix)]
return terminal_size(); return terminal_size();
@ -24,12 +24,12 @@ pub fn get_terminal_size(screen_manager: &Rc<Mutex<ScreenManager>>) -> (u16, u16
} }
/// Get the cursor position based on the current platform. /// Get the cursor position based on the current platform.
pub fn get_cursor_position(context: Rc<Context>) -> (u16, u16) { pub fn get_cursor_position(screen_manager: &ScreenManager) -> (u16, u16) {
#[cfg(unix)] #[cfg(unix)]
return pos(context.clone()); return pos(screen_manager);
#[cfg(windows)] #[cfg(windows)]
return pos(&context.screen_manager); return pos(screen_manager);
} }
/// exit the current terminal. /// exit the current terminal.

View File

@ -147,16 +147,13 @@ impl IAlternateScreenCommand for ToAlternateScreenBufferCommand {
// Make the new screen buffer the active screen buffer. // Make the new screen buffer the active screen buffer.
csbi::set_active_screen_buffer(new_handle)?; csbi::set_active_screen_buffer(new_handle)?;
let b: &mut WinApiScreenManager = match screen_manager match screen_manager
.as_any() .as_any_mut()
.downcast_mut::<WinApiScreenManager>() .downcast_mut::<WinApiScreenManager>()
{ {
Some(b) => b, Some(b) => b.set_alternate_handle(new_handle),
None => return Err(Error::new(ErrorKind::Other,"Invalid cast exception")), None => return Err(Error::new(ErrorKind::Other,"Invalid cast exception")),
}; };
b.set_alternate_handle(new_handle);
Ok(()) Ok(())
} }