feat(input): support custom text highlights
This commit is contained in:
parent
420d333eb5
commit
4d0dde1f23
2 changed files with 45 additions and 22 deletions
|
|
@ -752,30 +752,36 @@ impl TextElement {
|
||||||
} => (highlighter.borrow(), diagnostics),
|
} => (highlighter.borrow(), diagnostics),
|
||||||
_ => return None,
|
_ => return None,
|
||||||
};
|
};
|
||||||
let highlighter = highlighter.as_ref()?;
|
let highlighter = highlighter.as_ref();
|
||||||
|
|
||||||
let mut offset = visible_byte_range.start;
|
|
||||||
let mut styles = vec![];
|
let mut styles = vec![];
|
||||||
|
|
||||||
for line in text
|
if let Some(highlighter) = highlighter {
|
||||||
.iter_lines()
|
let mut offset = visible_byte_range.start;
|
||||||
.skip(visible_range.start)
|
for line in text
|
||||||
.take(visible_range.len())
|
.iter_lines()
|
||||||
{
|
.skip(visible_range.start)
|
||||||
let line_len = if is_multi_line {
|
.take(visible_range.len())
|
||||||
// +1 for `\n`
|
{
|
||||||
line.len() + 1
|
let line_len = if is_multi_line {
|
||||||
} else {
|
// +1 for `\n`
|
||||||
line.len()
|
line.len() + 1
|
||||||
};
|
} else {
|
||||||
|
line.len()
|
||||||
|
};
|
||||||
|
|
||||||
let range = offset..offset + line_len;
|
let range = offset..offset + line_len;
|
||||||
let line_styles = highlighter.styles(&range, &cx.theme().highlight_theme);
|
let line_styles = highlighter.styles(&range, &cx.theme().highlight_theme);
|
||||||
styles = gpui::combine_highlights(styles, line_styles).collect();
|
styles = gpui::combine_highlights(styles, line_styles).collect();
|
||||||
|
|
||||||
offset = range.end;
|
offset = range.end;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let custom_styles = state.custom_highlights.iter().filter(|(range, _)| {
|
||||||
|
range.start < visible_byte_range.end && range.end > visible_byte_range.start
|
||||||
|
});
|
||||||
|
styles = gpui::combine_highlights(styles, custom_styles.cloned()).collect();
|
||||||
|
|
||||||
let diagnostic_styles = diagnostics.styles_for_range(&visible_byte_range, cx);
|
let diagnostic_styles = diagnostics.styles_for_range(&visible_byte_range, cx);
|
||||||
|
|
||||||
// hover definition style
|
// hover definition style
|
||||||
|
|
|
||||||
|
|
@ -5,10 +5,11 @@
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use gpui::{
|
use gpui::{
|
||||||
Action, App, AppContext, Bounds, ClipboardItem, Context, Entity, EntityInputHandler,
|
Action, App, AppContext, Bounds, ClipboardItem, Context, Entity, EntityInputHandler,
|
||||||
EventEmitter, FocusHandle, Focusable, InteractiveElement as _, IntoElement, KeyBinding,
|
EventEmitter, FocusHandle, Focusable, HighlightStyle, InteractiveElement as _, IntoElement,
|
||||||
KeyDownEvent, MouseButton, MouseDownEvent, MouseMoveEvent, MouseUpEvent, ParentElement as _,
|
KeyBinding, KeyDownEvent, MouseButton, MouseDownEvent, MouseMoveEvent, MouseUpEvent,
|
||||||
Pixels, Point, Render, ScrollHandle, ScrollWheelEvent, SharedString, Styled as _, Subscription,
|
ParentElement as _, Pixels, Point, Render, ScrollHandle, ScrollWheelEvent, SharedString,
|
||||||
Task, UTF16Selection, Window, actions, div, point, prelude::FluentBuilder as _, px,
|
Styled as _, Subscription, Task, UTF16Selection, Window, actions, div, point,
|
||||||
|
prelude::FluentBuilder as _, px,
|
||||||
};
|
};
|
||||||
use ropey::{Rope, RopeSlice};
|
use ropey::{Rope, RopeSlice};
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
|
|
@ -298,6 +299,8 @@ pub struct InputState {
|
||||||
pub(crate) deferred_scroll_offset: Option<Point<Pixels>>,
|
pub(crate) deferred_scroll_offset: Option<Point<Pixels>>,
|
||||||
/// The size of the scrollable content.
|
/// The size of the scrollable content.
|
||||||
pub(crate) scroll_size: gpui::Size<Pixels>,
|
pub(crate) scroll_size: gpui::Size<Pixels>,
|
||||||
|
/// Additional presentation-only styles keyed by UTF-8 byte range.
|
||||||
|
pub(super) custom_highlights: Vec<(Range<usize>, HighlightStyle)>,
|
||||||
|
|
||||||
/// The mask pattern for formatting the input text
|
/// The mask pattern for formatting the input text
|
||||||
pub(crate) mask_pattern: MaskPattern,
|
pub(crate) mask_pattern: MaskPattern,
|
||||||
|
|
@ -395,6 +398,7 @@ impl InputState {
|
||||||
scroll_handle: ScrollHandle::new(),
|
scroll_handle: ScrollHandle::new(),
|
||||||
scroll_size: gpui::size(px(0.), px(0.)),
|
scroll_size: gpui::size(px(0.), px(0.)),
|
||||||
deferred_scroll_offset: None,
|
deferred_scroll_offset: None,
|
||||||
|
custom_highlights: Vec::new(),
|
||||||
preferred_column: None,
|
preferred_column: None,
|
||||||
placeholder: SharedString::default(),
|
placeholder: SharedString::default(),
|
||||||
mask_pattern: MaskPattern::default(),
|
mask_pattern: MaskPattern::default(),
|
||||||
|
|
@ -529,6 +533,19 @@ impl InputState {
|
||||||
cx.notify();
|
cx.notify();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Replace presentation-only text styles keyed by UTF-8 byte range.
|
||||||
|
///
|
||||||
|
/// Custom highlights are combined with syntax and diagnostic highlights and do not alter
|
||||||
|
/// the editor text, selection, or history.
|
||||||
|
pub fn set_custom_highlights(
|
||||||
|
&mut self,
|
||||||
|
highlights: Vec<(Range<usize>, HighlightStyle)>,
|
||||||
|
cx: &mut Context<Self>,
|
||||||
|
) {
|
||||||
|
self.custom_highlights = highlights;
|
||||||
|
cx.notify();
|
||||||
|
}
|
||||||
|
|
||||||
fn reset_highlighter(&mut self, cx: &mut Context<Self>) {
|
fn reset_highlighter(&mut self, cx: &mut Context<Self>) {
|
||||||
match &mut self.mode {
|
match &mut self.mode {
|
||||||
InputMode::CodeEditor { highlighter, .. } => {
|
InputMode::CodeEditor { highlighter, .. } => {
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue