summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/buffer.rs89
1 files changed, 57 insertions, 32 deletions
diff --git a/src/buffer.rs b/src/buffer.rs
index c27946f..366f20a 100644
--- a/src/buffer.rs
+++ b/src/buffer.rs
@@ -10,6 +10,7 @@ use std::sync::{Arc, Mutex};
pub const STDIN: i32 = 0;
// Key input types from the user
+#[derive(PartialEq)]
enum Key {
Up,
Down,
@@ -79,9 +80,6 @@ fn autocomplete(
index: usize,
pwd: &PathBuf,
) -> Result<(String, usize), Box<dyn std::error::Error>> {
- // Get the present working directory
- // let pwd = current_dir()?;
-
let buffer = buffer.lock().unwrap();
let word = match buffer.last() {
Some(c) if *c == b' ' => "".to_string(),
@@ -175,14 +173,21 @@ fn autocomplete(
/// that (ICANON and ECHO) are off. See the beginning of [crate::repl]
/// for more details.
pub fn getline(buffer: &mut Arc<Mutex<Vec<u8>>>, pos: &mut Arc<Mutex<usize>>) -> usize {
+ // Keep track of the last key
+ let mut last: Option<Key> = None;
+
// 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;
+ // Keep track of the length of the last buffer from autcomplete()
+ let mut length = 0;
+
// Loop over characters until there is a newline
loop {
- match getchar() {
+ let c = getchar();
+ match c {
Key::Up => {
continue;
}
@@ -204,6 +209,12 @@ pub fn getline(buffer: &mut Arc<Mutex<Vec<u8>>>, pos: &mut Arc<Mutex<usize>>) ->
*pos.lock().unwrap() -= 1;
}
Key::Tab => {
+ if last == Some(Key::ShiftTab) {
+ auindex += 2;
+ if auindex >= length {
+ auindex = 0;
+ }
+ }
while aulen > 0 {
buffer.lock().unwrap().pop();
print!("\u{8} \u{8}");
@@ -212,6 +223,7 @@ pub fn getline(buffer: &mut Arc<Mutex<Vec<u8>>>, pos: &mut Arc<Mutex<usize>>) ->
}
let (path, len) =
autocomplete(buffer, auindex, &pwd).unwrap_or(("".to_string(), 0));
+ length = len;
for c in path.into_bytes().iter() {
buffer.lock().unwrap().insert(*pos.lock().unwrap(), *c);
*pos.lock().unwrap() += 1;
@@ -223,6 +235,13 @@ pub fn getline(buffer: &mut Arc<Mutex<Vec<u8>>>, pos: &mut Arc<Mutex<usize>>) ->
}
}
Key::ShiftTab => {
+ if last == Some(Key::Tab) {
+ if auindex.checked_sub(2) == None {
+ auindex = length - 1;
+ } else {
+ auindex -= 2;
+ }
+ }
while aulen > 0 {
buffer.lock().unwrap().pop();
print!("\u{8} \u{8}");
@@ -231,6 +250,7 @@ pub fn getline(buffer: &mut Arc<Mutex<Vec<u8>>>, pos: &mut Arc<Mutex<usize>>) ->
}
let (path, len) =
autocomplete(buffer, auindex, &pwd).unwrap_or(("".to_string(), 0));
+ length = len;
for c in path.into_bytes().iter() {
buffer.lock().unwrap().insert(*pos.lock().unwrap(), *c);
*pos.lock().unwrap() += 1;
@@ -290,6 +310,35 @@ pub fn getline(buffer: &mut Arc<Mutex<Vec<u8>>>, pos: &mut Arc<Mutex<usize>>) ->
_ => {
let mut buffer = buffer.lock().unwrap();
+ // Print out the character as the user is typing
+ 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.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.len() {
+ print!(
+ "{}",
+ String::from_utf8_lossy(&buffer[*pos.lock().unwrap()..])
+ );
+ for _ in *pos.lock().unwrap()..buffer.len() {
+ print!("\u{8}");
+ }
+ }
+
+ // Update directory for autocomplete
let word = match buffer.last() {
Some(c) if *c == b' ' => "".to_string(),
None => "".to_string(),
@@ -309,7 +358,7 @@ pub fn getline(buffer: &mut Arc<Mutex<Vec<u8>>>, pos: &mut Arc<Mutex<usize>>) ->
}
loop {
match word.last() {
- Some(c) if *c == b'/' || *c == b'.' => {
+ Some(c) if *c == b'/' || *c == b'.' || *c == b'~' => {
break;
}
Some(_) => {
@@ -341,36 +390,12 @@ pub fn getline(buffer: &mut Arc<Mutex<Vec<u8>>>, pos: &mut Arc<Mutex<usize>>) ->
pwd = PathBuf::from(word);
auindex = 0;
aulen = 0;
-
- // Print out the character as the user is typing
- 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.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.len() {
- print!(
- "{}",
- String::from_utf8_lossy(&buffer[*pos.lock().unwrap()..])
- );
- for _ in *pos.lock().unwrap()..buffer.len() {
- print!("\u{8}");
- }
- }
}
},
}
+
+ // Update the last key
+ last = Some(c);
}
*pos.lock().unwrap() = 0;