# 機能設計書 9-omz plugin enable

## 概要

本ドキュメントは、Oh My Zsh（以下OMZ）のプラグイン有効化機能「omz plugin enable」コマンドに関する機能設計書である。指定プラグインを.zshrcに追加して有効化し、シェルをリロードする処理について記述する。

### 本機能の処理概要

本機能は、ユーザーが指定したプラグインを.zshrcのplugins配列に追加し、シェルをリロードすることで有効化を即座に反映する。

**業務上の目的・背景**：OMZには350以上のプラグインが用意されており、ユーザーが必要なプラグインを簡単に有効化できる仕組みが必要である。手動で.zshrcを編集する代わりに、コマンド一つでプラグインを追加できる利便性を提供。

**機能の利用シーン**：
- 新しいプラグインを有効化する時
- 一度無効化したプラグインを再度有効化する時
- 新規インストール時に必要なプラグインを設定する時

**主要な処理内容**：
1. 指定プラグインが既に有効化されていないか確認
2. AWKスクリプトで.zshrcを編集
3. 新しい.zshrcの構文チェック
4. バックアップ作成と置換
5. シェルのリロード

**関連システム・外部連携**：特になし

**権限による制御**：.zshrcファイルへの書き込み権限が必要。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 5 | omz plugin enable | 主機能 | 指定プラグインを.zshrcに追加して有効化し、シェルをリロード |

## 機能種別

CLI / 設定変更

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| plugin | 文字列 | Yes | 有効化するプラグイン名（複数指定可） | plugins配列に存在しないこと |

### 入力データソース

- コマンドライン引数
- 現在の$plugins配列
- ~/.zshrcファイル

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| stdout | テキスト | 成功/警告メッセージ |
| stderr | テキスト | エラーメッセージ |
| 戻り値 | 整数 | 0: 成功、1: エラー |

### 出力先

- 標準出力/標準エラー出力
- ~/.zshrc（編集）
- ~/.zshrc.bck（バックアップ）

## 処理フロー

### 処理シーケンス

```
1. 引数チェック
   └─ プラグイン名が指定されているか確認
   └─ 未指定の場合はUsage表示してreturn 1

2. プラグイン重複確認
   └─ 各プラグインが$plugins配列に存在しないか確認
   └─ 既に存在する場合は警告を出力して次へ
   └─ 新規プラグインをadd_plugins配列に追加

3. 有効化対象確認
   └─ add_plugins配列が空の場合はreturn 1

4. AWKスクリプト生成
   └─ 単一行/複数行のplugins=()形式に対応
   └─ プラグインを追加するロジックを生成

5. .zshrc編集
   └─ AWKスクリプトで新しい.zshrcを生成
   └─ .zshrc.bckにバックアップ
   └─ 新しい.zshrcで置換

6. 構文チェック
   └─ zsh -nで構文エラーをチェック
   └─ エラー時はバックアップから復元

7. シェルリロード
   └─ インタラクティブセッションの場合のみ
   └─ _omz::reloadを呼び出し
```

### フローチャート

