some fixes
This commit is contained in:
		
							parent
							
								
									7f05f6e8a7
								
							
						
					
					
						commit
						f1959589c8
					
				@ -15,7 +15,7 @@ readme = "README.md"
 | 
			
		||||
winapi = { version =  "0.3.5", features = ["winbase","winuser","consoleapi","processenv","wincon", "handleapi","errhandlingapi"] }
 | 
			
		||||
 | 
			
		||||
[target.'cfg(unix)'.dependencies]
 | 
			
		||||
libc = "0.2.37"
 | 
			
		||||
libc = "0.2.43"
 | 
			
		||||
termios = "0.3.0"
 | 
			
		||||
 | 
			
		||||
[lib]
 | 
			
		||||
 | 
			
		||||
@ -1,9 +1,9 @@
 | 
			
		||||
extern crate crossterm;
 | 
			
		||||
 | 
			
		||||
use crossterm::{Screen, Crossterm};
 | 
			
		||||
use crossterm::{Screen, Crossterm, screen};
 | 
			
		||||
use crossterm::terminal::{terminal,Terminal, ClearType};
 | 
			
		||||
use crossterm::cursor::TerminalCursor;
 | 
			
		||||
 | 
			
		||||
use crossterm::cursor::{TerminalCursor, cursor};
 | 
			
		||||
use crossterm::input::input;
 | 
			
		||||
use std::sync::{Arc,Mutex};
 | 
			
		||||
use std::io::Read;
 | 
			
		||||
use std::{thread,time};
 | 
			
		||||
