# 機能設計書 33-キーバインディング

## 概要

本ドキュメントは、Visual Studio Codeのキーバインディング機能の設計内容を記述する。キーバインディング機能は、キーボードショートカットの表示・検索・カスタマイズを行うための設定管理機能である。

### 本機能の処理概要

キーバインディング機能は、VS Codeのすべてのコマンドに対するキーボードショートカットを管理するための専用エディタを提供する。ユーザーは既存のキーバインドを検索・確認し、新しいショートカットの追加や既存ショートカットの変更・削除を行うことができる。

**業務上の目的・背景**：開発者はキーボード操作の効率化が生産性に直結するため、個人の作業スタイルに合わせたショートカットのカスタマイズが重要である。また、キーバインドの競合を検出・解決する機能により、拡張機能間やデフォルト設定との衝突を回避できる。

**機能の利用シーン**：
- 特定のコマンドのショートカットキーを確認する場合
- 新しいキーボードショートカットを設定する場合
- 競合するキーバインドを検出・解決する場合
- 他のエディタと同じショートカットに変更する場合
- 拡張機能が追加したキーバインドを確認・変更する場合

**主要な処理内容**：
1. すべてのキーバインド（デフォルト、ユーザー定義、拡張機能）の一覧表示
2. キーバインドの検索（コマンド名、キー入力、ソース別）
3. 「キーを記録」モードによる実際のキー入力での検索
4. キーバインドの追加・変更・削除
5. when条件（コンテキスト条件）の編集
6. 優先度順のソート表示
7. keybindings.jsonファイルへの永続化

**関連システム・外部連携**：
- KeybindingService: キーバインドの解決と実行
- KeybindingEditingService: keybindings.jsonへの書き込み
- ExtensionService: 拡張機能が提供するキーバインドの収集
- MenuService: コマンドパレットとの連携

**権限による制御**：特になし（すべてのユーザーが自由にキーバインドをカスタマイズ可能）

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 15 | キーバインド設定エディタ | 主画面 | キーボードショートカットの検索・編集 |
| 19 | プロファイルエディタ | 参照画面 | プロファイル別のキーバインド管理 |

## 機能種別

CRUD操作 / 設定管理

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| searchQuery | string | No | キーバインド検索クエリ | なし |
| recordKeys | boolean | No | キー記録モードの有効/無効 | なし |
| sortByPrecedence | boolean | No | 優先度順ソートの有効/無効 | なし |

### 入力データソース

- KeybindingService: 現在のキーバインド一覧
- keybindings.json: ユーザー定義のキーバインド
- 拡張機能のpackage.json: 拡張機能が定義するキーバインド

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| keybindingsEntries | IKeybindingItemEntry[] | 表示するキーバインド一覧 |
| searchResults | IKeybindingItemEntry[] | 検索結果 |

### 出力先

- キーバインドエディタUI（テーブル形式）
- keybindings.json（ユーザー設定ファイル）

## 処理フロー

### 処理シーケンス

```
1. ユーザーがキーバインドエディタを開く
   └─ Ctrl+K Ctrl+S または メニューから選択
2. KeybindingsEditorの初期化
   └─ KeybindingsEditorModelの構築
3. キーバインド一覧の取得
   └─ KeybindingServiceからすべてのキーバインドを取得
4. テーブル表示
   └─ WorkbenchTableによるレンダリング
5. ユーザーインタラクション
   └─ 検索、記録モード、ソート、編集
6. キーバインドの変更
   └─ DefineKeybindingWidgetでキー入力
7. 保存
   └─ KeybindingEditingServiceでkeybindings.jsonに書き込み
```

### フローチャート