```mermaid
flowchart TD
    A[omz plugin enable実行] --> B{引数あり?}
    B -->|No| C[Usage表示・return 1]
    B -->|Yes| D[プラグインループ開始]
    D --> E{plugins配列に存在?}
    E -->|Yes| F[警告出力・次へ]
    E -->|No| G[add_pluginsに追加]
    F --> H{次のプラグインあり?}
    G --> H
    H -->|Yes| D
    H -->|No| I{add_plugins空?}
    I -->|Yes| J[return 1]
    I -->|No| K[AWKスクリプト生成]
    K --> L[AWKで.zshrc編集]
    L --> M{編集成功?}
    M -->|No| N[エラー出力・return]
    M -->|Yes| O[.zshrc.bckにバックアップ]
    O --> P[新.zshrcで置換]
    P --> Q{構文チェックOK?}
    Q -->|No| R[バックアップ復元・return 1]
    Q -->|Yes| S[成功メッセージ]
    S --> T{インタラクティブ?}
    T -->|Yes| U[_omz::reload]
    T -->|No| V[完了]
    U --> V
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-01 | 引数必須 | プラグイン名の指定が必須 | 常時 |
| BR-02 | 未有効プラグインのみ | $plugins配列に存在しないプラグインのみ追加可能 | 常時 |
| BR-03 | 複数プラグイン対応 | 複数のプラグインを一度に有効化可能 | 常時 |
| BR-04 | バックアップ作成 | 編集前に.zshrc.bckを作成 | 常時 |
| BR-05 | 構文チェック | 編集後にzsh -nで構文チェック | 常時 |
| BR-06 | ロールバック | 構文エラー時はバックアップから復元 | エラー時 |
| BR-07 | 自動リロード | インタラクティブセッションでのみリロード | 成功時 |
| BR-08 | インデント保持 | 複数行形式の場合、既存のインデントを継承 | 複数行形式時 |

### 計算ロジック

**プラグイン存在確認**:
```zsh
[[ ${plugins[(Ie)$plugin]} -ne 0 ]]
```
- `(Ie)`: 正確なマッチで配列インデックスを取得
- 0以外の場合は既に存在

**インデント検出**:
```awk
for (i = 1; i <= length($0); i++) {
  char=substr($0, i, 1)
  if (char == " " || char == "\t") {
    indent = indent char
  } else {
    break
  }
}
```

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

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

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| 1 | 引数なしエラー | プラグイン名未指定 | Usage表示 |
| 1 | プラグイン既存警告 | 指定プラグインが既に有効 | 警告出力して継続 |
| 1 | 有効化対象なし | 新規プラグインが1つもない | return 1 |
| 1 | 編集エラー | AWK処理失敗 | エラー出力 |
| 1 | 構文エラー | 新.zshrcに構文エラー | バックアップ復元 |

### リトライ仕様

リトライは行わない。構文エラー時は自動的にバックアップから復元。

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

本機能はトランザクションを使用しないが、バックアップ・復元機構でデータ整合性を保護。

## パフォーマンス要件

特になし。ファイル編集処理のため即時完了。

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

- .zshrc編集前に必ずバックアップを作成
- 編集後に構文チェックを行い、不正な内容を防止
- エラー時は自動的に元の状態に復元

## 備考

- 複数プラグインを同時に有効化可能
- plugins配列の形式（単一行/複数行）に両対応
- 複数行形式の場合、既存プラグインと同じインデントで追加

---

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

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

### 推奨読解順序

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

プラグイン有効化で扱う変数を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | cli.zsh | `lib/cli.zsh` | add_plugins配列、awk_script変数 |

**読解のコツ**:
- `$plugins`は現在有効なプラグインの配列
- `add_plugins`は有効化対象のプラグインリスト

#### Step 2: _omz::plugin::enable関数を理解する

プラグイン有効化のメイン処理を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | cli.zsh | `lib/cli.zsh` | 324-416行目の_omz::plugin::enable関数 |

**主要処理フロー**:
- **325-328行目**: 引数チェック
- **331-338行目**: プラグイン重複確認ループ
- **341-343行目**: 有効化対象確認
- **346-389行目**: AWKスクリプト
- **391-395行目**: AWK実行と.zshrc置換
- **398-402行目**: エラーチェック
- **405-409行目**: 構文チェックとロールバック
- **412行目**: 成功メッセージ
- **415行目**: シェルリロード

#### Step 3: AWKスクリプトを理解する

plugins配列への追加ロジックを理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | cli.zsh | `lib/cli.zsh` | 346-389行目のAWKスクリプト |

**主要処理フロー**:
- **348-352行目**: 単一行形式の処理（`)`を` plugin1 plugin2)`に置換）
- **355-360行目**: 複数行形式の開始検出、インデント初期化
- **363-370行目**: 閉じ括弧検出時のプラグイン追加
- **376-386行目**: インデント検出（既存行から継承）

#### Step 4: インデント継承を理解する

複数行形式でのインデント保持ロジックを理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | cli.zsh | `lib/cli.zsh` | 376-386行目のインデント検出 |

**主要処理フロー**:
- 各行の先頭からスペース/タブを検出
- 最初の非空白文字で検出を終了
- 検出したインデントを新規プラグイン行に適用

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

```
omz plugin enable <plugin...>
    │
    └─ _omz::plugin::enable()
           │
           ├─ プラグイン重複確認
           │      └─ ${plugins[(Ie)$plugin]}
           │
           ├─ AWKスクリプト生成
           │      └─ 単一行: sub(/\)/, " new_plugins&")
           │      └─ 複数行: print indent p[i] (各プラグイン)
           │
           ├─ awk "$awk_script" "$zshrc"
           │      └─ > "$zdot/.zshrc.new"
           │
           ├─ cp -f "$zshrc" "$zdot/.zshrc.bck"
           │
           ├─ mv -f "$zdot/.zshrc.new" "$zshrc"
           │
           ├─ zsh -n "$zdot/.zshrc" (構文チェック)
           │      └─ 失敗時: mv -f "$zdot/.zshrc.bck" "$zshrc"
           │
           ├─ _omz::log info "plugins enabled: ..."
           │
           └─ _omz::reload (インタラクティブ時)
```

### データフロー図

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

plugin名(引数)        ───▶ 重複確認
                              │
$plugins配列          ───▶ │
                              ▼
~/.zshrc              ───▶ AWKスクリプト実行
                              │
                              ├─▶ ~/.zshrc.bck (バックアップ)
                              │
                              └─▶ ~/.zshrc.new
                                      │
                                      ├─▶ 新プラグイン追加
                                      │
                                      └─▶ ~/.zshrc (置換)
                                              │
                                              └─▶ zsh -n (構文チェック)
                                                      │
                                                      └─▶ _omz::reload
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| cli.zsh | `lib/cli.zsh` | ソース | _omz::plugin::enable関数 |
| .zshrc | `~/.zshrc` | 設定 | 編集対象 |
| .zshrc.bck | `~/.zshrc.bck` | バックアップ | 復元用 |
| .zshrc.new | `~/.zshrc.new` | 一時ファイル | AWK出力先 |
