diff options
-rw-r--r-- | Cargo.lock | 41 | ||||
-rw-r--r-- | Cargo.toml | 1 | ||||
-rw-r--r-- | src/error.rs | 9 | ||||
-rw-r--r-- | src/main.rs | 2 | ||||
-rw-r--r-- | src/terminal.rs | 34 | ||||
-rw-r--r-- | src/terminal/error.rs | 31 |
6 files changed, 107 insertions, 11 deletions
diff --git a/Cargo.lock b/Cargo.lock index 4f2703d..c775fd3 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -69,6 +69,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5f0dc55f2d8a1a85650ac47858bb001b4c0dd73d79e3c455a842925e68d29cd3" [[package]] +name = "bitflags" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693" + +[[package]] name = "blake2b_simd" version = "0.5.10" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -113,12 +119,24 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "08c48aae112d48ed9f069b33538ea9e3e90aa263cfa3d1c24309612b1f7472de" [[package]] +name = "cc" +version = "1.0.66" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c0496836a84f8d0495758516b8621a622beb77c0fed418570e50764093ced48" + +[[package]] name = "cfg-if" version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" [[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] name = "constant_time_eq" version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -131,7 +149,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c3c7c73a2d1e9fc0886a08b93e98eb643461230d5f1925e4036204d5f2e261a8" dependencies = [ "autocfg", - "cfg-if", + "cfg-if 0.1.10", "lazy_static", ] @@ -215,7 +233,7 @@ version = "0.1.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7abc8dd8451921606d809ba32e95b6111925cd2906060d2dcc29c070220503eb" dependencies = [ - "cfg-if", + "cfg-if 0.1.10", "libc", "wasi", ] @@ -296,9 +314,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] name = "libc" -version = "0.2.76" +version = "0.2.82" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "755456fae044e6fa1ebbbd1b3e902ae19e73097ed4ed87bb79934a867c007bc3" +checksum = "89203f3fba0a3795506acaad8ebce3c80c0af93f994d5a1d7a0b1eeb23271929" [[package]] name = "log" @@ -306,7 +324,7 @@ version = "0.4.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4fabed175da42fed1fa0746b0ea71f412aa9d35e76e95e59b192c64b9dc2bf8b" dependencies = [ - "cfg-if", + "cfg-if 0.1.10", ] [[package]] @@ -322,6 +340,18 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e4a24736216ec316047a1fc4252e27dabb04218aa4a3f37c6e7ddbf1f9782b54" [[package]] +name = "nix" +version = "0.19.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2ccba0cfe4fdf15982d1674c69b1fd80bad427d293849982668dfe454bd61f2" +dependencies = [ + "bitflags", + "cc", + "cfg-if 1.0.0", + "libc", +] + +[[package]] name = "opaque-debug" version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -455,6 +485,7 @@ version = "0.1.0" dependencies = [ "lalrpop", "lalrpop-util", + "nix", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index a0470e6..f858223 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,6 +7,7 @@ edition = "2018" [dependencies] #futures = "0.3" lalrpop-util = "0.19" +nix = "0.19" [build-dependencies] lalrpop = { version = "0.19", features = [ "lexer" ] } diff --git a/src/error.rs b/src/error.rs index 018d812..b8289f6 100644 --- a/src/error.rs +++ b/src/error.rs @@ -1,5 +1,6 @@ use crate::path::GenericPath; use crate::path::error::{FileNameError, DirectoryNameError}; +use crate::terminal::error::TerminalError; type ParseError<'a> = @@ -16,6 +17,7 @@ pub enum Error { PathLexicallyRelative(GenericPath), PathLexicallyInvalid(GenericPath), PathEmpiricallyFile(GenericPath), + Terminal(TerminalError), } impl std::error::Error for Error { } @@ -48,6 +50,7 @@ impl std::fmt::Display for Error { f.write_fmt(format_args!( "There's a file at {}, not a directory.", path)), + Error::Terminal(e) => e.fmt(f), } } } @@ -81,3 +84,9 @@ impl From<DirectoryNameError> for Error { Error::DirectoryName(e) } } + +impl From<TerminalError> for Error { + fn from(e: TerminalError) -> Error { + Error::Terminal(e) + } +} diff --git a/src/main.rs b/src/main.rs index 3199528..d7a2aff 100644 --- a/src/main.rs +++ b/src/main.rs @@ -39,7 +39,7 @@ fn repl() -> Result<()> { loop { prompt()?; - terminal::handle_input(io::stdin())?; + terminal::handle_input_terminal(io::stdin())?; let input = read()?; match input { Input::String(string) => execute(&string)?, 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(); diff --git a/src/terminal/error.rs b/src/terminal/error.rs new file mode 100644 index 0000000..6666e49 --- /dev/null +++ b/src/terminal/error.rs @@ -0,0 +1,31 @@ +#[derive(Clone,Debug,Eq,Hash,Ord,PartialEq,PartialOrd)] +pub enum TerminalError { + Input(String), + ModeSetting(String), +} + +impl std::error::Error for TerminalError { } + +impl std::fmt::Display for TerminalError { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + TerminalError::Input(s) => + f.write_fmt(format_args!( + "Can't read terminal input: {}", s)), + TerminalError::ModeSetting(s) => + f.write_fmt(format_args!( + "Can't set terminal mode: {}", s)), + } + } +} + + +pub fn input(e: impl std::error::Error) -> TerminalError { + TerminalError::ModeSetting(format!("{}", e)) +} + + +pub fn mode_setting(e: impl std::error::Error) -> TerminalError { + TerminalError::ModeSetting(format!("{}", e)) +} + |