| 📦 Turbo Rust 713ea5c k33g 22h ago | 1 | # Référence : langages colorés |
| 2 | |
| 3 | > Description neutre des fichiers que Turbo Rust colore, de la façon dont il décide, et de ce que reconnaît chaque scanner. |
| 4 | |
| 5 | ## Reconnaissance |
| 6 | |
| 7 | L'**extension** d'un fichier décide dès qu'elle fait partie de celles-ci : |
| 8 | |
| 9 | | Extension | Langage | |
| 10 | | --- | --- | |
| 11 | | `.rs` | Rust | |
| 12 | | `.toml` | TOML | |
| 13 | | `.yaml`, `.yml` | YAML | |
| 14 | | `.md`, `.markdown` | Markdown | |
| 15 | | `.js`, `.mjs`, `.cjs` | JavaScript | |
| 16 | | `.html`, `.htm` | HTML | |
| 17 | | `.xml`, `.xsd`, `.xsl`, `.xslt`, `.svg`, `.plist`, `.csproj`, `.pom` | XML | |
| 18 | | `.sh`, `.bash`, `.zsh` | Shell | |
| 19 | | `.dockerfile`, `.containerfile` | Dockerfile | |
| 20 | |
| 21 | Les extensions sont comparées sans tenir compte de la casse, et seule la dernière compte : `main.rs.backup` n'est pas du Rust. |
| 22 | |
| 23 | Un fichier dont l'extension ne décide de rien est ensuite cherché par son **nom**. Seuls les fichiers sans extension exploitable en ont besoin : |
| 24 | |
| 25 | | Nom | Langage | |
| 26 | | --- | --- | |
| 27 | | `Dockerfile`, `Containerfile` | Dockerfile | |
| 28 | |
| 29 | Un nom correspond sur sa totalité ou sur la partie précédant le premier point, sans tenir compte de la casse — ainsi `Dockerfile`, `dockerfile` et `Dockerfile.dev` sont tous reconnus, tandis que `Dockerfile.md` est du Markdown, puisque l'extension est consultée en premier. |
| 30 | |
| 31 | Un fichier qu'aucun des deux tableaux ne revendique est un **script shell** si sa première ligne est un shebang nommant un shell — `sh`, `bash`, `zsh`, `dash` ou `ksh`, comme élément de chemin ou comme argument d'`env`. C'est ce qui colore `configure`, un hook git, ou un script que quelqu'un a renommé. |
| 32 | |
| 33 | | Première ligne | Résultat | |
| 34 | | --- | --- | |
| 35 | | `#!/bin/sh` | Shell | |
| 36 | | `#!/usr/bin/env bash` | Shell | |
| 37 | | `#!/usr/bin/env -S bash -e` | Shell | |
| 38 | | `#!/usr/bin/env python3` | Non coloré | |
| 39 | | Tout ce qui ne commence pas par `#!` | Non coloré | |
| 40 | |
| 41 | L'ordre est fixe — extension, puis nom, puis première ligne — et le premier qui décide l'emporte : un fichier `.rs` commençant par un shebang reste du Rust. |
| 42 | |
| 43 | Tout le reste est affiché en texte brut. Ce n'est pas une erreur — ouvrir un PNG dans l'éditeur n'est pas une faute, c'est simplement non coloré. |
| 44 | |
| 45 | ## Classes |
| 46 | |
| 47 | Tous les scanners produisent le même vocabulaire de classes, et chacune correspond à une clé de thème. |
| 48 | |
| 49 | | Classe | Clé de thème | Produite par | |
| 50 | | --- | --- | --- | |
| 51 | | `identifier` | `syntax.identifier` | Rust, TOML, JavaScript, shell, YAML, Dockerfile | |
| 52 | | `keyword` | `syntax.keyword` | Rust, JavaScript, shell, HTML (doctype), XML, Dockerfile | |
| 53 | | `type` | `syntax.type` | Rust, TOML (en-têtes de table), YAML (étiquettes) | |
| 54 | | `builtin` | `syntax.builtin` | Rust, JavaScript, shell (builtins et expansions), YAML (ancres et alias), Dockerfile (variables) | |
| 55 | | `constant` | `syntax.constant` | Rust, TOML, JavaScript, shell, YAML, HTML et XML (entités) | |
| 56 | | `function` | `syntax.function` | Rust, JavaScript, shell (la commande) | |
| 57 | | `string` | `syntax.string` | tous | |
| 58 | | `char` | `syntax.char` | Rust | |
| 59 | | `number` | `syntax.number` | Rust, TOML, JavaScript, shell, YAML, Dockerfile | |
| 60 | | `comment` | `syntax.comment` | Rust, TOML, JavaScript, shell, HTML, YAML, XML, Dockerfile | |
| 61 | | `operator` | `syntax.operator` | Rust, TOML, JavaScript, shell, HTML, YAML (en-têtes de scalaire de bloc), XML, Dockerfile | |
| 62 | | `punctuation` | `syntax.punctuation` | Rust, TOML, JavaScript, shell, Markdown, YAML, Dockerfile | |
| 63 | | `heading` | `syntax.heading` | Markdown | |
| 64 | | `tag` | `syntax.tag` | HTML, XML | |
| 65 | | `attribute` | `syntax.attribute` | HTML, XML, Dockerfile (options) | |
| 66 | | `emphasis` | `syntax.emphasis` | Markdown | |
| 67 | | `link` | `syntax.link` | Markdown | |
| 68 | |
| 69 | ## Rust |
| 70 | |
| 71 | Écrit à la main, dans `internal/rustlang`. Trois constructions traversent un saut de ligne et sont transportées exactement plutôt que devinées : un commentaire de bloc (avec sa profondeur d'imbrication), une chaîne brute (avec son nombre de dièses), et une chaîne ordinaire. |
| 72 | |
| 73 | | Reconnu | Comme | |
| 74 | | --- | --- | |
| 75 | | `fn`, `let`, `impl`, `struct`, `enum`, `trait`, `match`, `pub`, `mut`, `async`, `await`, `unsafe`, … | mot-clé | |
| 76 | | les mots réservés pour l'avenir — `become`, `priv`, `typeof`, `unsized`, … | mot-clé | |
| 77 | | `bool`, `char`, `str`, `i8`…`i128`, `u8`…`u128`, `isize`, `usize`, `f32`, `f64`, `self`, `Self` | type | |
| 78 | | tout autre nom commençant par une majuscule | type | |
| 79 | | `true`, `false`, `None`, `Some`, `Ok`, `Err` | constante | |
| 80 | | un nom immédiatement avant `(` | fonction | |
| 81 | | `name!`, le `!` compris | builtin | |
| 82 | | `#[derive(Debug)]`, `#![no_std]` | attribut | |
| 83 | | `"…"`, `b"…"`, sur plusieurs lignes, échappements honorés | chaîne | |
| 84 | | `r"…"`, `r#"…"#`, `br##"…"##`, sur plusieurs lignes | chaîne | |
| 85 | | `'x'`, `'\n'`, `'\u{1F600}'`, `b'x'` | caractère | |
| 86 | | `'a`, `'static` | type | |
| 87 | | `42`, `1_000`, `0xFF`, `0b1010`, `0o77`, `1.5e-3`, `42u8`, `3.0f64` | nombre | |
| 88 | | `//`, `///`, `//!` jusqu'au bout de la ligne | commentaire | |
| 89 | | `/* … */`, **imbriqués**, sur plusieurs lignes | commentaire | |
| 90 | | `..`, `..=` | opérateur | |
| 91 | | `:`, `::` | ponctuation | |
| 92 | | suites de `+-*/%=<>!&\|^~?` | opérateur | |
| 93 | | `()[]{},;.` | ponctuation | |
| 94 | |
| 95 | **Une durée de vie se distingue d'un littéral de caractère** en cherchant le guillemet fermant là où un caractère devrait le mettre — une rune plus loin, ou davantage pour un échappement. `'a` est une durée de vie, `'a'` un caractère, `'static` une durée de vie, `'\u{1F600}'` un caractère. Se tromper là-dessus transforme le reste de la ligne en chaîne, d'où les tests dédiés. |
| 96 | |
| 97 | **Une durée de vie est colorée comme un type**, parce que c'est un paramètre générique, déclaré et utilisé aux mêmes endroits qu'un type. |
| 98 | |
| 99 | **Une majuscule veut dire un type.** La convention de nommage de Rust est assez forte pour qu'on s'y appuie : un type, un trait et une variante d'énumération sont tous en `UpperCamelCase` et rien d'autre ne l'est. Une constante en `SCREAMING_SNAKE_CASE` est colorée en type par cette règle, et c'est le seul endroit où l'heuristique se voit. |
| 100 | |
| 101 | **`None`, `Some`, `Ok` et `Err` appartiennent à Option et Result, pas au langage.** Ils sont colorés en constantes parce qu'un lecteur les rencontre avant toute autre variante et les lit comme il lit `true`. |
| 102 | |
| 103 | **Les macros emportent leur `!`.** `println!` est un seul segment ; `a != b` n'est pas une macro, et les deux se distinguent par le `=` qui suit. |
| 104 | |
| 105 | **Un nombre emporte son suffixe.** `42u8` est un seul littéral, et colorer le `u8` en type couperait en deux une chose qui n'en fait qu'une. |
| 106 | |
| 107 | **Un attribut qui dépasse la fin de sa ligne est coloré jusqu'au bout et n'est pas transporté.** Contrairement à un commentaire ou une chaîne, un attribut non fermé est presque toujours un attribut à moitié tapé, et le transporter repeindrait le reste du fichier. |
| 108 | |
| 109 | **Non reconnu**, chaque fois pour une raison donnée : |
| 110 | |
| 111 | | Non reconnu | Parce que | |
| 112 | | --- | --- | |
| 113 | | Quelle macro est invoquée | `println!` et une macro que vous avez écrite sont toutes deux des builtins ; les distinguer demande l'expansion de la caisse | |
| 114 | | L'intérieur d'un corps de macro | Les corps de `macro_rules!` sont colorés comme du Rust ordinaire, ce qui est le plus souvent juste et parfois non | |
| 115 | | Les constantes en `SCREAMING_SNAKE_CASE` | Indiscernables d'un nom de type par la règle de la majuscule, et une seconde règle mal-colorerait un type dont le nom est un acronyme | |
| 116 | | Le Markdown des commentaires de documentation | Un commentaire `///` est un commentaire, pas un document Markdown | |
| 117 | |
| 118 | ## TOML |
| 119 | |
| 120 | | Reconnu | Comme | |
| 121 | | --- | --- | |
| 122 | | `# commentaire` | comment | |
| 123 | | `[table]`, `[[array]]` | le nom en type, les crochets en punctuation | |
| 124 | | `clé =` | identifier, puis operator | |
| 125 | | `"basique"`, `'littérale'`, `"""multi-ligne"""`, `'''multi-ligne'''` | string | |
| 126 | | `true`, `false` | constant | |
| 127 | | nombres, dates, heures, `inf`, `nan` | number | |
| 128 | |
| 129 | ## YAML |
| 130 | |
| 131 | Un fichier compose, un manifeste Kubernetes et un workflow d'intégration continue sont tous cela : il n'y a pas de dialecte séparé, parce qu'un dialecte serait le schéma de quelqu'un d'autre à maintenir en phase. |
| 132 | |
| 133 | | Reconnu | Comme | |
| 134 | | --- | --- | |
| 135 | | `# commentaire` | commentaire | |
| 136 | | `clé:` suivie d'une espace ou de la fin de ligne | la clé en identifiant, le deux-points en ponctuation | |
| 137 | | `"entre guillemets": 1`, `'apostrophes': 1` | la clé citée en identifiant | |
| 138 | | `- ` ouvrant une entrée de séquence | ponctuation | |
| 139 | | `"…"`, `'…'` | chaîne | |
| 140 | | `true`, `false`, `yes`, `no`, `on`, `off`, `null` | constante, quelle que soit la casse | |
| 141 | | nombres, dates et heures écrits sans guillemets | nombre | |
| 142 | | `&ancre`, `*alias` | builtin | |
| 143 | | `!!str`, `!Custom` | type | |
| 144 | | `---`, `...` | toute la ligne en ponctuation | |
| 145 | | `{`, `}`, `[`, `]`, `,` | ponctuation | |
| 146 | | `\|`, `>`, avec leurs indicateurs de coupe et d'indentation | l'en-tête en opérateur, le corps en chaîne | |
| 147 | |
| 148 | **Un deux-points n'est un séparateur que si une espace ou la fin de ligne le suit.** `image: nginx:1.27` est une clé et une seule valeur, et `url: http://example.com/x` une clé et une seule URL — colorer les deux-points intérieurs en séparateurs mettrait chaque étiquette d'image et chaque URL en trois couleurs. |
| 149 | |
| 150 | **L'étendue d'un scalaire de bloc est décidée par l'indentation**, pas par un délimiteur. La première ligne de contenu après `|` ou `>` fixe l'indentation du bloc ; toute ligne indentée au moins autant lui appartient, et la première qui ne l'est pas y met fin. **Une ligne vide à l'intérieur d'un bloc y reste** : un scalaire littéral conserve ses lignes vides, et terminer le bloc au premier saut de paragraphe couperait en deux un script shell dans un fichier d'intégration continue. |
| 151 | |
| 152 | **Un `#` a besoin d'une espace devant lui pour ouvrir un commentaire**, si bien que `colour: ff#00aa` est un seul scalaire. |
| 153 | |
| 154 | | Non reconnu | Parce que | |
| 155 | | --- | --- | |
| 156 | | Le schéma d'un fichier compose, d'un manifeste ou d'un workflow | Colorer `services:` autrement qu'une clé quelconque revient à transporter le schéma de quelqu'un d'autre, qui se périme le jour où il ajoute une clé | |
| 157 | | Les flux multi-documents comme documents distincts | `---` est coloré, mais rien n'est réinitialisé à cet endroit ; rien dans la coloration ne dépend des frontières de documents | |
| 158 | | Si un mot nu est une chaîne ou un nombre pour un analyseur | `1.2.3` est une version pour un lecteur et une chaîne pour YAML ; l'analyseur colore ce à quoi cela ressemble | |
| 159 | |
| 160 | ## Markdown |
| 161 | |
| 162 | | Reconnu | Comme | |
| 163 | | --- | --- | |
| 164 | | `# Titre` … `###### Titre` | toute la ligne en heading | |
| 165 | | `**gras**`, `__gras__`, `*italique*`, `_italique_` | emphasis | |
| 166 | | `` `code` `` | string | |
| 167 | | `[texte](cible)`, `` | l'ensemble en link | |
| 168 | | `- `, `* `, `+ `, `1. `, `1) ` | le marqueur en punctuation | |
| 169 | | `>` | punctuation | |
| 170 | | `---`, `***`, `___` | punctuation | |
| 171 | | clôtures ` ``` ` et `~~~` | tout le bloc, lignes d'ouverture et de fermeture comprises, en string | |
| 172 | |
| 173 | Un bloc clôturé est **d'une seule couleur quel que soit le langage annoncé** : ```` ```rust ```` ne colore pas son contenu en Rust. La suite de marqueurs qui ouvre un bloc doit être fermée par le même caractère : une clôture en accents graves ne se ferme pas par des tildes. Une clôture non fermée colore jusqu'à la fin du fichier. |
| 174 | |
| 175 | La suite de marqueurs qui ouvre une emphase doit être fermée par une suite de même longueur, de sorte que `**gras**` fasse un seul span et non deux italiques. |
| 176 | |
| 177 | ## JavaScript |
| 178 | |
| 179 | | Reconnu | Comme | |
| 180 | | --- | --- | |
| 181 | | `const`, `let`, `function`, `class`, `async`, `await`, `import`, `export`, … | keyword | |
| 182 | | `true`, `false`, `null`, `undefined`, `NaN`, `Infinity`, `this` | constant | |
| 183 | | `console`, `document`, `window`, `Array`, `Object`, `Promise`, `Math`, `JSON`, … | builtin | |
| 184 | | un nom immédiatement suivi de `(` | function | |
| 185 | | `"…"`, `'…'` | string | |
| 186 | | `` `…` ``, interpolations comprises, sur plusieurs lignes | string | |
| 187 | | `//` jusqu'à la fin de la ligne, `/* … */` sur plusieurs lignes | comment | |
| 188 | | `42`, `3.14`, `0x1f`, `0b1010`, `0o777`, `1_000_000`, `1e6`, `10n` | number | |
| 189 | | suites de `+-*/%=<>!&|^~?:` | operator | |
| 190 | | `()[]{},;.` | punctuation | |
| 191 | |
| 192 | **Les littéraux d'expression régulière ne sont pas reconnus.** Distinguer `/x/g` d'une division exige de savoir si le token précédent pouvait terminer une expression ; une mauvaise supposition colore le reste de la ligne comme une chaîne, ce qui est pire que de laisser une regex à la couleur d'un opérateur. |
| 193 | |
| 194 | Les globales sont reconnues par leur nom : un fichier qui masque `Math` la voit quand même colorée comme un builtin — la même règle que les types primitifs de Rust. |
| 195 | |
| 196 | ## HTML |
| 197 | |
| 198 | | Reconnu | Comme | |
| 199 | | --- | --- | |
| 200 | | `<balise`, `</balise`, `>`, `/>` | tag | |
| 201 | | noms d'attributs, dont `data-*`, `xlink:href`, `@click`, `v-bind.prop` | attribute | |
| 202 | | `=` | operator | |
| 203 | | `"…"`, `'…'` | string | |
| 204 | | `<!-- … -->`, sur plusieurs lignes | comment | |
| 205 | | `&`, `©` | constant | |
| 206 | | `<!DOCTYPE …>` et les autres déclarations | keyword | |
| 207 | |
| 208 | Le texte entre balises n'est pas coloré. Une esperluette isolée sans `;` dans les 32 caractères qui suivent est laissée telle quelle, parce que c'est du texte légal. |
| 209 | |
| 210 | **Le contenu de `<script>` et de `<style>` n'est pas coloré** en JavaScript ni en CSS. |
| 211 | |
| 212 | ## XML |
| 213 | |
| 214 | Son propre analyseur plutôt que celui du HTML, pour une raison qui compte : CDATA. Tout l'intérêt de `<![CDATA[ … ]]>` est que son contenu n'est *pas* du balisage, et colorer les balises qu'il contient comme des balises est exactement l'inverse. |
| 215 | |
| 216 | | Reconnu | Comme | |
| 217 | | --- | --- | |
| 218 | | `<?xml version="1.0"?>` et les autres instructions de traitement | la cible et `?>` en mot-clé, les paires entre les deux en attributs et chaînes | |
| 219 | | `<!DOCTYPE …>` et les autres formes `<!` | mot-clé | |
| 220 | | `<!-- … -->`, sur plusieurs lignes | commentaire | |
| 221 | | `<![CDATA[ … ]]>`, sur plusieurs lignes | chaîne | |
| 222 | | `<balise`, `</balise`, `>`, `/>` | balise | |
| 223 | | `<ns:balise>`, `xsi:type` | le préfixe et le nom local en **un seul** segment | |
| 224 | | les noms d'attributs | attribut | |
| 225 | | `=` | opérateur | |
| 226 | | `"…"`, `'…'` | chaîne | |
| 227 | | `&`, `©` | constante | |
| 228 | |
| 229 | **Un commentaire et une section CDATA se ferment sur des délimiteurs différents**, et sont transportés séparément : un `-->` à l'intérieur d'une section CDATA n'y met pas fin. |
| 230 | |
| 231 | **Une esperluette isolée sans point-virgule dans les 32 caractères suivants est laissée telle quelle**, parce que c'est du texte légal dans bien des documents et qu'avaler le reste de la ligne serait la plus grosse erreur. |
| 232 | |
| 233 | Le texte entre balises n'est pas coloré. |
| 234 | |
| 235 | ## Shell |
| 236 | |
| 237 | S'applique indifféremment à `sh`, `bash` et `zsh` : les mots-clés reconnus sont ceux qu'ils partagent. |
| 238 | |
| 239 | | Reconnu | Comme | |
| 240 | | --- | --- | |
| 241 | | `if`, `then`, `fi`, `for`, `while`, `case`, `esac`, `function`, `return`, … | keyword | |
| 242 | | `true`, `false` | constant | |
| 243 | | `echo`, `printf`, `export`, `local`, `read`, `cd`, `set`, `source`, … | builtin | |
| 244 | | `$NOM`, `${…}`, `$(…)`, `$1`, `$?`, `$@` | builtin | |
| 245 | | le **premier mot nu d'une ligne** | function | |
| 246 | | tout mot nu suivant, et `NOM` dans `NOM=valeur` | identifier | |
| 247 | | `'…'`, sans échappement ni expansion à l'intérieur | string | |
| 248 | | `"…"`, avec les expansions colorées comme telles | string | |
| 249 | | `#` jusqu'à la fin de la ligne | comment | |
| 250 | |
| 251 | `$(a $(b) c)` fait un seul span : l'imbrication est comptée. Une option comme `-euo` est un seul mot, et non un moins suivi d'un mot. |
| 252 | |
| 253 | **Les heredocs ne sont pas reconnus.** `<<EOF` et le texte qui suit sont colorés comme du shell ordinaire. |
| 254 | |
| 255 | ## Dockerfile |
| 256 | |
| 257 | | Reconnu | Comme | |
| 258 | | --- | --- | |
| 259 | | `FROM`, `RUN`, `COPY`, `ADD`, `ARG`, `ENV`, `CMD`, `ENTRYPOINT`, `EXPOSE`, `LABEL`, `USER`, `VOLUME`, `WORKDIR`, `HEALTHCHECK`, `ONBUILD`, `SHELL`, `STOPSIGNAL`, `MAINTAINER` | mot-clé, quelle que soit la casse | |
| 260 | | `AS`, `NONE` | mot-clé | |
| 261 | | `# commentaire`, y compris les directives `# syntax=` et `# escape=` | commentaire | |
| 262 | | `--from=builder`, `--chown=me:me` | le nom de l'option en attribut | |
| 263 | | `$NOM`, `${NOM}`, `${NOM:-defaut}` | builtin, en un seul segment jusqu'à l'accolade fermante | |
| 264 | | `"…"`, `'…'` | chaîne | |
| 265 | | un `\` final | opérateur | |
| 266 | | les nombres | nombre | |
| 267 | | chemins et références d'images — `/usr/local/bin`, `golang:1.26-alpine` | identifiant, en **un seul** segment | |
| 268 | |
| 269 | **Seul le premier mot d'une ligne peut être une instruction**, et un mot qui n'en est pas une est un argument — ce qui garde le premier mot d'une ligne de continuation hors de la couleur des mots-clés. |
| 270 | |
| 271 | **Rien ne traverse un saut de ligne.** Un `\` joint deux lignes pour Docker, mais chaque moitié se lit encore comme une commande et est colorée pour elle-même. |
| 272 | |
| 273 | | Non reconnu | Parce que | |
| 274 | | --- | --- | |
| 275 | | Le shell à l'intérieur d'un `RUN` | Il faudrait passer l'analyseur shell sur une partie de ligne et en remonter les colonnes, et un `RUN` peut contenir n'importe quel langage | |
| 276 | | Les heredocs dans un `RUN` | La même raison que pour l'analyseur shell | |
| 277 | | Quelle étape nomme un `--from` | Rien ici ne lit le reste du fichier | |
| 278 | |
| 279 | ## Voir aussi |
| 280 | |
| 281 | - [Format des fichiers de thème](themes.md) — toutes les clés vers lesquelles ces classes se résolvent |
| 282 | - [Coloration et complétion](../explanation/colouring-and-completion.md) — pourquoi les scanners sont écrits ainsi |
| 283 | - [Écrire son propre thème](../how-to/write-a-theme.md) |