|
|
@ -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,
|
|
|
|
))?;
|
|
|
|
))?;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 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");
|
|
|
|
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() {
|
|
|
|