```mermaid
flowchart TD
    A[キーバインドエディタを開く] --> B[KeybindingsEditorModel構築]
    B --> C[KeybindingServiceからキーバインド取得]
    C --> D[テーブル表示]
    D --> E{ユーザー操作}
    E -->|検索| F[フィルタリング]
    E -->|記録モード| G[キー入力で検索]
    E -->|ソート| H[優先度順に並び替え]
    E -->|編集| I[DefineKeybindingWidget表示]
    F --> D
    G --> F
    H --> D
    I --> J[キー入力]
    J --> K{when条件編集?}
    K -->|Yes| L[when式エディタ]
    K -->|No| M[KeybindingEditingService]
    L --> M
    M --> N[keybindings.json保存]
    N --> O[再レンダリング]
    O --> D
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-33-01 | 優先度解決 | ユーザー定義 > 拡張機能 > デフォルト | キーバインド競合時 |
| BR-33-02 | when条件必須 | 同一キーで複数コマンドがある場合、when条件で区別 | キーバインド競合時 |
| BR-33-03 | 検索デバウンス | 検索は300msのデバウンス後に実行 | 検索入力時 |
| BR-33-04 | 履歴保存デバウンス | 検索履歴は500msのデバウンス後に保存 | 検索実行時 |
| BR-33-05 | コマンド無効化 | キーに"-"プレフィックスで無効化 | キーバインド削除時 |

### 計算ロジック

キーバインド優先度の解決:
1. ユーザー定義（keybindings.json）
2. 拡張機能定義
3. デフォルト定義

同一優先度内では、後から登録されたものが優先される。

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

### 操作別データベース影響一覧

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| 読み込み | keybindings.json | SELECT | ユーザー定義キーバインドの読み込み |
| 追加 | keybindings.json | INSERT | 新しいキーバインドの追加 |
| 変更 | keybindings.json | UPDATE | 既存キーバインドの変更 |
| 削除 | keybindings.json | DELETE | キーバインドの無効化 |

### テーブル別操作詳細

#### keybindings.json

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| INSERT | key, command, when | ユーザー入力値 | JSON配列に追加 |
| UPDATE | key, when | 変更後の値 | 既存エントリを更新 |
| DELETE | command | "-command"形式 | プレフィックス"-"で無効化 |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | 無効なキー入力 | 認識できないキーコンビネーション | エラーメッセージを表示 |
| - | when式エラー | 構文的に不正なwhen式 | エラーメッセージを表示 |
| - | ファイル書き込みエラー | keybindings.jsonへの書き込み失敗 | 通知を表示 |

### リトライ仕様

ファイル書き込みエラー時はユーザーに通知

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

なし（ファイルベースの設定管理）

## パフォーマンス要件

- キーバインドエディタ初期表示: 300ms以内
- 検索応答: デバウンス300ms後に開始、結果表示200ms以内
- キーバインド保存: 100ms以内

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

- キーバインドのカスタマイズはローカル設定ファイルに保存
- 拡張機能からのキーバインド登録は拡張機能の信頼性に依存
- 危険なシステムショートカット（Ctrl+Alt+Del等）はオーバーライド不可

## 備考

- KeybindingsEditor.ID = 'workbench.editor.keybindings'
- 「キーを記録」モードで実際のキー押下によるショートカット検索が可能
- when条件はコンテキストキー式で記述

---

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

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

### 推奨読解順序

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

キーバインドエディタで扱うデータ構造を把握する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | preferences.ts | `src/vs/workbench/services/preferences/common/preferences.ts` | IKeybindingItemEntry、IKeybindingsEditorPaneのインターフェース |
| 1-2 | keybindingsEditorModel.ts | `src/vs/workbench/services/preferences/browser/keybindingsEditorModel.ts` | KeybindingsEditorModelクラス |

**読解のコツ**: IKeybindingItemEntryはキーバインドの各行を表し、command、keybinding、when、sourceの情報を持つ。

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

キーバインドエディタの起動から表示までの流れを追う。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | keybindingsEditor.ts | `src/vs/workbench/contrib/preferences/browser/keybindingsEditor.ts` | KeybindingsEditorクラスのコンストラクタとcreateEditor |
| 2-2 | preferences.contribution.ts | `src/vs/workbench/contrib/preferences/browser/preferences.contribution.ts` | エディタの登録 |

**主要処理フロー**:
1. **74-76行目**: KeybindingsEditor.ID = 'workbench.editor.keybindings'
2. **119-150行目**: コンストラクタ - 各種サービスの注入と初期化
3. **136行目**: delayedFiltering = new Delayer<void>(300) - 検索デバウンス設定
4. **145-149行目**: recordKeysAction、sortByPrecedenceActionの初期化

#### Step 3: 検索とフィルタリングを理解する

キーバインド検索の実装を追う。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | keybindingWidgets.ts | `src/vs/workbench/contrib/preferences/browser/keybindingWidgets.ts` | KeybindingsSearchWidget、DefineKeybindingWidgetクラス |

**主要処理フロー**:
- KeybindingsSearchWidget: 検索入力と「キーを記録」モードの実装
- DefineKeybindingWidget: キーバインド定義時のオーバーレイウィジェット

#### Step 4: キーバインド編集を理解する

キーバインドの追加・変更・削除の処理を追う。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | keybindingsEditor.ts | `src/vs/workbench/contrib/preferences/browser/keybindingsEditor.ts` | 編集関連メソッド |
| 4-2 | keybindingEditing.ts | `src/vs/workbench/services/keybinding/common/keybindingEditing.ts` | IKeybindingEditingService |

**主要処理フロー**:
- DefineKeybindingWidget表示 → キー入力 → when条件編集（オプション）→ keybindings.jsonへ保存

#### Step 5: 永続化を理解する

設定ファイルへの保存処理を追う。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 5-1 | keybindingEditing.ts | `src/vs/workbench/services/keybinding/common/keybindingEditing.ts` | editKeybindingメソッド |

**主要処理フロー**:
- keybindings.jsonの読み込み → 編集 → 書き込み

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

```
OpenKeybindingsEditorAction.run()
    │
    ├─ IPreferencesService.openGlobalKeybindingSettings()
    │      │
    │      └─ KeybindingsEditor.setInput()
    │             │
    │             ├─ KeybindingsEditorModel構築
    │             │      └─ IKeybindingService.getKeybindings()
    │             │
    │             └─ WorkbenchTable.splice()
    │                    └─ KeybindingItemRenderer.renderTemplate()
    │
    └─ [キーバインド変更時]
           ├─ DefineKeybindingWidget.define()
           └─ IKeybindingEditingService.editKeybinding()
                  └─ keybindings.json への書き込み
