diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/cursor.rs | 12 | ||||
| -rw-r--r-- | src/lib.rs | 1 | ||||
| -rw-r--r-- | src/line/mod.rs | 45 | ||||
| -rw-r--r-- | src/syntax_highlighting.rs | 19 |
4 files changed, 42 insertions, 35 deletions
diff --git a/src/cursor.rs b/src/cursor.rs index 959b15f..e6f99f1 100644 --- a/src/cursor.rs +++ b/src/cursor.rs @@ -27,12 +27,20 @@ pub fn move_cursor(direction: Direction, n: usize) { fmove_cursor(direction, n, &mut std::io::stdout()).unwrap() } +pub fn f_save(stdout: &mut dyn Write) -> std::io::Result<()> { + stdout.write_all(b"\x1b[s") +} + +pub fn f_restore(stdout: &mut dyn Write) -> std::io::Result<()> { + stdout.write_all(b"\x1b[u") +} + pub fn save() { - std::io::stdout().lock().write_all(b"\x1b[s").unwrap(); + f_save(&mut std::io::stdout().lock()).unwrap(); } pub fn restore() { - std::io::stdout().lock().write_all(b"\x1b[u").unwrap(); + f_restore(&mut std::io::stdout().lock()).unwrap(); } /// Represents a cursor position @@ -431,6 +431,7 @@ pub fn event_loop() { drop(se); // not sure if/how to report this error - would be strange to print something to console every time a keybind command returns nonzero exit code. let _ = run::run_quiet(session.clone(), cmd); + session.lock().unwrap().cohere().unwrap(); continue 'repl; } } diff --git a/src/line/mod.rs b/src/line/mod.rs index c6c2f34..510c480 100644 --- a/src/line/mod.rs +++ b/src/line/mod.rs @@ -36,15 +36,15 @@ impl Line { } pub fn highlight_syntax(&mut self, h: &mut Highlighter) -> std::io::Result<()> { - if !self.is_dirty() { + if !self.dirty { return Ok(()); } + self.dirty = false; - self.mark_clean(); - - if !h.enabled { - return Ok(()); - } + // TODO this is currently needed to reprint the prompt upon modification so we can't skip it. + // if !h.enabled { + // return Ok(()); + // } use crate::parse::{self, Parse}; @@ -53,7 +53,7 @@ impl Line { let _ = parse::Ast::parse(&mut parser); let mut stdout = io::stdout().lock(); self.line_start.f_go_to(&mut stdout)?; - h.pretty_print(&buf, parser.highlights, &mut stdout)?; + h.pretty_print(&buf, self.left_len(), parser.highlights, &mut stdout)?; stdout.flush()?; Ok(()) @@ -159,8 +159,9 @@ macro_rules! mutating_impls { ($(pub fn $fun:ident(&mut $self:ident $($arg:tt)*) -> $ty:ty $body:block )*) => { impl Line {$( pub fn $fun(&mut $self $($arg)*) -> $ty { + let result = $body; $self.dirty = true; - $body + result } )*} }; @@ -168,25 +169,14 @@ macro_rules! mutating_impls { mutating_impls! { pub fn clear_prompt(&mut self) -> io::Result<()> { - let mut stdout = io::stdout().lock(); - cursor::fmove_cursor( - Direction::Right, - self.buf.distance_from_right_end(), - &mut stdout, - )?; - for _ in 0..self.buf.len() { - stdout.write_all(b"\x08 \x08")?; - } self.buf.clear(); - stdout.flush() + Ok(()) } pub fn type_bytes(&mut self, bs: &[u8]) -> io::Result<()> { for b in bs.iter() { self.buf.add(*b); } - io::stdout().lock().write_all(&bs)?; - self.buf.display_post(b""); Ok(()) } @@ -196,52 +186,43 @@ mutating_impls! { pub fn del_left(&mut self) -> io::Result<()> { if self.buf.del_left().is_some() { - cursor::fmove_cursor(Direction::Left, 1, &mut io::stdout())?; - self.buf.display_post(b" "); + let mut stdout = io::stdout().lock(); + cursor::fmove_cursor(Direction::Left, 1, &mut stdout)?; + stdout.flush()?; } Ok(()) } pub fn del_right(&mut self) -> io::Result<()> { self.buf.del_right(); - self.buf.display_post(b" "); Ok(()) } pub fn del_left_word(&mut self) -> io::Result<()> { - let mut del = 0; while let Some(x) = self.buf.get_left() && x == b' ' { self.buf.del_left(); - del += 1; } while let Some(x) = self.buf.get_left() && x != b' ' { self.buf.del_left(); - del += 1; } - cursor::fmove_cursor(Direction::Left, del, &mut io::stdout())?; - self.buf.display_post(&vec![b' '; del]); Ok(()) } pub fn del_right_word(&mut self) -> io::Result<()> { - let mut del = 0; while let Some(x) = self.buf.get_right() && x == b' ' { self.buf.del_right(); - del += 1; } while let Some(x) = self.buf.get_right() && x != b' ' { self.buf.del_right(); - del += 1; } - self.buf.display_post(&vec![b' '; del]); Ok(()) } diff --git a/src/syntax_highlighting.rs b/src/syntax_highlighting.rs index 043509a..19f44ab 100644 --- a/src/syntax_highlighting.rs +++ b/src/syntax_highlighting.rs @@ -1,7 +1,7 @@ use std::collections::HashMap; use crate::{ - BString, ansi, bstr, + BString, ansi, bstr, cursor, parse::{Highlight, HighlightKind}, }; @@ -15,6 +15,8 @@ pub enum SetColorError { NoSuchKeyword, } +const CLEAR_TO_END: &bstr = b"\x1b[K"; + impl Highlighter { pub fn new() -> Self { let mut this = Self { @@ -51,6 +53,7 @@ impl Highlighter { pub fn pretty_print( &self, bytes: &[u8], + cursor_offset: usize, colors: Vec<Highlight>, stdout: &mut dyn std::io::Write, ) -> std::io::Result<()> { @@ -104,7 +107,16 @@ impl Highlighter { let mut current_color = self.color(HighlightKind::None); + let mut saved_pos = false; + + stdout.write_all(CLEAR_TO_END)?; + for (i, x) in bytes.iter().cloned().enumerate() { + if i == cursor_offset { + cursor::f_save(stdout)?; + saved_pos = true; + } + while let Some(color_boundary) = coloring.first().cloned() && color_boundary.loc <= i { @@ -126,6 +138,7 @@ impl Highlighter { if x == b'\n' { stdout.write_all(b"\r\n")?; + stdout.write_all(CLEAR_TO_END)?; } else { stdout.write_all(&[x])?; } @@ -133,6 +146,10 @@ impl Highlighter { stdout.write_all(self.color(HighlightKind::None))?; + if saved_pos { + cursor::f_restore(stdout)?; + } + Ok(()) } } |
