Library / SDK
trishume/syntect avatar
trishume/syntect

syntect: Sublime Text grammars for Rust syntax highlighting

Rust library for syntax highlighting using Sublime Text syntax definitions.

2,436 stars180 forksRustMIT

At a glance

What is it?
syntect is a Rust library that highlights code using Sublime Text syntax definitions, with a compressed dump of default grammars baked into the binary. It suits editors and terminal tools that need Sublime-compatible parsing, and it is a poor fit if you want a pure-Rust regex engine today.
Who is it for?
Adopt syntect if you are writing a Rust editor, pager, or terminal tool that needs Sublime-compatible highlighting and you accept the onig dependency. Do not adopt it if you need pure-Rust regex today, a stable serialized parse state across versions, or a project under heavy development; the README says it is mostly complete and maintained rather than heavily developed.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 156 days ago.
What is it written in?
Mainly Rust, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 1, 2026, and from our analysis. They are not legal advice.

Editorial analysis

What syntect solves, and who it is written for

Writing a syntax highlighter from scratch means writing a grammar for every language you want to support. syntect takes the other route: it consumes Sublime Text syntax definitions, the .sublime-syntax files that Sublime itself uses, so a Rust program inherits an existing grammar ecosystem instead of inventing one. The README states the goal plainly, that it aims to be a good solution for any Rust project that needs syntax highlighting, including deep integration with text editors written in Rust.

The intended audience is narrow and technical. The author writes that if you are writing a text editor in Rust and the library does not fit your needs, he considers that a bug and you should file an issue or email him. That is an unusually direct invitation, and it tells you the design is shaped around editor workloads: piece tables, incremental re-highlighting, cached parse states, and semantic information for code intelligence. If you only need to colorize a log line or a short snippet, the library is heavier than the job requires.

How the parsing pipeline and the embedded packs work

The mechanism has three layers. A SyntaxSet holds the parsed grammars, a ThemeSet holds color schemes, and a HighlightLines object walks your text line by line, producing a vector of (Style, &str) pairs. The grammar engine is the part that does real work: syntect pre-links references between languages, so embedded languages such as script tags do not require tree traversal string lookups on the hot path, and it caches regex matches so the regex engine is not asked to search the same line repeatedly.

The regex backend is a deliberate trade-off. The default feature set uses onig, a binding to the Oniguruma engine, which is a C dependency. A regex-fancy feature exists to use the pure-Rust fancy-regex crate instead, but the README is candid that this is not yet faster than oniguruma on the project's benchmarks and might be in the future. In other words, the pure-Rust path exists, but choosing it today costs performance.

Startup cost is addressed by shipping data inside the binary. The README lists a compressed dump of all the default syntax definitions so users do not have to manage a folder of syntaxes, and claims load time in around 23ms. The Cargo.toml shows the pieces: dump-load and dump-create pull in flate2 and bincode, while parsing pulls in regex-syntax. A Makefile target regenerates the packs from the testdata submodule, so the shipped data is reproducible rather than hand-assembled.

Installing syntect and highlighting your first string

The README gives the install step as a single Cargo command. It adds the crate to your Cargo.toml, and the default features are what most users want.

bash
cargo add syntect

If you have cloned the repository rather than depending on the published crate, the README says to run a submodule update first, because the tests need the grammar packages.

bash
git submodule update --init

The README's example prints highlighted lines of a string to the terminal. It loads the default syntax and theme sets once at program start, looks up the Rust grammar by extension, and then walks the input with LinesWithEndings so each line keeps its newline. The ranges returned per line are converted to 24-bit ANSI escapes.

rust
use syntect::easy::HighlightLines;
use syntect::parsing::SyntaxSet;
use syntect::highlighting::{ThemeSet, Style};
use syntect::util::{as_24_bit_terminal_escaped, LinesWithEndings};

let ps = SyntaxSet::load_defaults_newlines();
let ts = ThemeSet::load_defaults();

let syntax = ps.find_syntax_by_extension("rs").unwrap();
let mut h = HighlightLines::new(syntax, &ts.themes["base16-ocean.dark"]);
let s = "pub struct Wow { hi: u64 }\nfn blah() -> u64 {}";
for line in LinesWithEndings::from(s) {
    let ranges: Vec<(Style, &str)> = h.highlight_line(line, &ps).unwrap();
    let escaped = as_24_bit_terminal_escaped(&ranges[..], true);
    print!("{}", escaped);
}

What you should see is colored output in a terminal that supports 24-bit color. Two details matter here. The theme is looked up by the key base16-ocean.dark, so if you swap themes you must use a key that exists in the default theme set. And find_syntax_by_extension returns an Option, so an unknown extension means you handle None rather than getting a default grammar. The repository also ships examples such as syncat and synhtml, which the README points to for more complete use cases.

Where syntect is the wrong tool

