synoptic 1.2.0

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

Synoptic

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.

Low-level

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

Fast

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

Simple

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.

Example

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
        println!("");
    }
}

That will render this result:

Installation

Just add it to your Cargo.toml:

[dependencies]
synoptic = "1"

License

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

you can check the LICENSE file for more info