...

Text file src/github.com/alecthomas/chroma/README.md

Documentation: github.com/alecthomas/chroma

     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, Bicep, 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, OpenEdge ABL, 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.

View as plain text