pub trait CodeHighlighter: Send + Sync {
// Required methods
fn highlight(
&self,
code: &str,
language: Option<&str>,
theme: &str,
) -> Result<HighlightedCode, HighlightError>;
fn default_theme(&self) -> &str;
fn themes(&self) -> Vec<String>;
fn languages(&self) -> Vec<String>;
// Provided methods
fn language_for_path(&self, _path: &Path) -> Option<String> { ... }
fn token_style(&self, _theme: &str, _token: &str) -> Option<Style> { ... }
}Expand description
A syntax-highlighting engine behind Syntax and
Markdown code blocks.
Upstream highlights with Pygments; the port’s default is
SyntectHighlighter, and anything that
implements this trait can replace it (see Syntax::highlighter).
§Contract
lineshas one entry per element ofcode.split('\n').- Spans are sorted, do not overlap, stay inside their line and start and end on UTF-8 character boundaries.
- An unknown language highlights as plain text rather than failing.
Core validates what an implementation returns: out-of-range, overlapping or misaligned spans are dropped, missing lines render unstyled, and span styles lose any hyperlink. The rendered characters always come from the source, so a highlighter cannot add text or terminal control sequences.
use rich::protocol::{CodeHighlighter, HighlightError, HighlightSpan, HighlightedCode, HighlightedLine};
use rich::Style;
/// Makes every line bold.
struct Bold;
impl CodeHighlighter for Bold {
fn highlight(&self, code: &str, _language: Option<&str>, _theme: &str)
-> Result<HighlightedCode, HighlightError>
{
let bold = Style::parse("bold").unwrap();
let lines = code
.split('\n')
.map(|line| HighlightedLine {
spans: vec![HighlightSpan { range: 0..line.len(), style: bold.clone() }]
.into_iter()
.filter(|span| !span.range.is_empty())
.collect(),
newline_style: None,
})
.collect();
Ok(HighlightedCode { lines, ..Default::default() })
}
fn default_theme(&self) -> &str { "bold" }
fn themes(&self) -> Vec<String> { vec!["bold".into()] }
fn languages(&self) -> Vec<String> { Vec::new() }
}
use rich::{Console, Syntax};
use std::sync::Arc;
let console = Console::builder().width(20).force_terminal(true).build();
let out = console.render_to_string(&Syntax::new("x = 1", "python").highlighter(Arc::new(Bold)));
assert!(out.contains("\x1b[1mx = 1"));Required Methods§
Sourcefn highlight(
&self,
code: &str,
language: Option<&str>,
theme: &str,
) -> Result<HighlightedCode, HighlightError>
fn highlight( &self, code: &str, language: Option<&str>, theme: &str, ) -> Result<HighlightedCode, HighlightError>
Highlight code. language is a name or file extension ("rust",
"rs"); None means plain text. theme is one of themes.
Sourcefn default_theme(&self) -> &str
fn default_theme(&self) -> &str
The theme used when none is chosen.
Provided Methods§
Sourcefn language_for_path(&self, _path: &Path) -> Option<String>
fn language_for_path(&self, _path: &Path) -> Option<String>
The language for a file path, if the highlighter recognises it.
Sourcefn token_style(&self, _theme: &str, _token: &str) -> Option<Style>
fn token_style(&self, _theme: &str, _token: &str) -> Option<Style>
theme’s style for a Pygments token type — "Text" or "Comment" —
as upstream’s SyntaxTheme.get_style_for_token. Syntax colours its
line numbers and indent guides with it; None (the default) means the
theme sets nothing for the token.
Dyn Compatibility§
This trait is dyn compatible.
In older versions of Rust, dyn compatibility was called "object safety".