aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/linebuf.rs28
-rw-r--r--src/main.rs56
2 files changed, 74 insertions, 10 deletions
diff --git a/src/linebuf.rs b/src/linebuf.rs
index 1d28549..836cfee 100644
--- a/src/linebuf.rs
+++ b/src/linebuf.rs
@@ -27,6 +27,10 @@ impl LineBuf {
self.post.pop()
}
+ pub fn len(&self) -> usize {
+ self.pre.len() + self.post.len()
+ }
+
pub fn left(&mut self) -> bool {
if let Some(byte) = self.del_left() {
self.post.push(byte);
@@ -64,6 +68,19 @@ impl LineBuf {
self.post = Vec::new();
}
+ pub fn into_bytes(&self) -> Vec<u8> {
+ let mut buf = Vec::with_capacity(self.pre.len() + self.post.len());
+ buf.extend_from_slice(&self.pre);
+ for b in self.post.iter().rev() {
+ buf.push(*b);
+ }
+ buf
+ }
+
+ pub fn distance_from_right_end(&self) -> usize {
+ self.post.len()
+ }
+
/// returns the whole contents of the buffer, and empties it in the process
pub fn dump(&mut self) -> Vec<u8> {
while self.right() {}
@@ -73,12 +90,19 @@ impl LineBuf {
buf
}
+ pub fn clear(&mut self) {
+ self.pre.clear();
+ self.post.clear();
+ self.dirty = false;
+ }
+
/// TODO: kinda ugly that this is here
- pub fn display_post(&self) {
+ pub fn display_post(&self, post: &[u8]) {
for &x in self.post.iter().rev() {
std::io::stdout().write_all(&[x]).unwrap();
}
- move_cursor(Direction::Left, self.post.len());
+ std::io::stdout().write_all(post).unwrap();
+ move_cursor(Direction::Left, self.post.len() + post.len());
std::io::stdout().flush().unwrap();
}
}
diff --git a/src/main.rs b/src/main.rs
index 19b98c2..81cc5d3 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -96,6 +96,12 @@ impl Session {
}
}
+fn read1() -> u8 {
+ let mut buf = [0];
+ io::stdin().lock().read_exact(&mut buf).unwrap();
+ buf[0]
+}
+
fn event_loop() {
let stdin = io::stdin();
let stdout = io::stdout();
@@ -121,6 +127,17 @@ fn event_loop() {
};
match buf[0] {
+ // Ctrl+C
+ 3 => {
+ // clear line
+ cursor::move_cursor(Direction::Right, se.line.distance_from_right_end());
+ for _ in 0..se.line.len() {
+ write!(io::stdout(), "\x08 \x08").unwrap();
+ }
+ io::stdout().lock().flush().unwrap();
+ se.line.clear();
+ }
+
// EOF
4 => {
break;
@@ -129,7 +146,10 @@ fn event_loop() {
// Ctrl+L
12 => {
clear_screen();
- print!("{}", se.prompt());
+ write!(io::stdout(), "{}", se.prompt()).unwrap();
+ io::stdout().write_all(&se.line.into_bytes()).unwrap();
+ cursor::move_cursor(Direction::Left, se.line.distance_from_right_end());
+ io::stdout().lock().flush().unwrap();
}
// Ctrl+R
@@ -164,10 +184,17 @@ fn event_loop() {
// Escape sequence
27 => {
- let mut seq = [0u8; 2];
- stdin.lock().read_exact(&mut seq).unwrap();
+ let mut seq = vec![read1()];
if seq[0] == b'[' {
+ // still more
+ while {
+ let last = seq[seq.len() - 1];
+ last < 0x40 || last > 0x7E || seq.len() == 1
+ } {
+ seq.push(read1());
+ }
+
match seq[1] {
b'A' => {
// up
@@ -176,12 +203,25 @@ fn event_loop() {
// down
}
b'C' => {
- move_cursor(Direction::Right, 1);
- se.line.right();
+ if se.line.right() {
+ move_cursor(Direction::Right, 1);
+ io::stdout().lock().flush().unwrap();
+ }
}
b'D' => {
- move_cursor(Direction::Left, 1);
- se.line.left();
+ if se.line.left() {
+ move_cursor(Direction::Left, 1);
+ io::stdout().lock().flush().unwrap();
+ }
+ }
+ b'3' => {
+ if seq.len() > 2 && seq[2] == b'~' {
+ // delete
+ se.line.del_right();
+ se.line.display_post(b" ");
+ } else {
+ todo!("unhandled: {seq:?}");
+ }
}
x => todo!("escape character {x}"),
}
@@ -200,7 +240,7 @@ fn event_loop() {
x => {
se.line.add(x);
stdout.lock().write_all(&[x]).unwrap();
- se.line.display_post();
+ se.line.display_post(b"");
}
}
}