# 機能設計書 47-open_command

## 概要

本ドキュメントは、Oh My Zshのopen_command機能について、その設計と実装の詳細を記載したものである。この機能は、macOS、Linux、Windows/WSL、Cygwinなど異なるプラットフォームで統一的にファイルやURLを開くためのクロスプラットフォーム対応ラッパー関数を提供する。

### 本機能の処理概要

この機能は、実行中のOSを検出し、プラットフォームに応じた適切な「開く」コマンド（open、xdg-open、cygstart、cmd.exe start等）を選択して実行する。これにより、異なる環境間で同じopen_commandという関数名で統一的にファイルやURLを開くことができる。

**業務上の目的・背景**：異なるOSではファイルやURLを開くためのコマンドが異なる（macOSはopen、LinuxはXdg-open、WindowsはstartなD）。シェルスクリプトやOh My Zshのプラグインがこれらの環境間で動作するためには、プラットフォームに依存しない抽象化が必要である。本機能により、開発者やユーザーはプラットフォームを意識せずにファイルやURLを開くことができる。

**機能の利用シーン**：
- URLをデフォルトブラウザで開きたい場面
- ファイルを関連付けられたアプリケーションで開きたい場面
- ディレクトリをファイルマネージャで開きたい場面
- Oh My Zshの他の機能（omz shopなど）からの呼び出し

**主要な処理内容**：
1. $OSTYPE変数からプラットフォームを検出
2. プラットフォームに応じた開くコマンドを選択
3. WSL環境の場合は追加のパス変換処理を実行
4. $BROWSER環境変数が設定されている場合はそちらを優先（URL時）
5. 選択したコマンドで引数を開く

**関連システム・外部連携**：
- macOS: open コマンド
- Linux: xdg-open コマンド（または $BROWSER）
- Windows/WSL: cmd.exe /c start
- Cygwin: cygstart コマンド
- MSYS: start コマンド

**権限による制御**：特になし。全ユーザーが利用可能。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 16 | omz shop | 補助機能 | Oh My Zshグッズショップをブラウザで開く際に使用 |

## 機能種別

外部連携処理 / プラットフォーム抽象化 / ユーティリティ関数

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| $1 | 文字列 | Yes | 開くファイルパス、URL、またはディレクトリ | なし |
| $@ | 文字列... | No | 追加の引数（そのまま渡される） | なし |

### 入力データソース

- コマンドライン引数
- $OSTYPE環境変数
- $BROWSER環境変数（オプション）

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| 戻り値 | 整数 | 0: 成功、1: エラー |
| エラーメッセージ | 文字列 | プラットフォーム未対応時のメッセージ |

### 出力先

- ファイルは関連アプリケーションで開かれる
- URLはデフォルトブラウザで開かれる
- エラー時は標準出力にメッセージ

## 処理フロー

### 処理シーケンス

```
1. プラットフォーム検出
   └─ $OSTYPE変数からOS種別を判定

2. 開くコマンドの選択
   └─ プラットフォームに応じたコマンドを設定

3. WSL固有処理（該当時）
   └─ パスをWindows形式に変換
   └─ URL内の特殊文字をエスケープ

4. $BROWSERの確認（URL時）
   └─ 設定されていれば$BROWSERを使用

5. コマンド実行
   └─ 選択したコマンドで引数を開く
```

### フローチャート

