diff options
-rw-r--r-- | src/buffer.rs | 149 |
1 files changed, 134 insertions, 15 deletions
diff --git a/src/buffer.rs b/src/buffer.rs index 3ea70b9..d41f883 100644 --- a/src/buffer.rs +++ b/src/buffer.rs @@ -3,7 +3,7 @@ use nix::unistd::Pid; use std::env::current_dir; use std::fs; use std::io::{self, Read, Write}; -// use std::path::PathBuf; +use std::path::PathBuf; use std::sync::{Arc, Mutex}; // STDIN is file descriptor (fd) 0 on Linux and other UN*X-likes @@ -16,6 +16,7 @@ enum Key { Right, Left, Tab, + ShiftTab, Ctrlc, Else(u8), Ignored, @@ -45,6 +46,9 @@ fn getchar() -> Key { 67 => return Key::Right, 68 => return Key::Left, + // Shift tab + 90 => return Key::ShiftTab, + // Everything else _ => return Key::Ignored, } @@ -73,9 +77,10 @@ fn getchar() -> Key { fn autocomplete( buffer: &mut Arc<Mutex<Vec<u8>>>, index: usize, + pwd: &PathBuf, ) -> Result<(String, usize), Box<dyn std::error::Error>> { // Get the present working directory - let pwd = current_dir()?; + // let pwd = current_dir()?; let buffer = buffer.lock().unwrap(); let word = match buffer.last() { @@ -84,7 +89,7 @@ fn autocomplete( _ => { let mut word: Vec<u8> = vec![]; for c in buffer.iter().rev() { - if *c == b' ' { + if *c == b' ' || *c == b'/' { break; } word.push(*c); @@ -171,6 +176,7 @@ fn autocomplete( /// for more details. pub fn getline(buffer: &mut Arc<Mutex<Vec<u8>>>, pos: &mut Arc<Mutex<usize>>) -> usize { // Keep track of index for autocomplete + let mut pwd = current_dir().unwrap_or(PathBuf::from(env!("HOME"))); let mut auindex = 0; let mut aulen = 0; @@ -204,7 +210,7 @@ pub fn getline(buffer: &mut Arc<Mutex<Vec<u8>>>, pos: &mut Arc<Mutex<usize>>) -> *pos.lock().unwrap() -= 1; aulen -= 1; } - let (path, len) = autocomplete(buffer, auindex).unwrap(); + let (path, len) = autocomplete(buffer, auindex, &pwd).unwrap(); for c in path.into_bytes().iter() { buffer.lock().unwrap().insert(*pos.lock().unwrap(), *c); *pos.lock().unwrap() += 1; @@ -215,6 +221,21 @@ pub fn getline(buffer: &mut Arc<Mutex<Vec<u8>>>, pos: &mut Arc<Mutex<usize>>) -> auindex = 0; } } + Key::ShiftTab => { + while aulen > 0 { + buffer.lock().unwrap().pop(); + print!("\u{8} \u{8}"); + *pos.lock().unwrap() -= 1; + aulen -= 1; + } + let (path, len) = autocomplete(buffer, auindex, &pwd).unwrap(); + for c in path.into_bytes().iter() { + buffer.lock().unwrap().insert(*pos.lock().unwrap(), *c); + *pos.lock().unwrap() += 1; + aulen += 1; + } + auindex = if auindex == 0 { len - 1 } else { auindex - 1 }; + } Key::Ctrlc => { kill(Pid::from_raw(0 as i32), Signal::SIGINT).unwrap(); } @@ -263,33 +284,131 @@ pub fn getline(buffer: &mut Arc<Mutex<Vec<u8>>>, pos: &mut Arc<Mutex<usize>>) -> aulen = 0; } + // forward slash + // b'/' => { + // let mut buffer = buffer.lock().unwrap(); + // + // match buffer.last() { + // Some(c) if *c == b'/' => {} + // Some(_) | None => { + // buffer.insert(*pos.lock().unwrap(), b'/'); + // *pos.lock().unwrap() += 1; + // print!("/"); + // } + // } + // + // let word = match buffer.last() { + // Some(c) if *c == b' ' => "".to_string(), + // None => "".to_string(), + // _ => { + // let mut word: Vec<u8> = vec![]; + // for c in buffer.iter().rev() { + // if *c == b' ' { + // break; + // } + // word.push(*c); + // } + // word.reverse(); + // String::from_utf8_lossy(&mut word).to_string() + // } + // }; + // + // // Check for the ~ character (used to represent $HOME) + // let word = if word.starts_with("~") { + // let home = env!("HOME"); + // format!("{}{}", home, &word[1..]).to_string() + // } else { + // word + // }; + // + // // Reset autocomplete variables + // pwd = PathBuf::from(word); + // auindex = 0; + // aulen = 0; + // } + // everything else _ => { + let mut buffer = buffer.lock().unwrap(); + + let word = match buffer.last() { + Some(c) if *c == b' ' => "".to_string(), + None => "".to_string(), + _ => { + let mut word: Vec<u8> = vec![]; + for c in buffer.iter().rev() { + if *c == b' ' { + break; + } + word.push(*c); + } + word.reverse(); + if word.starts_with(b"..") + && word.iter().filter(|c| *c == &b'/').count() == 1 + { + word = vec![b'.', b'.'] + } + loop { + match word.last() { + Some(c) if *c == b'/' || *c == b'.' => { + break; + } + Some(_) => { + word.pop(); + } + None => { + break; + } + } + } + String::from_utf8_lossy(&mut word).to_string() + } + }; + + // Check for the ~ character (used to represent $HOME) + let word = if word.is_empty() { + current_dir() + .unwrap_or(PathBuf::from(env!("HOME"))) + .to_string_lossy() + .to_string() + } else if word.starts_with("~") { + let home = env!("HOME"); + format!("{}{}", home, &word[1..]).to_string() + } else { + word + }; + + // Reset autocomplete variables + pwd = PathBuf::from(word); + auindex = 0; + aulen = 0; + // Print out the character as the user is typing - print!("{}", c as char); + match buffer.last() { + Some(last) if *last == b'/' && c == b'/' => { + buffer.pop(); + *pos.lock().unwrap() -= 1; + } + Some(_) => print!("{}", c as char), + None => print!("{}", c as char), + } // Insert the character onto the buffer at whatever *pos.lock().unwrap()ition the cursor is at - buffer.lock().unwrap().insert(*pos.lock().unwrap(), c); + buffer.insert(*pos.lock().unwrap(), c); // Increment our *pos.lock().unwrap()ition *pos.lock().unwrap() += 1; // Reprint the end of the buffer if inserting at the front or middle - if *pos.lock().unwrap() != buffer.lock().unwrap().len() { + if *pos.lock().unwrap() != buffer.len() { print!( "{}", - String::from_utf8_lossy( - &buffer.lock().unwrap()[*pos.lock().unwrap()..] - ) + String::from_utf8_lossy(&buffer[*pos.lock().unwrap()..]) ); - for _ in *pos.lock().unwrap()..buffer.lock().unwrap().len() { + for _ in *pos.lock().unwrap()..buffer.len() { print!("\u{8}"); } } - - // Reset autocomplete variables - auindex = 0; - aulen = 0; } }, } |