feat(gui): add ANSI escape sequence renderer with full panel integration

- new ansi_render module: SGR, cursor movement, erase, scroll
- integrate ANSI rendering into console panel output pipeline
- wire app_state, buffers, hex_view, and shortcuts for ANSI-aware display
- add test_ansi.py for manual ANSI sequence testing
This commit is contained in:
2026-06-14 04:12:35 +08:00
parent e600418da8
commit 4e4c9cee65
11 changed files with 819 additions and 55 deletions

View File

@@ -1,3 +1,4 @@
use crate::ansi_render::{ansi_to_layout_job, ansi_to_layout_job_highlighted};
use crate::app::{DisplayOptions, SearchState};
use crate::buffers::{ConsoleLine, LineDirection, TextBuffer};
use egui::{
@@ -31,42 +32,6 @@ pub fn render(
line_count
}
fn highlight_matches(
text: &str,
query: &str,
case_sensitive: bool,
default_format: TextFormat,
highlight_format: TextFormat,
) -> LayoutJob {
let search_text = if case_sensitive {
text.to_string()
} else {
text.to_lowercase()
};
let query = if case_sensitive {
query.to_string()
} else {
query.to_lowercase()
};
let mut job = LayoutJob::default();
let mut last_end = 0;
let mut idx = 0;
while let Some(pos) = search_text[idx..].find(&query) {
let start = idx + pos;
let end = start + query.len();
if last_end < start {
job.append(&text[last_end..start], 0.0, default_format.clone());
}
job.append(&text[start..end], 0.0, highlight_format.clone());
last_end = end;
idx = end;
}
if last_end < text.len() {
job.append(&text[last_end..], 0.0, default_format);
}
job
}
fn monospace_format(style: &egui::Style) -> TextFormat {
TextFormat {
font_id: style
@@ -121,9 +86,13 @@ pub fn format_console_line(
};
match search {
Some(state) if state.active && !state.query.is_empty() => {
highlight_matches(&full_text, &state.query, state.case_sensitive, default, highlight)
}
_ => LayoutJob::single_section(full_text, default),
Some(state) if state.active && !state.query.is_empty() => ansi_to_layout_job_highlighted(
&full_text,
default,
&state.query,
state.case_sensitive,
highlight,
),
_ => ansi_to_layout_job(&full_text, default),
}
}