...

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

Documentation: github.com/alecthomas/chroma/v2

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

View as plain text