summaryrefslogtreecommitdiffstats
path: root/src/main.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/main.rs')
-rw-r--r--src/main.rs39
1 files changed, 31 insertions, 8 deletions
diff --git a/src/main.rs b/src/main.rs
index 98b49ed..527fb8c 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -1,11 +1,14 @@
use std::env;
use std::io::{self, Write};
use std::sync::{Arc, Mutex};
+mod buffer;
mod path;
mod poem;
use poem::{read::Readable, recite::Reciteable, Poem};
mod compose;
+use buffer::{getline, STDIN};
use compose::Environment;
+use termios::{tcsetattr, Termios, ECHO, ICANON, TCSANOW};
/// Starts the main shell loop
///
@@ -22,12 +25,27 @@ use compose::Environment;
/// repl(&mut away, &mut env);
/// }
/// ```
-fn repl(away: &mut Arc<Mutex<bool>>, env: &mut Environment) {
+fn repl(
+ away: &mut Arc<Mutex<bool>>,
+ buffer: &mut Arc<Mutex<Vec<u8>>>,
+ pos: &mut Arc<Mutex<usize>>,
+ env: &mut Environment,
+) {
+ // Setup termios flags
+ let mut termios = Termios::from_fd(STDIN).unwrap();
+ termios.c_lflag &= !(ICANON | ECHO);
+
// Initial path refresh on startup
env.bins = path::refresh();
// Main shell loop
loop {
+ // Reset terminal using proper termios flags
+ tcsetattr(STDIN, TCSANOW, &mut termios).unwrap();
+
+ // Clear the buffer
+ buffer.lock().unwrap().clear();
+
// Get the prompt
let prompt = match env::var("PS1") {
Ok(val) => val,
@@ -42,10 +60,7 @@ fn repl(away: &mut Arc<Mutex<bool>>, env: &mut Environment) {
*away.lock().unwrap() = false;
// Wait for user input
- let mut poetry = String::new();
- let bytes = io::stdin()
- .read_line(&mut poetry)
- .expect("dwvsh: error: unable to evaluate the input string");
+ let bytes = getline(buffer, pos);
// Check if we've reached EOF (i.e. <C-d>)
if bytes == 0 {
@@ -53,8 +68,10 @@ fn repl(away: &mut Arc<Mutex<bool>>, env: &mut Environment) {
break;
}
- // Trim the input
- let poetry = String::from(poetry.trim());
+ // Convert buffer to a string and trim it
+ let poetry = String::from_utf8_lossy(&buffer.lock().unwrap())
+ .trim()
+ .to_string();
// Skip parsing if there is no poetry
if poetry.is_empty() {
@@ -132,9 +149,15 @@ fn main() {
// Handle signals
let mut away = Arc::new(Mutex::new(true));
+ let mut buffer: Arc<Mutex<Vec<u8>>> = Arc::new(Mutex::new(vec![]));
+ let mut pos: Arc<Mutex<usize>> = Arc::new(Mutex::new(0));
unsafe {
let away = Arc::clone(&away);
+ let buffer = Arc::clone(&buffer);
+ let pos = Arc::clone(&pos);
signal_hook::low_level::register(signal_hook::consts::SIGINT, move || {
+ buffer.lock().unwrap().clear();
+ *pos.lock().unwrap() = 0;
if *away.lock().unwrap() {
println!();
} else {
@@ -153,5 +176,5 @@ fn main() {
options(&mut env);
// Begin evaluating commands
- repl(&mut away, &mut env);
+ repl(&mut away, &mut buffer, &mut pos, &mut env);
}