# 機能設計書 21-キーテーブル

## 概要

本ドキュメントは、Ghosttyターミナルエミュレータにおける「キーテーブル」機能の設計を記述する。キーテーブルは、名前付きのキーバインディングセットを定義し、動的にキーバインドモードを切り替えることで、コンテキストに応じた異なるキーボード操作を可能にする機能である。

### 本機能の処理概要

**業務上の目的・背景**：
端末操作において、ユーザーは様々なコンテキスト（通常編集、コピーモード、プレフィックスモードなど）で異なるキー操作を必要とする。従来のターミナルでは単一のキーバインドセットしか使用できなかったが、キーテーブル機能により、ユーザーは複数のキーバインドセット（テーブル）を定義し、必要に応じて動的に切り替えることができる。これにより、tmuxやvimのようなモード切り替え機能をターミナル自体に組み込むことが可能となり、ユーザーの生産性向上に寄与する。

**機能の利用シーン**：
- tmux風のプレフィックスキー操作（Ctrl+b の後に特定のキーで操作）
- vim風のコマンドモードの実装
- カスタムコピー/選択モード
- アプリケーション固有のキーバインドモード

**主要な処理内容**：
1. 設定ファイルでの名前付きキーテーブルの定義
2. `activate_key_table` アクションによるテーブルのアクティベーション
3. `activate_key_table_once` による一回限りのテーブルアクティベーション
4. `deactivate_key_table` による現在のテーブルの非アクティベーション
5. `deactivate_all_key_tables` による全テーブルの非アクティベーション
6. キーテーブルスタックの管理（最大8テーブルまで）

**関連システム・外部連携**：
- 設定システム（Config.zig）との連携によるテーブル定義の読み込み
- キーバインドシステム（Binding.zig）との連携によるバインド解決
- UIシステムとの連携によるアクティブテーブルの表示

**権限による制御**：
本機能に特別な権限制御はない。すべてのユーザーが利用可能。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 1 | メインターミナルウィンドウ | 主画面 | キーテーブルのアクティベーション/非アクティベーション |

## 機能種別

イベント処理 / 状態管理

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| table_name | []const u8 | Yes | アクティベートするキーテーブル名 | 設定で定義されたテーブル名であること |

### 入力データソース

- 設定ファイル（~/.config/ghostty/config）でのキーテーブル定義
- キーボード入力によるアクティベーションアクション

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| active_table | ?[]const u8 | 現在アクティブなキーテーブル名（なければnull） |
| table_stack | []TableEntry | アクティブなテーブルのスタック |

### 出力先

- Surface内部状態（keyboard.table_stack）
- UIへの通知（key_table アクション経由）

## 処理フロー

### 処理シーケンス

```
1. キーテーブルアクティベーションアクション受信
   └─ activate_key_table または activate_key_table_once

2. テーブル名の検証
   └─ 設定からテーブル名に対応するBinding.Setを検索

3. テーブルスタック更新
   └─ 最大8テーブルまでスタックにプッシュ
   └─ onceフラグの設定

4. UIへの通知
   └─ key_table アクションで状態変更を通知

5. キー入力処理時のテーブル参照
   └─ スタックトップのテーブルを優先使用
   └─ onceテーブルは使用後に自動解除
```

### フローチャート

