fixed raw mode

This commit is contained in:
= 2018-08-23 18:15:18 +02:00
parent cc55c190d8
commit 99fffee6b3
10 changed files with 110 additions and 50 deletions

View File

@ -19,6 +19,7 @@ use std::io::Write;
use std::{thread,time}; use std::{thread,time};
fn main() fn main()
{ {
input::keyboard::async_input::read_async_demo();
terminal::raw_mode::print_wait_screen_on_alternate_window(); terminal::raw_mode::print_wait_screen_on_alternate_window();
thread::sleep(time::Duration::from_millis(2000)); thread::sleep(time::Duration::from_millis(2000));
} }

View File

@ -13,42 +13,45 @@ fn main() {
let screen = Screen::new(true); let screen = Screen::new(true);
let crossterm = Crossterm::new(&screen); let crossterm = Crossterm::new(&screen);
let input = crossterm.input();
let terminal = crossterm.terminal();
let cursor = crossterm.cursor(); let cursor = crossterm.cursor();
let mut stdin = input.read_async().bytes();
cursor.hide(); cursor.hide();
let mut input_buf = Arc::new(Mutex::new(String::new())); let mut input_buf = Arc::new(Mutex::new(String::new()));
let mut count = 0; let mut count = 0;
let threads = log(input_buf.clone()); let threads = log(input_buf.clone(),&screen);
loop thread::spawn(move || {
{ let t = Crossterm::new(&screen);
let a = stdin.next(); let input = t.input();
let mut stdin = input.read_async().bytes();
match a { loop
Some(Ok(b'\n')) =>
{ {
input_buf.lock().unwrap().clear(); let a = stdin.next();
// need to start receiving again because if pressed enter then async reading will stop match a {
stdin = input.read_async().bytes(); Some(Ok(10)) =>
} {
Some(Ok(val)) => input_buf.lock().unwrap().clear();
{
input_buf.lock().unwrap().push(val as char); // need to start receiving again because if pressed enter then async reading will stop
} stdin = input.read_async().bytes();
_ => {} }
} Some(Ok(val)) =>
{
println!("{:?}",a);
input_buf.lock().unwrap().push(a.unwrap().unwrap() as char);
}
_ => {}
}
thread::sleep(time::Duration::from_millis(100));
count += 1;
}
});
thread::sleep(time::Duration::from_millis(100));
count += 1;
}
for thread in threads for thread in threads
{ {
@ -58,18 +61,19 @@ fn main() {
cursor.show(); cursor.show();
} }
fn log(input_buf: Arc<Mutex<String>>) -> Vec<thread::JoinHandle<()>> fn log(input_buf: Arc<Mutex<String>>, screen: &Screen) -> Vec<thread::JoinHandle<()>>
{ {
let mut threads = Vec::with_capacity(10); let mut threads = Vec::with_capacity(10);
let (_, term_height) = terminal(&Screen::default()).terminal_size();
for i in 0..10 let (_, term_height) = terminal(&screen).terminal_size();
for i in 0..1
{ {
let input_buffer = input_buf.clone(); let input_buffer = input_buf.clone();
let clone_stdout = screen.stdout.clone();
let join = thread::spawn( move || { let join = thread::spawn( move || {
let crossterm = Crossterm::new(&Screen::from(clone_stdout));
let crossterm = Crossterm::new(&Screen::new(true));
let cursor = crossterm.cursor(); let cursor = crossterm.cursor();
let terminal = crossterm.terminal(); let terminal = crossterm.terminal();

View File

@ -78,7 +78,9 @@ fn main() {
map.spawn_food(&free_positions, &screen); map.spawn_food(&free_positions, &screen);
} }
} }
drop(screen);
} }
game_over_screen(); game_over_screen();
} }

View File

@ -41,7 +41,7 @@ impl Position
pub fn remove(&self, screen: &Screen) pub fn remove(&self, screen: &Screen)
{ {
cursor(screen).goto(self.x as u16, self.y as u16); cursor(screen).goto(self.x as u16, self.y as u16);
terminal(&screen).write(" "); terminal(&screen).write(" ");
} }
} }

View File

@ -42,6 +42,6 @@ pub fn print_wait_screen_on_alternate_window() {
{ {
print_wait_screen(&mut alternate.screen); print_wait_screen(&mut alternate.screen);
} }
drop(screen);
println!("Whe are back at the main screen"); println!("Whe are back at the main screen");
} }

View File

@ -4,6 +4,9 @@ use super::{ IStateCommand};
use kernel::unix_kernel::terminal; use kernel::unix_kernel::terminal;
use termios::{tcsetattr, Termios, CREAD, ECHO, ICANON, TCSAFLUSH}; use termios::{tcsetattr, Termios, CREAD, ECHO, ICANON, TCSAFLUSH};
use std::sync::{Once, ONCE_INIT};
static TERMINAL_MODE: Once = ONCE_INIT;
const FD_STDIN: ::std::os::unix::io::RawFd = 1; const FD_STDIN: ::std::os::unix::io::RawFd = 1;
use std::io::{Error, ErrorKind, Result}; use std::io::{Error, ErrorKind, Result};
@ -55,3 +58,25 @@ impl NoncanonicalModeCommand {
} }
} }
// This command is used for enabling and disabling raw mode for the terminal.
/// This command is used for enabling and disabling raw mode for the terminal.
pub struct RawModeCommand;
impl RawModeCommand {
pub fn new() -> Self {
return RawModeCommand {}
}
/// Enables raw mode.
pub fn enable(&mut self) -> Result<()> {
terminal::into_raw_mode();
Ok(())
}
/// Disables raw mode.
pub fn disable(&mut self) -> Result<()> {
terminal::disable_raw_mode();
Ok(())
}
}

