• Home
  • History
  • Annotate
Name Date Size #Lines LOC

..03-May-2022-

.github/H16-Oct-2021-8569

_tools/H16-Oct-2021-471394

bin/H16-Oct-2021-245177

cmd/H16-Oct-2021-742653

formatters/H16-Oct-2021-1,4421,149

lexers/H16-Oct-2021-57,49053,325

quick/H16-Oct-2021-6546

styles/H16-Oct-2021-2,0511,835

.gitignoreH A D16-Oct-2021316 2014

.golangci.ymlH A D16-Oct-20211.8 KiB7771

.goreleaser.ymlH A D16-Oct-2021722 3837

COPYINGH A D16-Oct-20211 KiB2016

MakefileH A D16-Oct-2021508 2013

README.mdH A D16-Oct-202111.6 KiB286212

coalesce.goH A D16-Oct-2021780 3631

coalesce_test.goH A D16-Oct-2021394 2016

colour.goH A D16-Oct-20214.5 KiB165116

colour_test.goH A D16-Oct-20211.1 KiB4334

delegate.goH A D16-Oct-20213.2 KiB138114

delegate_test.goH A D16-Oct-20212.6 KiB112103

doc.goH A D16-Oct-2021326 81

formatter.goH A D16-Oct-20211 KiB4428

go.modH A D16-Oct-2021176 107

go.sumH A D16-Oct-20211.3 KiB1514

iterator.goH A D16-Oct-20211.7 KiB7757

lexer.goH A D16-Oct-20212.8 KiB12965

lexer_test.goH A D16-Oct-20211.2 KiB5348

mutators.goH A D16-Oct-20213.3 KiB132100

mutators_test.goH A D16-Oct-20211.2 KiB5853

regexp.goH A D16-Oct-202115.2 KiB573427

regexp_test.goH A D16-Oct-20214.4 KiB187173

remap.goH A D16-Oct-20211.7 KiB8163

remap_test.goH A D16-Oct-2021745 3025

style.goH A D16-Oct-20217.9 KiB345277

style_test.goH A D16-Oct-20211.9 KiB6657

table.pyH A D16-Oct-2021916 3322

tokentype_string.goH A D16-Oct-20217.4 KiB214204

types.goH A D16-Oct-20217 KiB348276

README.md

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