# 機能設計書 114-スニペットの保存

## 概要

コマンドラインスニペットを settings.json のアクションとして保存する機能（SaveSnippet アクション）の設計書である。

### 本機能の処理概要

本機能は、ユーザーが指定したコマンドライン文字列を sendInput アクションとして settings.json に永続保存する。保存されたスニペットはコマンドパレットやスニペットペインから呼び出して実行可能となる。

**業務上の目的・背景**：ユーザーが頻繁に使用するコマンドを手動で settings.json を編集せずに、Terminal のUI上から直接保存できる仕組みが必要である。これにより、コマンドの再利用性が向上し、settings.json の JSON 構文を理解していないユーザーでもスニペットの追加が可能になる。

**機能の利用シーン**：ターミナルで選択したテキストや入力されたコマンドラインをスニペットとして保存する場面で使用される。保存時に名前とオプションのキーバインドを指定できる。Feature_SaveSnippet フィーチャーフラグにより有効/無効が制御される。

**主要な処理内容**：
1. SaveSnippetArgs から Commandline、Name、KeyChord を取得する
2. Commandline が空の場合、アクティブターミナルの選択テキストを使用する
3. ActionMap の AddSendInputAction で sendInput アクションを追加する
4. settings.json に書き込む（WriteSettingsToDisk）
5. 保存成功時に ActionSaved トースト通知を表示する

**関連システム・外部連携**：ActionMap（アクション管理）と CascadiaSettings（設定管理）を通じて settings.json に書き込む。

**権限による制御**：Feature_SaveSnippet フィーチャーフラグが有効な場合のみ機能する（内部アクション）。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 9 | SnippetsPaneContent（スニペット管理） | 主画面 | スニペットをsettings.jsonに保存 |
| 1 | TerminalPage（メイン画面） | 結果表示画面 | ActionSaved/ActionSaveFailed トースト通知の表示 |

## 機能種別

データ永続化処理

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| Commandline | String | No（空の場合は選択テキストを使用） | 保存するコマンドライン文字列 | 最終的に空でないこと |
| Name | String | No | スニペットの表示名 | 任意の文字列 |
| KeyChord | String | No | スニペットに割り当てるキーバインド | KeyChordSerialization で変換可能な形式 |

### 入力データソース

- SaveSnippetArgs のパラメータ
- アクティブターミナルの選択テキスト（Commandline が空の場合のフォールバック）

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| settings.json への書き込み | ファイル | sendInput アクションとして追記 |
| ActionSaved イベント | イベント | 保存成功時の通知 |
| ActionSaveFailed イベント | イベント | 保存失敗時の通知 |

### 出力先

- settings.json ファイル
- UI上のトースト通知（TeachingTip）

## 処理フロー

### 処理シーケンス

```
1. _HandleSaveSnippet が呼び出される
   └─ Feature_SaveSnippet が有効か確認
2. SaveSnippetArgs から Commandline を取得
   └─ 空の場合はアクティブターミナルの選択テキストを使用
3. Commandline が空か確認
   └─ 空の場合は ActionSaveFailed("CommandLine is Required") で失敗
4. KeyChord が指定されている場合は KeyChordSerialization で変換
   └─ 文字列からキーバインドオブジェクトに変換
5. ActionMap.AddSendInputAction で sendInput アクションを追加
   └─ Name、Commandline、KeyChord を指定
6. WriteSettingsToDisk で settings.json に書き込み
   └─ 設定ファイルを更新
7. ActionSaved で成功通知
   └─ トースト通知を表示
```

### フローチャート

