From cb173ffbc083f08aed1bad58c3bcd979a96d3bb6 Mon Sep 17 00:00:00 2001 From: gwenn Date: Sat, 24 Aug 2024 12:07:06 +0200 Subject: [PATCH] Fix unix impl --- .github/workflows/rust.yml | 5 +++++ src/edit.rs | 7 +++---- src/highlight.rs | 38 +++++++++++++++++++++++++++++++++----- src/tty/mod.rs | 8 ++++---- src/tty/test.rs | 4 ++-- src/tty/unix.rs | 25 +++++++++++++++++++------ src/tty/windows.rs | 4 ++-- 7 files changed, 68 insertions(+), 23 deletions(-) diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index 169b31f9b..bf2e10d14 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -48,6 +48,11 @@ jobs: run: cargo check --workspace --no-default-features env: RUSTFLAGS: "-D warnings" + - name: Check split-highlight feature + run: | + cargo check --workspace --all-targets --features 'split-highlight' + cargo check --workspace --all-targets --features 'split-highlight ansi-str' + cargo check --workspace --all-targets --features 'split-highlight anstyle' direct-minimal-versions: name: Test min versions diff --git a/src/edit.rs b/src/edit.rs index c231e4a42..fa02a4249 100644 --- a/src/edit.rs +++ b/src/edit.rs @@ -7,7 +7,6 @@ use unicode_width::UnicodeWidthChar; use super::{Context, Helper, Result}; use crate::error::ReadlineError; -use crate::highlight::Highlighter; use crate::hint::Hint; use crate::history::SearchDirection; use crate::keymap::{Anchor, At, CharSearch, Cmd, Movement, RepeatCount, Word}; @@ -70,9 +69,9 @@ impl<'out, 'prompt, H: Helper> State<'out, 'prompt, H> { } } - pub fn highlighter(&self) -> Option<&dyn Highlighter> { + pub fn highlighter(&self) -> Option<&H> { if self.out.colors_enabled() { - self.helper.map(|h| h as &dyn Highlighter) + self.helper } else { None } @@ -169,7 +168,7 @@ impl<'out, 'prompt, H: Helper> State<'out, 'prompt, H> { Info::Msg(msg) => msg, }; let highlighter = if self.out.colors_enabled() { - self.helper.map(|h| h as &dyn Highlighter) + self.helper } else { None }; diff --git a/src/highlight.rs b/src/highlight.rs index 228d72976..ef8740893 100644 --- a/src/highlight.rs +++ b/src/highlight.rs @@ -101,7 +101,7 @@ impl StyledBlock for (anstyle::Style, &str) { pub trait Highlighter { /// ANSI Style #[cfg(all(feature = "split-highlight", not(feature = "ansi-str")))] - type Style: Style + Default + type Style: Style where Self: Sized; /// Takes the currently edited `line` with the cursor `pos`ition and @@ -122,6 +122,8 @@ pub trait Highlighter { /// Takes the currently edited `line` with the cursor `pos`ition and /// returns the styled blocks. + /// + /// Returns an empty vec when there is no highlighting. #[cfg(all(feature = "split-highlight", not(feature = "ansi-str")))] #[cfg_attr( docsrs, @@ -132,9 +134,8 @@ pub trait Highlighter { where Self: Sized, { - let _ = pos; - // TODO default style vs empty vec to indicate no highlighting - vec![(Self::Style::default(), line)] + let _ = (line, pos); + vec![] } /// Takes the `prompt` and @@ -229,6 +230,8 @@ impl<'r, H: Highlighter> Highlighter for &'r H { /// Highlight matching bracket when typed or cursor moved on. #[derive(Default)] pub struct MatchingBracketHighlighter { + #[cfg(feature = "anstyle")] + style: anstyle::Style, bracket: Cell>, // memorize the character to search... } @@ -237,13 +240,21 @@ impl MatchingBracketHighlighter { #[must_use] pub fn new() -> Self { Self { + #[cfg(feature = "anstyle")] + style: anstyle::Style::new() + .bold() + .fg_color(Some(anstyle::AnsiColor::Blue.into())), bracket: Cell::new(None), } } } -#[cfg(any(not(feature = "split-highlight"), feature = "ansi-str"))] +#[cfg(any(not(feature = "split-highlight"), feature = "anstyle"))] impl Highlighter for MatchingBracketHighlighter { + #[cfg(all(feature = "split-highlight", not(feature = "ansi-str")))] + type Style = anstyle::Style; + + #[cfg(any(not(feature = "split-highlight"), feature = "ansi-str"))] fn highlight<'l>(&self, line: &'l str, _pos: usize) -> Cow<'l, str> { if line.len() <= 1 { return Borrowed(line); @@ -259,6 +270,23 @@ impl Highlighter for MatchingBracketHighlighter { Borrowed(line) } + #[cfg(all(feature = "split-highlight", not(feature = "ansi-str")))] + fn highlight_line<'l>(&self, line: &'l str, _pos: usize) -> Vec<(Self::Style, &'l str)> { + if line.len() <= 1 { + return vec![]; + } + if let Some((bracket, pos)) = self.bracket.get() { + if let Some((_, idx)) = find_matching_bracket(line, pos, bracket) { + return vec![ + (Self::Style::default(), &line[0..idx]), + (self.style, &line[idx..=idx]), + (Self::Style::default(), &line[idx + 1..]), + ]; + } + } + vec![] + } + fn highlight_char(&self, line: &str, pos: usize, forced: bool) -> bool { if forced { self.bracket.set(None); diff --git a/src/tty/mod.rs b/src/tty/mod.rs index 62484f042..f2abf0df5 100644 --- a/src/tty/mod.rs +++ b/src/tty/mod.rs @@ -47,14 +47,14 @@ pub trait Renderer { /// Display `prompt`, line and cursor in terminal output #[allow(clippy::too_many_arguments)] - fn refresh_line( + fn refresh_line( &mut self, prompt: &str, line: &LineBuffer, hint: Option<&str>, old_layout: &Layout, new_layout: &Layout, - highlighter: Option<&dyn Highlighter>, + highlighter: Option<&H>, ) -> Result<()>; /// Compute layout for rendering prompt + line + some info (either hint, @@ -126,14 +126,14 @@ impl<'a, R: Renderer + ?Sized> Renderer for &'a mut R { (**self).move_cursor(old, new) } - fn refresh_line( + fn refresh_line( &mut self, prompt: &str, line: &LineBuffer, hint: Option<&str>, old_layout: &Layout, new_layout: &Layout, - highlighter: Option<&dyn Highlighter>, + highlighter: Option<&H>, ) -> Result<()> { (**self).refresh_line(prompt, line, hint, old_layout, new_layout, highlighter) } diff --git a/src/tty/test.rs b/src/tty/test.rs index 00ef42152..45828e61f 100644 --- a/src/tty/test.rs +++ b/src/tty/test.rs @@ -100,14 +100,14 @@ impl Renderer for Sink { Ok(()) } - fn refresh_line( + fn refresh_line( &mut self, _prompt: &str, _line: &LineBuffer, _hint: Option<&str>, _old_layout: &Layout, _new_layout: &Layout, - _highlighter: Option<&dyn Highlighter>, + _highlighter: Option<&H>, ) -> Result<()> { Ok(()) } diff --git a/src/tty/unix.rs b/src/tty/unix.rs index 08d754810..cc8c8d074 100644 --- a/src/tty/unix.rs +++ b/src/tty/unix.rs @@ -27,7 +27,7 @@ use utf8parse::{Parser, Receiver}; use super::{width, Event, RawMode, RawReader, Renderer, Term}; use crate::config::{Behavior, BellStyle, ColorMode, Config}; -use crate::highlight::Highlighter; +use crate::highlight::{Highlighter, Style}; use crate::keys::{KeyCode as K, KeyEvent, KeyEvent as E, Modifiers as M}; use crate::layout::{Layout, Position}; use crate::line_buffer::LineBuffer; @@ -979,14 +979,14 @@ impl Renderer for PosixRenderer { Ok(()) } - fn refresh_line( + fn refresh_line( &mut self, prompt: &str, line: &LineBuffer, hint: Option<&str>, old_layout: &Layout, new_layout: &Layout, - highlighter: Option<&dyn Highlighter>, + highlighter: Option<&H>, ) -> Result<()> { use std::fmt::Write; self.buffer.clear(); @@ -1002,8 +1002,21 @@ impl Renderer for PosixRenderer { self.buffer .push_str(&highlighter.highlight_prompt(prompt, default_prompt)); // display the input line - self.buffer - .push_str(&highlighter.highlight(line, line.pos())); + cfg_if::cfg_if! { + if #[cfg(not(feature = "split-highlight"))] { + self.buffer + .push_str(&highlighter.highlight(line, line.pos())); + } else if #[cfg(feature = "ansi-str")] { + self.buffer + .push_str(&highlighter.highlight(line, line.pos())); + } else { + for (style, block) in highlighter.highlight_line(line, line.pos()) { + write!(self.buffer, "{}", style.start())?; + self.buffer.push_str(block); + write!(self.buffer, "{}", style.end())?; + } + } + } } else { // display the prompt self.buffer.push_str(prompt); @@ -1695,7 +1708,7 @@ mod test { let new_layout = out.compute_layout(prompt_size, default_prompt, &line, None); assert_eq!(Position { col: 1, row: 1 }, new_layout.cursor); assert_eq!(new_layout.cursor, new_layout.end); - out.refresh_line(prompt, &line, None, &old_layout, &new_layout, None) + out.refresh_line::<()>(prompt, &line, None, &old_layout, &new_layout, None) .unwrap(); #[rustfmt::skip] assert_eq!( diff --git a/src/tty/windows.rs b/src/tty/windows.rs index 7574403f0..12cf187a2 100644 --- a/src/tty/windows.rs +++ b/src/tty/windows.rs @@ -429,14 +429,14 @@ impl Renderer for ConsoleRenderer { .map(|_| ()) } - fn refresh_line( + fn refresh_line( &mut self, prompt: &str, line: &LineBuffer, hint: Option<&str>, old_layout: &Layout, new_layout: &Layout, - highlighter: Option<&dyn Highlighter>, + highlighter: Option<&H>, ) -> Result<()> { let default_prompt = new_layout.default_prompt; let cursor = new_layout.cursor;