fixed input and cursor with new implementation
This commit is contained in:
parent
d7387ed227
commit
26472359bc
@ -25,4 +25,12 @@ use crossterm::Terminal;
|
||||
use std::{thread, time};
|
||||
|
||||
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)
|
||||
}
|
||||
|
@ -4,95 +4,63 @@
|
||||
|
||||
use super::*;
|
||||
use shared::functions;
|
||||
use Context;
|
||||
use {Context,ScreenManager};
|
||||
|
||||
/// This struct is an ansi implementation for cursor related actions.
|
||||
pub struct AnsiCursor {
|
||||
context: Rc<Context>,
|
||||
}
|
||||
pub struct AnsiCursor;
|
||||
|
||||
impl AnsiCursor {
|
||||
pub fn new(context: Rc<Context>) -> Box<AnsiCursor> {
|
||||
Box::from(AnsiCursor { context })
|
||||
pub fn new() -> Box<AnsiCursor> {
|
||||
Box::from(AnsiCursor { })
|
||||
}
|
||||
}
|
||||
|
||||
impl ITerminalCursor for AnsiCursor {
|
||||
fn goto(&self, x: u16, y: u16) {
|
||||
let mut screen = self.context.screen_manager.lock().unwrap();
|
||||
{
|
||||
screen.write_string(format!(csi!("{};{}H"), y + 1, x + 1));
|
||||
}
|
||||
fn goto(&self, x: u16, y: u16, screen_manager: &ScreenManager) {
|
||||
screen_manager.write_string(format!(csi!("{};{}H"), y + 1, x + 1));
|
||||
}
|
||||
|
||||
fn pos(&self) -> (u16, u16) {
|
||||
functions::get_cursor_position(self.context.clone())
|
||||
fn pos(&self, screen_manager: &ScreenManager) -> (u16, u16) {
|
||||
functions::get_cursor_position(screen_manager)
|
||||
}
|
||||
|
||||
fn move_up(&self, count: u16) {
|
||||
let mut screen = self.context.screen_manager.lock().unwrap();
|
||||
{
|
||||
screen.write_string(format!(csi!("{}A"), count));
|
||||
}
|
||||
fn move_up(&self, count: u16, screen_manager: &ScreenManager) {
|
||||
screen_manager.write_string(format!(csi!("{}A"), count));
|
||||
}
|
||||
|
||||
fn move_right(&self, count: u16) {
|
||||
let mut screen = self.context.screen_manager.lock().unwrap();
|
||||
{
|
||||
screen.write_string(format!(csi!("{}C"), count));
|
||||
}
|
||||
fn move_right(&self, count: u16, screen_manager: &ScreenManager) {
|
||||
screen_manager.write_string(format!(csi!("{}C"), count));
|
||||
}
|
||||
|
||||
fn move_down(&self, count: u16) {
|
||||
let mut screen = self.context.screen_manager.lock().unwrap();
|
||||
{
|
||||
screen.write_string(format!(csi!("{}B"), count));
|
||||
}
|
||||
fn move_down(&self, count: u16, screen_manager: &ScreenManager) {
|
||||
screen_manager.write_string(format!(csi!("{}B"), count));
|
||||
}
|
||||
|
||||
fn move_left(&self, count: u16) {
|
||||
let mut screen = self.context.screen_manager.lock().unwrap();
|
||||
{
|
||||
screen.write_string(format!(csi!("{}D"), count));
|
||||
}
|
||||
fn move_left(&self, count: u16, screen_manager: &ScreenManager) {
|
||||
screen_manager.write_string(format!(csi!("{}D"), count));
|
||||
}
|
||||
|
||||
fn save_position(&self) {
|
||||
let mut screen = self.context.screen_manager.lock().unwrap();
|
||||
{
|
||||
screen.write_str(csi!("s"));
|
||||
}
|
||||
fn save_position(&self, screen_manager: &ScreenManager) {
|
||||
screen_manager.write_str(csi!("s"));
|
||||
}
|
||||
|
||||
fn reset_position(&self) {
|
||||
let mut screen = self.context.screen_manager.lock().unwrap();
|
||||
{
|
||||
screen.write_str(csi!("u"));
|
||||
}
|
||||
fn reset_position(&self, screen_manager: &ScreenManager) {
|
||||
screen_manager.write_str(csi!("u"));
|
||||
}
|
||||
|
||||
fn hide(&self) {
|
||||
let mut screen = self.context.screen_manager.lock().unwrap();
|
||||
{
|
||||
screen.write_str(csi!("?25l"));
|
||||
}
|
||||
fn hide(&self, screen_manager: &ScreenManager) {
|
||||
screen_manager.write_str(csi!("?25l"));
|
||||
}
|
||||
|
||||
fn show(&self) {
|
||||
let mut screen = self.context.screen_manager.lock().unwrap();
|
||||
{
|
||||
screen.write_str(csi!("?25h"));
|
||||
}
|
||||
fn show(&self, screen_manager: &ScreenManager) {
|
||||
screen_manager.write_str(csi!("?25h"));
|
||||
}
|
||||
|
||||
fn blink(&self, blink: bool) {
|
||||
let mut screen = self.context.screen_manager.lock().unwrap();
|
||||
{
|
||||
if blink {
|
||||
screen.write_str(csi!("?12h"));
|
||||
} else {
|
||||
screen.write_str(csi!("?12l"));
|
||||
}
|
||||
fn blink(&self, blink: bool, screen_manager: &ScreenManager) {
|
||||
if blink {
|
||||
screen_manager.write_str(csi!("?12h"));
|
||||
} else {
|
||||
screen_manager.write_str(csi!("?12l"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -13,25 +13,25 @@ use std::rc::Rc;
|
||||
|
||||
/// Struct that stores an specific platform implementation for cursor related actions.
|
||||
pub struct TerminalCursor<'cursor> {
|
||||
context: &'cursor ScreenManager,
|
||||
screen_manager: &'cursor ScreenManager,
|
||||
terminal_cursor: Box<ITerminalCursor>,
|
||||
}
|
||||
|
||||
impl<'cursor> TerminalCursor<'cursor> {
|
||||
/// 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")]
|
||||
let cursor = functions::get_module::<Box<ITerminalCursor>>(
|
||||
WinApiCursor::new(context.screen_manager.clone()),
|
||||
AnsiCursor::new(context.clone()),
|
||||
WinApiCursor::new(),
|
||||
AnsiCursor::new(),
|
||||
).unwrap();
|
||||
|
||||
#[cfg(not(target_os = "windows"))]
|
||||
let cursor = AnsiCursor::new(context.clone()) as Box<ITerminalCursor>;
|
||||
let cursor = AnsiCursor::new() as Box<ITerminalCursor>;
|
||||
|
||||
TerminalCursor {
|
||||
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 {
|
||||
self.terminal_cursor.goto(x, y);
|
||||
pub fn goto(&mut self, x: u16, y: u16) -> &mut TerminalCursor<'cursor> {
|
||||
self.terminal_cursor.goto(x, y, &self.screen_manager);
|
||||
self
|
||||
}
|
||||
|
||||
@ -83,7 +83,7 @@ impl<'cursor> TerminalCursor<'cursor> {
|
||||
///
|
||||
/// ```
|
||||
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.
|
||||
@ -107,8 +107,8 @@ impl<'cursor> TerminalCursor<'cursor> {
|
||||
/// }
|
||||
///
|
||||
/// ```
|
||||
pub fn move_up(&mut self, count: u16) -> &mut TerminalCursor {
|
||||
self.terminal_cursor.move_up(count);
|
||||
pub fn move_up(&mut self, count: u16) -> &mut TerminalCursor<'cursor> {
|
||||
self.terminal_cursor.move_up(count, &self.screen_manager);
|
||||
self
|
||||
}
|
||||
|
||||
@ -131,8 +131,8 @@ impl<'cursor> TerminalCursor<'cursor> {
|
||||
/// cursor.move_right(3);
|
||||
/// }
|
||||
/// ```
|
||||
pub fn move_right(&mut self, count: u16) -> &mut TerminalCursor {
|
||||
self.terminal_cursor.move_right(count);
|
||||
pub fn move_right(&mut self, count: u16) -> &mut TerminalCursor<'cursor> {
|
||||
self.terminal_cursor.move_right(count, &self.screen_manager);
|
||||
self
|
||||
}
|
||||
|
||||
@ -157,8 +157,8 @@ impl<'cursor> TerminalCursor<'cursor> {
|
||||
/// }
|
||||
///
|
||||
/// ```
|
||||
pub fn move_down(&mut self, count: u16) -> &mut TerminalCursor {
|
||||
self.terminal_cursor.move_down(count);
|
||||
pub fn move_down(&mut self, count: u16) -> &mut TerminalCursor<'cursor> {
|
||||
self.terminal_cursor.move_down(count, &self.screen_manager);
|
||||
self
|
||||
}
|
||||
|
||||
@ -183,8 +183,8 @@ impl<'cursor> TerminalCursor<'cursor> {
|
||||
/// }
|
||||
///
|
||||
/// ```
|
||||
pub fn move_left(&mut self, count: u16) -> &mut TerminalCursor {
|
||||
self.terminal_cursor.move_left(count);
|
||||
pub fn move_left(&mut self, count: u16) -> &mut TerminalCursor<'cursor> {
|
||||
self.terminal_cursor.move_left(count, &self.screen_manager);
|
||||
self
|
||||
}
|
||||
|
||||
@ -224,19 +224,13 @@ impl<'cursor> TerminalCursor<'cursor> {
|
||||
/// .print("@");
|
||||
///
|
||||
/// ```
|
||||
pub fn print<D: Display>(&mut self, value: D) -> &mut TerminalCursor {
|
||||
{
|
||||
use std::fmt::Write;
|
||||
let mut string = String::new();
|
||||
write!(string, "{}", value).unwrap();
|
||||
pub fn print<D: Display>(&mut self, value: D) -> &mut TerminalCursor<'cursor> {
|
||||
use std::fmt::Write;
|
||||
let mut string = String::new();
|
||||
write!(string, "{}", value).unwrap();
|
||||
|
||||
let mut mutex = &self.context.screen_manager;
|
||||
{
|
||||
let mut screen_manager = mutex.lock().unwrap();
|
||||
screen_manager.write_string(string);
|
||||
screen_manager.flush();
|
||||
}
|
||||
}
|
||||
&self.screen_manager.write_string(string);
|
||||
&self.screen_manager.flush();
|
||||
self
|
||||
}
|
||||
|
||||
@ -257,7 +251,7 @@ impl<'cursor> TerminalCursor<'cursor> {
|
||||
///
|
||||
/// ```
|
||||
pub fn save_position(&self) {
|
||||
self.terminal_cursor.save_position();
|
||||
self.terminal_cursor.save_position(&self.screen_manager);
|
||||
}
|
||||
|
||||
/// Return to saved cursor position
|
||||
@ -277,7 +271,7 @@ impl<'cursor> TerminalCursor<'cursor> {
|
||||
///
|
||||
/// ```
|
||||
pub fn reset_position(&self) {
|
||||
self.terminal_cursor.reset_position();
|
||||
self.terminal_cursor.reset_position(&self.screen_manager);
|
||||
}
|
||||
|
||||
/// Hide de cursor in the console.
|
||||
@ -295,7 +289,7 @@ impl<'cursor> TerminalCursor<'cursor> {
|
||||
///
|
||||
/// ```
|
||||
pub fn hide(&self) {
|
||||
self.terminal_cursor.hide();
|
||||
self.terminal_cursor.hide(&self.screen_manager);
|
||||
}
|
||||
|
||||
/// Show the cursor in the console.
|
||||
@ -313,7 +307,7 @@ impl<'cursor> TerminalCursor<'cursor> {
|
||||
///
|
||||
/// ```
|
||||
pub fn show(&self) {
|
||||
self.terminal_cursor.show();
|
||||
self.terminal_cursor.show(&self.screen_manager);
|
||||
}
|
||||
|
||||
/// Enable or disable blinking of the terminal.
|
||||
@ -335,37 +329,37 @@ impl<'cursor> TerminalCursor<'cursor> {
|
||||
///
|
||||
/// ```
|
||||
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.
|
||||
///
|
||||
/// Check `/examples/version/cursor` in the libary for more spesific examples.
|
||||
///
|
||||
/// #Example
|
||||
///
|
||||
/// ```rust
|
||||
///
|
||||
/// extern crate crossterm;
|
||||
/// use self::crossterm::Context;
|
||||
/// use self::crossterm::cursor;
|
||||
///
|
||||
/// let context = Context::new();
|
||||
///
|
||||
/// // Get cursor and goto pos X: 5, Y: 10
|
||||
/// let mut cursor = cursor::cursor(&context);
|
||||
/// cursor.goto(5,10);
|
||||
///
|
||||
/// cursor.show();
|
||||
/// cursor.hide();
|
||||
/// cursor.blink();
|
||||
/// cursor.move_left(2);
|
||||
///
|
||||
/// //Or you can do it in one line.
|
||||
/// cursor::cursor(&context).goto(5,10);
|
||||
///
|
||||
/// ```
|
||||
pub fn cursor(context: &Rc<Context>) -> Box<TerminalCursor> {
|
||||
Box::from(TerminalCursor::new(context.clone()))
|
||||
}
|
||||
// Get an TerminalCursor implementation whereon cursor related actions can be performed.
|
||||
//
|
||||
// Check `/examples/version/cursor` in the libary for more spesific examples.
|
||||
//
|
||||
// #Example
|
||||
//
|
||||
// ```rust
|
||||
//
|
||||
// extern crate crossterm;
|
||||
// use self::crossterm::Context;
|
||||
// use self::crossterm::cursor;
|
||||
//
|
||||
// let context = Context::new();
|
||||
//
|
||||
// // Get cursor and goto pos X: 5, Y: 10
|
||||
// let mut cursor = cursor::cursor(&context);
|
||||
// cursor.goto(5,10);
|
||||
//
|
||||
// cursor.show();
|
||||
// cursor.hide();
|
||||
// cursor.blink();
|
||||
// cursor.move_left(2);
|
||||
//
|
||||
// //Or you can do it in one line.
|
||||
// cursor::cursor(&context).goto(5,10);
|
||||
//
|
||||
// ```
|
||||
//pub fn cursor(context: &ScreenManager) -> Box<TerminalCursor> {
|
||||
// Box::from(TerminalCursor::new(context.clone()))
|
||||
//}
|
||||
|
@ -17,8 +17,8 @@ use self::ansi_cursor::AnsiCursor;
|
||||
#[cfg(target_os = "windows")]
|
||||
use self::winapi_cursor::WinApiCursor;
|
||||
|
||||
pub use self::cursor::{cursor, TerminalCursor};
|
||||
|
||||
pub use self::cursor::{TerminalCursor};
|
||||
use ScreenManager;
|
||||
use std::rc::Rc;
|
||||
|
||||
///! This trait defines the actions that can be preformed with the terminal cursor.
|
||||
|
@ -20,47 +20,47 @@ impl WinApiCursor {
|
||||
|
||||
impl ITerminalCursor for WinApiCursor {
|
||||
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) {
|
||||
cursor::pos(&self.screen_manager)
|
||||
cursor::pos(screen_manager)
|
||||
}
|
||||
|
||||
fn move_up(&self, count: u16, screen_manager: &ScreenManager) {
|
||||
let (xpos, ypos) = self.pos();
|
||||
self.goto(xpos, ypos - count);
|
||||
let (xpos, ypos) = self.pos(screen_manager);
|
||||
self.goto(xpos, ypos - count, screen_manager);
|
||||
}
|
||||
|
||||
fn move_right(&self, count: u16, screen_manager: &ScreenManager) {
|
||||
let (xpos, ypos) = self.pos();
|
||||
self.goto(xpos + count, ypos);
|
||||
let (xpos, ypos) = self.pos(screen_manager);
|
||||
self.goto(xpos + count, ypos, screen_manager);
|
||||
}
|
||||
|
||||
fn move_down(&self, count: u16, screen_manager: &ScreenManager) {
|
||||
let (xpos, ypos) = self.pos();
|
||||
self.goto(xpos, ypos + count);
|
||||
let (xpos, ypos) = self.pos(screen_manager);
|
||||
self.goto(xpos, ypos + count, screen_manager);
|
||||
}
|
||||
|
||||
fn move_left(&self, count: u16, screen_manager: &ScreenManager) {
|
||||
let (xpos, ypos) = self.pos();
|
||||
self.goto(xpos - count, ypos);
|
||||
let (xpos, ypos) = self.pos(screen_manager);
|
||||
self.goto(xpos - count, ypos, screen_manager);
|
||||
}
|
||||
|
||||
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) {
|
||||
cursor::reset_to_saved_position(&self.screen_manager);
|
||||
cursor::reset_to_saved_position(screen_manager);
|
||||
}
|
||||
|
||||
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) {
|
||||
cursor::cursor_visibility(true, &self.screen_manager);
|
||||
cursor::cursor_visibility(true, screen_manager);
|
||||
}
|
||||
|
||||
fn blink(&self, blink: bool, screen_manager: &ScreenManager) {}
|
||||
|
@ -2,48 +2,44 @@ use std::io;
|
||||
|
||||
use super::*;
|
||||
use std::rc::Rc;
|
||||
use Context;
|
||||
use {Context, ScreenManager };
|
||||
|
||||
pub struct TerminalInput {
|
||||
context: Rc<Context>,
|
||||
pub struct TerminalInput<'terminal> {
|
||||
terminal_input: Box<ITerminalInput>,
|
||||
screen_manager: &'terminal ScreenManager
|
||||
}
|
||||
|
||||
impl TerminalInput {
|
||||
pub fn new(context: Rc<Context>) -> TerminalInput {
|
||||
impl<'terminal> TerminalInput<'terminal> {
|
||||
pub fn new(screen_manager: &'terminal ScreenManager) -> TerminalInput<'terminal> {
|
||||
#[cfg(target_os = "windows")]
|
||||
let input = Box::from(WindowsInput::new(context.clone()));
|
||||
let input = Box::from(WindowsInput::new());
|
||||
|
||||
#[cfg(not(target_os = "windows"))]
|
||||
let input = Box::from(UnixInput::new());
|
||||
|
||||
TerminalInput {
|
||||
terminal_input: input,
|
||||
context,
|
||||
screen_manager: screen_manager
|
||||
}
|
||||
}
|
||||
|
||||
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> {
|
||||
return self.terminal_input.read_char();
|
||||
}
|
||||
|
||||
pub fn read_key(&self) -> io::Result<Key> {
|
||||
self.terminal_input.read_pressed_key()
|
||||
return self.terminal_input.read_char(&self.screen_manager);
|
||||
}
|
||||
|
||||
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 {
|
||||
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> {
|
||||
return Box::from(TerminalInput::new(context.clone()));
|
||||
pub fn input(screen_manager: &ScreenManager) -> TerminalInput {
|
||||
return TerminalInput::new(screen_manager)
|
||||
}
|
||||
|
@ -13,18 +13,18 @@ use self::unix_input::UnixInput;
|
||||
mod unix_input;
|
||||
|
||||
pub use self::input::{input, TerminalInput};
|
||||
use ScreenManager;
|
||||
|
||||
use std::io::Read;
|
||||
use std::sync::mpsc;
|
||||
|
||||
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_pressed_key(&self) -> io::Result<Key>;
|
||||
fn read_char(&self, screen_manger: &ScreenManager) -> io::Result<char>;
|
||||
|
||||
fn read_async(&self) -> AsyncReader;
|
||||
fn read_until_async(&self, delimiter: u8) -> AsyncReader;
|
||||
fn read_async(&self, screen_manger: &ScreenManager) -> AsyncReader;
|
||||
fn read_until_async(&self, delimiter: u8, screen_manger: &ScreenManager) -> AsyncReader;
|
||||
}
|
||||
|
||||
pub struct AsyncReader {
|
||||
|
@ -8,7 +8,7 @@ use std::thread;
|
||||
use super::super::kernel::unix_kernel::terminal::{get_tty, read_char};
|
||||
use super::super::terminal::terminal;
|
||||
use super::{AsyncReader, ITerminalInput, Key};
|
||||
|
||||
use ScreenManager;
|
||||
pub struct UnixInput;
|
||||
|
||||
impl UnixInput {
|
||||
@ -18,7 +18,7 @@ impl 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();
|
||||
io::stdin().read_line(&mut rv)?;
|
||||
let len = rv.trim_right_matches(&['\r', '\n'][..]).len();
|
||||
@ -26,15 +26,11 @@ impl ITerminalInput for UnixInput {
|
||||
Ok(rv)
|
||||
}
|
||||
|
||||
fn read_char(&self) -> io::Result<char> {
|
||||
fn read_char(&self, screen_manger: &ScreenManager) -> io::Result<char> {
|
||||
read_char()
|
||||
}
|
||||
|
||||
fn read_pressed_key(&self) -> io::Result<Key> {
|
||||
Ok(Key::Unknown)
|
||||
}
|
||||
|
||||
fn read_async(&self) -> AsyncReader {
|
||||
fn read_async(&self, screen_manger: &ScreenManager) -> AsyncReader {
|
||||
let (send, recv) = mpsc::channel();
|
||||
|
||||
thread::spawn(move || for i in get_tty().unwrap().bytes() {
|
||||
@ -46,7 +42,7 @@ impl ITerminalInput for UnixInput {
|
||||
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();
|
||||
|
||||
thread::spawn(move || for i in get_tty().unwrap().bytes() {
|
||||
|
@ -9,36 +9,23 @@ use super::{AsyncReader, ITerminalInput, Key};
|
||||
use winapi::um::winnt::INT;
|
||||
use winapi::um::winuser;
|
||||
|
||||
use super::super::terminal::terminal;
|
||||
use std::rc::Rc;
|
||||
use Context;
|
||||
use ScreenManager;
|
||||
|
||||
pub struct WindowsInput {
|
||||
context: Rc<Context>,
|
||||
pub display_input: bool,
|
||||
}
|
||||
pub struct WindowsInput;
|
||||
|
||||
impl WindowsInput {
|
||||
pub fn new(context: Rc<Context>) -> WindowsInput {
|
||||
WindowsInput {
|
||||
context,
|
||||
display_input: false,
|
||||
}
|
||||
pub fn new() -> WindowsInput {
|
||||
WindowsInput {}
|
||||
}
|
||||
}
|
||||
|
||||
impl ITerminalInput for WindowsInput {
|
||||
fn read_line(&self) -> io::Result<String> {
|
||||
let term = terminal(&self.context);
|
||||
fn read_line(&self,screen_manger: &ScreenManager) -> io::Result<String> {
|
||||
let mut chars: Vec<char> = Vec::new();
|
||||
|
||||
loop {
|
||||
let mut is_raw_screen = false;
|
||||
{
|
||||
let mutex = &self.context.screen_manager;
|
||||
let screen = mutex.lock().unwrap();
|
||||
is_raw_screen = screen.is_raw_screen();
|
||||
}
|
||||
let is_raw_screen = screen_manger.is_raw_screen();
|
||||
|
||||
// _getwch is without echo and _getwche is with echo
|
||||
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());
|
||||
}
|
||||
|
||||
fn read_char(&self) -> io::Result<char> {
|
||||
let term = terminal(&self.context);
|
||||
|
||||
let mut is_raw_screen = false;
|
||||
{
|
||||
let mutex = &self.context.screen_manager;
|
||||
let screen = mutex.lock().unwrap();
|
||||
is_raw_screen = screen.is_raw_screen();
|
||||
}
|
||||
fn read_char(&self, screen_manger: &ScreenManager) -> io::Result<char> {
|
||||
let is_raw_screen = screen_manger.is_raw_screen();
|
||||
|
||||
// _getwch is without echo and _getwche is with echo
|
||||
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) {
|
||||
Some(c) => {
|
||||
if self.display_input {
|
||||
term.write(c);
|
||||
}
|
||||
return Ok(c);
|
||||
}
|
||||
None => Err(io::Error::new(
|
||||
@ -98,41 +75,11 @@ impl ITerminalInput for WindowsInput {
|
||||
}
|
||||
}
|
||||
|
||||
fn read_pressed_key(&self) -> io::Result<Key> {
|
||||
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 {
|
||||
fn read_async(&self,screen_manger: &ScreenManager) -> AsyncReader {
|
||||
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 || {
|
||||
loop {
|
||||
|
||||
@ -155,15 +102,10 @@ impl ITerminalInput for WindowsInput {
|
||||
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 mut is_raw_screen = false;
|
||||
{
|
||||
let mutex =&self.context.screen_manager;
|
||||
let screen = mutex.lock().unwrap();
|
||||
is_raw_screen = screen.is_raw_screen();
|
||||
}
|
||||
let is_raw_screen = screen_manger.is_raw_screen();
|
||||
|
||||
thread::spawn(move || {
|
||||
loop {
|
||||
|
@ -16,7 +16,7 @@ use std::sync::Mutex;
|
||||
use ScreenManager;
|
||||
|
||||
/// 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 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.
|
||||
pub fn get_csbi_and_handle(
|
||||
screen_manager: &Rc<Mutex<ScreenManager>>,
|
||||
screen_manager: &ScreenManager,
|
||||
) -> Result<(CONSOLE_SCREEN_BUFFER_INFO, HANDLE)> {
|
||||
let handle = handle::get_current_handle(screen_manager)?;
|
||||
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
|
||||
pub fn set_console_screen_buffer_size(
|
||||
size: COORD,
|
||||
screen_manager: &Rc<Mutex<ScreenManager>>,
|
||||
screen_manager: &ScreenManager,
|
||||
) -> bool {
|
||||
let handle = handle::get_current_handle(screen_manager).unwrap();
|
||||
|
||||
|
@ -16,7 +16,7 @@ use std::sync::Mutex;
|
||||
static mut SAVED_CURSOR_POS: (u16, u16) = (0, 0);
|
||||
|
||||
/// 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 {
|
||||
set_console_cursor_position(
|
||||
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.
|
||||
pub fn save_cursor_pos(screen_manager: &Rc<Mutex<ScreenManager>>) {
|
||||
pub fn save_cursor_pos(screen_manager: &ScreenManager) {
|
||||
let position = pos(screen_manager);
|
||||
|
||||
unsafe {
|
||||
@ -36,7 +36,7 @@ pub fn save_cursor_pos(screen_manager: &Rc<Mutex<ScreenManager>>) {
|
||||
}
|
||||
|
||||
/// 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();
|
||||
|
||||
@ -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();
|
||||
|
||||
@ -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.
|
||||
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() {
|
||||
panic!(
|
||||
"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.
|
||||
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 cursor_info = CONSOLE_CURSOR_INFO {
|
||||
|
@ -6,27 +6,23 @@ use winapi::um::winnt::HANDLE;
|
||||
use std::io::{self, ErrorKind, Result};
|
||||
use std::rc::Rc;
|
||||
use std::sync::Mutex;
|
||||
|
||||
use super::super::super::manager::{ScreenManager, WinApiScreenManager};
|
||||
|
||||
/// 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 handle: Result<HANDLE>;
|
||||
|
||||
let mut screen_manager = mutex.lock().unwrap();
|
||||
{
|
||||
let winapi_screen_manager: &mut WinApiScreenManager = match screen_manager
|
||||
let winapi_screen_manager: &WinApiScreenManager = match screen_manager
|
||||
.as_any()
|
||||
.downcast_mut::<WinApiScreenManager>()
|
||||
.downcast_ref::<WinApiScreenManager>()
|
||||
{
|
||||
Some(win_api) => win_api,
|
||||
None => return Err(io::Error::new(io::ErrorKind::Other,"Could not convert to winapi screen manager, this could happen when the user has an ANSI screen manager and is calling the platform specific operations 'get_cursor_pos' or 'get_terminal_size'"))
|
||||
};
|
||||
|
||||
handle = Ok(*winapi_screen_manager.get_handle());
|
||||
}
|
||||
handle = Ok(*winapi_screen_manager.get_handle());
|
||||
|
||||
return handle;
|
||||
}
|
||||
|
@ -37,7 +37,7 @@ pub fn get_console_mode(handle: &HANDLE, current_mode: &mut u32) -> bool {
|
||||
}
|
||||
|
||||
/// 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();
|
||||
|
||||
unsafe {
|
||||
@ -49,7 +49,7 @@ pub fn set_console_text_attribute(value: u16, screen_manager: &Rc<Mutex<ScreenMa
|
||||
pub fn set_console_info(
|
||||
absolute: bool,
|
||||
rect: &SMALL_RECT,
|
||||
screen_manager: &Rc<Mutex<ScreenManager>>,
|
||||
screen_manager: &ScreenManager,
|
||||
) -> bool {
|
||||
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.
|
||||
//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);
|
||||
// console_buffer_info.wAttributes as u16
|
||||
//}
|
||||
|
@ -5,7 +5,7 @@ use ScreenManager;
|
||||
use super::{csbi, handle};
|
||||
|
||||
/// 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();
|
||||
|
||||
@ -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();
|
||||
|
||||
|
@ -20,7 +20,7 @@ pub fn fill_console_output_character(
|
||||
cells_written: &mut u32,
|
||||
start_location: COORD,
|
||||
cells_to_write: u32,
|
||||
screen_manager: &Rc<Mutex<ScreenManager>>,
|
||||
screen_manager: &ScreenManager,
|
||||
) -> bool {
|
||||
let handle = handle::get_current_handle(screen_manager).unwrap();
|
||||
|
||||
@ -42,7 +42,7 @@ pub fn fill_console_output_attribute(
|
||||
cells_written: &mut u32,
|
||||
start_location: COORD,
|
||||
cells_to_write: u32,
|
||||
screen_manager: &Rc<Mutex<ScreenManager>>,
|
||||
screen_manager: &ScreenManager,
|
||||
) -> bool {
|
||||
// Get the position of the current console window
|
||||
|
||||
|
@ -11,11 +11,11 @@ mod state;
|
||||
pub mod cursor;
|
||||
pub mod input;
|
||||
pub mod manager;
|
||||
pub mod style;
|
||||
//pub mod style;
|
||||
pub mod terminal;
|
||||
|
||||
pub use shared::Terminal::Terminal;
|
||||
pub use shared::crossterm::Crossterm;
|
||||
//pub use shared::crossterm::Crossterm;
|
||||
pub use shared::raw;
|
||||
pub use shared::screen;
|
||||
pub use state::context::Context;
|
||||
|
@ -4,14 +4,14 @@
|
||||
|
||||
use std::any::Any;
|
||||
use std::io::{self, Read, Write};
|
||||
|
||||
use std::sync::Mutex;
|
||||
use super::IScreenManager;
|
||||
use std::str::from_utf8;
|
||||
|
||||
pub struct AnsiScreenManager {
|
||||
is_alternate_screen: bool,
|
||||
is_raw_screen: bool,
|
||||
output: Box<Write>,
|
||||
input: Box<Read>,
|
||||
output: Mutex<Box<Write>>
|
||||
}
|
||||
|
||||
impl IScreenManager for AnsiScreenManager {
|
||||
@ -31,41 +31,37 @@ impl IScreenManager for AnsiScreenManager {
|
||||
self.is_alternate_screen
|
||||
}
|
||||
|
||||
fn write_string(&mut self, string: String) -> io::Result<usize> {
|
||||
write!(self.output, "{}", string)?;
|
||||
fn write_str(&self, string: &str) -> io::Result<usize> {
|
||||
{
|
||||
let mx = &self.output;
|
||||
|
||||
let mut output = mx.lock().unwrap();
|
||||
write!(output, "{}", string)?;
|
||||
}
|
||||
self.flush();
|
||||
Ok(0)
|
||||
}
|
||||
|
||||
fn write_str(&mut self, string: &str) -> io::Result<usize> {
|
||||
write!(self.output, "{}", string)?;
|
||||
self.flush();
|
||||
fn write(&self, buf: &[u8]) -> io::Result<usize> {
|
||||
{
|
||||
let mx = &self.output;
|
||||
let mut output = mx.lock().unwrap();
|
||||
output.write(buf)?;
|
||||
}
|
||||
Ok(0)
|
||||
}
|
||||
|
||||
// fn read_line(&mut self) -> io::Result<String>
|
||||
// {
|
||||
// let mut rv = String::new();
|
||||
// self.input.read_line(&mut rv)?;
|
||||
// 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(&self) -> io::Result<()> {
|
||||
let mx = &self.output;
|
||||
let mut output = mx.lock().unwrap();
|
||||
output.flush()
|
||||
}
|
||||
|
||||
fn flush(&mut self) -> io::Result<()> {
|
||||
self.output.flush()
|
||||
fn as_any(&self) -> &Any {
|
||||
self
|
||||
}
|
||||
|
||||
fn as_any(&mut self) -> &mut Any {
|
||||
fn as_any_mut(&mut self) -> &mut Any {
|
||||
self
|
||||
}
|
||||
}
|
||||
@ -73,8 +69,7 @@ impl IScreenManager for AnsiScreenManager {
|
||||
impl AnsiScreenManager {
|
||||
pub fn new() -> Self {
|
||||
AnsiScreenManager {
|
||||
input: (Box::from(io::stdin()) as Box<Read>),
|
||||
output: (Box::from(io::stdout()) as Box<Write>),
|
||||
output: Mutex::new(Box::from(io::stdout()) as Box<Write>),
|
||||
is_alternate_screen: false,
|
||||
is_raw_screen: false,
|
||||
}
|
||||
|
@ -52,27 +52,26 @@ impl ScreenManager {
|
||||
}
|
||||
|
||||
/// Write an ANSI code as String.
|
||||
pub fn write_string(&mut self, string: String) -> io::Result<usize> {
|
||||
self.screen_manager.write_string(string)
|
||||
pub fn write_string(&self, string: String) -> io::Result<usize> {
|
||||
self.screen_manager.write_str(string.as_str())
|
||||
}
|
||||
|
||||
pub fn flush(&self) -> io::Result<()>
|
||||
{
|
||||
self.screen_manager.flush()
|
||||
}
|
||||
/// 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)
|
||||
}
|
||||
|
||||
/// 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()
|
||||
}
|
||||
}
|
||||
|
||||
impl Write for ScreenManager {
|
||||
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
|
||||
self.screen_manager.write(buf)
|
||||
}
|
||||
|
||||
fn flush(&mut self) -> io::Result<()> {
|
||||
self.screen_manager.flush()
|
||||
/// Can be used to get an specific implementation used for the current platform.
|
||||
pub fn as_any_mut(&mut self) -> &mut Any {
|
||||
self.screen_manager.as_any_mut()
|
||||
}
|
||||
}
|
||||
|
@ -39,14 +39,14 @@ pub trait IScreenManager {
|
||||
fn is_raw_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.
|
||||
fn write_str(&mut self, string: &str) -> io::Result<usize>;
|
||||
fn write_str(&self, string: &str) -> io::Result<usize>;
|
||||
/// 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.
|
||||
fn flush(&mut self) -> io::Result<()>;
|
||||
fn flush(&self) -> io::Result<()>;
|
||||
/// 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;
|
||||
}
|
||||
|
@ -15,7 +15,6 @@ pub struct WinApiScreenManager {
|
||||
}
|
||||
|
||||
impl IScreenManager for WinApiScreenManager {
|
||||
|
||||
fn set_is_raw_screen(&mut self, value: bool) {
|
||||
self.is_raw_screen = value;
|
||||
}
|
||||
@ -31,16 +30,11 @@ impl IScreenManager for WinApiScreenManager {
|
||||
self.is_alternate_screen
|
||||
}
|
||||
|
||||
|
||||
fn write_string(&mut self, string: String) -> io::Result<usize> {
|
||||
fn write_str(&self, string: &str) -> io::Result<usize> {
|
||||
self.write(string.as_bytes())
|
||||
}
|
||||
|
||||
fn write_str(&mut self, string: &str) -> io::Result<usize> {
|
||||
self.write(string.as_bytes())
|
||||
}
|
||||
|
||||
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
|
||||
fn write(&self, buf: &[u8]) -> io::Result<usize> {
|
||||
if self.is_alternate_screen {
|
||||
writing::write_char_buffer(&self.alternate_handle, buf)
|
||||
} else {
|
||||
@ -48,11 +42,15 @@ impl IScreenManager for WinApiScreenManager {
|
||||
}
|
||||
}
|
||||
|
||||
fn flush(&mut self) -> io::Result<()> {
|
||||
fn flush(&self) -> io::Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn as_any(&mut self) -> &mut Any {
|
||||
fn as_any(&self) -> &Any {
|
||||
self
|
||||
}
|
||||
|
||||
fn as_any_mut(&mut self) -> &mut Any {
|
||||
self
|
||||
}
|
||||
}
|
||||
@ -76,7 +74,7 @@ impl WinApiScreenManager {
|
||||
}
|
||||
|
||||
/// get the current screen handle.
|
||||
pub fn get_handle(&mut self) -> &HANDLE {
|
||||
pub fn get_handle(&self) -> &HANDLE {
|
||||
if self.is_alternate_screen {
|
||||
return &self.alternate_handle;
|
||||
} else {
|
||||
|
@ -2,6 +2,12 @@ use {StateManager, ScreenManager};
|
||||
use super::super::state::commands::*;
|
||||
use super::raw::RawTerminal;
|
||||
use super::screen::AlternateScreen;
|
||||
|
||||
use super::super::cursor;
|
||||
use super::super::input;
|
||||
use super::super::terminal;
|
||||
|
||||
|
||||
use std::collections::HashMap;
|
||||
|
||||
use std::io::Result;
|
||||
@ -93,6 +99,18 @@ impl Terminal{
|
||||
|
||||
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
|
||||
|
@ -1,183 +1,183 @@
|
||||
//! 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).
|
||||
//!
|
||||
//! You have to provide this `Context` to the modules: `cursor::cursor(), color::color(), terminal::terminal()`.
|
||||
//!
|
||||
//! use crossterm::Context;
|
||||
//! use crossterm::cursor;
|
||||
//! use crossterm::color;
|
||||
//! use crossterm::terminal;
|
||||
//!
|
||||
//! let context = Context::new();
|
||||
//! let cursor = cursor::cursor(&context)
|
||||
//! let terminal = terminal::terminal(&context);
|
||||
//! let color = terminal::color(&context);
|
||||
//!
|
||||
//! 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.
|
||||
//! `Crossterm` handles the Context internally so jo do not have to bother about it, for example:
|
||||
//!
|
||||
//! let crossterm = Crossterm::new();
|
||||
//! let color = crossterm.color();
|
||||
//! let cursor = crossterm.cursor();
|
||||
//! let terminal = crossterm.terminal();
|
||||
|
||||
use super::super::cursor;
|
||||
use super::super::input::input;
|
||||
use super::super::style;
|
||||
use super::super::terminal::terminal;
|
||||
|
||||
use Context;
|
||||
|
||||
use std::convert::From;
|
||||
use std::fmt::Display;
|
||||
use std::mem;
|
||||
use std::rc::Rc;
|
||||
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`.
|
||||
/// 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:
|
||||
///
|
||||
/// Check `/examples/Crossterm 0.3.0/program_examples/first_depth_search` in the library for more specific examples.
|
||||
///
|
||||
/// let crossterm = Crossterm::new();
|
||||
/// let color = crossterm.color();
|
||||
/// let cursor = crossterm.cursor();
|
||||
/// let terminal = crossterm.terminal();
|
||||
////! 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).
|
||||
////!
|
||||
////! You have to provide this `Context` to the modules: `cursor::cursor(), color::color(), terminal::terminal()`.
|
||||
////!
|
||||
////! use crossterm::Context;
|
||||
////! use crossterm::cursor;
|
||||
////! use crossterm::color;
|
||||
////! use crossterm::terminal;
|
||||
////!
|
||||
////! let context = Context::new();
|
||||
////! let cursor = cursor::cursor(&context)
|
||||
////! let terminal = terminal::terminal(&context);
|
||||
////! let color = terminal::color(&context);
|
||||
////!
|
||||
////! 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.
|
||||
////! `Crossterm` handles the Context internally so jo do not have to bother about it, for example:
|
||||
////!
|
||||
////! let crossterm = Crossterm::new();
|
||||
////! let color = crossterm.color();
|
||||
////! let cursor = crossterm.cursor();
|
||||
////! let terminal = crossterm.terminal();
|
||||
//
|
||||
//use super::super::cursor;
|
||||
//use super::super::input::input;
|
||||
//use super::super::style;
|
||||
//use super::super::terminal::terminal;
|
||||
//
|
||||
//use Context;
|
||||
//
|
||||
//use std::convert::From;
|
||||
//use std::fmt::Display;
|
||||
//use std::mem;
|
||||
//use std::rc::Rc;
|
||||
//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`.
|
||||
///// 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:
|
||||
/////
|
||||
///// Check `/examples/Crossterm 0.3.0/program_examples/first_depth_search` in the library for more specific examples.
|
||||
/////
|
||||
///// let crossterm = Crossterm::new();
|
||||
///// let color = crossterm.color();
|
||||
///// let cursor = crossterm.cursor();
|
||||
///// let terminal = crossterm.terminal();
|
||||
pub struct Crossterm {
|
||||
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()
|
||||
}
|
||||
// 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()
|
||||
// }
|
||||
//}
|
||||
|
@ -15,7 +15,7 @@ use kernel::windows_kernel::cursor::{pos, absolute_cursor_pos};
|
||||
use kernel::unix_kernel::terminal::{exit, pos, terminal_size};
|
||||
|
||||
/// 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)]
|
||||
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.
|
||||
pub fn get_cursor_position(context: Rc<Context>) -> (u16, u16) {
|
||||
pub fn get_cursor_position(screen_manager: &ScreenManager) -> (u16, u16) {
|
||||
#[cfg(unix)]
|
||||
return pos(context.clone());
|
||||
return pos(screen_manager);
|
||||
|
||||
#[cfg(windows)]
|
||||
return pos(&context.screen_manager);
|
||||
return pos(screen_manager);
|
||||
}
|
||||
|
||||
/// exit the current terminal.
|
||||
|
@ -147,16 +147,13 @@ impl IAlternateScreenCommand for ToAlternateScreenBufferCommand {
|
||||
// Make the new screen buffer the active screen buffer.
|
||||
csbi::set_active_screen_buffer(new_handle)?;
|
||||
|
||||
let b: &mut WinApiScreenManager = match screen_manager
|
||||
.as_any()
|
||||
match screen_manager
|
||||
.as_any_mut()
|
||||
.downcast_mut::<WinApiScreenManager>()
|
||||
{
|
||||
Some(b) => b,
|
||||
Some(b) => b.set_alternate_handle(new_handle),
|
||||
None => return Err(Error::new(ErrorKind::Other,"Invalid cast exception")),
|
||||
};
|
||||
|
||||
b.set_alternate_handle(new_handle);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user