pub struct StreamLineRenderer { /* private fields */ }Expand description
Incremental renderer for a single mutable line without terminal width assumptions.
This renderer avoids absolute cursor positioning. It assumes each emitted patch is written to the same terminal line and the cursor remains at the end of the previously rendered line.
Implementations§
Source§impl StreamLineRenderer
impl StreamLineRenderer
Sourcepub fn new() -> Self
pub fn new() -> Self
Creates a line renderer with truecolor output.
Examples found in repository?
132fn main() -> Result<(), Box<dyn Error>> {
133 let args: Vec<String> = env::args().collect();
134 let options = match parse_args(&args) {
135 Ok(options) => options,
136 Err(err) => {
137 eprintln!("invalid arguments: {err}");
138 eprintln!();
139 print_usage();
140 return Ok(());
141 }
142 };
143
144 let grammar =
145 parse_grammar(&options.grammar_name).map_err(|msg| format!("invalid grammar: {msg}"))?;
146 let source = fs::read(&options.source_path)?;
147 let theme = load_theme(&options.theme_name)?;
148 let mut highlighter = SpanHighlighter::new()?;
149 let mut renderer = StreamLineRenderer::new();
150 renderer.set_color_mode(options.color_mode);
151 renderer.set_preserve_terminal_background(options.preserve_terminal_background);
152
153 if let Some(previous_source_path) = &options.previous_source_path {
154 let previous_source = fs::read(previous_source_path)?;
155 let _ = renderer.highlight_line_to_patch(
156 &mut highlighter,
157 &previous_source,
158 grammar,
159 &theme,
160 )?;
161 }
162
163 let patch = renderer.highlight_line_to_patch(&mut highlighter, &source, grammar, &theme)?;
164 print!("{patch}");
165 io::stdout().flush()?;
166
167 Ok(())
168}More examples
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 clear_state(&mut self)
pub fn clear_state(&mut self)
Clears prior line state.
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?
132fn main() -> Result<(), Box<dyn Error>> {
133 let args: Vec<String> = env::args().collect();
134 let options = match parse_args(&args) {
135 Ok(options) => options,
136 Err(err) => {
137 eprintln!("invalid arguments: {err}");
138 eprintln!();
139 print_usage();
140 return Ok(());
141 }
142 };
143
144 let grammar =
145 parse_grammar(&options.grammar_name).map_err(|msg| format!("invalid grammar: {msg}"))?;
146 let source = fs::read(&options.source_path)?;
147 let theme = load_theme(&options.theme_name)?;
148 let mut highlighter = SpanHighlighter::new()?;
149 let mut renderer = StreamLineRenderer::new();
150 renderer.set_color_mode(options.color_mode);
151 renderer.set_preserve_terminal_background(options.preserve_terminal_background);
152
153 if let Some(previous_source_path) = &options.previous_source_path {
154 let previous_source = fs::read(previous_source_path)?;
155 let _ = renderer.highlight_line_to_patch(
156 &mut highlighter,
157 &previous_source,
158 grammar,
159 &theme,
160 )?;
161 }
162
163 let patch = renderer.highlight_line_to_patch(&mut highlighter, &source, grammar, &theme)?;
164 print!("{patch}");
165 io::stdout().flush()?;
166
167 Ok(())
168}More examples
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?
132fn main() -> Result<(), Box<dyn Error>> {
133 let args: Vec<String> = env::args().collect();
134 let options = match parse_args(&args) {
135 Ok(options) => options,
136 Err(err) => {
137 eprintln!("invalid arguments: {err}");
138 eprintln!();
139 print_usage();
140 return Ok(());
141 }
142 };
143
144 let grammar =
145 parse_grammar(&options.grammar_name).map_err(|msg| format!("invalid grammar: {msg}"))?;
146 let source = fs::read(&options.source_path)?;
147 let theme = load_theme(&options.theme_name)?;
148 let mut highlighter = SpanHighlighter::new()?;
149 let mut renderer = StreamLineRenderer::new();
150 renderer.set_color_mode(options.color_mode);
151 renderer.set_preserve_terminal_background(options.preserve_terminal_background);
152
153 if let Some(previous_source_path) = &options.previous_source_path {
154 let previous_source = fs::read(previous_source_path)?;
155 let _ = renderer.highlight_line_to_patch(
156 &mut highlighter,
157 &previous_source,
158 grammar,
159 &theme,
160 )?;
161 }
162
163 let patch = renderer.highlight_line_to_patch(&mut highlighter, &source, grammar, &theme)?;
164 print!("{patch}");
165 io::stdout().flush()?;
166
167 Ok(())
168}More examples
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_line_patch(
&mut self,
source: &[u8],
spans: &[StyledSpan],
) -> Result<String, RenderError>
pub fn render_line_patch( &mut self, source: &[u8], spans: &[StyledSpan], ) -> Result<String, RenderError>
Renders a width-independent patch for a single line.
§Errors
Returns an error when spans are invalid or input contains a newline.
Sourcepub fn highlight_line_to_patch(
&mut self,
highlighter: &mut SpanHighlighter,
source: &[u8],
flavor: Grammar,
theme: &Theme,
) -> Result<String, RenderError>
pub fn highlight_line_to_patch( &mut self, highlighter: &mut SpanHighlighter, source: &[u8], flavor: Grammar, theme: &Theme, ) -> Result<String, RenderError>
Runs highlight + theme resolution + stream-safe single-line diff.
§Errors
Returns an error if highlighting fails, spans are invalid, or input has newlines.
Examples found in repository?
132fn main() -> Result<(), Box<dyn Error>> {
133 let args: Vec<String> = env::args().collect();
134 let options = match parse_args(&args) {
135 Ok(options) => options,
136 Err(err) => {
137 eprintln!("invalid arguments: {err}");
138 eprintln!();
139 print_usage();
140 return Ok(());
141 }
142 };
143
144 let grammar =
145 parse_grammar(&options.grammar_name).map_err(|msg| format!("invalid grammar: {msg}"))?;
146 let source = fs::read(&options.source_path)?;
147 let theme = load_theme(&options.theme_name)?;
148 let mut highlighter = SpanHighlighter::new()?;
149 let mut renderer = StreamLineRenderer::new();
150 renderer.set_color_mode(options.color_mode);
151 renderer.set_preserve_terminal_background(options.preserve_terminal_background);
152
153 if let Some(previous_source_path) = &options.previous_source_path {
154 let previous_source = fs::read(previous_source_path)?;
155 let _ = renderer.highlight_line_to_patch(
156 &mut highlighter,
157 &previous_source,
158 grammar,
159 &theme,
160 )?;
161 }
162
163 let patch = renderer.highlight_line_to_patch(&mut highlighter, &source, grammar, &theme)?;
164 print!("{patch}");
165 io::stdout().flush()?;
166
167 Ok(())
168}More examples
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 StreamLineRenderer
impl Clone for StreamLineRenderer
Source§fn clone(&self) -> StreamLineRenderer
fn clone(&self) -> StreamLineRenderer
1.0.0 · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read more