summary refs log tree commit diff
path: root/src/terminal.rs
diff options
context:
space:
mode:
authorIrene Knapp <ireneista@gmail.com>2021-01-16 03:05:28 -0800
committerIrene Knapp <ireneista@gmail.com>2021-01-16 03:05:28 -0800
commit380db764e0c5466f1564045c7da40fdde967612c (patch)
tree1007d0d9501ae1d359a2295289fb9bfd431785dd /src/terminal.rs
parent031c033745060fc2c83db5a2bf63fd1942ad3176 (diff)
put the terminal in raw mode; also add a TerminalError type
Diffstat (limited to 'src/terminal.rs')
-rw-r--r--src/terminal.rs34
1 files changed, 29 insertions, 5 deletions
diff --git a/src/terminal.rs b/src/terminal.rs
index 6d65c82..27e3c68 100644
--- a/src/terminal.rs
+++ b/src/terminal.rs
@@ -1,6 +1,12 @@
-use std::io::{self, BufRead, BufReader, Read};
+use crate::terminal::error::{TerminalError};
+
+use nix::sys::termios;
+use std::io::{BufRead, BufReader, Read};
+use std::os::unix::io::AsRawFd;
 use std::str;
 
+pub mod error;
+
 
 struct CharBufReader<R: Read> {
   reader: BufReader<R>,
@@ -17,10 +23,10 @@ impl<R: Read> CharBufReader<R> {
   }
 
   pub fn fill_buf(&mut self)
-    -> std::result::Result<&str, io::Error>
+    -> std::result::Result<&str, TerminalError>
   {
     loop {
-      let byte_buffer = self.reader.fill_buf()?;
+      let byte_buffer = self.reader.fill_buf().map_err(error::input)?;
 
       match str::from_utf8(byte_buffer) {
         Err(error) => {
@@ -63,13 +69,31 @@ impl<R: Read> CharBufReader<R> {
 }
 
 
+pub fn handle_input_terminal(input_stream: impl Read + AsRawFd)
+  -> std::result::Result<(), TerminalError>
+{
+  let fd = input_stream.as_raw_fd();
+  let mut termios = termios::tcgetattr(fd)
+      .map_err(error::mode_setting)?;
+  termios.local_flags.insert(termios::LocalFlags::ECHO);
+  termios.local_flags.remove(termios::LocalFlags::ECHOCTL);
+  termios.local_flags.remove(termios::LocalFlags::ICANON);
+  termios.control_chars[termios::SpecialCharacterIndices::VMIN as usize] = 1;
+  termios.control_chars[termios::SpecialCharacterIndices::VTIME as usize] = 0;
+  termios::tcsetattr(fd, termios::SetArg::TCSANOW, &termios)
+      .map_err(error::mode_setting)?;
+
+  handle_input(input_stream)
+}
+
+
 pub fn handle_input(input_stream: impl Read)
-  -> std::result::Result<(), io::Error>
+  -> std::result::Result<(), TerminalError>
 {
   let reader = BufReader::new(input_stream);
   let mut reader = CharBufReader::new(reader);
 
-  let string = reader.fill_buf()?;
+  let string = reader.fill_buf().map_err(error::input)?;
   println!("top level {:?}", string);
 
   let n_to_consume = string.len();