View File

@ -28,7 +28,7 @@ impl RawScreen {
pub fn into_raw_mode() -> io::Result<()> pub fn into_raw_mode() -> io::Result<()>
{ {
#[cfg(not(target_os = "windows"))] #[cfg(not(target_os = "windows"))]
let mut command = unix_command::NoncanonicalModeCommand::new(); let mut command = unix_command::RawModeCommand::new();
#[cfg(target_os = "windows")] #[cfg(target_os = "windows")]
let mut command = win_commands::RawModeCommand::new(); let mut command = win_commands::RawModeCommand::new();
@ -40,9 +40,9 @@ impl RawScreen {
pub fn disable_raw_modes() -> io::Result<()> pub fn disable_raw_modes() -> io::Result<()>
{ {
#[cfg(not(target_os = "windows"))] #[cfg(not(target_os = "windows"))]
let command = unix_command::NoncanonicalModeCommand::new(); let mut command = unix_command::RawModeCommand::new();
#[cfg(target_os = "windows")] #[cfg(target_os = "windows")]
let command = win_commands::RawModeCommand::new(); let mut command = win_commands::RawModeCommand::new();
command.disable()?; command.disable()?;
return Ok(()) return Ok(())

View File

@ -107,25 +107,52 @@ pub fn make_raw(termios: &mut Termios) {
static mut ORIGINAL_TERMINAL_MODE: Option<Termios> = None; static mut ORIGINAL_TERMINAL_MODE: Option<Termios> = None;
/// Get the current terminal mode. pub fn into_raw_mode() -> io::Result<()>
pub fn get_terminal_mode() -> io::Result<Termios> { {
extern "C" { let tty_f;
pub fn tcgetattr(fd: c_int, termptr: *mut Termios) -> c_int;
} let fd = unsafe {
if libc::isatty(libc::STDIN_FILENO) == 1 {
libc::STDIN_FILENO
} else {
tty_f = fs::File::open("/dev/tty")?;
tty_f.as_raw_fd()
}
};
let mut termios = Termios::from_fd(fd)?;
let original = termios.clone();
unsafe { unsafe {
if let Some(original_mode) = ORIGINAL_TERMINAL_MODE if let None = ORIGINAL_TERMINAL_MODE
{ {
return Ok(original_mode.clone()) ORIGINAL_TERMINAL_MODE = Some(original.clone())
} }
else {
let mut termios = mem::zeroed();
is_true(tcgetattr(0, &mut termios))?;
ORIGINAL_TERMINAL_MODE = Some(termios.clone());
return Ok(termios)
}
} }
make_raw(&mut termios);
tcsetattr(fd, TCSADRAIN, &termios)?;
Ok(())
}
pub fn disable_raw_mode() -> io::Result<()>
{
let tty_f;
let fd = unsafe {
if libc::isatty(libc::STDIN_FILENO) == 1 {
libc::STDIN_FILENO
} else {
tty_f = fs::File::open("/dev/tty")?;
tty_f.as_raw_fd()
}
};
if let Some(original) = unsafe { ORIGINAL_TERMINAL_MODE }
{
tcsetattr(fd, TCSADRAIN, &original)?;
}
Ok(())
} }
/// Get the TTY device. /// Get the TTY device.

View File

@ -6,7 +6,6 @@ static mut HAS_BEEN_TRIED_TO_ENABLE: bool = false;
static mut IS_ANSI_ON_WINDOWS_ENABLED: Option<bool> = None; static mut IS_ANSI_ON_WINDOWS_ENABLED: Option<bool> = None;
static mut DOES_WINDOWS_SUPPORT_ANSI: Option<bool> = None; static mut DOES_WINDOWS_SUPPORT_ANSI: Option<bool> = None;
static ENABLE_ANSI: Once = ONCE_INIT; static ENABLE_ANSI: Once = ONCE_INIT;
use common::commands::win_commands::EnableAnsiCommand; use common::commands::win_commands::EnableAnsiCommand;
use common::commands::IEnableAnsiCommand; use common::commands::IEnableAnsiCommand;

View File

@ -5,6 +5,7 @@ use super::*;
/// This struct is an ansi escape code implementation for terminal related actions. /// This struct is an ansi escape code implementation for terminal related actions.
pub struct AnsiTerminal; pub struct AnsiTerminal;
use cursor::TerminalCursor;
impl AnsiTerminal { impl AnsiTerminal {
pub fn new() -> AnsiTerminal { pub fn new() -> AnsiTerminal {
@ -17,6 +18,7 @@ impl ITerminal for AnsiTerminal {
match clear_type { match clear_type {
ClearType::All => { ClearType::All => {
stdout.write_str(csi!("2J")); stdout.write_str(csi!("2J"));
TerminalCursor::new(stdout).goto(0,0);
} }
ClearType::FromCursorDown => { ClearType::FromCursorDown => {
stdout.write_str(csi!("J")); stdout.write_str(csi!("J"));