```

### データフロー図

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

KeybindingService      ───▶  KeybindingsEditor              ───▶  テーブルUI
(デフォルト/拡張機能)              │
                                  ├─ KeybindingsEditorModel
keybindings.json       ───▶       ├─ KeybindingsSearchWidget ───▶  検索結果
(ユーザー定義)                    │
                                  └─ DefineKeybindingWidget
ユーザー入力           ───▶                                   ───▶  keybindings.json
(検索、キー入力)                        │
                                       └─ KeybindingEditingService
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| keybindingsEditor.ts | `src/vs/workbench/contrib/preferences/browser/keybindingsEditor.ts` | ソース | キーバインドエディタのメインクラス |
| keybindingWidgets.ts | `src/vs/workbench/contrib/preferences/browser/keybindingWidgets.ts` | ソース | 検索ウィジェット、定義ウィジェット |
| keybindingsEditorModel.ts | `src/vs/workbench/services/preferences/browser/keybindingsEditorModel.ts` | ソース | キーバインドデータモデル |
| keybindingEditing.ts | `src/vs/workbench/services/keybinding/common/keybindingEditing.ts` | ソース | キーバインド編集サービス |
| keybindings.contribution.ts | `src/vs/workbench/contrib/keybindings/browser/keybindings.contribution.ts` | ソース | キーバインドトラブルシューティング機能 |
| preferences.contribution.ts | `src/vs/workbench/contrib/preferences/browser/preferences.contribution.ts` | ソース | エディタの登録とアクション |
| keybindingsEditorInput.ts | `src/vs/workbench/services/preferences/browser/keybindingsEditorInput.ts` | ソース | エディタ入力クラス |
| preferences.ts | `src/vs/workbench/contrib/preferences/common/preferences.ts` | ソース | コンテキストキー、コマンドID定義 |
