# syntax Colours source code, and is where an editor built on this library adds the language it is *for*. Eight languages are coloured here — TOML, Markdown, JavaScript, HTML, shell scripts, **YAML**, **XML** and **Dockerfiles** — because every editor meets them whatever it is for: a project's configuration is TOML or YAML, its documentation Markdown, its scripts shell, its container build a Dockerfile. The language that defines an editor is not: Turbo Go registers Go, Turbo Rust registers Rust, and neither is known here. A compose file is not a language of its own. `compose.yaml` and `docker-compose.yml` are YAML, and colouring `services:` differently from any other key would mean carrying Docker's schema here and watching it go stale. Each scanner is one file of ordinary Go. They share `LineScanner` — a line in runes, a position in it, and the spans found so far — and nothing else: there is no pattern language and no grammar format, so adding a language means writing ordinary Go beside the others rather than learning a notation. `LineScanner` and the helpers around it are **exported**, because that is what makes writing one outside this package possible at all. `Language` is a string, because it is written down outside this package: a snippets file restricts itself to `languages = ["go"]`. `LanguageOf(path, firstLine)` names a file by its **extension**, then by its **name**, then by a **shebang**; `LanguageNone` — anything no registered language claims — is coloured not at all rather than wrongly. The name step is what finds a `Dockerfile`, which has neither an extension nor a shebang. A `Definition` lists whole names in `Filenames`, and a file matches on its whole name or on the part before its first dot — so `Dockerfile` also answers for `Dockerfile.dev`. ## The extension point ```go syntax.Register(syntax.Definition{ Language: "rust", Extensions: []string{".rs"}, Highlight: highlightRust, }) ``` The registry is package-level state, which is the shape the standard library gives the same problem in `image.RegisterFormat`: an editor registers once at start-up, before it opens a file, and nothing ever removes an entry. Registering a language already known replaces it, so an editor can override one of the eight. The **classes are closed**. A language registered from outside colours itself with the seventeen `Class` values and no others, which is what lets one theme colour every language an editor will ever learn. ## Every scanner guesses nothing Where a construct cannot be recognised from what one line holds, it is left alone rather than approximated. A highlighter that is wrong is worse than one that is quiet, and each of these was a decision: | Not recognised | Because | | --- | --- | | JavaScript regex literals | Telling `/x/g` from a division needs to know whether the previous token could end an expression; a wrong guess colours the rest of the line as a string | | Shell heredocs | Carrying an arbitrary delimiter across lines, plus `<<-` and quoted spellings, for a few lines of plain text | | JavaScript inside `