WIP
This commit is contained in:
parent
638bb6db8e
commit
7b2bfa77cf
@ -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.
|
||||
|
||||
@ -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);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user