inkjet 0.5.2

A batteries-included syntax highlighting library for Rust, based on tree-sitter.
Documentation
<h1 align="center">Inkjet</h1>
<h3 align="center">A batteries-included syntax highlighting library for Rust, based on <code>tree-sitter</code>.</h3>
<p align="center">
<img src=".github/logo.png" width="256">
</p>

<p align="center">
<img src="https://img.shields.io/crates/v/inkjet">
<img src="https://img.shields.io/github/actions/workflow/status/SomewhereOutInSpace/inkjet/rust.yml">
<img src="https://img.shields.io/crates/l/inkjet">
</p>

## Features

- Language grammars are linked into the executable as C functions - no need to load anything at runtime!
- Pluggable formatters. Inkjet includes a formatter for HTML, and you can write your own if needed.
- Highlight into a new `String` or a `std::io::Writer`, depending on your use case.
- Specify languages explicitly (from an `enum`) or look them up using a token like `"rs"` or `"rust"`.
- ~~Extremely cursed `build.rs`~~

## Included Languages

Inkjet comes bundled with support for around sixty languages, and it's easy to add more - see the FAQ section.

- Ada
- Assembly (generic)
- Bash
- BibTeX
- Blueprint
- C
- Cap'n Proto
- Clojure
- C#
- Common Lisp
- C++
- CSS
- Cue
- D
- Dart
- `diff` output
- Dockerfile
- Emacs Lisp
- Elixir
- Elm
- Erlang
- Fortran
- Go
- GLSL
- Haskell
- HCL/Terraform
- HTML
- Java
- JavaScript
- JSON
- Kotlin
- LLVM
- Lua
- GNU Make
- MatLab
- Meson
- Nim
- Nix
- OCaml
- OpenSCAD
- Pascal
- PHP
- Protobuf
- Python
- R
- Racket
- Regex
- Ruby
- Rust
- Scala
- Scheme
- SCSS
- SQL (generic)
- Swift
- TOML
- TypeScript
- x86 Assembly
- WGSL
- Zig

## FAQ

### *"Why is Inkjet so large?"*

Parser sources generated by `tree-sitter` can grow quite big, with some being dozens of megabytes in size. Inkjet has to bundle these sources for all the languages it supports, so it adds up. (According to `loc`, there are over 16 *million* lines of C code!)

### *"Why is Inkjet taking so long to build?"*

Because it has to compile and link in dozens of C/C++ programs (the parsers and scanners for every language Inkjet bundles.)

However, after the first build, these artifacts will be cached and subsequent builds should be much faster.

### *"Why does highlighting require a mutable reference to the highlighter?*

Under the hood, Inkjet creates a `tree-sitter` highlighter/parser object, which in turn dynamically allocates a chunk of working memory. Using the same highlighter for multiple simultaneous jobs would therefore cause all sorts of nasty UB.

If you want to highlight in parallel, you'll have to create a clone of the highlighter for each thread.

### *"A language I want to highlight isn't bundled with Inkjet!"*

Assuming that you or someone else has implemented a highlighting-ready `tree-sitter` grammar for the language you want, adding it to Inkjet is easy! Just open an issue asking for it to be added, linking to the grammar repository for the language.

However, please note that: 
- Inkjet currently only supports grammar repositories that check in the parser generated by `tree-sitter` (in order to avoid a build-time dependency on `node`/`npm`.)
- Inkjet requires that the grammar include (at minimum) a `highlights.scm` query targeted at the base `tree-sitter` library. Extended queries (such as those from `nvim-treesitter`) will not work.

## Building
For normal use, Inkjet will compile automatically just like any other crate.

However, if you have forked the repository and want to update the bundled languages, you'll need to set some environment variables:
- `INKJET_REDOWNLOAD_LANGS` will wipe the `languages/` directory and redownload everything from scratch.
- `INKJET_REBUILD_LANGS_MODULE` will wipe `src/languages.rs` and regenerate it from scratch.

The value of these variables doesn't matter - they just have to be set.

## Acknowledgements
- Inkjet would not be possible without `tree-sitter` and the ecosystem of grammars surrounding it.