summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/buffer.rs149
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;
}
},
}