@ -18,13 +18,13 @@ fn main() {
 | 
			
		||||
 | 
			
		||||
    let mut input_buf = Arc::new(Mutex::new(String::new()));
 | 
			
		||||
 | 
			
		||||
    let mut count = 0;
 | 
			
		||||
 | 
			
		||||
    let threads = log(input_buf.clone(),&screen);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    let mut count = 0;
 | 
			
		||||
 | 
			
		||||
    thread::spawn(move || {
 | 
			
		||||
        let t = Crossterm::new(&screen);
 | 
			
		||||
        let input = t.input();
 | 
			
		||||
        let input = input(&screen);
 | 
			
		||||
        let mut stdin = input.read_async().bytes();
 | 
			
		||||
 | 
			
		||||
        loop
 | 
			
		||||
@ -32,16 +32,16 @@ fn main() {
 | 
			
		||||
                let a = stdin.next();
 | 
			
		||||
 | 
			
		||||
                match a {
 | 
			
		||||
                    Some(Ok(10)) =>
 | 
			
		||||
                    Some(Ok(13)) =>
 | 
			
		||||
                        {
 | 
			
		||||
                            input_buf.lock().unwrap().clear();
 | 
			
		||||
 | 
			
		||||
                            // need to start receiving again because if pressed enter then async reading will stop
 | 
			
		||||
                            stdin = input.read_async().bytes();
 | 
			
		||||
//                            stdin = input.read_async().bytes();
 | 
			
		||||
                        }
 | 
			
		||||
                    Some(Ok(val)) =>
 | 
			
		||||
                        Some(Ok(val)) =>
 | 
			
		||||
                        {
 | 
			
		||||
                            println!("{:?}",a);
 | 
			
		||||
//                            println!("{:?}",a);
 | 
			
		||||
                            input_buf.lock().unwrap().push(a.unwrap().unwrap() as char);
 | 
			
		||||
                        }
 | 
			
		||||
                    _ => {}
 | 
			
		||||
@ -50,7 +50,7 @@ fn main() {
 | 
			
		||||
                thread::sleep(time::Duration::from_millis(100));
 | 
			
		||||
                count += 1;
 | 
			
		||||
            }
 | 
			
		||||
    });
 | 
			
		||||
    }).join();
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    for thread in threads
 | 
			
		||||
@ -72,8 +72,9 @@ fn log(input_buf: Arc<Mutex<String>>, screen: &Screen) -> Vec<thread::JoinHandle
 | 
			
		||||
        let input_buffer = input_buf.clone();
 | 
			
		||||
        let clone_stdout = screen.stdout.clone();
 | 
			
		||||
 | 
			
		||||
        let crossterm = Crossterm::from(screen.stdout.clone());
 | 
			
		||||
 | 
			
		||||
        let join = thread::spawn( move || {
 | 
			
		||||
            let crossterm = Crossterm::new(&Screen::from(clone_stdout));
 | 
			
		||||
            let cursor = crossterm.cursor();
 | 
			
		||||
            let terminal = crossterm.terminal();
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -0,0 +1,98 @@
 | 
			
		||||
extern crate crossterm;
 | 
			
		||||
 | 
			
		||||
use crossterm::{Screen, Crossterm};
 | 
			
		||||
use crossterm::terminal::{terminal,Terminal, ClearType};
 | 
			
		||||
use crossterm::cursor::TerminalCursor;
 | 
			
		||||
 | 
			
		||||
use std::sync::{Arc,Mutex};
 | 
			
		||||
use std::io::Read;
 | 
			
		||||
use std::{thread,time};
 | 
			
		||||
 | 
			
		||||
fn main() {
 | 
			
		||||
    use crossterm::color;
 | 
			
		||||
 | 
			
		||||
    let screen = Screen::new(true);
 | 
			
		||||
    let crossterm = Arc::new(Crossterm::new(&screen));
 | 
			
		||||
 | 
			
		||||
    let cursor = crossterm.cursor();
 | 
			
		||||
    cursor.hide();
 | 
			
		||||
 | 
			
		||||
    let mut input_buf = Arc::new(Mutex::new(String::new()));
 | 
			
		||||
 | 
			
		||||
    let mut count = 0;
 | 
			
		||||
 | 
			
		||||
    let threads = log(input_buf.clone(),crossterm.clone());
 | 
			
		||||
 | 
			
		||||
    let crossterm_clone = crossterm.clone();
 | 
			
		||||
 | 
			
		||||
    thread::spawn(move || {
 | 
			
		||||
        let input = crossterm_clone.input();
 | 
			
		||||
        let mut stdin = input.read_async().bytes();
 | 
			
		||||
 | 
			
		||||
        loop
 | 
			
		||||
            {
 | 
			
		||||
                let a = stdin.next();
 | 
			
		||||
 | 
			
		||||
                match a {
 | 
			
		||||
                    Some(Ok(13)) =>
 | 
			
		||||
                        {
 | 
			
		||||
                            input_buf.lock().unwrap().clear();
 | 
			
		||||
                            // need to start receiving again because if pressed enter then async reading will stop
 | 
			
		||||
//                            stdin = input.read_async().bytes();
 | 
			
		||||
                        }
 | 
			
		||||
                    Some(Ok(val)) =>
 | 
			
		||||
                        {
 | 
			
		||||
//                            println!("{}",val);
 | 
			
		||||
                            input_buf.lock().unwrap().push(a.unwrap().unwrap() as u8 as char);
 | 
			
		||||
                        }
 | 
			
		||||
                    _ => {}
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                thread::sleep(time::Duration::from_millis(100));
 | 
			
		||||
                count += 1;
 | 
			
		||||
            }
 | 
			
		||||
    }).join();
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    for thread in threads
 | 
			
		||||
    {
 | 
			
		||||
        thread.join();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    cursor.show();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fn log(input_buf: Arc<Mutex<String>>, crossterm: Arc<Crossterm>) -> Vec<thread::JoinHandle<()>>
 | 
			
		||||
{
 | 
			
		||||
    let mut threads = Vec::with_capacity(10);
 | 
			
		||||
 | 
			
		||||
    let (_, term_height) = crossterm.terminal().terminal_size();
 | 
			
		||||
 | 
			
		||||
    for i in 0..1
 | 
			
		||||
    {
 | 
			
		||||
        let input_buffer = input_buf.clone();
 | 
			
		||||
        let crossterm_clone = crossterm.clone();
 | 
			
		||||
        let join = thread::spawn( move || {
 | 
			
		||||
 | 
			
		||||
            let cursor = crossterm_clone.cursor();
 | 
			
		||||
            let terminal = crossterm_clone.terminal();
 | 
			
		||||
 | 
			
		||||
            for j in 0..1000
 | 
			
		||||
            {
 | 
			
		||||
                swap_write(format!("Some output: {} from thread: {}", j, i).as_ref(), &input_buffer.lock().unwrap(), &terminal, &cursor, term_height);
 | 
			
		||||
                thread::sleep(time::Duration::from_millis(300));
 | 
			
		||||
            }
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        threads.push(join);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return threads;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub fn swap_write(msg: &str, input_buf: &String, terminal: &Terminal, cursor: &TerminalCursor, term_height: u16) {
 | 
			
		||||
    cursor.goto(0, term_height);
 | 
			
		||||
    terminal.clear(ClearType::CurrentLine);
 | 
			
		||||
    terminal.write(format!("{}\r\n", msg));
 | 
			
		||||
    terminal.write(format!(">{}", input_buf));
 | 
			
		||||
}
 | 
			
		||||
@ -2,12 +2,11 @@
 | 
			
		||||
 | 
			
		||||
use super::{ IStateCommand};
 | 
			
		||||
use kernel::unix_kernel::terminal;
 | 
			
		||||
use termios::{tcsetattr, Termios, CREAD, ECHO, ICANON, TCSAFLUSH};
 | 
			
		||||
 | 
			
		||||
use termios::{tcsetattr, Termios, CREAD, ECHO, ICANON, TCSAFLUSH, BRKINT, ICRNL, INPCK, ISTRIP, IXON, OPOST, CS8, IEXTEN, ISIG,VTIME, VMIN};
 | 
			
		||||
use libc::STDIN_FILENO;
 | 
			
		||||
use std::sync::{Once, ONCE_INIT};
 | 
			
		||||
static TERMINAL_MODE: Once = ONCE_INIT;
 | 
			
		||||
 | 
			
		||||
const FD_STDIN: ::std::os::unix::io::RawFd = 1;
 | 
			
		||||
 | 
			
		||||
use std::io::{Error, ErrorKind, Result};
 | 
			
		||||
 | 
			
		||||
@ -20,16 +19,25 @@ impl NoncanonicalModeCommand {
 | 
			
		||||
        NoncanonicalModeCommand {}
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
static mut ORIGINAL: Option<Termios> = None;
 | 
			
		||||
 | 
			
		||||
impl NoncanonicalModeCommand {
 | 
			
		||||
    pub fn enable(&mut self) -> Result<()> {
 | 
			
		||||
        // Set noncanonical mode
 | 
			
		||||
        if let Ok(orig) = Termios::from_fd(FD_STDIN) {
 | 
			
		||||
        if let Ok(orig) = Termios::from_fd(STDIN_FILENO) {
 | 
			
		||||
            TERMINAL_MODE.call_once(|| {
 | 
			
		||||
               unsafe { ORIGINAL = Some(orig.clone()); }
 | 
			
		||||
            });
 | 
			
		||||
 | 
			
		||||
            let mut noncan = orig.clone();
 | 
			
		||||
            noncan.c_lflag &= !ICANON;
 | 
			
		||||
            noncan.c_lflag &= !ECHO;
 | 
			
		||||
            noncan.c_lflag &= !CREAD;
 | 
			
		||||
            tcsetattr(FD_STDIN, TCSAFLUSH, &noncan)?;
 | 
			
		||||
            noncan.c_iflag &= !(BRKINT | ICRNL | INPCK | ISTRIP | IXON);
 | 
			
		||||
            noncan.c_oflag &= !(OPOST);
 | 
			
		||||
            noncan.c_cflag |= (CS8);
 | 
			
		||||
            noncan.c_lflag &= !(ECHO | ICANON | IEXTEN | ISIG);
 | 
			
		||||
            noncan.c_cc[VMIN] = 0;
 | 
			
		||||
            noncan.c_cc[VTIME] = 1;
 | 
			
		||||
 | 
			
		||||
            tcsetattr(STDIN_FILENO, TCSAFLUSH, &noncan)?;
 | 
			
		||||
        } else {
 | 
			
		||||
            return Err(Error::new(
 | 
			
		||||
                ErrorKind::Other,
 | 
			
		||||
@ -40,20 +48,14 @@ impl NoncanonicalModeCommand {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    pub fn disable(&self) -> Result<()> {
 | 
			
		||||
        // Disable noncanonical mode
 | 
			
		||||
        if let Ok(orig) = Termios::from_fd(FD_STDIN) {
 | 
			
		||||
            let mut noncan = orig.clone();
 | 
			
		||||
            noncan.c_lflag &= ICANON;
 | 
			
		||||
            noncan.c_lflag &= ECHO;
 | 
			
		||||
            noncan.c_lflag &= CREAD;
 | 
			
		||||
 | 
			
		||||
            tcsetattr(FD_STDIN, TCSAFLUSH, &noncan)?;
 | 
			
		||||
        } else {
 | 
			
		||||
            return Err(Error::new(
 | 
			
		||||
                ErrorKind::Other,
 | 
			
		||||
                "Could not set console mode when enabling raw mode",
 | 
			
		||||
            ));
 | 
			
		||||
        unsafe {
 | 
			
		||||
            if let Some(original) = ORIGINAL
 | 
			
		||||
            {
 | 
			
		||||
                tcsetattr(STDIN_FILENO, TCSAFLUSH, &original)?;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        Ok(())
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -122,4 +122,11 @@ impl<'crossterm> Crossterm {
 | 
			
		||||
        D: Display,    {
 | 
			
		||||
        style::ObjectStyle::new().apply_to(val)
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl From<Arc<TerminalOutput>> for Crossterm
 | 
			
		||||
{
 | 
			
		||||
    fn from(stdout: Arc<TerminalOutput>) -> Self {
 | 
			
		||||
        Crossterm { stdout: stdout }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@ -32,7 +32,8 @@ impl RawScreen {
 | 
			
		||||
        #[cfg(target_os = "windows")]
 | 
			
		||||
        let mut command = win_commands::RawModeCommand::new();
 | 
			
		||||
 | 
			
		||||
        command.enable()?;
 | 
			
		||||
        let result = command.enable();
 | 
			
		||||
 | 
			
		||||
        Ok(())
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -56,7 +56,7 @@ impl Screen
 | 
			
		||||
        if raw_mode
 | 
			
		||||
        {
 | 
			
		||||
            let screen = Screen { stdout: Arc::new(TerminalOutput::new(true)), buffer: Vec::new() };
 | 
			
		||||
            RawScreen::into_raw_mode();
 | 
			
		||||
            RawScreen::into_raw_mode().unwrap();
 | 
			
		||||
            return screen;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@ -123,6 +123,7 @@ impl Drop for Screen
 | 
			
		||||
        if self.stdout.is_in_raw_mode
 | 
			
		||||
        {
 | 
			
		||||
            RawScreen::disable_raw_modes();
 | 
			
		||||
            panic!("drop");
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -159,10 +159,18 @@ pub fn disable_raw_mode() -> io::Result<()>
 | 
			
		||||
///
 | 
			
		||||
/// This allows for getting stdio representing _only_ the TTY, and not other streams.
 | 
			
		||||
pub fn get_tty() -> io::Result<fs::File> {
 | 
			
		||||
    fs::OpenOptions::new()
 | 
			
		||||
        .read(true)
 | 
			
		||||
        .write(true)
 | 
			
		||||
        .open("/dev/tty")
 | 
			
		||||
    let mut tty_f: fs::File = unsafe { ::std::mem::zeroed() };
 | 
			
		||||
 | 
			
		||||
    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()
 | 
			
		||||
        }
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    return Ok(tty_f);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub fn read_char() -> io::Result<char> {
 | 
			
		||||
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user