diff --git a/.gitignore b/.gitignore index 53eaa21..2bb8d25 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ /target **/*.rs.bk +.idea diff --git a/Cargo.lock b/Cargo.lock index 705b95c..c8886bc 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -15,6 +15,11 @@ name = "cfg-if" version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "lazy_static" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "libc" version = "0.2.62" @@ -37,6 +42,15 @@ name = "rs-kilo" version = "0.1.0" dependencies = [ "nix 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)", + "term-parser 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "term-parser" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -48,6 +62,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3d155346769a6855b86399e9bc3814ab343cd3d62c7e985113d46a0ec3c281fd" "checksum cc 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)" = "b548a4ee81fccb95919d4e22cfea83c7693ebfd78f0495493178db20b3139da7" "checksum cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "b486ce3ccf7ffd79fdeb678eac06a9e6c09fc88d33836340becb8fffe87c5e33" +"checksum lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bc5729f27f159ddd61f4df6228e827e86643d4d3e7c32183cb30a1c08f604a14" "checksum libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)" = "34fcd2c08d2f832f376f4173a231990fa5aef4e99fb569867318a227ef4c06ba" "checksum nix 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3b2e0b4f3320ed72aaedb9a5ac838690a8047c7b275da22711fddff4f8a14229" +"checksum term-parser 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3c483a684059c71636d0e4ff927bd5feb5f2a533e7a8f16a0008dd33c8752cbc" "checksum void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" diff --git a/Cargo.toml b/Cargo.toml index 578f619..ca28f08 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,4 +7,5 @@ edition = "2018" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -nix = "0.15.0" \ No newline at end of file +nix = "0.15.0" +term-parser = "0.2.0" \ No newline at end of file diff --git a/src/editor.rs b/src/editor.rs new file mode 100644 index 0000000..d4aebac --- /dev/null +++ b/src/editor.rs @@ -0,0 +1,11 @@ +//! Editor functionality + +pub struct Editor {} + +impl Editor { + pub fn new() -> Self { + Editor { + + } + } +} \ No newline at end of file diff --git a/src/helpers.rs b/src/helpers.rs new file mode 100644 index 0000000..6fb3b1a --- /dev/null +++ b/src/helpers.rs @@ -0,0 +1,16 @@ +/// Helper functions, especially to reproduce C std/posix functions +use nix::errno::*; +use std::process::exit; + +/// Is this character an ASCII control character? +pub fn is_cntrl(c: char) -> bool { + let code = c as u8; + + code < 32 || code == 127 +} + +pub fn die(code: &Errno, msg: &str) -> ! { + eprintln!("{:?} ({})", code, msg); + + exit(1) +} \ No newline at end of file diff --git a/src/main.rs b/src/main.rs index fbe669d..0b1ffc3 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,43 +1,108 @@ use nix::Error as NixError; use nix::sys::termios; -use nix::sys::termios::Termios; -// use nix::unistd; +use nix::sys::termios::{InputFlags, LocalFlags, OutputFlags, SpecialCharacterIndices, Termios}; + use std::io; use std::io::{BufReader, Error}; use std::io::prelude::*; +use term_parser::ActionIter; + +mod editor; +mod helpers; + +// use crate::editor::Editor; +use crate::helpers::*; + // Redefine the posix constants for rust land const STDIN_FILENO: i32 = 0; -const STDOUT_FILENO: i32 = 1; -const STDERR_FILENO: i32 = 2; +// const STDOUT_FILENO: i32 = 1; +// const STDERR_FILENO: i32 = 2; + +fn disable_raw_mode(original: &Termios) -> Result<(), Error> { + match termios::tcsetattr(STDIN_FILENO, termios::SetArg::TCSAFLUSH, original) { + Ok(()) => Ok(()), + Err(E) => match E.as_errno() { + Some(errno) => die(&errno, "tcsetattr"), + None => panic!("Failed to disable raw mode") + } + } +} fn enable_raw_mode() -> Result<(), Error> { - let raw: Result = termios::tcgetattr(STDIN_FILENO); - let mut raw = raw.unwrap(); - raw.local_flags.remove(termios::LocalFlags::ECHO); + let mut raw = termios::tcgetattr(STDIN_FILENO).unwrap(); + + raw.input_flags.remove( + InputFlags::BRKINT & + InputFlags::ICRNL & + InputFlags::INPCK & + InputFlags::ISTRIP & + InputFlags::IXON + ); + + raw.output_flags.remove(OutputFlags::OPOST); + + raw.local_flags.remove( + LocalFlags::ECHO & + LocalFlags::ICANON & + LocalFlags::IEXTEN & + LocalFlags::ISIG + ); + + // 8 bit characters + raw.control_flags |= termios::ControlFlags::CS8; + + raw.control_chars[SpecialCharacterIndices::VMIN as usize] = 0; + raw.control_chars[SpecialCharacterIndices::VTIME as usize] = 1; match termios::tcsetattr(STDIN_FILENO, termios::SetArg::TCSAFLUSH, &raw) { Ok(()) => Ok(()), - _ => panic!("Failed to set raw mode"), + Err(e) => match e.as_errno() { + Some(errno) => die(&errno, "tcsetattr"), + None => panic!("Failed to enable raw mode") + } } } fn main() -> Result<(), Error> { + let orig_termios = termios::tcgetattr(STDIN_FILENO).unwrap(); + enable_raw_mode()?; - loop { - let stdin = io::stdin(); - let mut in_str = String::new(); - let mut input = BufReader::new(stdin.take(1)); - input.read_to_string(&mut in_str)?; + let stdin = io::stdin(); + let buffer = BufReader::new(stdin); + let term_code_iter = ActionIter::new(buffer); - let mut chars = in_str.chars(); - let char = chars.next().unwrap(); - - if char == 'q' { - return Ok(()); - } + for term_code in term_code_iter { + let term_code = match term_code { + Ok(code) => code, + Err(e) => panic!("{:?}", e), + }; + println!("\r{:?}", term_code); } Ok(()) + +// loop { +// let stdin = io::stdin(); +// let mut in_str = String::new(); +// let mut input = BufReader::new(stdin.take(1)); +// input.read_to_string(&mut in_str)?; +// +// let mut chars = in_str.chars(); +// let char = chars.next().unwrap(); +// +// if char == 'q' { +// return disable_raw_mode(&orig_termios); +// } +// +// // Echo characters +// if is_cntrl(char) { +// print!("{}\r\n", char as u8); +// continue; +// } else { +// print!("{} ('{}')\r\n", char as u8, char); +// continue; +// } +// } }