Add syntax highlighting to editor and logs
Introduce a `highlight_myc` function to provide syntax highlighting for the source code editor and trace logs, improving code readability.
This commit is contained in:
+102
-1
@@ -348,12 +348,18 @@ impl eframe::App for CompilerApp {
|
||||
},
|
||||
AppTab::Trace => {
|
||||
let mut combined = self.trace_logs.join("\n");
|
||||
let mut layouter = |ui: &egui::Ui, buffer: &dyn egui::TextBuffer, _wrap_width: f32| {
|
||||
let layout_job = highlight_myc(ui.ctx(), buffer.as_str());
|
||||
ui.painter().layout_job(layout_job)
|
||||
};
|
||||
|
||||
ui.add_sized(
|
||||
ui.available_size(),
|
||||
egui::TextEdit::multiline(&mut combined)
|
||||
.font(egui::TextStyle::Monospace)
|
||||
.desired_width(f32::INFINITY)
|
||||
.interactive(false)
|
||||
.layouter(&mut layouter)
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -387,15 +393,110 @@ impl eframe::App for CompilerApp {
|
||||
egui::ScrollArea::vertical()
|
||||
.id_salt("source_code_scroll")
|
||||
.show(ui, |ui| {
|
||||
let mut layouter = |ui: &egui::Ui, buffer: &dyn egui::TextBuffer, _wrap_width: f32| {
|
||||
let layout_job = highlight_myc(ui.ctx(), buffer.as_str());
|
||||
ui.painter().layout_job(layout_job)
|
||||
};
|
||||
|
||||
ui.add_sized(
|
||||
ui.available_size(),
|
||||
egui::TextEdit::multiline(&mut self.source_code)
|
||||
.id(editor_id)
|
||||
.font(egui::TextStyle::Monospace)
|
||||
.desired_width(f32::INFINITY)
|
||||
.lock_focus(true),
|
||||
.lock_focus(true)
|
||||
.layouter(&mut layouter),
|
||||
);
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
fn highlight_myc(ctx: &egui::Context, code: &str) -> egui::text::LayoutJob {
|
||||
let mut job = egui::text::LayoutJob::default();
|
||||
let theme = &ctx.style().visuals;
|
||||
|
||||
let color_kw = egui::Color32::from_rgb(86, 156, 214); // Blue
|
||||
let color_str = egui::Color32::from_rgb(206, 145, 120); // Orange/Brown
|
||||
let color_num = egui::Color32::from_rgb(181, 206, 168); // Greenish
|
||||
let color_comment = egui::Color32::from_rgb(106, 153, 85); // Green
|
||||
let color_bracket = [
|
||||
egui::Color32::from_rgb(255, 215, 0), // Gold
|
||||
egui::Color32::from_rgb(218, 112, 214), // Orchid
|
||||
egui::Color32::from_rgb(24, 131, 215), // Blue
|
||||
];
|
||||
|
||||
let mut chars = code.chars().peekable();
|
||||
let mut bracket_depth = 0;
|
||||
|
||||
while let Some(c) = chars.next() {
|
||||
let mut text = String::from(c);
|
||||
let mut color = theme.widgets.noninteractive.text_color();
|
||||
|
||||
match c {
|
||||
';' => {
|
||||
while let Some(&next) = chars.peek() {
|
||||
if next == '\n' { break; }
|
||||
text.push(chars.next().unwrap());
|
||||
}
|
||||
color = color_comment;
|
||||
}
|
||||
'"' => {
|
||||
while let Some(next) = chars.next() {
|
||||
text.push(next);
|
||||
if next == '"' { break; }
|
||||
if next == '\\' {
|
||||
if let Some(escaped) = chars.next() { text.push(escaped); }
|
||||
}
|
||||
}
|
||||
color = color_str;
|
||||
}
|
||||
':' => {
|
||||
while let Some(&next) = chars.peek() {
|
||||
if next.is_whitespace() || "()[]{}".contains(next) { break; }
|
||||
text.push(chars.next().unwrap());
|
||||
}
|
||||
color = color_kw;
|
||||
}
|
||||
'(' | '[' | '{' => {
|
||||
color = color_bracket[bracket_depth % 3];
|
||||
bracket_depth += 1;
|
||||
}
|
||||
')' | ']' | '}' => {
|
||||
if bracket_depth > 0 { bracket_depth -= 1; }
|
||||
color = color_bracket[bracket_depth % 3];
|
||||
}
|
||||
'0'..='9' => {
|
||||
while let Some(&next) = chars.peek() {
|
||||
if next.is_ascii_digit() || next == '.' {
|
||||
text.push(chars.next().unwrap());
|
||||
} else { break; }
|
||||
}
|
||||
color = color_num;
|
||||
}
|
||||
_ if c.is_alphabetic() || "+-*/<=>!$%&_?.".contains(c) => {
|
||||
while let Some(&next) = chars.peek() {
|
||||
if next.is_alphanumeric() || "+-*/<=>!$%&_?.".contains(next) {
|
||||
text.push(chars.next().unwrap());
|
||||
} else { break; }
|
||||
}
|
||||
if ["fn", "def", "do", "if", "assign", "recur", "cond"].contains(&text.as_str()) {
|
||||
color = color_kw;
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
||||
job.append(
|
||||
&text,
|
||||
0.0,
|
||||
egui::TextFormat {
|
||||
font_id: egui::FontId::monospace(14.0),
|
||||
color,
|
||||
..Default::default()
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
job
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user