Skip to main content

CodeHighlighter

Trait CodeHighlighter 

Source
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

  • lines has one entry per element of code.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§

Source

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.

Source

fn default_theme(&self) -> &str

The theme used when none is chosen.

Source

fn themes(&self) -> Vec<String>

Every theme name highlight accepts.

Source

fn languages(&self) -> Vec<String>

Language names this highlighter knows, for help text and completion.

Provided Methods§

Source

fn language_for_path(&self, _path: &Path) -> Option<String>

The language for a file path, if the highlighter recognises it.

Source

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".

Implementors§