diff options
Diffstat (limited to 'src/main.rs')
| -rw-r--r-- | src/main.rs | 118 |
1 files changed, 61 insertions, 57 deletions
diff --git a/src/main.rs b/src/main.rs index 9c30520..b40d9b1 100644 --- a/src/main.rs +++ b/src/main.rs @@ -5,9 +5,10 @@ use rope::Rope; use std::error::Error; use std::ffi::{OsStr, OsString}; use std::fs::File; -use std::io::{stderr, stdout, BufReader, Stdin, Write}; +use std::io::{stderr, stdout, Write}; use std::path::{Path, PathBuf}; use term::Key; +use term::Reader; fn open(file: &Path) -> Result<Rope, std::io::Error> { let mut f = File::open(file)?; @@ -15,11 +16,7 @@ fn open(file: &Path) -> Result<Rope, std::io::Error> { Ok(r) } -fn line_offset( - stdin: &mut BufReader<Stdin>, - line: &Rope, - col: u16, -) -> Result<usize, Box<dyn Error>> { +fn line_offset(stdin: &mut Reader, line: &Rope, col: u16) -> Result<usize, Box<dyn Error>> { let mut n = 0; for i in 0.. { if i == line.len() { @@ -49,7 +46,7 @@ fn line_offset( } write!(stdout(), "\x1b[G")?; line.slice(0, h).print(&mut stdout())?; - let (_, c) = term::cursor_pos(stdin)?; + let (_, c) = stdin.cursor_pos()?; if c <= col { lo = h + 1; if lo < line.len() { @@ -64,14 +61,14 @@ fn line_offset( } if lo == 0 { // You might think this case is impossible (I did), but terminals can do a lot of - // weird things. - return Ok(0); + // weird things and I'm trying to make this robust. + return Err(Box::from("incorrect cursor_pos")); } Ok(line.floor_char_boundary(lo - 1)) } fn floor_grapheme_cluster( - stdin: &mut BufReader<Stdin>, + stdin: &mut Reader, line: &Rope, offset: usize, ) -> Result<usize, Box<dyn Error>> { @@ -82,11 +79,11 @@ fn floor_grapheme_cluster( write!(stdout(), "\x1b[G")?; line.slice(0, line.ceil_char_boundary(offset + 1)) .print(&mut stdout())?; - let (_, target_col) = term::cursor_pos(stdin)?; + let (_, target_col) = stdin.cursor_pos()?; while offset > 0 { write!(stdout(), "\x1b[G")?; line.slice(0, offset).print(&mut stdout())?; - let (_, col) = term::cursor_pos(stdin)?; + let (_, col) = stdin.cursor_pos()?; if col < target_col { return Ok(offset); } @@ -96,7 +93,7 @@ fn floor_grapheme_cluster( } fn ceil_grapheme_cluster( - stdin: &mut BufReader<Stdin>, + stdin: &mut Reader, line: &Rope, offset: usize, ) -> Result<usize, Box<dyn Error>> { @@ -106,7 +103,7 @@ fn ceil_grapheme_cluster( } write!(stdout(), "\x1b[G")?; line.slice(0, offset).print(&mut stdout())?; - let (_, target_col) = term::cursor_pos(stdin)?; + let (_, target_col) = stdin.cursor_pos()?; loop { if offset >= line.len() { return Ok(line.len()); @@ -114,7 +111,7 @@ fn ceil_grapheme_cluster( let old_offset = offset; offset = line.ceil_char_boundary(old_offset + 1); line.slice(old_offset, offset).print(&mut stdout())?; - let (_, col) = term::cursor_pos(stdin)?; + let (_, col) = stdin.cursor_pos()?; if col > target_col { return Ok(line.floor_char_boundary(offset - 1)); } @@ -139,6 +136,7 @@ struct State { cursor_row: u16, cursor_col: u16, + stdin: Reader, path: PathBuf, inserting: bool, need_repaint_screen: bool, @@ -150,12 +148,12 @@ impl State { self.buf.line(self.row_start + usize::from(self.cursor_row)) } - fn update_cursor_col(&mut self, stdin: &mut BufReader<Stdin>) -> Result<(), Box<dyn Error>> { + fn update_cursor_col(&mut self) -> Result<(), Box<dyn Error>> { let size = term::size()?; let line = self.line(); write!(stdout(), "\x1b[{}H", self.cursor_row + 1)?; line.slice(0, self.line_offset).print(&mut stdout())?; - let (_, col) = term::cursor_pos(stdin)?; + let (_, col) = self.stdin.cursor_pos()?; if col == size.ws_col - 1 { self.cursor_col = col - 1; write!( @@ -237,7 +235,7 @@ impl State { self.history.push(self.snapshot()); } - fn keypress(&mut self, stdin: &mut BufReader<Stdin>, key: Key) -> Result<bool, Box<dyn Error>> { + fn keypress(&mut self, key: Key) -> Result<bool, Box<dyn Error>> { const CTRL_Q: u8 = b'Q' - b'@'; const CTRL_S: u8 = b'S' - b'@'; const CTRL_Y: u8 = b'Y' - b'@'; @@ -260,7 +258,7 @@ impl State { self.repaint_screen()?; self.need_repaint_screen = false; } - self.update_cursor_col(stdin)?; + self.update_cursor_col()?; self.need_repaint_line = false; stdout().flush()?; } @@ -272,17 +270,17 @@ impl State { .buf .line(self.row_start + usize::from(self.cursor_row) - 1); if self.cursor_row == 0 { - self.line_offset = line_offset(stdin, &prev_line, self.cursor_col)?; + self.line_offset = line_offset(&mut self.stdin, &prev_line, self.cursor_col)?; self.row_start -= 1; self.repaint_screen()?; - self.update_cursor_col(stdin)?; + self.update_cursor_col()?; stdout().flush()?; return Ok(true); } write!(stdout(), "\x1b[{}H", self.cursor_row)?; - self.line_offset = line_offset(stdin, &prev_line, self.cursor_col)?; + self.line_offset = line_offset(&mut self.stdin, &prev_line, self.cursor_col)?; self.cursor_row -= 1; - self.update_cursor_col(stdin)?; + self.update_cursor_col()?; stdout().flush()?; } Key::Down => { @@ -295,23 +293,24 @@ impl State { .line(self.row_start + usize::from(self.cursor_row) + 1); if self.cursor_row < size.ws_row - 1 { write!(stdout(), "\x1b[{}H", self.cursor_row + 2)?; - self.line_offset = line_offset(stdin, &next_line, self.cursor_col)?; + self.line_offset = line_offset(&mut self.stdin, &next_line, self.cursor_col)?; self.cursor_row += 1; - self.update_cursor_col(stdin)?; + self.update_cursor_col()?; stdout().flush()?; return Ok(true); } - self.line_offset = line_offset(stdin, &next_line, self.cursor_col)?; + self.line_offset = line_offset(&mut self.stdin, &next_line, self.cursor_col)?; self.row_start += 1; self.repaint_screen()?; - self.update_cursor_col(stdin)?; + self.update_cursor_col()?; stdout().flush()?; } Key::Left => { if self.line_offset > 0 { + let line = self.line(); self.line_offset = - floor_grapheme_cluster(stdin, &self.line(), self.line_offset - 1)?; - self.update_cursor_col(stdin)?; + floor_grapheme_cluster(&mut self.stdin, &line, self.line_offset - 1)?; + self.update_cursor_col()?; stdout().flush()?; return Ok(true); } @@ -319,14 +318,14 @@ impl State { let size = term::size()?; write!(stdout(), "\x1b[{}H", self.cursor_row)?; self.line_offset = line_offset( - stdin, + &mut self.stdin, &self .buf .line(self.row_start + usize::from(self.cursor_row) - 1), size.ws_col - 2, )?; self.cursor_row -= 1; - self.update_cursor_col(stdin)?; + self.update_cursor_col()?; stdout().flush()?; return Ok(true); } @@ -335,7 +334,7 @@ impl State { } let size = term::size()?; self.line_offset = line_offset( - stdin, + &mut self.stdin, &self .buf .line(self.row_start + usize::from(self.cursor_row) - 1), @@ -343,15 +342,16 @@ impl State { )?; self.row_start -= 1; self.repaint_screen()?; - self.update_cursor_col(stdin)?; + self.update_cursor_col()?; stdout().flush()?; } Key::Right => { let size = term::size()?; let line = self.line(); if self.cursor_col < size.ws_col - 2 && self.line_offset < line.len() { - self.line_offset = ceil_grapheme_cluster(stdin, &line, self.line_offset + 1)?; - self.update_cursor_col(stdin)?; + self.line_offset = + ceil_grapheme_cluster(&mut self.stdin, &line, self.line_offset + 1)?; + self.update_cursor_col()?; stdout().flush()?; return Ok(true); } @@ -381,8 +381,9 @@ impl State { } Key::End => { let size = term::size()?; - self.line_offset = line_offset(stdin, &self.line(), size.ws_col - 2)?; - self.update_cursor_col(stdin)?; + let line = self.line(); + self.line_offset = line_offset(&mut self.stdin, &line, size.ws_col - 2)?; + self.update_cursor_col()?; stdout().flush()?; } Key::PgUp => { @@ -400,13 +401,13 @@ impl State { start = self.row_start + 2 - usize::from(size.ws_row); }; self.line_offset = line_offset( - stdin, + &mut self.stdin, &self.buf.line(start + usize::from(self.cursor_row)), self.cursor_col, )?; self.row_start = start; self.repaint_screen()?; - self.update_cursor_col(stdin)?; + self.update_cursor_col()?; stdout().flush()?; } Key::PgDn => { @@ -415,7 +416,7 @@ impl State { self.cursor_row = u16::try_from(self.buf.lines() - self.row_start) .expect("self.buf.lines() - self.row_start < size.ws_row"); self.line_offset = self.line().len(); - self.update_cursor_col(stdin)?; + self.update_cursor_col()?; stdout().flush()?; return Ok(true); } @@ -425,23 +426,26 @@ impl State { } if start + usize::from(self.cursor_row) <= self.buf.lines() { self.line_offset = line_offset( - stdin, + &mut self.stdin, &self.buf.line(start + usize::from(self.cursor_row)), self.cursor_col, )?; self.row_start = start; self.repaint_screen()?; - self.update_cursor_col(stdin)?; + self.update_cursor_col()?; stdout().flush()?; return Ok(true); } - self.line_offset = - line_offset(stdin, &self.buf.line(self.buf.lines()), self.cursor_col)?; + self.line_offset = line_offset( + &mut self.stdin, + &self.buf.line(self.buf.lines()), + self.cursor_col, + )?; self.row_start = start; self.cursor_row = u16::try_from(self.buf.lines() - start) .expect("start + self.cursor_row > self.buf.lines()"); self.repaint_screen()?; - self.update_cursor_col(stdin)?; + self.update_cursor_col()?; stdout().flush()?; } Key::Byte(CTRL_Q) => { @@ -463,7 +467,7 @@ impl State { } self.load(); self.repaint_screen()?; - self.update_cursor_col(stdin)?; + self.update_cursor_col()?; stdout().flush()?; } Key::Byte(CTRL_Y) => { @@ -476,7 +480,7 @@ impl State { self.n = Some(n + 1); self.load(); self.repaint_screen()?; - self.update_cursor_col(stdin)?; + self.update_cursor_col()?; stdout().flush()?; } Key::Byte(BACKSPACE) | Key::Byte(OTHER_BACKSPACE) => { @@ -500,21 +504,21 @@ impl State { .slice(0, offset - 1) .concat(&self.buf.slice(offset, self.buf.len())); self.repaint_screen()?; - self.update_cursor_col(stdin)?; + self.update_cursor_col()?; stdout().flush()?; return Ok(true); } let line = self.line(); - self.line_offset = match floor_grapheme_cluster(stdin, &line, self.line_offset - 1) - { - Ok(x) => x, - Err(_) => line.floor_char_boundary(self.line_offset - 1), - }; + self.line_offset = + match floor_grapheme_cluster(&mut self.stdin, &line, self.line_offset - 1) { + Ok(x) => x, + Err(_) => line.floor_char_boundary(self.line_offset - 1), + }; self.buf = self .buf .slice(0, line_start + self.line_offset) .concat(&self.buf.slice(offset, self.buf.len())); - self.update_cursor_col(stdin)?; + self.update_cursor_col()?; stdout().flush()?; } Key::Byte(b'\r') | Key::Byte(b'\n') => { @@ -575,7 +579,6 @@ fn edit(file: &OsStr) -> Result<(), String> { return Err(format!("enter raw mode: {}", err)); } }; - let mut stdin = BufReader::new(std::io::stdin()); let mut state = State { history: vec