pub struct IncrementalRenderer { /* private fields */ }Implementations§
Source§impl IncrementalRenderer
impl IncrementalRenderer
Sourcepub fn new(width: usize, height: usize) -> Self
pub fn new(width: usize, height: usize) -> Self
Creates an incremental renderer with a bounded viewport size.
A minimum viewport size of 1x1 is enforced.
The render origin defaults to terminal row 1, column 1.
Examples found in repository?
276fn main() -> Result<(), Box<dyn Error>> {
277 let args: Vec<String> = env::args().collect();
278 let options = match parse_args(&args) {
279 Ok(options) => options,
280 Err(err) => {
281 eprintln!("invalid arguments: {err}");
282 eprintln!();
283 print_usage();
284 return Ok(());
285 }
286 };
287
288 let grammar =
289 parse_grammar(&options.grammar_name).map_err(|msg| format!("invalid grammar: {msg}"))?;
290 let source = fs::read(&options.source_path)?;
291 let previous_source = if let Some(previous_source_path) = &options.previous_source_path {
292 Some(fs::read(previous_source_path)?)
293 } else {
294 None
295 };
296 let theme = load_theme(&options.theme_name)?;
297 let mut highlighter = SpanHighlighter::new()?;
298
299 let patch = if let Some(origin_row) = options.origin_row {
300 let mut renderer = IncrementalRenderer::new(options.width, options.height);
301 renderer.set_origin(origin_row, options.origin_col);
302 renderer.set_color_mode(options.color_mode);
303 renderer.set_preserve_terminal_background(options.preserve_terminal_background);
304
305 if let Some(previous_source) = previous_source.as_deref() {
306 let _ =
307 renderer.highlight_to_patch(&mut highlighter, previous_source, grammar, &theme)?;
308 }
309
310 renderer.highlight_to_patch(&mut highlighter, &source, grammar, &theme)?
311 } else {
312 let source_is_multiline = source.contains(&b'\n');
313 let previous_is_multiline = previous_source
314 .as_ref()
315 .is_some_and(|snapshot| snapshot.contains(&b'\n'));
316
317 if source_is_multiline || previous_is_multiline {
318 let rendered = highlight_to_ansi_with_highlighter_and_mode_and_background(
319 &mut highlighter,
320 &source,
321 grammar,
322 &theme,
323 options.color_mode,
324 options.preserve_terminal_background,
325 )?;
326 build_full_rerender_patch(rendered, previous_source.as_deref())
327 } else {
328 let mut renderer = StreamLineRenderer::new();
329 renderer.set_color_mode(options.color_mode);
330 renderer.set_preserve_terminal_background(options.preserve_terminal_background);
331
332 if let Some(previous_source) = previous_source.as_deref() {
333 let _ = renderer
334 .highlight_line_to_patch(&mut highlighter, previous_source, grammar, &theme)
335 .map_err(streamline_mode_error)?;
336 }
337
338 renderer
339 .highlight_line_to_patch(&mut highlighter, &source, grammar, &theme)
340 .map_err(streamline_mode_error)?
341 }
342 };
343
344 print!("{patch}");
345 io::stdout().flush()?;
346
347 Ok(())
348}Sourcepub fn resize(&mut self, width: usize, height: usize)
pub fn resize(&mut self, width: usize, height: usize)
Resizes the viewport and clips cached state to the new bounds.
Sourcepub fn clear_state(&mut self)
pub fn clear_state(&mut self)
Clears all cached frame state for this renderer.
Sourcepub fn set_origin(&mut self, row: usize, col: usize)
pub fn set_origin(&mut self, row: usize, col: usize)
Sets the terminal origin used for generated CUP cursor positions.
The origin is 1-based terminal coordinates (row, col) in display cells.
Values lower than 1 are clamped to 1.
Examples found in repository?
276fn main() -> Result<(), Box<dyn Error>> {
277 let args: Vec<String> = env::args().collect();
278 let options = match parse_args(&args) {
279 Ok(options) => options,
280 Err(err) => {
281 eprintln!("invalid arguments: {err}");
282 eprintln!();
283 print_usage();
284 return Ok(());
285 }
286 };
287
288 let grammar =
289 parse_grammar(&options.grammar_name).map_err(|msg| format!("invalid grammar: {msg}"))?;
290 let source = fs::read(&options.source_path)?;
291 let previous_source = if let Some(previous_source_path) = &options.previous_source_path {
292 Some(fs::read(previous_source_path)?)
293 } else {
294 None
295 };
296 let theme = load_theme(&options.theme_name)?;
297 let mut highlighter = SpanHighlighter::new()?;
298
299 let patch = if let Some(origin_row) = options.origin_row {
300 let mut renderer = IncrementalRenderer::new(options.width, options.height);
301 renderer.set_origin(origin_row, options.origin_col);
302 renderer.set_color_mode(options.color_mode);
303 renderer.set_preserve_terminal_background(options.preserve_terminal_background);
304
305 if let Some(previous_source) = previous_source.as_deref() {
306 let _ =
307 renderer.highlight_to_patch(&mut highlighter, previous_source, grammar, &theme)?;
308 }
309
310 renderer.highlight_to_patch(&mut highlighter, &source, grammar, &theme)?
311 } else {
312 let source_is_multiline = source.contains(&b'\n');
313 let previous_is_multiline = previous_source
314 .as_ref()
315 .is_some_and(|snapshot| snapshot.contains(&b'\n'));
316
317 if source_is_multiline || previous_is_multiline {
318 let rendered = highlight_to_ansi_with_highlighter_and_mode_and_background(
319 &mut highlighter,
320 &source,
321 grammar,
322 &theme,
323 options.color_mode,
324 options.preserve_terminal_background,
325 )?;
326 build_full_rerender_patch(rendered, previous_source.as_deref())
327 } else {
328 let mut renderer = StreamLineRenderer::new();
329 renderer.set_color_mode(options.color_mode);
330 renderer.set_preserve_terminal_background(options.preserve_terminal_background);
331
332 if let Some(previous_source) = previous_source.as_deref() {
333 let _ = renderer
334 .highlight_line_to_patch(&mut highlighter, previous_source, grammar, &theme)
335 .map_err(streamline_mode_error)?;
336 }
337
338 renderer
339 .highlight_line_to_patch(&mut highlighter, &source, grammar, &theme)
340 .map_err(streamline_mode_error)?
341 }
342 };
343
344 print!("{patch}");
345 io::stdout().flush()?;
346
347 Ok(())
348}Sourcepub fn set_color_mode(&mut self, color_mode: ColorMode)
pub fn set_color_mode(&mut self, color_mode: ColorMode)
Sets the ANSI color mode used by this renderer.
Examples found in repository?
276fn main() -> Result<(), Box<dyn Error>> {
277 let args: Vec<String> = env::args().collect();
278 let options = match parse_args(&args) {
279 Ok(options) => options,
280 Err(err) => {
281 eprintln!("invalid arguments: {err}");
282 eprintln!();
283 print_usage();
284 return Ok(());
285 }
286 };
287
288 let grammar =
289 parse_grammar(&options.grammar_name).map_err(|msg| format!("invalid grammar: {msg}"))?;
290 let source = fs::read(&options.source_path)?;
291 let previous_source = if let Some(previous_source_path) = &options.previous_source_path {
292 Some(fs::read(previous_source_path)?)
293 } else {
294 None
295 };
296 let theme = load_theme(&options.theme_name)?;
297 let mut highlighter = SpanHighlighter::new()?;
298
299 let patch = if let Some(origin_row) = options.origin_row {
300 let mut renderer = IncrementalRenderer::new(options.width, options.height);
301 renderer.set_origin(origin_row, options.origin_col);
302 renderer.set_color_mode(options.color_mode);
303 renderer.set_preserve_terminal_background(options.preserve_terminal_background);
304
305 if let Some(previous_source) = previous_source.as_deref() {
306 let _ =
307 renderer.highlight_to_patch(&mut highlighter, previous_source, grammar, &theme)?;
308 }
309
310 renderer.highlight_to_patch(&mut highlighter, &source, grammar, &theme)?
311 } else {
312 let source_is_multiline = source.contains(&b'\n');
313 let previous_is_multiline = previous_source
314 .as_ref()
315 .is_some_and(|snapshot| snapshot.contains(&b'\n'));
316
317 if source_is_multiline || previous_is_multiline {
318 let rendered = highlight_to_ansi_with_highlighter_and_mode_and_background(
319 &mut highlighter,
320 &source,
321 grammar,
322 &theme,
323 options.color_mode,
324 options.preserve_terminal_background,
325 )?;
326 build_full_rerender_patch(rendered, previous_source.as_deref())
327 } else {
328 let mut renderer = StreamLineRenderer::new();
329 renderer.set_color_mode(options.color_mode);
330 renderer.set_preserve_terminal_background(options.preserve_terminal_background);
331
332 if let Some(previous_source) = previous_source.as_deref() {
333 let _ = renderer
334 .highlight_line_to_patch(&mut highlighter, previous_source, grammar, &theme)
335 .map_err(streamline_mode_error)?;
336 }
337
338 renderer
339 .highlight_line_to_patch(&mut highlighter, &source, grammar, &theme)
340 .map_err(streamline_mode_error)?
341 }
342 };
343
344 print!("{patch}");
345 io::stdout().flush()?;
346
347 Ok(())
348}Sourcepub fn color_mode(&self) -> ColorMode
pub fn color_mode(&self) -> ColorMode
Returns the current ANSI color mode.
Sourcepub fn set_preserve_terminal_background(
&mut self,
preserve_terminal_background: bool,
)
pub fn set_preserve_terminal_background( &mut self, preserve_terminal_background: bool, )
Controls whether ANSI rendering preserves the terminal’s existing background.
When set to true (default), background colors from the theme are ignored.
When set to false, background colors from resolved theme styles are emitted.
Examples found in repository?
276fn main() -> Result<(), Box<dyn Error>> {
277 let args: Vec<String> = env::args().collect();
278 let options = match parse_args(&args) {
279 Ok(options) => options,
280 Err(err) => {
281 eprintln!("invalid arguments: {err}");
282 eprintln!();
283 print_usage();
284 return Ok(());
285 }
286 };
287
288 let grammar =
289 parse_grammar(&options.grammar_name).map_err(|msg| format!("invalid grammar: {msg}"))?;
290 let source = fs::read(&options.source_path)?;
291 let previous_source = if let Some(previous_source_path) = &options.previous_source_path {
292 Some(fs::read(previous_source_path)?)
293 } else {
294 None
295 };
296 let theme = load_theme(&options.theme_name)?;
297 let mut highlighter = SpanHighlighter::new()?;
298
299 let patch = if let Some(origin_row) = options.origin_row {
300 let mut renderer = IncrementalRenderer::new(options.width, options.height);
301 renderer.set_origin(origin_row, options.origin_col);
302 renderer.set_color_mode(options.color_mode);
303 renderer.set_preserve_terminal_background(options.preserve_terminal_background);
304
305 if let Some(previous_source) = previous_source.as_deref() {
306 let _ =
307 renderer.highlight_to_patch(&mut highlighter, previous_source, grammar, &theme)?;
308 }
309
310 renderer.highlight_to_patch(&mut highlighter, &source, grammar, &theme)?
311 } else {
312 let source_is_multiline = source.contains(&b'\n');
313 let previous_is_multiline = previous_source
314 .as_ref()
315 .is_some_and(|snapshot| snapshot.contains(&b'\n'));
316
317 if source_is_multiline || previous_is_multiline {
318 let rendered = highlight_to_ansi_with_highlighter_and_mode_and_background(
319 &mut highlighter,
320 &source,
321 grammar,
322 &theme,
323 options.color_mode,
324 options.preserve_terminal_background,
325 )?;
326 build_full_rerender_patch(rendered, previous_source.as_deref())
327 } else {
328 let mut renderer = StreamLineRenderer::new();
329 renderer.set_color_mode(options.color_mode);
330 renderer.set_preserve_terminal_background(options.preserve_terminal_background);
331
332 if let Some(previous_source) = previous_source.as_deref() {
333 let _ = renderer
334 .highlight_line_to_patch(&mut highlighter, previous_source, grammar, &theme)
335 .map_err(streamline_mode_error)?;
336 }
337
338 renderer
339 .highlight_line_to_patch(&mut highlighter, &source, grammar, &theme)
340 .map_err(streamline_mode_error)?
341 }
342 };
343
344 print!("{patch}");
345 io::stdout().flush()?;
346
347 Ok(())
348}Sourcepub fn preserve_terminal_background(&self) -> bool
pub fn preserve_terminal_background(&self) -> bool
Returns whether terminal background passthrough is enabled.
Sourcepub fn render_patch(
&mut self,
source: &[u8],
spans: &[StyledSpan],
) -> Result<String, RenderError>
pub fn render_patch( &mut self, source: &[u8], spans: &[StyledSpan], ) -> Result<String, RenderError>
Renders only the VT patch from the cached frame to source.
The method validates input spans, projects them to styled terminal cells, diffs against previous state, and returns only changed cursor/style output.
§Errors
Returns an error when spans are out of bounds, unsorted, or overlapping.
Sourcepub fn highlight_to_patch(
&mut self,
highlighter: &mut SpanHighlighter,
source: &[u8],
flavor: Grammar,
theme: &Theme,
) -> Result<String, RenderError>
pub fn highlight_to_patch( &mut self, highlighter: &mut SpanHighlighter, source: &[u8], flavor: Grammar, theme: &Theme, ) -> Result<String, RenderError>
Runs highlight + theme resolution + incremental diff in one call.
§Errors
Returns an error if highlighting fails or spans fail validation.
Examples found in repository?
276fn main() -> Result<(), Box<dyn Error>> {
277 let args: Vec<String> = env::args().collect();
278 let options = match parse_args(&args) {
279 Ok(options) => options,
280 Err(err) => {
281 eprintln!("invalid arguments: {err}");
282 eprintln!();
283 print_usage();
284 return Ok(());
285 }
286 };
287
288 let grammar =
289 parse_grammar(&options.grammar_name).map_err(|msg| format!("invalid grammar: {msg}"))?;
290 let source = fs::read(&options.source_path)?;
291 let previous_source = if let Some(previous_source_path) = &options.previous_source_path {
292 Some(fs::read(previous_source_path)?)
293 } else {
294 None
295 };
296 let theme = load_theme(&options.theme_name)?;
297 let mut highlighter = SpanHighlighter::new()?;
298
299 let patch = if let Some(origin_row) = options.origin_row {
300 let mut renderer = IncrementalRenderer::new(options.width, options.height);
301 renderer.set_origin(origin_row, options.origin_col);
302 renderer.set_color_mode(options.color_mode);
303 renderer.set_preserve_terminal_background(options.preserve_terminal_background);
304
305 if let Some(previous_source) = previous_source.as_deref() {
306 let _ =
307 renderer.highlight_to_patch(&mut highlighter, previous_source, grammar, &theme)?;
308 }
309
310 renderer.highlight_to_patch(&mut highlighter, &source, grammar, &theme)?
311 } else {
312 let source_is_multiline = source.contains(&b'\n');
313 let previous_is_multiline = previous_source
314 .as_ref()
315 .is_some_and(|snapshot| snapshot.contains(&b'\n'));
316
317 if source_is_multiline || previous_is_multiline {
318 let rendered = highlight_to_ansi_with_highlighter_and_mode_and_background(
319 &mut highlighter,
320 &source,
321 grammar,
322 &theme,
323 options.color_mode,
324 options.preserve_terminal_background,
325 )?;
326 build_full_rerender_patch(rendered, previous_source.as_deref())
327 } else {
328 let mut renderer = StreamLineRenderer::new();
329 renderer.set_color_mode(options.color_mode);
330 renderer.set_preserve_terminal_background(options.preserve_terminal_background);
331
332 if let Some(previous_source) = previous_source.as_deref() {
333 let _ = renderer
334 .highlight_line_to_patch(&mut highlighter, previous_source, grammar, &theme)
335 .map_err(streamline_mode_error)?;
336 }
337
338 renderer
339 .highlight_line_to_patch(&mut highlighter, &source, grammar, &theme)
340 .map_err(streamline_mode_error)?
341 }
342 };
343
344 print!("{patch}");
345 io::stdout().flush()?;
346
347 Ok(())
348}Trait Implementations§
Source§impl Clone for IncrementalRenderer
impl Clone for IncrementalRenderer
Source§fn clone(&self) -> IncrementalRenderer
fn clone(&self) -> IncrementalRenderer
1.0.0 · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read more