summaryrefslogtreecommitdiffstats
path: root/src/main.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/main.rs')
-rw-r--r--src/main.rs58
1 files changed, 45 insertions, 13 deletions
diff --git a/src/main.rs b/src/main.rs
index 8cfd680..a73c2c4 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -6,7 +6,7 @@ mod path;
mod poem;
use poem::{read::Readable, recite::Reciteable, Poem};
mod compose;
-use buffer::{getline, STDIN};
+use buffer::{getline, Key, STDIN};
use compose::Environment;
use termios::{tcsetattr, Termios, ECHO, ECHOE, ICANON, TCSANOW};
@@ -27,8 +27,11 @@ use termios::{tcsetattr, Termios, ECHO, ECHOE, ICANON, TCSANOW};
/// ```
fn repl(
away: &mut Arc<Mutex<bool>>,
- buffer: &mut Arc<Mutex<Vec<u8>>>,
+ buffer: &mut Arc<Mutex<Vec<char>>>,
pos: &mut Arc<Mutex<usize>>,
+ comp_pos: &mut Arc<Mutex<usize>>,
+ comp_len: &mut Arc<Mutex<usize>>,
+ last_key: &mut Arc<Mutex<Key>>,
env: &mut Environment,
) {
// Setup termios flags
@@ -39,9 +42,6 @@ fn repl(
// Main shell loop
loop {
- // Clear the buffer
- buffer.lock().unwrap().clear();
-
// Get the prompt
let prompt = match env::var("PS1") {
Ok(val) => val,
@@ -60,7 +60,7 @@ fn repl(
tcsetattr(STDIN, TCSANOW, &mut termios).unwrap();
// Wait for user input
- let bytes = getline(buffer, pos);
+ let bytes = getline(buffer, pos, comp_pos, comp_len, last_key);
// Check if we've reached EOF (i.e. <C-d>)
if bytes == 0 {
@@ -69,9 +69,7 @@ fn repl(
}
// Convert buffer to a string and trim it
- let poetry = String::from_utf8_lossy(&buffer.lock().unwrap())
- .trim()
- .to_string();
+ let poetry = buffer.lock().unwrap().iter().collect::<String>();
// Skip parsing if there is no poetry
if poetry.is_empty() {
@@ -86,7 +84,7 @@ fn repl(
*away.lock().unwrap() = true;
// Parse the poem
- let poem = Poem::read(poetry, env);
+ let poem = Poem::read(poetry.to_string(), env);
let poem = match poem {
Ok(poem) => poem,
Err(e) => {
@@ -151,17 +149,43 @@ fn main() {
// Compose the environment for dwvsh
let mut env = compose::env();
- // Handle signals
+ // Set when we are not on the buffer
let mut away = Arc::new(Mutex::new(true));
- let mut buffer: Arc<Mutex<Vec<u8>>> = Arc::new(Mutex::new(vec![]));
+
+ // Any text in the current buffer
+ let mut buffer: Arc<Mutex<Vec<char>>> = Arc::new(Mutex::new(Vec::new()));
+
+ // Position in the buffer. Subject to change based on input from the user. Typing a character
+ // increments the position, while backspacing will decrement it. The user may also move it
+ // manually using the arrow keys to insert or delete at an arbitrary location in the buffer.
let mut pos: Arc<Mutex<usize>> = Arc::new(Mutex::new(0));
+
+ // Position in the autocomplete list. This value gets reset if a new autocomplete list is
+ // generated (for instance, if the user preses '/' to start autocomplete in a new directory).
+ let mut comp_pos: Arc<Mutex<usize>> = Arc::new(Mutex::new(0));
+
+ // Keep track of the length of the last buffer from [crate::buffer::comp].
+ let mut comp_len: Arc<Mutex<usize>> = Arc::new(Mutex::new(0));
+
+ // Keep track of the last key for autocomplete, as we may need to add or sub additionally from
+ // [comp_pos] before calling [crate::buffer::comp] (i.e. swapping directions (tab vs. shift +
+ // tab)).
+ let mut last_key: Arc<Mutex<Key>> = Arc::new(Mutex::new(Key::Ignored));
+
+ // Handle signals
unsafe {
let away = Arc::clone(&away);
let buffer = Arc::clone(&buffer);
let pos = Arc::clone(&pos);
+ let comp_pos = Arc::clone(&comp_pos);
+ let comp_len = Arc::clone(&comp_len);
+ let last_key = Arc::clone(&last_key);
signal_hook::low_level::register(signal_hook::consts::SIGINT, move || {
buffer.lock().unwrap().clear();
*pos.lock().unwrap() = 0;
+ *comp_pos.lock().unwrap() = 0;
+ *comp_len.lock().unwrap() = 0;
+ *last_key.lock().unwrap() = Key::Ignored;
if *away.lock().unwrap() {
println!();
} else {
@@ -180,5 +204,13 @@ fn main() {
options(&mut env);
// Begin evaluating commands
- repl(&mut away, &mut buffer, &mut pos, &mut env);
+ repl(
+ &mut away,
+ &mut buffer,
+ &mut pos,
+ &mut comp_pos,
+ &mut comp_len,
+ &mut last_key,
+ &mut env,
+ );
}