```mermaid
flowchart TD
    A[open_command実行] --> B{OSタイプ判定}
    B -->|darwin| C[open_cmd='open']
    B -->|cygwin| D[open_cmd='cygstart']
    B -->|linux| E{WSL?}
    E -->|Yes| F[open_cmd='cmd.exe /c start'<br>パス変換]
    E -->|No| G[open_cmd='nohup xdg-open']
    B -->|msys| H[open_cmd='start']
    B -->|その他| I[エラー出力<br>return 1]
    C --> J{$BROWSERが設定<br>かつURL?}
    D --> J
    F --> J
    G --> J
    H --> J
    J -->|Yes| K[$BROWSERで開く]
    J -->|No| L[open_cmdで開く]
    K --> M[終了]
    L --> M
    I --> M
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-47-1 | プラットフォーム自動検出 | $OSTYPEによりOSを自動判定 | 常時 |
| BR-47-2 | WSLパス変換 | WSL環境ではwslpathでパスをWindows形式に変換 | WSL環境時 |
| BR-47-3 | WSL特殊文字エスケープ | WSL環境でURLの特殊文字（&\|()<>^）をエスケープ | WSL環境でURL時 |
| BR-47-4 | $BROWSER優先 | URLを開く際、$BROWSERが設定されていればそちらを使用 | URL && $BROWSER設定時 |
| BR-47-5 | バックグラウンド実行 | コマンドは&>/dev/nullでバックグラウンド実行 | 常時 |

### 計算ロジック

特になし

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

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

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| - | - | - | 本機能はデータベースを使用しない |

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

該当なし

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| 1 | プラットフォーム未対応 | 未サポートのOS | エラーメッセージを表示してreturn 1 |
| 1 | パス変換失敗 | WSLでwslpathが失敗 | return 1 |

### リトライ仕様

該当なし

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

該当なし

## パフォーマンス要件

- 即座にコマンドを実行
- バックグラウンドで実行するため、呼び出し元はブロックされない

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

- WSL環境ではURL内の特殊文字がエスケープされる（シェルインジェクション対策）
- 任意のファイルやURLが開かれるため、信頼できる入力のみを渡すこと

## 備考

- nohup xdg-openを使用することで、ターミナルを閉じてもアプリケーションが終了しない
- SSHセッション内では$BROWSERがローカルブラウザに設定されている場合がある

---

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

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

### 推奨読解順序

#### Step 1: 関数定義とプラットフォーム検出を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | functions.zsh | `lib/functions.zsh` | 16-44行目のopen_command関数定義 |

**主要処理フロー**:
1. **17行目**: `local open_cmd` - ローカル変数宣言
2. **20-34行目**: case文によるプラットフォーム検出
   - **21行目**: darwin（macOS）→ `open`
   - **22行目**: cygwin → `cygstart`
   - **23-29行目**: linux → WSL判定を含む
   - **30行目**: msys → `start ""`
   - **31-33行目**: その他 → エラー

**読解のコツ**:
- `case "$OSTYPE" in ... esac`でOS判定
- `*)`は「その他のパターン」を意味する
- WSL判定は`uname -r`の出力に"icrosoft"が含まれるかで判断

#### Step 2: WSL固有処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | functions.zsh | `lib/functions.zsh` | 23-29行目のWSL処理 |

**主要処理フロー**:
- **23行目**: `[[ "$(uname -r)" != *icrosoft* ]]` - WSL判定
- **24行目**: WSLの場合`open_cmd='cmd.exe /c start ""'`
- **25行目**: `[[ -e "$1" ]] && { 1="$(wslpath -w "${1:a}")" || return 1 }` - ファイルパス変換
- **26-28行目**: URL内の特殊文字をエスケープ

**読解のコツ**:
- `${1:a}`は絶対パスに展開
- `wslpath -w`はLinuxパスをWindowsパスに変換
- `sed -E 's/([&|()<>^])/^\1/g'`で特殊文字を`^`でエスケープ

#### Step 3: $BROWSER処理と実行を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | functions.zsh | `lib/functions.zsh` | 36-44行目 |

**主要処理フロー**:
- **38-41行目**: $BROWSERが設定されていてURLの場合は$BROWSERを使用
- **43行目**: `${=open_cmd} "$@" &>/dev/null` - コマンド実行
  - `${=...}`は変数をワード分割して展開
  - `&>/dev/null`で出力を破棄

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

```
open_command関数
    │
    ├─ case $OSTYPE（プラットフォーム検出）
    │      │
    │      ├─ darwin → open
    │      ├─ cygwin → cygstart
    │      ├─ linux → xdg-open または cmd.exe
    │      │      └─ WSL判定 (uname -r)
    │      │             └─ wslpath（パス変換）
    │      └─ msys → start
    │
    ├─ $BROWSER確認
    │      └─ URLの場合は$BROWSERを使用
    │
    └─ コマンド実行
           └─ &>/dev/null でバックグラウンド
```

### データフロー図

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

ファイルパス/URL            open_command                  アプリ起動
     │                            │                            │
     ▼                            ▼                            ▼
$1（引数）───────────▶  プラットフォーム検出 ───▶  適切なコマンド選択
                              │
                              ▼
$OSTYPE ───────────────▶  case分岐 ───────────▶  open/xdg-open/
                              │                  cygstart/cmd.exe
                              ▼
$BROWSER ─────────────▶  URL判定 ─────────────▶  ブラウザ起動
                              │
                              ▼
                        バックグラウンド実行
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| functions.zsh | `lib/functions.zsh` | ソース | open_command関数の定義（16-44行目） |
| cli.zsh | `lib/cli.zsh` | ソース | omz shopからの呼び出し |
