From 1a64a21df2a96aadd1189814fd62dac9cbe71654 Mon Sep 17 00:00:00 2001 From: Timon Date: Thu, 26 Jul 2018 16:25:20 +0000 Subject: [PATCH] unix fixed not fully tested jet --- examples/Crossterm 0.3.1/bin.rs | 59 +++++------- .../input/keyboard/async_input.rs | 13 +-- src/cursor/ansi_cursor.rs | 5 - src/cursor/cursor.rs | 5 - src/cursor/mod.rs | 3 - src/cursor/winapi_cursor.rs | 5 - src/input/unix_input.rs | 31 +++--- src/kernel/unix_kernel/terminal.rs | 96 +++++++++---------- src/shared/functions.rs | 10 -- src/terminal/ansi_terminal.rs | 2 - src/terminal/mod.rs | 4 - src/terminal/terminal.rs | 4 - src/terminal/winapi_terminal.rs | 2 - 13 files changed, 85 insertions(+), 154 deletions(-) diff --git a/examples/Crossterm 0.3.1/bin.rs b/examples/Crossterm 0.3.1/bin.rs index a66119e..afeff6e 100644 --- a/examples/Crossterm 0.3.1/bin.rs +++ b/examples/Crossterm 0.3.1/bin.rs @@ -27,19 +27,7 @@ use crossterm::raw::IntoRawMode; use std::{thread, time}; fn main() { - // let context = Context::new(); - crossterm(); - { - // let screen = ::crossterm::screen::AlternateScreen::from(context.clone()); - // screen.into_raw_mode(context.clone()); - - // async_input::async_reading_on_alternate_screen(); - // async_input::test(); - // stdin::t(); - // stdin::read_line(); - // stdin::read_char(); - // stdin::read_char(); - } + async_input::read_async(); } use crossterm::raw::RawTerminal; @@ -63,29 +51,34 @@ pub fn crossterm() { let mut raw_screen = RawTerminal::new(&crossterm.context()); raw_screen.enable(); - let mut stdin = input.read_until_async().bytes(); + let mut stdin = input.read_async().bytes(); let mut buf = String::new(); - - let (term_x, term_y) = term.terminal_size(); - let mut command_bar_y = term_y; - let (curs_x, curs_y) = cursor.pos(); - - let mut counter: u16 = 0 + curs_y; +// +// let (term_x, term_y) = term.terminal_size(); +// +// let mut command_bar_y = term_y; +// let (curs_x, curs_y) = cursor.pos(); +// + let mut counter: u16 = 0; loop { - cursor.goto(0, counter); - let (curs_x, curs_y) = cursor.pos(); - term.write(format!("cursor pos {} term pos: {} command pos: {}", curs_y, term_y, command_bar_y)); - cursor.goto(0, counter + 1); - - if (curs_y >= term_y - 1 ) - { - cursor.goto(0, counter + 1); - term.clear(ClearType::CurrentLine); - cursor.goto(0, counter + 2); - term.write(format!("> {}", buf)); - term.scroll_up(1); - } +// cursor.goto(0, counter); +// +// let (curs_x, curs_y) = cursor.pos(); +// term.write(format!("cursor pos {} term pos: {} command pos: {}", curs_y, term_y, command_bar_y)); +// +// cursor.goto(0, counter + 1); +// +// if (curs_y >= term_y - 1 ) +// { +// cursor.goto(0, counter + 1); +// term.clear(ClearType::CurrentLine); +// cursor.goto(0, counter + 2); +// term.write(format!("> {}", buf)); +// term.scroll_up(1); +// } +// + term.write(format!("> {}", buf)); while let Some(b) = stdin.next() { if let Ok(b) = b { diff --git a/examples/Crossterm 0.3.1/input/keyboard/async_input.rs b/examples/Crossterm 0.3.1/input/keyboard/async_input.rs index 8c415da..24b44a0 100644 --- a/examples/Crossterm 0.3.1/input/keyboard/async_input.rs +++ b/examples/Crossterm 0.3.1/input/keyboard/async_input.rs @@ -83,8 +83,8 @@ pub fn read_async_demo() { // get the next pressed key let pressed_key = stdin.next(); + terminal.write(format!("\r{:?} <- Character pressed", pressed_key)); - write!(stdout, "\r{:?} <- Character pressed", pressed_key).unwrap(); // check if pressed key is enter (\r) if let Some(Ok(b'\r')) = pressed_key { @@ -114,11 +114,6 @@ pub fn async_reading_on_alternate_screen() { // this will setup the async reading. let mut stdin = input.read_async().bytes(); - // clear terminal and reset the cursor. - terminal.clear(ClearType::All); - cursor.goto(1, 1); - - // panic!(); // loop until the enter key (\r) is pressed. loop { @@ -128,11 +123,7 @@ pub fn async_reading_on_alternate_screen() { // get the next pressed key let pressed_key = stdin.next(); - write!( - alternate_screen, - "\r{:?} <- Character pressed", - pressed_key - ).unwrap(); + terminal.write(format!("\r{:?} <- Character pressed", pressed_key)); // check if pressed key is enter (\r) if let Some(Ok(b'\r')) = pressed_key { diff --git a/src/cursor/ansi_cursor.rs b/src/cursor/ansi_cursor.rs index 7f50a06..79c6284 100644 --- a/src/cursor/ansi_cursor.rs +++ b/src/cursor/ansi_cursor.rs @@ -29,11 +29,6 @@ impl ITerminalCursor for AnsiCursor { functions::get_cursor_position(self.context.clone()) } - fn absolute_pos(&self) -> (u16, u16) - { - functions::get_absolute_cursor_pos(&self.context) - } - fn move_up(&self, count: u16) { let mut screen = self.context.screen_manager.lock().unwrap(); { diff --git a/src/cursor/cursor.rs b/src/cursor/cursor.rs index 963c6e6..bc32910 100644 --- a/src/cursor/cursor.rs +++ b/src/cursor/cursor.rs @@ -86,11 +86,6 @@ impl TerminalCursor { self.terminal_cursor.pos() } - pub fn absolute_pos(&self) -> (u16, u16) - { - self.terminal_cursor.absolute_pos() - } - /// Move the current cursor position `n` times up. /// /// #Example diff --git a/src/cursor/mod.rs b/src/cursor/mod.rs index 941799d..6285902 100644 --- a/src/cursor/mod.rs +++ b/src/cursor/mod.rs @@ -34,9 +34,6 @@ pub trait ITerminalCursor { fn goto(&self, x: u16, y: u16); /// Get the location (x,y) of the current cusror in the context fn pos(&self) -> (u16, u16); - - fn absolute_pos(&self) -> (u16, u16); - /// Move cursor n times up fn move_up(&self, count: u16); /// Move the cursor `n` times to the right. diff --git a/src/cursor/winapi_cursor.rs b/src/cursor/winapi_cursor.rs index 689d72e..0488306 100644 --- a/src/cursor/winapi_cursor.rs +++ b/src/cursor/winapi_cursor.rs @@ -29,11 +29,6 @@ impl ITerminalCursor for WinApiCursor { cursor::pos(&self.screen_manager) } - fn absolute_pos(&self) -> (u16, u16) - { - cursor::absolute_cursor_pos(&self.screen_manager) - } - fn move_up(&self, count: u16) { let (xpos, ypos) = self.pos(); self.goto(xpos, ypos - count); diff --git a/src/input/unix_input.rs b/src/input/unix_input.rs index 0e10780..086d3ac 100644 --- a/src/input/unix_input.rs +++ b/src/input/unix_input.rs @@ -37,11 +37,9 @@ impl ITerminalInput for UnixInput { fn read_async(&self) -> AsyncReader { let (send, recv) = mpsc::channel(); - thread::spawn(move || { - for i in get_tty().unwrap().bytes() { - if send.send(i).is_err() { - return; - } + thread::spawn(move || for i in get_tty().unwrap().bytes() { + if send.send(i).is_err() { + return; } }); @@ -51,21 +49,16 @@ impl ITerminalInput for UnixInput { fn read_until_async(&self, delimiter: u8) -> AsyncReader { let (send, recv) = mpsc::channel(); - thread::spawn(move || { - for i in get_tty().unwrap().bytes() { - match i { - Ok(byte) => { - let end_of_stream = &byte == &delimiter; - let send_error = send.send(Ok(byte)).is_err(); + thread::spawn(move || for i in get_tty().unwrap().bytes() { - if end_of_stream || send_error { - return; - } - } - Err(_) => { - return; - } - } + match i { + Ok(byte) => { + let end_of_stream = &byte == &delimiter; + let send_error = send.send(Ok(byte)).is_err(); + + if end_of_stream || send_error { return; } + }, + Err(_) => { return; } } }); diff --git a/src/kernel/unix_kernel/terminal.rs b/src/kernel/unix_kernel/terminal.rs index 7595072..08454e1 100644 --- a/src/kernel/unix_kernel/terminal.rs +++ b/src/kernel/unix_kernel/terminal.rs @@ -2,7 +2,7 @@ pub use self::libc::termios; use self::libc::{c_int, c_ushort, ioctl, STDOUT_FILENO, TIOCGWINSZ}; -use state::commands::{IStateCommand, NoncanonicalModeCommand}; +use state::commands::{IStateCommand, NoncanonicalModeCommand, EnableRawModeCommand}; use {libc, CommandManager, Context, StateManager}; use std::io::Error; @@ -19,8 +19,8 @@ pub struct UnixSize { pub rows: c_ushort, /// number of columns pub cols: c_ushort, - x: c_ushort, - y: c_ushort, + pub ws_xpixel: c_ushort, + pub ws_ypixel: c_ushort, } /// Get the current terminal size. @@ -29,81 +29,75 @@ pub fn terminal_size() -> (u16, u16) { let us = UnixSize { rows: 0, cols: 0, - x: 0, - y: 0, + ws_xpixel: 0, + ws_ypixel: 0, }; let r = unsafe { ioctl(STDOUT_FILENO, TIOCGWINSZ, &us) }; if r == 0 { // because crossterm works starts counting at 0 and unix terminal starts at cell 1 you have subtract one to get 0-based results. (us.cols - 1, us.rows - 1) + } else { (0, 0) } } + +use std::time::{SystemTime, Duration}; +use std::io::ErrorKind; +use Crossterm; +use std::io::Read; /// Get the current cursor position. pub fn pos(context: Rc) -> (u16, u16) { - use std::io::{Read, Write}; + let crossterm = Crossterm::from(context.clone()); + let input = crossterm.input(); - let mut command_id = NoncanonicalModeCommand::new(&context.state_manager); + let delimiter = b'R'; + let mut stdin = input.read_until_async(delimiter); - CommandManager::execute(context.clone(), command_id); + // Where is the cursor? + // Use `ESC [ 6 n`. - // This code is original written by term_cursor credits to them. - use std::io; - let mut std = io::stdout(); - // Write command - std.write(b"\x1B[6n"); - std.flush(); + crossterm.write("\x1B[6n"); - // Read back result - let mut buf = [0u8; 2]; - // Expect `ESC[` - io::stdin().read_exact(&mut buf); - if buf[0] != 0x1B || buf[1] as char != '[' { - return (0, 0); - } + let mut buf: [u8; 1] = [0]; + let mut read_chars = Vec::new(); - // Read rows and cols through a ad-hoc integer parsing function - let read_num = || -> (i32, char) { - let mut num = 0; - let mut c; + let timeout = Duration::from_millis(2000); + let now = SystemTime::now(); - loop { - let mut buf = [0u8; 1]; - io::stdin().read_exact(&mut buf); - c = buf[0] as char; - if let Some(d) = c.to_digit(10) { - num = if num == 0 { 0 } else { num * 10 }; - num += d as i32; - } else { - break; + // Either consume all data up to R or wait for a timeout. + while buf[0] != delimiter && now.elapsed().unwrap() < timeout { + if let Ok(c) = stdin.read(&mut buf){ + if c >= 0 + { + read_chars.push(buf[0]); } } + } - (num, c) - }; - - // Read rows and expect `;` - let (rows, c) = read_num(); - - if c != ';' { + if read_chars.len() == 0 { return (0, 0); } - // Read cols - let (cols, c) = read_num(); + // The answer will look like `ESC [ Cy ; Cx R`. - // Expect `R` - let res = if c == 'R' { - (cols as u16, rows as u16) - } else { - return (0, 0); - }; + read_chars.pop(); // remove trailing R. + let read_str = String::from_utf8(read_chars).unwrap(); + let beg = read_str.rfind('[').unwrap(); + let coords: String = read_str.chars().skip(beg + 1).collect(); + let mut nums = coords.split(';'); - CommandManager::undo(context.clone(), command_id); + let cy = nums.next() + .unwrap() + .parse::() + .unwrap(); + let cx = nums.next() + .unwrap() + .parse::() + .unwrap(); - res + (cx, cy) } /// Set the terminal mode to the given mode. diff --git a/src/shared/functions.rs b/src/shared/functions.rs index f7d2034..a54e97c 100644 --- a/src/shared/functions.rs +++ b/src/shared/functions.rs @@ -32,16 +32,6 @@ pub fn get_cursor_position(context: Rc) -> (u16, u16) { return pos(&context.screen_manager); } -pub fn get_buffer_size(context: &Rc) -> (u16, u16) -{ - return buffer_size(&context.screen_manager); -} - -pub fn get_absolute_cursor_pos(context: &Rc) -> (u16, u16) -{ - return absolute_cursor_pos(&context.screen_manager); -} - /// exit the current terminal. pub fn exit_terminal() { #[cfg(unix)] diff --git a/src/terminal/ansi_terminal.rs b/src/terminal/ansi_terminal.rs index 1063ad9..ff6dc41 100644 --- a/src/terminal/ansi_terminal.rs +++ b/src/terminal/ansi_terminal.rs @@ -45,8 +45,6 @@ impl ITerminal for AnsiTerminal { functions::get_terminal_size(&self.context.screen_manager) } - fn buffer_size(&self) -> (u16, u16) { functions::get_buffer_size(&self.context) } - fn scroll_up(&self, count: i16) { let mut screen = self.context.screen_manager.lock().unwrap(); { diff --git a/src/terminal/mod.rs b/src/terminal/mod.rs index 0662b95..47ee25b 100644 --- a/src/terminal/mod.rs +++ b/src/terminal/mod.rs @@ -42,10 +42,6 @@ pub trait ITerminal { fn clear(&self, clear_type: ClearType); /// Get the terminal size (x,y) fn terminal_size(&self) -> (u16, u16); - - // get the size of the current buffer - fn buffer_size(&self) -> (u16, u16); - /// Scroll `n` lines up in the current terminal. fn scroll_up(&self, count: i16); /// Scroll `n` lines down in the current terminal. diff --git a/src/terminal/terminal.rs b/src/terminal/terminal.rs index 33c6248..240659f 100644 --- a/src/terminal/terminal.rs +++ b/src/terminal/terminal.rs @@ -85,10 +85,6 @@ impl Terminal { return self.terminal.terminal_size(); } - pub fn buffer_size(&self) -> (u16, u16) { - return self.terminal.buffer_size(); - } - /// Scroll `n` lines up in the current terminal. /// /// #Example diff --git a/src/terminal/winapi_terminal.rs b/src/terminal/winapi_terminal.rs index aae70fb..77171f0 100644 --- a/src/terminal/winapi_terminal.rs +++ b/src/terminal/winapi_terminal.rs @@ -40,8 +40,6 @@ impl ITerminal for WinApiTerminal { terminal::terminal_size(&self.context.screen_manager) } - fn buffer_size(&self) -> (u16, u16) {terminal::buffer_size(&self.context.screen_manager)} - fn scroll_up(&self, count: i16) { let csbi = csbi::get_csbi(&self.context.screen_manager).unwrap();