refactor(tui): split app query and viewport cache helpers
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
This commit is contained in:
@@ -0,0 +1,99 @@
|
||||
use log_viewer_core::types::LogLevel;
|
||||
use unicode_width::UnicodeWidthChar;
|
||||
|
||||
pub(super) struct ViewportEntry {
|
||||
pub(super) wrapped_rows: Vec<String>,
|
||||
pub(super) level: Option<LogLevel>,
|
||||
pub(super) visual_height: usize,
|
||||
}
|
||||
|
||||
pub(super) struct ViewportCache {
|
||||
pub(super) entries: Vec<ViewportEntry>,
|
||||
pub(super) logical_start: usize,
|
||||
pub(super) width: usize,
|
||||
json_format: bool,
|
||||
pub(super) cached_total_visual_rows: Option<usize>,
|
||||
}
|
||||
|
||||
impl ViewportCache {
|
||||
pub(super) fn new() -> Self {
|
||||
Self {
|
||||
entries: Vec::new(),
|
||||
logical_start: 0,
|
||||
width: 0,
|
||||
json_format: false,
|
||||
cached_total_visual_rows: None,
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) fn invalidate(&mut self) {
|
||||
self.entries.clear();
|
||||
self.logical_start = 0;
|
||||
self.width = 0;
|
||||
self.cached_total_visual_rows = None;
|
||||
}
|
||||
|
||||
pub(super) fn needs_recompute(&self, width: usize, json_format: bool) -> bool {
|
||||
self.width != width || self.json_format != json_format
|
||||
}
|
||||
|
||||
pub(super) fn set_json_format(&mut self, json_format: bool) {
|
||||
self.json_format = json_format;
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub(super) fn get_entry(&self, logical_line: usize) -> Option<&ViewportEntry> {
|
||||
if logical_line >= self.logical_start {
|
||||
let idx = logical_line - self.logical_start;
|
||||
self.entries.get(idx)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) const TRUNCATE_TAB_WIDTH: usize = 4;
|
||||
|
||||
pub(super) fn gutter_width_for(total_lines: usize, is_loading: bool) -> usize {
|
||||
if total_lines == 0 {
|
||||
return 0;
|
||||
}
|
||||
let line_num_width = total_lines.to_string().len();
|
||||
let loading_extra = if is_loading { 1 } else { 0 };
|
||||
line_num_width + loading_extra + 1 + 1
|
||||
}
|
||||
|
||||
pub(super) fn truncate_to_columns(s: &str, max_cols: usize) -> String {
|
||||
if max_cols == 0 || s.is_empty() {
|
||||
return String::new();
|
||||
}
|
||||
|
||||
let mut out = String::new();
|
||||
let mut col = 0;
|
||||
|
||||
for ch in s.chars() {
|
||||
if ch == '\t' {
|
||||
let tab_stop = TRUNCATE_TAB_WIDTH - (col % TRUNCATE_TAB_WIDTH);
|
||||
if col + tab_stop > max_cols {
|
||||
break;
|
||||
}
|
||||
for _ in 0..tab_stop {
|
||||
out.push(' ');
|
||||
}
|
||||
col += tab_stop;
|
||||
} else {
|
||||
let w = if ch.is_control() {
|
||||
0
|
||||
} else {
|
||||
ch.width().unwrap_or(0)
|
||||
};
|
||||
if col + w > max_cols {
|
||||
break;
|
||||
}
|
||||
out.push(ch);
|
||||
col += w;
|
||||
}
|
||||
}
|
||||
|
||||
out
|
||||
}
|
||||
Reference in New Issue
Block a user