This PR for fix some incorrect changes in #1204 ## Before <img width="854" height="864" alt="image" src="https://github.com/user-attachments/assets/eebd07e5-3437-444d-a55d-2941228e3b08" /> ## After <img width="954" height="962" alt="image" src="https://github.com/user-attachments/assets/60761848-8d4f-4fe9-88b9-f0b0f0985d2f" /> <img width="1515" height="867" alt="image" src="https://github.com/user-attachments/assets/3d4654a7-f977-4919-9c9e-f013fcdd8fde" />
This commit is contained in:
parent
78dccd4d79
commit
a9e6b49a15
2 changed files with 99 additions and 50 deletions
|
|
@ -49,11 +49,19 @@ impl Lang {
|
|||
}
|
||||
}
|
||||
|
||||
const LANGUAGES: [(Lang, &'static str); 10] = [
|
||||
const LANGUAGES: [(Lang, &'static str); 12] = [
|
||||
(
|
||||
Lang::BuiltIn(Language::Rust),
|
||||
include_str!("./fixtures/test.rs"),
|
||||
),
|
||||
(
|
||||
Lang::BuiltIn(Language::Markdown),
|
||||
include_str!("./fixtures/test.md"),
|
||||
),
|
||||
(
|
||||
Lang::BuiltIn(Language::Html),
|
||||
include_str!("./fixtures/test.html"),
|
||||
),
|
||||
(
|
||||
Lang::BuiltIn(Language::JavaScript),
|
||||
include_str!("./fixtures/test.js"),
|
||||
|
|
@ -90,8 +98,17 @@ const LANGUAGES: [(Lang, &'static str); 10] = [
|
|||
];
|
||||
|
||||
impl Example {
|
||||
pub fn new(window: &mut Window, cx: &mut Context<Self>) -> Self {
|
||||
let default_language = LANGUAGES[0].clone();
|
||||
pub fn new(default: Option<String>, window: &mut Window, cx: &mut Context<Self>) -> Self {
|
||||
let default_language = if let Some(name) = default {
|
||||
LANGUAGES
|
||||
.iter()
|
||||
.find(|s| s.0.name().starts_with(name.trim()))
|
||||
.cloned()
|
||||
.unwrap_or(LANGUAGES[0].clone())
|
||||
} else {
|
||||
LANGUAGES[0].clone()
|
||||
};
|
||||
|
||||
let editor = cx.new(|cx| {
|
||||
InputState::new(window, cx)
|
||||
.code_editor(default_language.0.name().to_string())
|
||||
|
|
@ -147,10 +164,6 @@ impl Example {
|
|||
}
|
||||
}
|
||||
|
||||
fn view(window: &mut Window, cx: &mut App) -> Entity<Self> {
|
||||
cx.new(|cx| Self::new(window, cx))
|
||||
}
|
||||
|
||||
fn set_markers(&mut self, window: &mut Window, cx: &mut Context<Self>) {
|
||||
if self.language.name() != "rust" {
|
||||
return;
|
||||
|
|
@ -310,11 +323,18 @@ impl Render for Example {
|
|||
fn main() {
|
||||
let app = Application::new().with_assets(Assets);
|
||||
|
||||
// Parse `cargo run -- <story_name>`
|
||||
let name = std::env::args().nth(1);
|
||||
|
||||
app.run(move |cx| {
|
||||
story::init(cx);
|
||||
init(cx);
|
||||
cx.activate(true);
|
||||
|
||||
story::create_new_window("Code Editor", Example::view, cx);
|
||||
story::create_new_window(
|
||||
"Code Editor",
|
||||
|window, cx| cx.new(|cx| Example::new(name, window, cx)),
|
||||
cx,
|
||||
);
|
||||
});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -579,7 +579,6 @@ impl SyntaxHighlighter {
|
|||
});
|
||||
filter.next();
|
||||
|
||||
let mut last_range = start_offset..start_offset;
|
||||
// let mut iter_count = 0;
|
||||
while let Some(item) = filter.item() {
|
||||
// iter_count += 1;
|
||||
|
|
@ -592,18 +591,7 @@ impl SyntaxHighlighter {
|
|||
node_range.end = node_range.start;
|
||||
}
|
||||
|
||||
// Ensure every range is connected.
|
||||
if last_range.end < node_range.start {
|
||||
styles.push((last_range.end..node_range.start, HighlightStyle::default()));
|
||||
}
|
||||
|
||||
let start = node_range.start.max(last_range.end);
|
||||
styles.push((
|
||||
start..node_range.end,
|
||||
theme.style(name.as_ref()).unwrap_or_default(),
|
||||
));
|
||||
last_range = node_range;
|
||||
|
||||
styles.push((node_range, theme.style(name.as_ref()).unwrap_or_default()));
|
||||
filter.next();
|
||||
}
|
||||
// dbg!(iter_count);
|
||||
|
|
@ -613,12 +601,7 @@ impl SyntaxHighlighter {
|
|||
return vec![(start_offset..range.end, HighlightStyle::default())];
|
||||
}
|
||||
|
||||
// Ensure the last range is connected to the end of the line.
|
||||
if last_range.end < range.end {
|
||||
styles.push((last_range.end..range.end, HighlightStyle::default()));
|
||||
}
|
||||
|
||||
let styles = unique_styles(styles);
|
||||
let styles = unique_styles(&range, styles);
|
||||
|
||||
// NOTE: DO NOT remove this comment, it is used for debugging.
|
||||
// for style in &styles {
|
||||
|
|
@ -645,44 +628,58 @@ impl SyntaxHighlighter {
|
|||
///
|
||||
/// AABCCDDCEEEE
|
||||
pub(crate) fn unique_styles(
|
||||
total_range: &Range<usize>,
|
||||
styles: Vec<(Range<usize>, HighlightStyle)>,
|
||||
) -> Vec<(Range<usize>, HighlightStyle)> {
|
||||
if styles.is_empty() {
|
||||
return styles;
|
||||
}
|
||||
|
||||
// Collect all boundary points and track which are "significant" (range endpoints)
|
||||
let mut boundaries = BTreeSet::new();
|
||||
let mut significant_boundaries = BTreeSet::new();
|
||||
let mut intervals = BTreeSet::new();
|
||||
let mut significant_intervals = BTreeSet::new();
|
||||
|
||||
// For example
|
||||
//
|
||||
// from: [(6..11), (6..11), (11..17), (17..25), (16..19), (25..59))]
|
||||
// to: [6, 11, 16, 17, 19, 25, 59]
|
||||
intervals.insert(total_range.start);
|
||||
intervals.insert(total_range.end);
|
||||
for (range, _) in &styles {
|
||||
boundaries.insert(range.start);
|
||||
boundaries.insert(range.end);
|
||||
significant_boundaries.insert(range.end); // End points are significant for merging decisions
|
||||
intervals.insert(range.start);
|
||||
intervals.insert(range.end);
|
||||
significant_intervals.insert(range.end); // End points are significant for merging decisions
|
||||
}
|
||||
|
||||
let boundaries: Vec<usize> = boundaries.into_iter().collect();
|
||||
let mut result = Vec::with_capacity(boundaries.len().saturating_sub(1));
|
||||
let intervals: Vec<usize> = intervals.into_iter().collect();
|
||||
let mut result = Vec::with_capacity(intervals.len().saturating_sub(1));
|
||||
|
||||
// For each interval between boundaries, find the top-most style
|
||||
for i in 0..boundaries.len().saturating_sub(1) {
|
||||
let interval_start = boundaries[i];
|
||||
let interval_end = boundaries[i + 1];
|
||||
|
||||
if interval_start >= interval_end {
|
||||
//
|
||||
// Result e.g.:
|
||||
//
|
||||
// [(6..11, red), (11..16, green), (16..17, blue), (17..19, red), (19..25, clean), (25..59, blue)]
|
||||
for i in 0..intervals.len().saturating_sub(1) {
|
||||
let interval = intervals[i]..intervals[i + 1];
|
||||
if interval.start >= interval.end {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Find the last (top-most) style that covers this interval
|
||||
let mut top_style: Option<&HighlightStyle> = None;
|
||||
let mut top_style: Option<HighlightStyle> = None;
|
||||
for (range, style) in &styles {
|
||||
if range.start <= interval_start && interval_end <= range.end {
|
||||
top_style = Some(style);
|
||||
if range.start <= interval.start && interval.end <= range.end {
|
||||
if let Some(top_style) = &mut top_style {
|
||||
merge_highlight_style(top_style, style);
|
||||
} else {
|
||||
top_style = Some(*style);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(style) = top_style {
|
||||
result.push((interval_start..interval_end, *style));
|
||||
result.push((interval, style));
|
||||
} else {
|
||||
result.push((interval, HighlightStyle::default()));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -692,7 +689,7 @@ pub(crate) fn unique_styles(
|
|||
if let Some((last_range, last_style)) = merged.last_mut() {
|
||||
if last_range.end == range.start
|
||||
&& *last_style == style
|
||||
&& !significant_boundaries.contains(&range.start)
|
||||
&& !significant_intervals.contains(&range.start)
|
||||
{
|
||||
// Merge adjacent ranges with same style, but not across significant boundaries
|
||||
last_range.end = range.end;
|
||||
|
|
@ -705,6 +702,31 @@ pub(crate) fn unique_styles(
|
|||
merged
|
||||
}
|
||||
|
||||
/// Merge other style (Other on top)
|
||||
fn merge_highlight_style(style: &mut HighlightStyle, other: &HighlightStyle) {
|
||||
if let Some(color) = other.color {
|
||||
style.color = Some(color);
|
||||
}
|
||||
if let Some(font_weight) = other.font_weight {
|
||||
style.font_weight = Some(font_weight);
|
||||
}
|
||||
if let Some(font_style) = other.font_style {
|
||||
style.font_style = Some(font_style);
|
||||
}
|
||||
if let Some(background_color) = other.background_color {
|
||||
style.background_color = Some(background_color);
|
||||
}
|
||||
if let Some(underline) = other.underline {
|
||||
style.underline = Some(underline);
|
||||
}
|
||||
if let Some(strikethrough) = other.strikethrough {
|
||||
style.strikethrough = Some(strikethrough);
|
||||
}
|
||||
if let Some(fade_out) = other.fade_out {
|
||||
style.fade_out = Some(fade_out);
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use gpui::Hsla;
|
||||
|
|
@ -720,6 +742,7 @@ mod tests {
|
|||
|
||||
#[track_caller]
|
||||
fn assert_unique_styles(
|
||||
range: Range<usize>,
|
||||
left: Vec<(Range<usize>, HighlightStyle)>,
|
||||
right: Vec<(Range<usize>, HighlightStyle)>,
|
||||
) {
|
||||
|
|
@ -740,7 +763,7 @@ mod tests {
|
|||
}
|
||||
}
|
||||
|
||||
let left = unique_styles(left);
|
||||
let left = unique_styles(&range, left);
|
||||
if left.len() != right.len() {
|
||||
println!("\n---------------------------------------------");
|
||||
for (range, style) in left.iter() {
|
||||
|
|
@ -770,18 +793,21 @@ mod tests {
|
|||
let clean = HighlightStyle::default();
|
||||
|
||||
assert_unique_styles(
|
||||
0..65,
|
||||
vec![
|
||||
(0..10, clean),
|
||||
(0..10, clean),
|
||||
(2..10, clean),
|
||||
(2..10, clean),
|
||||
(5..11, red),
|
||||
(0..6, clean),
|
||||
(2..6, clean),
|
||||
(10..15, green),
|
||||
(15..30, clean),
|
||||
(29..35, blue),
|
||||
(35..40, green),
|
||||
(45..60, blue),
|
||||
],
|
||||
vec![
|
||||
(0..6, clean),
|
||||
(0..5, clean),
|
||||
(5..6, red),
|
||||
(6..10, red),
|
||||
(10..11, green),
|
||||
(11..15, green),
|
||||
|
|
@ -789,6 +815,9 @@ mod tests {
|
|||
(29..30, blue),
|
||||
(30..35, blue),
|
||||
(35..40, green),
|
||||
(40..45, clean),
|
||||
(45..60, blue),
|
||||
(60..65, clean),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue