1# Chroma — A general purpose syntax highlighter in pure Go [](https://godoc.org/github.com/alecthomas/chroma) [](https://travis-ci.org/alecthomas/chroma) [](https://gitter.im/alecthomas/Lobby)
2
3> **NOTE:** As Chroma has just been released, its API is still in flux. That said, the high-level interface should not change significantly.
4
5Chroma takes source code and other structured text and converts it into syntax
6highlighted HTML, ANSI-coloured text, etc.
7
8Chroma is based heavily on [Pygments](http://pygments.org/), and includes
9translators for Pygments lexers and styles.
10
11<a id="markdown-table-of-contents" name="table-of-contents"></a>
12## Table of Contents
13
14<!-- TOC -->
15
161. [Table of Contents](#table-of-contents)
172. [Supported languages](#supported-languages)
183. [Try it](#try-it)
194. [Using the library](#using-the-library)
20 1. [Quick start](#quick-start)
21 2. [Identifying the language](#identifying-the-language)
22 3. [Formatting the output](#formatting-the-output)
23 4. [The HTML formatter](#the-html-formatter)
245. [More detail](#more-detail)
25 1. [Lexers](#lexers)
26 2. [Formatters](#formatters)
27 3. [Styles](#styles)
286. [Command-line interface](#command-line-interface)
297. [What's missing compared to Pygments?](#whats-missing-compared-to-pygments)
30
31<!-- /TOC -->
32
33<a id="markdown-supported-languages" name="supported-languages"></a>
34## Supported languages
35
36Prefix | Language
37:----: | --------
38A | ABAP, ABNF, ActionScript, ActionScript 3, Ada, Angular2, ANTLR, ApacheConf, APL, AppleScript, Arduino, Awk
39B | Ballerina, Base Makefile, Bash, Batchfile, BlitzBasic, BNF, Brainfuck
40C | C, C#, C++, Cap'n Proto, Cassandra CQL, Ceylon, CFEngine3, cfstatement, ChaiScript, Cheetah, Clojure, CMake, COBOL, CoffeeScript, Common Lisp, Coq, Crystal, CSS, Cython
41D | D, Dart, Diff, Django/Jinja, Docker, DTD
42E | EBNF, Elixir, Elm, EmacsLisp, Erlang
43F | Factor, Fish, Forth, Fortran, FSharp
44G | GAS, GDScript, Genshi, Genshi HTML, Genshi Text, GLSL, Gnuplot, Go, Go HTML Template, Go Text Template, GraphQL, Groovy
45H | Handlebars, Haskell, Haxe, HCL, Hexdump, HTML, HTTP, Hy
46I | Idris, INI, Io
47J | J, Java, JavaScript, JSON, Julia, Jungle
48K | Kotlin
49L | Lighttpd configuration file, LLVM, Lua
50M | Mako, markdown, Mason, Mathematica, Matlab, MiniZinc, Modula-2, MonkeyC, MorrowindScript, Myghty, MySQL
51N | NASM, Newspeak, Nginx configuration file, Nim, Nix
52O | Objective-C, OCaml, Octave, OpenSCAD, Org Mode
53P | PacmanConf, Perl, PHP, Pig, PkgConfig, PL/pgSQL, plaintext, PostgreSQL SQL dialect, PostScript, POVRay, PowerShell, Prolog, Protocol Buffer, Puppet, Python, Python 3
54Q | QBasic
55R | R, Racket, Ragel, react, reg, reStructuredText, Rexx, Ruby, Rust
56S | Sass, Scala, Scheme, Scilab, SCSS, Smalltalk, Smarty, Snobol, Solidity, SPARQL, SQL, SquidConf, Swift, SYSTEMD, systemverilog
57T | TASM, Tcl, Tcsh, Termcap, Terminfo, Terraform, TeX, Thrift, TOML, TradingView, Transact-SQL, Turing, Turtle, Twig, TypeScript, TypoScript, TypoScriptCssData, TypoScriptHtmlData
58V | VB.net, verilog, VHDL, VimL, vue
59W | WDTE
60X | XML, Xorg
61Y | YAML
62
63
64_I will attempt to keep this section up to date, but an authoritative list can be
65displayed with `chroma --list`._
66
67<a id="markdown-try-it" name="try-it"></a>
68## Try it
69
70Try out various languages and styles on the [Chroma Playground](https://swapoff.org/chroma/playground/).
71
72<a id="markdown-using-the-library" name="using-the-library"></a>
73## Using the library
74
75Chroma, like Pygments, has the concepts of
76[lexers](https://github.com/alecthomas/chroma/tree/master/lexers),
77[formatters](https://github.com/alecthomas/chroma/tree/master/formatters) and
78[styles](https://github.com/alecthomas/chroma/tree/master/styles).
79
80Lexers convert source text into a stream of tokens, styles specify how token
81types are mapped to colours, and formatters convert tokens and styles into
82formatted output.
83
84A package exists for each of these, containing a global `Registry` variable
85with all of the registered implementations. There are also helper functions
86for using the registry in each package, such as looking up lexers by name or
87matching filenames, etc.
88
89In all cases, if a lexer, formatter or style can not be determined, `nil` will
90be returned. In this situation you may want to default to the `Fallback`
91value in each respective package, which provides sane defaults.
92
93<a id="markdown-quick-start" name="quick-start"></a>
94### Quick start
95
96A convenience function exists that can be used to simply format some source
97text, without any effort:
98
99```go
100err := quick.Highlight(os.Stdout, someSourceCode, "go", "html", "monokai")
101```
102
103<a id="markdown-identifying-the-language" name="identifying-the-language"></a>
104### Identifying the language
105
106To highlight code, you'll first have to identify what language the code is
107written in. There are three primary ways to do that:
108
1091. Detect the language from its filename.
110
111 ```go
112 lexer := lexers.Match("foo.go")
113 ```
114
1153. Explicitly specify the language by its Chroma syntax ID (a full list is available from `lexers.Names()`).
116
117 ```go
118 lexer := lexers.Get("go")
119 ```
120
1213. Detect the language from its content.
122
123 ```go
124 lexer := lexers.Analyse("package main\n\nfunc main()\n{\n}\n")
125 ```
126
127In all cases, `nil` will be returned if the language can not be identified.
128
129```go
130if lexer == nil {
131 lexer = lexers.Fallback
132}
133```
134
135At this point, it should be noted that some lexers can be extremely chatty. To
136mitigate this, you can use the coalescing lexer to coalesce runs of identical
137token types into a single token:
138
139```go
140lexer = chroma.Coalesce(lexer)
141```
142
143<a id="markdown-formatting-the-output" name="formatting-the-output"></a>
144### Formatting the output
145
146Once a language is identified you will need to pick a formatter and a style (theme).
147
148```go
149style := styles.Get("swapoff")
150if style == nil {
151 style = styles.Fallback
152}
153formatter := formatters.Get("html")
154if formatter == nil {
155 formatter = formatters.Fallback
156}
157```
158
159Then obtain an iterator over the tokens:
160
161```go
162contents, err := ioutil.ReadAll(r)
163iterator, err := lexer.Tokenise(nil, string(contents))
164```
165
166And finally, format the tokens from the iterator:
167
168```go
169err := formatter.Format(w, style, iterator)
170```
171
172<a id="markdown-the-html-formatter" name="the-html-formatter"></a>
173### The HTML formatter
174
175By default the `html` registered formatter generates standalone HTML with
176embedded CSS. More flexibility is available through the `formatters/html` package.
177
178Firstly, the output generated by the formatter can be customised with the
179following constructor options:
180
181- `Standalone()` - generate standalone HTML with embedded CSS.
182- `WithClasses()` - use classes rather than inlined style attributes.
183- `ClassPrefix(prefix)` - prefix each generated CSS class.
184- `TabWidth(width)` - Set the rendered tab width, in characters.
185- `WithLineNumbers()` - Render line numbers (style with `LineNumbers`).
186- `HighlightLines(ranges)` - Highlight lines in these ranges (style with `LineHighlight`).
187- `LineNumbersInTable()` - Use a table for formatting line numbers and code, rather than spans.
188
189If `WithClasses()` is used, the corresponding CSS can be obtained from the formatter with:
190
191```go
192formatter := html.New(html.WithClasses())
193err := formatter.WriteCSS(w, style)
194```
195
196<a id="markdown-more-detail" name="more-detail"></a>
197## More detail
198
199<a id="markdown-lexers" name="lexers"></a>
200### Lexers
201
202See the [Pygments documentation](http://pygments.org/docs/lexerdevelopment/)
203for details on implementing lexers. Most concepts apply directly to Chroma,
204but see existing lexer implementations for real examples.
205
206In many cases lexers can be automatically converted directly from Pygments by
207using the included Python 3 script `pygments2chroma.py`. I use something like
208the following:
209
210```sh
211python3 ~/Projects/chroma/_tools/pygments2chroma.py \
212 pygments.lexers.jvm.KotlinLexer \
213 > ~/Projects/chroma/lexers/kotlin.go \
214 && gofmt -s -w ~/Projects/chroma/lexers/*.go
215```
216
217See notes in [pygments-lexers.go](https://github.com/alecthomas/chroma/blob/master/pygments-lexers.txt)
218for a list of lexers, and notes on some of the issues importing them.
219
220<a id="markdown-formatters" name="formatters"></a>
221### Formatters
222
223Chroma supports HTML output, as well as terminal output in 8 colour, 256 colour, and true-colour.
224
225A `noop` formatter is included that outputs the token text only, and a `tokens`
226formatter outputs raw tokens. The latter is useful for debugging lexers.
227
228<a id="markdown-styles" name="styles"></a>
229### Styles
230
231Chroma styles use the [same syntax](http://pygments.org/docs/styles/) as Pygments.
232
233All Pygments styles have been converted to Chroma using the `_tools/style.py` script.
234
235When you work with one of [Chroma's styles](https://github.com/alecthomas/chroma/tree/master/styles), know that the `chroma.Background` token type provides the default style for tokens. It does so by defining a foreground color and background color.
236
237For example, this gives each token name not defined in the style a default color of `#f8f8f8` and uses `#000000` for the highlighted code block's background:
238
239~~~go
240chroma.Background: "#f8f8f2 bg:#000000",
241~~~
242
243Also, token types in a style file are hierarchical. For instance, when `CommentSpecial` is not defined, Chroma uses the token style from `Comment`. So when several comment tokens use the same color, you'll only need to define `Comment` and override the one that has a different color.
244
245For a quick overview of the available styles and how they look, check out the [Chroma Style Gallery](https://xyproto.github.io/splash/docs/).
246
247<a id="markdown-command-line-interface" name="command-line-interface"></a>
248## Command-line interface
249
250A command-line interface to Chroma is included. It can be installed with:
251
252```sh
253go get -u github.com/alecthomas/chroma/cmd/chroma
254```
255
256<a id="markdown-whats-missing-compared-to-pygments" name="whats-missing-compared-to-pygments"></a>
257## What's missing compared to Pygments?
258
259- Quite a few lexers, for various reasons (pull-requests welcome):
260 - Pygments lexers for complex languages often include custom code to
261 handle certain aspects, such as Perl6's ability to nest code inside
262 regular expressions. These require time and effort to convert.
263 - I mostly only converted languages I had heard of, to reduce the porting cost.
264- Some more esoteric features of Pygments are omitted for simplicity.
265- Though the Chroma API supports content detection, very few languages support them.
266 I have plans to implement a statistical analyser at some point, but not enough time.