# 機能設計書 50-設定編集

## 概要

本ドキュメントは、Ghosttyターミナルエミュレータにおける「設定編集」機能の設計を記述する。この機能は、CLIコマンド`+edit-config`を通じて、Ghosttyの設定ファイルをユーザーの好みのエディタで開く。

### 本機能の処理概要

**業務上の目的・背景**：Ghosttyの設定ファイルを編集する際、ユーザーはファイルパスを覚えておく必要がなく、単純なコマンドで即座にエディタを起動できることが望ましい。設定編集機能は、`$VISUAL`または`$EDITOR`環境変数で指定されたエディタを使用して、デフォルトの設定ファイルを開くことで、設定変更のワークフローを簡素化する。

**機能の利用シーン**：
- Ghosttyの設定を変更したい時
- 設定ファイルの場所を覚えていない時
- 素早く設定ファイルにアクセスしたい時

**主要な処理内容**：
1. `$VISUAL`または`$EDITOR`環境変数の取得
2. デフォルト設定ファイルパスの解決
3. エディタへのexec実行
4. エラー時のユーザーフレンドリーなメッセージ表示

**関連システム・外部連携**：
- 環境変数（$VISUAL, $EDITOR）
- ファイルシステム（設定ファイル）
- 外部エディタ（vim, nano, code等）

**権限による制御**：特になし。すべてのユーザーが設定編集を実行可能。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 10 | 設定画面 | 遷移先機能 | 設定ファイルをエディタで開く案内 |

## 機能種別

外部連携 / CLI実行

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| なし | - | - | コマンドライン引数なし | - |

### 入力データソース

- コマンドライン: `ghostty +edit-config`
- 環境変数: `$VISUAL`（優先）または`$EDITOR`
- 設定ファイルパス: XDG仕様に基づく

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| なし | - | 正常時はエディタにexecするため出力なし |
| エラーメッセージ | []const u8 | 異常時のエラー詳細 |

### 出力先

- 正常時: エディタへのexec（プロセス置換）
- エラー時: 標準エラー出力（stderr）

## 処理フロー

### 処理シーケンス

```
1. コマンドライン引数のパース
   └─ Options構造体への値設定（現在は空）

2. 設定の初期読み込み
   └─ Config.load()でデフォルト設定ファイルを作成

3. デフォルト設定ファイルパスの取得
   └─ configpkg.preferredDefaultFilePath()

4. プラットフォーム確認
   └─ Windowsの場合はエラー（未サポート）

5. エディタの取得
   └─ $VISUALを優先的に確認
   └─ $EDITORをフォールバックとして確認

6. exec実行
   └─ execvpeZでエディタを起動
   └─ 現在のプロセスをエディタで置換

7. エラー処理
   └─ exec失敗時はエラーメッセージを表示
```

### フローチャート

