aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorRose Hogenson <rosehogenson@posteo.net>2024-01-06 13:36:43 -0800
committerRose Hogenson <rosehogenson@posteo.net>2024-01-06 13:36:43 -0800
commit94626edd6df13d2bcac561f99334a075b1ac8941 (patch)
tree788eef132deb445adfe0ff6c87b0138baafbc3d9 /src
parent46bed3055b52bc916360249f0a08f9686b22332a (diff)
downloadeditor-94626edd6df13d2bcac561f99334a075b1ac8941.tar.zst
Fix input issues when scrolling quickly.
Unfortunately the user input comes on the same channel as the terminal status report from 6n, so there's a possibility of getting confused here. As long as the program is relatively efficient, it shouldn't be observable.
Diffstat (limited to 'src')
-rw-r--r--src/main.rs45
-rw-r--r--src/rope.rs3
2 files changed, 31 insertions, 17 deletions
diff --git a/src/main.rs b/src/main.rs
index 3745553..54b644d 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -49,20 +49,24 @@ impl State {
fn repaint_all(&mut self) -> Result<(), Box<dyn Error>> {
let size = term::size()?;
+ let mut stdout = stdout().lock();
- write!(stdout(), "\x1b[H\x1b[J")?;
+ write!(stdout, "\x1b[H\x1b[J")?;
for i in self.row_start..self.row_start+usize::from(size.ws_row) {
if i > 0 {
- write!(stdout(), "\r\n")?;
+ write!(stdout, "\r\n")?;
}
if i > self.buf.lines() {
break;
}
- let line = self.buf.line(i);
+ let mut line = self.buf.line(i);
let max_len = line.char(usize::from(size.ws_col-1));
- line.slice(0, max_len).print(&mut stdout())?;
if max_len < line.len() {
- write!(stdout(), "\x1b[30m\x1b[47m>\x1b[m")?;
+ line = line.slice(0, max_len);
+ }
+ line.print(&mut stdout)?;
+ if max_len < line.len() {
+ write!(stdout, "\x1b[30m\x1b[47m>\x1b[m")?;
}
}
return Ok(());
@@ -70,8 +74,9 @@ impl State {
fn repaint_line_full(&mut self) -> Result<(), Box<dyn Error>> {
let term_size = term::size()?;
+ let mut stdout = stdout().lock();
- write!(stdout(), "\x1b[{}H\x1b[K", self.cursor_row+1)?;
+ write!(stdout, "\x1b[{}H\x1b[K", self.cursor_row+1)?;
let mut line = self.buf.line(self.row_start+self.cursor_row);
let max_len = line.char(usize::from(term_size.ws_col-1));
let mut truncated = false;
@@ -80,24 +85,34 @@ impl State {
truncated = true;
}
- line.print(&mut stdout())?;
+ line.print(&mut stdout)?;
let (_, col) = self.cursor_pos()?;
self.line_cols = col;
if self.cursor_col >= self.line_cols {
self.line_offset = line.len();
if truncated {
- write!(stdout(), "\x1b[30m\x1b[47m>\x1b[m\x1b[{}G", self.cursor_col+1)?;
+ write!(stdout, "\x1b[30m\x1b[47m>\x1b[m\x1b[{}G", self.cursor_col+1)?;
}
return Ok(());
}
- let mut lo = line.char(self.cursor_col);
+ let offset_guess = line.char(self.cursor_col);
+ write!(stdout, "\x1b[G")?;
+ line.slice(0, offset_guess).print(&mut stdout)?;
+ let (_, col) = self.cursor_pos()?;
+ if col == self.cursor_col {
+ // One codepoint per column, like God intended.
+ self.line_offset = offset_guess;
+ return Ok(());
+ }
+
+ let mut lo = offset_guess;
let mut hi = line.len();
// Binary search :D
while hi > lo {
let x = line.floor_char_boundary(lo + (hi - lo) / 2);
- write!(stdout(), "\x1b[G")?;
- line.slice(0, x).print(&mut stdout())?;
+ write!(stdout, "\x1b[G")?;
+ line.slice(0, x).print(&mut stdout)?;
let (_, col) = self.cursor_pos()?;
if col <= self.cursor_col {
lo = line.ceil_char_boundary(x+1);
@@ -106,12 +121,12 @@ impl State {
}
}
self.line_offset = line.floor_char_boundary(lo-1);
- write!(stdout(), "\x1b[G")?;
- line.print(&mut stdout())?;
+ write!(stdout, "\x1b[G")?;
+ line.print(&mut stdout)?;
if truncated {
- write!(stdout(), "\x1b[30m\x1b[47m>\x1b[m")?;
+ write!(stdout, "\x1b[30m\x1b[47m>\x1b[m")?;
}
- write!(stdout(), "\x1b[{}G", self.cursor_col+1)?;
+ write!(stdout, "\x1b[{}G", self.cursor_col+1)?;
return Ok(());
}
diff --git a/src/rope.rs b/src/rope.rs
index 5454557..7d00dcd 100644
--- a/src/rope.rs
+++ b/src/rope.rs
@@ -4,8 +4,7 @@ use std::path::Path;
use std::error::Error;
use std::rc::Rc;
-// Set to a small value to help identify bugs in the implementation.
-const MAX_NODE_SIZE: usize = 4;
+const MAX_NODE_SIZE: usize = 254;
#[derive(Debug, Clone)]
struct Leaf {