
# ANSI出力

`lang`を`'ansi'`に設定すると、文法でトークン化する代わりに、ANSIエスケープシーケンスを含むターミナル出力テキストをハイライトします。shikiphpはエスケープコードを解析し、テーマのANSIパレットから色を付けます。これはShikiの`lang: 'ansi'`トークナイザーの移植版であり、4つのオラクルシナリオでShiki 3.23.0とのHTMLを検証しています。

```php
use Shikiphp\Shikiphp;

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

テストランナーやビルドログ、`git`の出力など、取得したCLI出力を元の色のまま表示する自然な方法です。エスケープシーケンスは出力から取り除かれ、テキストだけが色付きスパンで囲まれます。

二重引用符で囲まれたPHP文字列に注意してください。`"\e"`はエスケープ文字です。プロセスから取得した出力（たとえば`shell_exec`や`proc_open`を使う場合）を表示するとき、エスケープ文字はすでに文字列に含まれています。

## 対応する内容

トークナイザーは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/ja/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`を返します。