```mermaid
flowchart TD
    A[キー入力受信] --> B{キーテーブル関連アクション?}
    B -->|activate_key_table| C[テーブル名検証]
    B -->|activate_key_table_once| D[テーブル名検証 + onceフラグ]
    B -->|deactivate_key_table| E[スタックからポップ]
    B -->|deactivate_all| F[スタッククリア]
    B -->|通常のキー入力| G[現在のテーブルでバインド検索]

    C --> H{テーブル存在?}
    D --> H
    H -->|Yes| I[スタックにプッシュ]
    H -->|No| J[処理終了]

    I --> K[UIに通知]
    E --> K
    F --> K

    G --> L{onceテーブル?}
    L -->|Yes| M[バインド実行後テーブル解除]
    L -->|No| N[バインド実行]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-21-1 | テーブルスタック制限 | テーブルスタックは最大8テーブルまで | activate_key_table実行時 |
| BR-21-2 | 同一テーブル重複禁止 | 既にアクティブなテーブルは再度アクティベート不可 | activate_key_table実行時 |
| BR-21-3 | onceテーブル自動解除 | once指定テーブルは有効なバインド実行後に自動解除 | キーバインド実行時 |

### 計算ロジック

該当なし

## データベース操作仕様

該当なし（本機能はデータベースを使用しない）

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | テーブル未定義 | 指定されたテーブル名が設定に存在しない | performableがfalseを返し、処理をスキップ |
| - | スタック上限 | 8テーブル以上のアクティベーション | 処理を無視 |
| - | 重複アクティベーション | 既にアクティブなテーブルを再アクティベート | performableがfalseを返す |

### リトライ仕様

該当なし

## トランザクション仕様

該当なし

## パフォーマンス要件

- キーテーブル切り替え: 即時（マイクロ秒オーダー）
- キーバインド検索: テーブル内エントリ数に依存するが、通常は即時

## セキュリティ考慮事項

- キーテーブルはローカル設定ファイルからのみ定義可能
- 外部からの動的なテーブル定義注入は不可

## 備考

- キーテーブル機能はtmuxのプレフィックスキーに相当する機能を提供
- global/allフラグとの組み合わせは不可（キーシーケンスと同様）

---

## コードリーディングガイド

本機能を理解するために参照すべきファイルと、推奨する読み解き順序を以下に示す。

### 推奨読解順序

#### Step 1: データ構造を理解する

キーテーブルの中核となるデータ構造を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | Binding.zig | `src/input/Binding.zig` | Action union内のactivate_key_table, activate_key_table_once, deactivate_key_table, deactivate_all_key_tablesの定義（869-898行目） |
| 1-2 | Surface.zig | `src/Surface.zig` | Keyboard structのtable_stack定義（276-279行目） |

**読解のコツ**: Zigの `union(enum)` 構文に注目。各アクションタグに対応するペイロード型を確認する。

#### Step 2: エントリーポイントを理解する

アクションがどこから発火されるかを確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | Binding.zig | `src/input/Binding.zig` | Action.parse関数でのアクション解析（1207-1271行目） |

**主要処理フロー**:
1. **1207行目**: parse関数でaction文字列を解析
2. **1218-1268行目**: unionフィールドを走査してアクション名にマッチするものを探索
3. **1229-1230行目**: コロン以降のパラメータを抽出

#### Step 3: アクション処理を理解する

Surface側でのアクション処理実装を確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | Surface.zig | `src/Surface.zig` | performBindingAction関数でのactivate_key_table処理 |
| 3-2 | action.zig | `src/apprt/action.zig` | KeyTableアクション定義（258行目） |

**主要処理フロー**:
- **Surface.zig**: activate_key_tableアクション受信時にtable_stackにプッシュ
- **action.zig**: UIへの通知用key_tableアクション定義

### プログラム呼び出し階層図

```
キー入力
    │
    ├─ Surface.keyInput()
    │      │
    │      └─ performBindingAction()
    │             │
    │             ├─ activate_key_table
    │             │      └─ keyboard.table_stack.push()
    │             │
    │             ├─ activate_key_table_once
    │             │      └─ keyboard.table_stack.push() with once=true
    │             │
    │             ├─ deactivate_key_table
    │             │      └─ keyboard.table_stack.pop()
    │             │
    │             └─ deactivate_all_key_tables
    │                    └─ keyboard.table_stack.clear()
    │
    └─ rt_surface.performAction(.key_table)
           └─ UI通知
```

### データフロー図

```
[入力]                    [処理]                         [出力]

設定ファイル ────▶ Config.keybind.tables ────▶ Binding.Set（テーブル定義）
       │
キーボード入力 ────▶ Surface.keyInput() ────▶ keyboard.table_stack
                            │                        │
                            ▼                        ▼
                    performBindingAction() ────▶ Action.key_table
                                                     │
                                                     ▼
                                             apprt（UI更新）
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| Binding.zig | `src/input/Binding.zig` | ソース | キーバインドアクション定義 |
| Surface.zig | `src/Surface.zig` | ソース | Surface状態管理、アクション処理 |
| action.zig | `src/apprt/action.zig` | ソース | apprtアクション定義 |
| Config.zig | `src/config/Config.zig` | ソース | 設定解析、テーブル定義の読み込み |
| command.zig | `src/input/command.zig` | ソース | コマンド実行 |