```mermaid
flowchart TD
    A[+edit-config実行] --> B[引数パース]
    B --> C[Config.load]
    C --> D[preferredDefaultFilePath取得]
    D --> E{Windows?}
    E -->|Yes| F[エラー: 未サポート]
    E -->|No| G{$VISUAL設定あり?}
    G -->|Yes| H[editor = $VISUAL]
    G -->|No| I{$EDITOR設定あり?}
    I -->|Yes| J[editor = $EDITOR]
    I -->|No| K[エラー: エディタ未設定]
    H --> L[execvpeZ実行]
    J --> L
    L --> M{exec成功?}
    M -->|Yes| N[プロセス置換完了]
    M -->|No| O[エラー: exec失敗]
    F --> P[終了コード1]
    K --> P
    O --> P
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-50-01 | VISUAL優先 | $VISUALが$EDITORより優先される | 両方設定されている場合 |
| BR-50-02 | Windows未サポート | Windowsではexecが使用できないためエラー | builtin.os.tag == .windows |
| BR-50-03 | 空値チェック | 環境変数が空文字列の場合は未設定扱い | 環境変数が空の場合 |
| BR-50-04 | パス表示 | エディタ未設定時は設定ファイルパスを表示 | $VISUAL/$EDITOR未設定時 |

### 計算ロジック

特になし。

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

本機能はデータベースを使用しない。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| 1 | Windows未サポート | Windowsプラットフォームで実行 | ファイルパスを表示して手動編集を促す |
| 1 | エディタ未設定 | $VISUALも$EDITORも未設定または空 | ファイルパスを表示して環境変数設定を促す |
| 1 | exec失敗 | エディタの起動に失敗 | エラーコードとエディタパスを表示 |

### リトライ仕様

リトライなし。ユーザーが環境変数を設定後に再実行する必要がある。

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

トランザクションは使用しない。

## パフォーマンス要件

- 瞬時に実行完了すること（execによるプロセス置換）

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

- ユーザー指定のエディタを実行するため、信頼できるコマンドのみを$VISUAL/$EDITORに設定すべき
- 設定ファイルはユーザー権限で読み書き可能

## 備考

- execはプロセスを置換するため、成功時は戻り値がない
- Config.load()は設定ファイルが存在しない場合にデフォルト設定を作成する
- OSC8形式のハイパーリンクでファイルパスを表示

---

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

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

### 推奨読解順序

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

Options構造体と環境変数取得の仕組みを理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | edit_config.zig | `src/cli/edit_config.zig` | Options構造体の定義（11-21行目） |
| 1-2 | main.zig | `src/os/main.zig` | getenv関数 |

**読解のコツ**: Optionsは空の構造体であり、このコマンドには引数がない。

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

run関数とrunInner関数の処理フローを理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | edit_config.zig | `src/cli/edit_config.zig` | run関数（23-67行目） |
| 2-2 | edit_config.zig | `src/cli/edit_config.zig` | runInner関数（69-168行目） |

**主要処理フロー**:
1. **43-67行目**: run関数の引数パースとrunInner呼び出し
2. **69-77行目**: Config.load呼び出しとパス取得
3. **79-91行目**: Windowsチェック
4. **93-109行目**: 環境変数取得（$VISUAL優先、$EDITORフォールバック）
5. **111-137行目**: エディタ未設定時のエラー処理
6. **143-154行目**: execvpeZ実行

#### Step 3: exec実行

execvpeZによるプロセス置換を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | edit_config.zig | `src/cli/edit_config.zig` | exec部分（143-168行目） |

**主要処理フロー**:
- **143行目**: comptime assert for libc
- **145-148行目**: 文字列のnull終端化
- **149-154行目**: execvpeZ実行
- **156-167行目**: exec失敗時のエラー処理

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

```
ghostty +edit-config
    │
    └─ cli.edit_config.run
           │
           ├─ args.parse (Optionsへ)
           │
           └─ runInner
                  │
                  ├─ Config.load
                  │
                  ├─ configpkg.preferredDefaultFilePath
                  │
                  ├─ internal_os.getenv
                  │      ├─ $VISUAL
                  │      └─ $EDITOR
                  │
                  └─ std.posix.execvpeZ
                         └─ [プロセス置換]
```

### データフロー図

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

コマンドライン ──────▶ 引数パース
     │                     │
     │                     ▼
環境変数 ────────────▶ エディタ取得
 ├─ $VISUAL               │
 └─ $EDITOR               │
     │                     ▼
設定ファイルパス ────▶ execvpeZ ─────────────▶ エディタ起動
     │                     │
     │                     ▼
     └──────────────▶ [失敗時] stderr
                          ├─ エラーメッセージ
                          └─ ファイルパス表示
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| edit_config.zig | `src/cli/edit_config.zig` | ソース | 設定編集コマンドの実装 |
| Config.zig | `src/config/Config.zig` | ソース | 設定の読み込みとデフォルト作成 |
| path.zig | `src/config/path.zig` | ソース | 設定ファイルパスの解決 |
| main.zig | `src/os/main.zig` | ソース | 環境変数取得 |
| args.zig | `src/cli/args.zig` | ソース | コマンドライン引数パーサー |
