#unicode #text-processing


A simple, low-level, syntax highlighting library with unicode support

12 releases (6 stable)

1.2.0 May 22, 2022
1.1.0 May 22, 2022
1.0.3 Jul 6, 2021
1.0.0 Jan 7, 2021
0.1.0 Jan 4, 2021

#160 in Text processing

42 downloads per month
Used in code_snippet_generator

MIT license

720 lines


Syntax highlighting for Rust applications

I originally wrote this for my text editor, Ox. It needed a fast, robust and reliable syntax highlighter that was configurable and was able to easily plug-in to a front end.


No pre-built language rules so everything is entirely up to you. Outputs a simple stream of tokens.


Takes advantage of Rust's speed. Benches say that it can highlight 18470 lines of Rust code in around 60 milliseconds


You can highlight code for most languages in just a few steps:

  • Construct a Highlighter instance
  • Add regular expressions and keywords to the highlighter and assign each a name
  • Use the run method to recieve a stream of start, end and text tokens to use in your program.

You can also very quickly add, remove and modify build syntax highlighting rules to adjust to your liking.


Here's an example of a Rust syntax highlighter, using the termion crate.

use synoptic::{Token, Highlighter};
use termion::color;

const DEMO: &str = r#"/*
Multiline comments
Work great

pub fn main() -> bool {
	// Demonstrate syntax highlighting in Rust!
	println!("Full Unicode Support: 你好!Pretty cool");
	return true;

fn main() {
	// Build the rust syntax highlighter
    let mut rust = Highlighter::new();
    // Add keywords
    rust.join(&["fn", "return", "pub"], "keyword").unwrap();
    rust.join(&["bool"], "type").unwrap();
    rust.join(&["true", "false"], "boolean").unwrap();
	// Add comment definitions
    rust.add(r"(?m)(//.*)$", "comment").unwrap();
    rust.add(r"(?ms)/\*.*?\*/", "comment").unwrap();
    // Add string definition
    rust.add("\".*?\"", "string").unwrap();
    // Add identifier definition
    rust.add(r"([a-z_][A-Za-z0-9_]*)\s*\(", "identifier").unwrap();
    // Add macro definition
    rust.add(r"([a-z_][A-Za-z0-9_]*!)\s*", "macro").unwrap();

    // Run highlighter
    let highlighting = rust.run(DEMO);
    // For each row
    for (c, row) in highlighting.iter().enumerate() {
    	// Print line number (with padding)
        print!("{: >3} |", c);
        // For each token within each row
        for tok in row {
        	// Handle the tokens
            match tok {
            	// Handle the start token (start foreground colour)
                Token::Start(kind) => match *kind {
                    "comment" => print!("{}", color::Fg(color::Black)),
                    "string" => print!("{}", color::Fg(color::Green)),
                    "keyword" => print!("{}", color::Fg(color::Blue)),
                    "type" => print!("{}", color::Fg(color::LightMagenta)),
                    "boolean" => print!("{}", color::Fg(color::LightGreen)),
                    "identifier" => print!("{}", color::Fg(color::Yellow)),
                    "macro" => print!("{}", color::Fg(color::Magenta)),
                    _ => (),
                // Handle a text token (print out the contents)
                Token::Text(txt) => print!("{}", txt),
                // Handle an end token (reset foreground colour)
                Token::End(_) => print!("{}", color::Fg(color::Reset)),
        // Prevent text being cut off without a newline

That will render this result:


Just add it to your Cargo.toml:

synoptic = "1"


MIT license to ensure that you can use it in your project

you can check the LICENSE file for more info


~38K SLoC