aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRose Hogenson <rosehogenson@posteo.net>2024-01-13 17:45:37 -0800
committerRose Hogenson <rosehogenson@posteo.net>2024-01-13 17:45:37 -0800
commitd3f52cf5dc1e06a81fb75a8631ac00e8adc04ac7 (patch)
tree5d4c71c7e2b2d8b6490a8afb57d7ba209637ce1e
parent1e32f5d480ecefa3a1c8fd1c43ac6b4260459266 (diff)
downloadeditor-d3f52cf5dc1e06a81fb75a8631ac00e8adc04ac7.tar.zst
Escape control characters.
-rw-r--r--src/main.rs24
-rw-r--r--src/rope.rs25
2 files changed, 36 insertions, 13 deletions
diff --git a/src/main.rs b/src/main.rs
index 0cc9ad4..3663052 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -21,7 +21,7 @@ fn line_offset(stdin: &mut Reader, line: &Rope, col: u16) -> Result<usize, Box<d
return Ok(i);
}
let c = line.byte(i);
- if c > 127 {
+ if !(c == b'\t' || b' ' <= c && c <= b'~') {
break;
}
if n == col {
@@ -231,12 +231,12 @@ impl State {
}
fn keypress(&mut self, key: Key) -> Result<bool, Box<dyn Error>> {
- const CTRL_Q: char = (b'Q' - b'@') as char;
- const CTRL_S: char = (b'S' - b'@') as char;
- const CTRL_Y: char = (b'Y' - b'@') as char;
- const CTRL_Z: char = (b'Z' - b'@') as char;
- const BACKSPACE: char = (b'H' - b'@') as char;
- const OTHER_BACKSPACE: char = '\x7f';
+ const CTRL_Q: char = (b'Q' ^ b'@') as char;
+ const CTRL_S: char = (b'S' ^ b'@') as char;
+ const CTRL_Y: char = (b'Y' ^ b'@') as char;
+ const CTRL_Z: char = (b'Z' ^ b'@') as char;
+ const BACKSPACE: char = (b'H' ^ b'@') as char;
+ const OTHER_BACKSPACE: char = (b'?' ^ b'@') as char;
let inserting = self.inserting;
self.inserting = false;
@@ -448,7 +448,7 @@ impl State {
}
Key::Char(CTRL_S) => {
let mut f = File::create(&self.path)?;
- self.buf.print(&mut f)?;
+ self.buf.write(&mut f)?;
f.sync_all()?;
}
Key::Char(CTRL_Z) => {
@@ -546,15 +546,15 @@ impl State {
.line_start(self.row_start + usize::from(self.cursor_row))
+ self.line_offset;
let mut buf = [0; 4];
- let s = c.encode_utf8(&mut buf);
+ let r = Rope::new(c.encode_utf8(&mut buf));
self.buf = self
.buf
.slice(0, offset)
- .concat(&Rope::new(s))
+ .concat(&r)
.concat(&self.buf.slice(offset, self.buf.len()));
- self.line_offset += s.len();
+ self.line_offset += r.len();
self.need_repaint_line = true;
- stdout().write_all(s.as_bytes())?;
+ r.print(&mut stdout())?;
stdout().flush()?;
}
}
diff --git a/src/rope.rs b/src/rope.rs
index ab9a7bc..ec25f61 100644
--- a/src/rope.rs
+++ b/src/rope.rs
@@ -342,7 +342,16 @@ impl Rope {
pub fn print(&self, w: &mut dyn Write) -> Result<(), std::io::Error> {
match self {
Rope(Node::Leaf(l)) => {
- w.write_all(l.buf().as_bytes())?;
+ for c in l.buf().chars() {
+ if c < ' ' || c == '\x7f' {
+ let b = u8::try_from(c).expect("c should be less than \\x7f");
+ write!(w, "\x1b[36m^{}\x1b[m", char::from(b ^ 0x40))?;
+ } else if '\u{80}' <= c && c <= '\u{9f}' {
+ write!(w, "\x1b[36m<{:x}>\x1b[m", u32::from(c))?;
+ } else {
+ write!(w, "{}", c)?;
+ }
+ }
Ok(())
}
Rope(Node::Branch(b)) => {
@@ -354,6 +363,20 @@ impl Rope {
}
}
+ pub fn write(&self, w: &mut dyn Write) -> Result<(), std::io::Error> {
+ match self {
+ Rope(Node::Leaf(l)) => {
+ w.write_all(l.buf().as_bytes())?;
+ }
+ Rope(Node::Branch(b)) => {
+ for c in b.children.iter() {
+ c.write(w)?;
+ }
+ }
+ }
+ Ok(())
+ }
+
pub fn slice(&self, start: usize, end: usize) -> Rope {
if start > self.len() {
panic!(