```mermaid
flowchart TD
    A[_HandleSaveSnippet 呼び出し] --> B{Feature_SaveSnippet 有効?}
    B -->|No| Z[return]
    B -->|Yes| C{SaveSnippetArgs 取得成功?}
    C -->|No| Z
    C -->|Yes| D[Commandline 取得]
    D --> E{Commandline が空?}
    E -->|Yes| F[選択テキストを使用]
    F --> G{最終的に空?}
    G -->|Yes| H[ActionSaveFailed]
    G -->|No| I[KeyChord 変換]
    E -->|No| I
    I --> J[AddSendInputAction]
    J --> K[WriteSettingsToDisk]
    K --> L{例外発生?}
    L -->|Yes| M[ActionSaveFailed]
    L -->|No| N[ActionSaved 通知]
    N --> O[Handled = true]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-114-01 | フィーチャーフラグ | Feature_SaveSnippet が有効な場合のみ動作する | 常時 |
| BR-114-02 | Commandline フォールバック | Commandline が空の場合、アクティブターミナルの選択テキストを使用する | Commandline 空の場合 |
| BR-114-03 | 必須チェック | 最終的に Commandline が空の場合はエラー | 保存実行時 |
| BR-114-04 | KeyChord オプション | KeyChord は任意。指定された場合のみキーバインドが設定される | KeyChord 指定時 |

### 計算ロジック

特になし。

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

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

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| 保存 | settings.json（ファイル） | INSERT | sendInput アクションとして新規追加 |

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

#### settings.json

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| INSERT | actions[].command | "sendInput" | アクション種別 |
| INSERT | actions[].input | Commandline の値 | 送信するテキスト |
| INSERT | actions[].name | Name の値 | 表示名（オプション） |
| INSERT | actions[].keys | KeyChord の値 | キーバインド（オプション） |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | 必須チェックエラー | Commandline が空でフォールバックもない場合 | ActionSaveFailed("CommandLine is Required") を発行 |
| - | KeyChord 変換エラー | KeyChord 文字列が不正な場合 | KeyChordSerialization::FromString が例外をスローする可能性あり |
| - | 設定書き込みエラー | settings.json への書き込みに失敗した場合 | hresult_error をキャッチし ActionSaveFailed でエラーメッセージを表示 |

### リトライ仕様

リトライは行わない。

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

settings.json の書き込みはアトミックではないが、CascadiaSettings の WriteSettingsToDisk がファイルI/Oを管理する。

## パフォーマンス要件

settings.json への書き込みは同期的に行われるが、通常は高速に完了する。

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

- 保存されるコマンドラインはユーザーが指定したものであり、信頼された入力
- settings.json はユーザーのアプリケーションデータ領域に保存される

## 備考

- Feature_SaveSnippet フィーチャーフラグは features.xml で定義される
- 内部アクション（Internal Action）として扱われる
- 保存成功時は ActionSavedToast（TeachingTip）でコマンドライン、名前、キーバインドが表示される

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | ActionArgs.h | `src/cascadia/TerminalSettingsModel/ActionArgs.h` | SaveSnippetArgs の定義。Commandline, Name, KeyChord プロパティを持つ |
| 1-2 | AllShortcutActions.h | `src/cascadia/TerminalSettingsModel/AllShortcutActions.h` | SaveSnippet アクションの登録 |

**読解のコツ**: SaveSnippetArgs は内部アクション向けの引数クラスで、ユーザーがUIから操作した際にプログラム的に生成される。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | AppActionHandlers.cpp | `src/cascadia/TerminalApp/AppActionHandlers.cpp` | **1281-1336行目**: _HandleSaveSnippet メソッド。フィーチャーフラグチェック、Commandline の取得とフォールバック、ActionMap への追加、settings.json への書き込みを行う |

**主要処理フロー**:
1. **1284行目**: Feature_SaveSnippet::IsEnabled() チェック
2. **1291行目**: SaveSnippetArgs への try_as キャスト
3. **1293-1305行目**: Commandline の取得。空の場合は選択テキストをフォールバック
4. **1307-1311行目**: Commandline が空の場合はエラー
5. **1315-1319行目**: KeyChord の変換
6. **1320行目**: ActionMap.AddSendInputAction でアクション追加
7. **1321行目**: WriteSettingsToDisk で設定ファイル書き込み
8. **1322行目**: ActionSaved で成功通知

#### Step 3: 成功・失敗通知の表示を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | AppActionHandlers.cpp | `src/cascadia/TerminalApp/AppActionHandlers.cpp` | **1338-1360行目**: ActionSaved メソッド。TeachingTip を使用したトースト通知の表示 |

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

```
TerminalPage::_HandleSaveSnippet (AppActionHandlers.cpp:1281)
    |
    +-- Feature_SaveSnippet::IsEnabled() (フィーチャーフラグ確認)
    |
    +-- SaveSnippetArgs::try_as (型キャスト)
    |
    +-- TermControl::SelectedText (選択テキスト取得、フォールバック時)
    |
    +-- KeyChordSerialization::FromString (キーバインド変換)
    |
    +-- ActionMap::AddSendInputAction (アクション追加)
    |
    +-- CascadiaSettings::WriteSettingsToDisk (設定ファイル書き込み)
    |
    +-- TerminalPage::ActionSaved (成功通知)
    |       |
    |       +-- Toast::Open (TeachingTip 表示)
    |
    +-- TerminalPage::ActionSaveFailed (失敗通知)
```

### データフロー図

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

Commandline (パラメータ)  ──>  AddSendInputAction ──────> settings.json
Name (パラメータ)         ──>  で sendInput アクション     (sendInput追加)
KeyChord (パラメータ)     ──>  を生成
                                    |
選択テキスト (フォールバック) ──>  WriteSettingsToDisk ──> ファイル書き込み
                                    |
                              ActionSaved/Failed ──────> トースト通知
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| AppActionHandlers.cpp | `src/cascadia/TerminalApp/AppActionHandlers.cpp` | ソース | _HandleSaveSnippet ハンドラと ActionSaved/ActionSaveFailed |
| ActionArgs.h | `src/cascadia/TerminalSettingsModel/ActionArgs.h` | ソース | SaveSnippetArgs の定義 |
| ActionMap.cpp | `src/cascadia/TerminalSettingsModel/ActionMap.cpp` | ソース | AddSendInputAction の実装 |
| features.xml | `src/features.xml` | 設定 | Feature_SaveSnippet フィーチャーフラグ定義 |
| AllShortcutActions.h | `src/cascadia/TerminalSettingsModel/AllShortcutActions.h` | ソース | SaveSnippet アクション登録 |
