ctrl+u clears to the beginning of the line

parse-tree
Jordan Orelli 2 years ago
parent a727b6cfc5
commit 3fd068d4c8

@ -1,3 +1,5 @@
use crate::log::*;
pub struct Line { pub struct Line {
/// the current contents of the line /// the current contents of the line
chars: Vec<char>, chars: Vec<char>,
@ -17,11 +19,13 @@ impl Line {
pub fn clear(&mut self) { pub fn clear(&mut self) {
self.cursor = 0; self.cursor = 0;
self.chars.clear(); self.chars.clear();
self.show_debug();
} }
pub fn pop(&mut self) -> String { pub fn pop(&mut self) -> String {
let s: String = self.chars.iter().collect(); let s: String = self.chars.iter().collect();
self.clear(); self.clear();
self.show_debug();
s s
} }
@ -32,6 +36,7 @@ impl Line {
pub fn back(&mut self) -> bool { pub fn back(&mut self) -> bool {
if self.cursor > 0 { if self.cursor > 0 {
self.cursor -= 1; self.cursor -= 1;
self.show_debug();
true true
} else { } else {
false false
@ -39,18 +44,34 @@ impl Line {
} }
pub fn backspace(&mut self) -> bool { pub fn backspace(&mut self) -> bool {
if self.chars.len() > 0 {
if self.cursor > 0 { if self.cursor > 0 {
self.cursor -= 1; self.cursor -= 1;
}
self.chars.remove(self.cursor); self.chars.remove(self.cursor);
self.show_debug();
true true
} else { } else {
false false
} }
} }
/// removes the elements left of the cursor, returning the count of removed elements
pub fn clear_left(&mut self) -> usize {
if self.cursor > 0 {
let n = self.chars.drain(..self.cursor).count();
self.cursor = 0;
self.show_debug();
n
} else {
0
}
}
pub fn forward(&mut self) -> bool { pub fn forward(&mut self) -> bool {
if self.cursor < self.chars.len() { if self.cursor < self.chars.len() {
self.cursor += 1; self.cursor += 1;
self.show_debug();
true true
} else { } else {
false false
@ -60,6 +81,7 @@ impl Line {
pub fn insert(&mut self, c: char) { pub fn insert(&mut self, c: char) {
self.chars.insert(self.cursor, c); self.chars.insert(self.cursor, c);
self.cursor += 1; self.cursor += 1;
self.show_debug();
} }
pub fn tail(&self) -> String { pub fn tail(&self) -> String {
@ -71,4 +93,8 @@ impl Line {
let chars = &self.chars[start..]; let chars = &self.chars[start..];
chars.iter().collect() chars.iter().collect()
} }
fn show_debug(&self) {
debug!(" {: <4} {: >5} {}", self.cursor, self.chars.len(), self.show());
}
} }

@ -318,12 +318,14 @@ fn main() -> Result<()> {
if event.code == key::BACKSPACE { if event.code == key::BACKSPACE {
if line.backspace() { if line.backspace() {
let text = format!("\x1b[2D");
unsafe { unsafe {
Error::check(Console::WriteConsoleA(stdout, text.as_bytes(), None, None))?; // move cursor back two spaces
Error::check(Console::WriteConsoleA(stdout, "\x1b[2D".as_bytes(), None, None))?;
} }
let tail = format!("{} ", line.tail()); let tail = format!("{} ", line.tail());
let n = tail.chars().count();
unsafe { unsafe {
// write the rest of the line plus a space to erase the last character
Error::check(Console::WriteConsoleA( Error::check(Console::WriteConsoleA(
stdout, stdout,
tail.as_bytes(), tail.as_bytes(),
@ -331,14 +333,26 @@ fn main() -> Result<()> {
None, None,
))?; ))?;
} }
let text = format!("\x1b[1D");
// after writing out the tail, rewind by the number of characters in
// the tail
if n > 1 {
let text = format!("\x1b[{}D", n-1);
unsafe {
Error::check(Console::WriteConsoleA(stdout, text.as_bytes(), None, None))?;
}
} else {
// honestly I can't remember how I figured this out
let text = format!(" \x1b[1D");
unsafe { unsafe {
Error::check(Console::WriteConsoleA(stdout, text.as_bytes(), None, None))?; Error::check(Console::WriteConsoleA(stdout, text.as_bytes(), None, None))?;
} }
} }
}
continue; continue;
} }
// CTRL-D to exit
if event.ctrl && event.code == key::D { if event.ctrl && event.code == key::D {
info!("» exit"); info!("» exit");
unsafe { unsafe {
@ -347,6 +361,7 @@ fn main() -> Result<()> {
return Ok(()); return Ok(());
} }
// CTRL-J to draw a cool little dot
if event.ctrl && event.code == key::J { if event.ctrl && event.code == key::J {
debug!("⎈ j: dot"); debug!("⎈ j: dot");
unsafe { unsafe {
@ -357,6 +372,7 @@ fn main() -> Result<()> {
continue; continue;
} }
// CTRL-L to clear the screen
if event.ctrl && event.code == key::L { if event.ctrl && event.code == key::L {
info!("» clear"); info!("» clear");
let text = "\x1b[2J\x1b[0;0H"; let text = "\x1b[2J\x1b[0;0H";
@ -370,6 +386,31 @@ fn main() -> Result<()> {
continue; continue;
} }
// CTRL-U to erase to the beginning of the line
if event.ctrl && event.code == key::U {
info!("» clear-left");
let n = line.clear_left();
if n > 0 {
// move left by the number of elements removed
let text = format!("\x1b[{}D", n);
unsafe {
Error::check(Console::WriteConsoleA(stdout, text.as_bytes(), None, None))?;
}
// draw the elements remaining, followed by a space for each removed
// element
let kept = line.show();
let text = format!("{}{:width$}", kept, "", width = n);
unsafe {
Error::check(Console::WriteConsoleA(stdout, text.as_bytes(), None, None))?;
}
let text = format!("\x1b[{}D", n + kept.chars().count());
unsafe {
Error::check(Console::WriteConsoleA(stdout, text.as_bytes(), None, None))?;
}
}
continue;
}
// TODO: something better here, this is crappy. I should be checking characters // TODO: something better here, this is crappy. I should be checking characters
// based on their unicode categories, not this garbo // based on their unicode categories, not this garbo
if !event.char.is_control() { if !event.char.is_control() {

Loading…
Cancel
Save