This commit is contained in:
Hassan Abedi 2026-03-23 10:13:10 +01:00
parent 638bb6db8e
commit 7b2bfa77cf
2 changed files with 79 additions and 36 deletions

View File

@ -19,7 +19,7 @@ Priorities, in order:
3. Focused, maintainable changes with good regression coverage.
4. Performance only after correctness and testability are preserved.
## Core Rules
## Core Rucargo run --features gui --bin geolog-guiles
- Use English for code, comments, docs, tests, and commit-facing text.
- Prefer small, targeted changes over broad rewrites.

View File

@ -53,12 +53,18 @@ impl EditorPanel {
fn show_editor_content(&mut self, ui: &mut egui::Ui, state: &mut GuiState) {
// Use a monospace font for code
let font_id = egui::FontId::monospace(14.0);
let mut layouter = |ui: &egui::Ui, text: &dyn egui::TextBuffer, wrap_width: f32| {
let mut layout_job = geolog_highlighter(ui, text.as_str(), wrap_width);
layout_job.wrap.max_width = wrap_width;
ui.fonts_mut(|fonts| fonts.layout_job(layout_job))
};
// Main editor area - simplified layout without line numbers column
// to avoid layout instability from horizontal split calculations
let text_edit = egui::TextEdit::multiline(&mut state.editor_content)
.font(font_id)
.code_editor()
.layouter(&mut layouter)
.desired_width(f32::INFINITY)
.desired_rows(20)
.lock_focus(true);
@ -84,24 +90,42 @@ impl Default for EditorPanel {
}
/// Simple syntax highlighting for Geolog code
/// Returns a layouter function for egui's code_editor
#[allow(dead_code)]
fn geolog_highlighter(
_ui: &egui::Ui,
text: &str,
_wrap_width: f32,
) -> egui::text::LayoutJob {
fn geolog_highlighter(ui: &egui::Ui, text: &str, wrap_width: f32) -> egui::text::LayoutJob {
let mut job = egui::text::LayoutJob::default();
job.wrap.max_width = wrap_width;
let keywords = [
"theory", "instance", "query", "forall", "exists", "Sort", "Prop", "true", "false",
"namespace",
"theory",
"instance",
"query",
"forall",
"exists",
"chase",
"Sort",
"Prop",
"true",
"false",
];
let font_id = egui::FontId::monospace(14.0);
let default_color = egui::Color32::WHITE;
let keyword_color = egui::Color32::from_rgb(86, 156, 214); // Blue
let comment_color = egui::Color32::from_rgb(106, 153, 85); // Green
let string_color = egui::Color32::from_rgb(206, 145, 120); // Orange
let default_format = egui::TextFormat::simple(font_id.clone(), ui.visuals().text_color());
let keyword_format = egui::TextFormat {
font_id: font_id.clone(),
color: egui::Color32::from_rgb(0, 92, 197),
..Default::default()
};
let comment_format = egui::TextFormat {
font_id: font_id.clone(),
color: egui::Color32::from_rgb(35, 110, 55),
italics: true,
..Default::default()
};
let string_format = egui::TextFormat {
font_id: font_id.clone(),
color: egui::Color32::from_rgb(145, 70, 15),
..Default::default()
};
let mut chars = text.char_indices().peekable();
@ -116,11 +140,7 @@ fn geolog_highlighter(
}
}
let end = chars.peek().map(|(i, _)| *i).unwrap_or(text.len());
job.append(
&text[start..end],
0.0,
egui::TextFormat::simple(font_id.clone(), comment_color),
);
job.append(&text[start..end], 0.0, comment_format.clone());
continue;
}
@ -136,11 +156,7 @@ fn geolog_highlighter(
}
}
let end = chars.peek().map(|(i, _)| *i).unwrap_or(text.len());
job.append(
&text[start..end],
0.0,
egui::TextFormat::simple(font_id.clone(), string_color),
);
job.append(&text[start..end], 0.0, string_format.clone());
continue;
}
@ -153,27 +169,54 @@ fn geolog_highlighter(
let end = chars.peek().map(|(i, _)| *i).unwrap_or(text.len());
let word = &text[start..end];
let color = if keywords.contains(&word) {
keyword_color
let format = if keywords.contains(&word) {
keyword_format.clone()
} else {
default_color
default_format.clone()
};
job.append(
word,
0.0,
egui::TextFormat::simple(font_id.clone(), color),
);
job.append(word, 0.0, format);
continue;
}
// Default: single character
job.append(
&text[i..i + c.len_utf8()],
0.0,
egui::TextFormat::simple(font_id.clone(), default_color),
);
job.append(&text[i..i + c.len_utf8()], 0.0, default_format.clone());
}
job
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn highlighter_marks_keywords_comments_and_strings() {
egui::__run_test_ui(|ui| {
let job = geolog_highlighter(
ui,
"theory Demo { // note\n label = \"hi\";\n}",
f32::INFINITY,
);
assert!(!job.sections.is_empty());
let has_keyword = job
.sections
.iter()
.any(|section| section.format.color == egui::Color32::from_rgb(0, 92, 197));
let has_comment = job
.sections
.iter()
.any(|section| section.format.color == egui::Color32::from_rgb(35, 110, 55));
let has_string = job
.sections
.iter()
.any(|section| section.format.color == egui::Color32::from_rgb(145, 70, 15));
assert!(has_keyword);
assert!(has_comment);
assert!(has_string);
});
}
}