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
41KB
720 lines
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
Dependencies
~1–1.3MB
~38K SLoC