The clearest limitation is stated by the author himself: the project is mostly complete, still maintained with PRs reviewed, but not under heavy development. If you need a library with an active roadmap and frequent breaking releases, this is not it. The last push to the repository was on 2026-04-28, and the most recent release listed is v5.3.0 from 2025-09-27, so the cadence is measured rather than fast.

The regex backend is the second constraint. Oniguruma is a C library, which complicates cross-compilation and static builds, and the pure-Rust alternative is documented as slower in the project's own benchmarks. If your build target makes C dependencies painful, you are choosing between a harder build and a slower highlighter.

Third, the performance claims in the README come with their own caveats, and you should read them that way. The numbers were taken on a mid 2012 15-inch retina MacBook Pro, the editor comparisons were measured by hand with a stopwatch and are described as approximate, and the author notes the comparisons are not totally fair except the one against Sublime Text, since only that one uses the same theme and the same complex ES6 definition. Vim is called instantaneous but explicitly excluded as an unfair comparison because its highlighting is far more basic. None of this is hidden, but it does mean the headline numbers are not a controlled benchmark you can transfer to your own workload.

Finally, this is a library, not a program. There is no configuration file, no daemon, and no CLI beyond the examples in the repository. If what you actually want is a highlighting tool to run, syntect is a component you would have to wrap.

syntect compared with tree-sitter based highlighting

The relevant alternative in the Rust ecosystem is tree-sitter, which takes a different approach to the same problem. tree-sitter grammars are generated parsers written for tree-sitter itself, producing a concrete syntax tree that supports incremental reparsing and queries for captures. syntect instead interprets Sublime Text syntax definitions, which are declarative regex-driven rules, and its compatibility target is Sublime Text 3 rather than a parser generator format.

The practical difference is where the grammar ecosystem comes from and what the output is. With tree-sitter you get a real parse tree and can build code intelligence on top of it; the trade-off is that each language needs a tree-sitter grammar, and those grammars are separate projects. With syntect you get Sublime's grammar corpus plus its theme format, and the README claims nearly complete compatibility with Sublime Text 3 including many edge cases. If your users already have Sublime themes they expect to work, that compatibility is the reason to pick syntect. If you need structural queries over the parse tree, syntect's scope-based output is the wrong shape.

Maintenance cost, licence, and upgrade surface

The licence is MIT, declared in both the Cargo.toml and the repository, which is permissive and places few obligations on downstream users. This is not legal advice, and if you redistribute the crate you should read LICENSE.txt yourself.

The upgrade surface is larger than the version number suggests, because the crate ships serialized data. The Cargo.toml exposes dump-load and dump-create features built on flate2 and bincode, and the Makefile regenerates assets/default_newlines.packdump, assets/default_nonewlines.packdump, assets/default_metadata.packdump and assets/default.themedump from the testdata submodule. If you generate your own packdumps with the gendata example, a change in the dump format between versions is something you would have to regenerate, and the README points to the changelogs and upgrade notes on the releases page for past releases. Budget for that if you are not using the built-in defaults.

The feature flags are the other thing to pin down. regex-onig and regex-fancy are alternatives, parsing and metadata pull in different optional dependencies, and docs.rs is configured to build with the metadata feature enabled, so the API surface shown on docs.rs is slightly wider than a default build. Upgrading without checking which features you enable can change both your dependency tree and your compile times.

Editorial conclusion

Adopt syntect if you are writing a Rust editor, pager, or terminal tool that needs Sublime-compatible highlighting and you accept the onig dependency. Do not adopt it if you need pure-Rust regex today, a stable serialized parse state across versions, or a project under heavy development; the README says it is mostly complete and maintained rather than heavily developed. Verify first that your target languages are covered by the default packs, and check the feature flags you enable against the Cargo.toml.

Frequently asked questions

How do I install syntect in a Rust project?

The README gives the command cargo add syntect, which adds the crate to your Cargo.toml. If you cloned the repository instead, run git submodule update --init first so the tests have the grammar packages they need.

Which languages does syntect support?

syntect works with Sublime Text syntax definitions, and the README states a compressed dump of all the default syntax definitions is included in the library binary. That means coverage follows the default packages shipped with the crate rather than a list maintained separately; the README does not enumerate the languages.

Does syntect need a C compiler because of Oniguruma?

The default regex backend is onig, a binding to the Oniguruma engine, which is a C dependency. A regex-fancy feature exists to use the pure-Rust fancy-regex crate instead, but the README says that path is not yet faster than oniguruma on the project's benchmarks.

Can syntect output HTML instead of terminal colors?

Yes. The README lists built-in output to coloured HTML pre tags or 24-bit colour ANSI terminal escape sequences, and the repository includes examples named synhtml and synhtml-css-classes. The example in the README itself uses as_24_bit_terminal_escaped for terminal output.

Official sources

  1. License: MIT
  2. Project website
  3. README
  4. Releases
  5. trishume/syntect on GitHub
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/trishume-syntect.svg)](https://hysenlabs.com/projects/trishume-syntect)