
# ANSI изход

Задайте `lang` на `'ansi'`, за да оцветявате изхода от терминала — текст, съдържащ ANSI
escape последователности — вместо да го токенизирате с граматика. shikiphp анализира
escape кодовете и оцветява текста според ANSI палитрата на темата. Това е пренасяне на
токенизатора `lang: 'ansi'` на Shiki, а четири сценария за проверка сравняват неговия HTML
с Shiki 3.23.0.

```php
use Shikiphp\Shikiphp;

echo Shikiphp::codeToHtml("\e[31merror\e[0m: something broke", [
    'lang'  => 'ansi',
    'theme' => 'github-dark',
]);
```

Това е естественият начин да се визуализира заснет CLI изход — например от тестови изпълнители, компилационни
дневници и изход на `git` — със запазени оригинални цветове. Escape последователностите
се премахват от изхода; остава само текстът, обвит в цветни span елементи.

Обърнете внимание на низа PHP в двойни кавички: `"\e"` е escape символът. Когато
визуализирате изход, заснет от процес (например с `shell_exec` или
`proc_open`), escape символите вече са в низа.

## Какво разпознава

Токенизаторът чете SGR (Select Graphic Rendition) последователности, `ESC [ … m`, с
произволен брой кодове, разделени с `;`:

| Кодове | Ефект |
| --- | --- |
| `0` | нулира всички цветове и атрибути |
| `1`, `3`, `4`, `9` | получер, курсив, подчертаване, зачеркване |
| `2` | приглушен: предният план се изобразява с половин непрозрачност |
| `7` | инверсия: предният и задният план разменят местата си |
| `21`, `23`, `24`, `27`, `29` | изключва съответния атрибут |
| `22` | нормална наситеност: изключва приглушаването и получерния шрифт |
| `30`–`37`, `90`–`97` | преден план: 8-те стандартни и 8-те ярки цвята |
| `40`–`47`, `100`–`107` | заден план: 8-те стандартни и 8-те ярки цвята |
| `38;5;n`, `48;5;n` | цвят на предния или задния план от таблицата с 256 цвята |
| `38;2;r;g;b`, `48;2;r;g;b` | 24-битов цвят с пълна гама за предния или задния план |
| `39`, `49` | стандартен цвят на предния или задния план |

Скритият (`8`) и надчертаването (`53`) се анализират, но не променят изхода; останалите кодове се игнорират. Стиловете се запазват при преминаване на нов ред, докато не бъдат нулирани, както в терминала.

## Цветове

16-те именувани цвята идват от цветовете `terminal.ansi*` на темата
(`terminal.ansiRed`, `terminal.ansiBrightBlue` и т.н.). Ако темата не дефинира даден цвят,
се използва стандартната палитра на VS Code (`#cd3131` за червено,
`#2472C8` за синьо и т.н.). Текстът без зададен цвят използва
цвета на предния план на темата, а фонът на блока — фона на темата, както при
оцветяване по граматика. В таблицата с 256 цвята записите 0–15 са същите
16 именувани цвята; записите 16–255 (цветният куб 6×6×6 и скалата на сивото)
и стойностите за цвят с пълна гама не зависят от темата.

[`colorReplacements`](https://shikiphp.inline0.dev/bg/docs/options#colorreplacements) важат и за ANSI цветовете.

## Две теми

ANSI спазва картата `themes` точно както оцветяването по граматика, като излъчва
варианти CSS за всяка тема, различна от стандартната:

```php
use Shikiphp\Shikiphp;

$log = "\e[32mPASS\e[0m tests/Unit\n\e[31mFAIL\e[0m tests/Integration";

echo Shikiphp::codeToHtml($log, [
    'lang'   => 'ansi',
    'themes' => ['light' => 'github-light', 'dark' => 'github-dark'],
]);
```

Всеки именуван цвят се определя според собствената палитра на всяка тема, затова червеното в светлата тема може да се различава от червеното в тъмната.

## Без състояние на граматиката

Тъй като ANSI не използва граматика TextMate, няма състояние на граматиката за запазване.
`getLastGrammarState` извежда грешка при `lang: 'ansi'`, а `codeToTokensResult` връща
`null` `grammarState`.
