Files
codex/codex-rs/tui/src/history_cell/markdown_render_cache.rs
T
Charlie Marsh 6a54efb76b Cache finalized Markdown history rendering (#34223)
## Why

Finalized Markdown can be rendered repeatedly at the same width while measuring and displaying transcript history.

## What changed

- Cache the latest rendered lines for finalized agent messages and proposed plans.
- Invalidate cached lines when the width, syntax theme, terminal colors, or color level changes.
- Keep visualization directives uncached because resolving their local files depends on current filesystem state.

## Testing

Add tests for cache reuse, render-state invalidation, raw Markdown rendering, and visualization cache bypass.

GitOrigin-RevId: ba08140041a229b8cb9d297de87dc7bb39ebfe5d
2026-07-19 20:16:35 +00:00

50 lines
1.7 KiB
Rust

//! Single-width render cache shared by finalized source-backed markdown history cells.
use crate::terminal_hyperlinks::HyperlinkLine;
use std::sync::Mutex;
use std::sync::PoisonError;
#[derive(Debug, Default)]
pub(super) struct MarkdownRenderCache {
pub(super) cached: Mutex<Option<(MarkdownRenderCacheKey, Vec<HyperlinkLine>)>>,
}
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub(super) struct MarkdownRenderCacheKey {
pub(super) width: u16,
pub(super) syntax_theme_revision: u64,
pub(super) terminal_fg: Option<(u8, u8, u8)>,
pub(super) terminal_bg: Option<(u8, u8, u8)>,
pub(super) color_level: crate::terminal_palette::StdoutColorLevel,
}
impl MarkdownRenderCache {
/// Return lines cached for this width and terminal render state, rendering on a cache miss.
///
/// Only the most recent entry is retained, so changing width, syntax theme, or terminal colors
/// replaces the cached render.
pub(super) fn render(
&self,
width: u16,
render: impl FnOnce() -> Vec<HyperlinkLine>,
) -> Vec<HyperlinkLine> {
let key = MarkdownRenderCacheKey {
width,
syntax_theme_revision: crate::render::highlight::syntax_theme_revision(),
terminal_fg: crate::terminal_palette::default_fg(),
terminal_bg: crate::terminal_palette::default_bg(),
color_level: crate::terminal_palette::stdout_color_level(),
};
let mut cached = self.cached.lock().unwrap_or_else(PoisonError::into_inner);
if let Some((cached_key, lines)) = cached.as_ref()
&& *cached_key == key
{
return lines.clone();
}
let lines = render();
*cached = Some((key, lines.clone()));
lines
}
}