# 機能設計書 6-ハイパーリンク

## 概要

本ドキュメントは、GhosttyターミナルエミュレータにおけるOSC 8でエンコードされたハイパーリンクを認識し、クリック可能にする「ハイパーリンク」機能の設計を記述する。

### 本機能の処理概要

ハイパーリンク機能は、OSC 8エスケープシーケンスで定義されたハイパーリンクを解析し、端末画面上のテキストにリンク情報を関連付ける。ユーザーがリンク上でクリックまたはCmd/Ctrlクリックすることで、対応するURLをシステムのデフォルトブラウザで開く。

**業務上の目的・背景**：現代の開発ワークフローでは、エラーメッセージやログにURLが頻繁に含まれる。OSC 8対応により、コンパイラのエラーメッセージ、テスト結果のリンク、ドキュメントへのリンクなどを直接クリックして開くことができ、開発効率が向上する。

**機能の利用シーン**：
- コンパイラがソースファイルへのリンクを出力する場面
- テストフレームワークが失敗したテストへのリンクを出力する場面
- lsコマンドがファイルパスをリンクとして出力する場面（ls --hyperlink）
- GitHubのCLIがIssueやPRへのリンクを出力する場面

**主要な処理内容**：
1. OSC 8シーケンスの解析（URI、ID）
2. ハイパーリンクのページ内ストレージへの格納
3. セルへのハイパーリンクID関連付け
4. マウスホバー時のリンク検出とハイライト
5. クリック時のURL起動

**関連システム・外部連携**：
- OSCパーサーとの連携
- Screen/Cursorとの連携
- システムのデフォルトブラウザ

**権限による制御**：特になし。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 1 | メインターミナルウィンドウ | 主画面 | OSC 8エンコードされたハイパーリンクの認識とクリック |

## 機能種別

データ処理 / ユーザーインタラクション

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| uri | []const u8 | Yes | リンク先URI | 有効なURI |
| id | ?[]const u8 | No | リンクID（明示的/暗黙的） | - |

### 入力データソース

- OSC 8エスケープシーケンス

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| hyperlink_id | Id | セルに関連付けられたハイパーリンクID |
| uri | []const u8 | リンク先URI |

### 出力先

- Page内のハイパーリンクストレージ
- セルのハイパーリンクマッピング

## 処理フロー

### 処理シーケンス

```
1. OSC 8シーケンス受信
   └─ OSCパーサーで解析
   └─ URI、ID抽出

2. ハイパーリンク登録
   └─ PageEntry作成
   └─ ページのハイパーリンクセットに追加
   └─ IDを取得/生成

3. カーソルへのID設定
   └─ cursor.hyperlink_id設定
   └─ 以降の文字にリンク適用

4. セルへの関連付け
   └─ 文字書き込み時にhyperlink_idをセルに記録
   └─ Map経由でセル→ID参照

5. リンク終了
   └─ OSC 8;;（空URI）でリンク終了
   └─ cursor.hyperlink_id = 0

6. クリック処理
   └─ マウス位置のセルからhyperlink_id取得
   └─ IDからURI解決
   └─ システムブラウザで開く
```

### フローチャート

```mermaid
flowchart TD
    A[OSC 8シーケンス受信] --> B{URI空?}
    B -->|No| C[ハイパーリンク登録]
    B -->|Yes| D[リンク終了]

    C --> E[PageEntry作成]
    E --> F[hyperlink_id取得]
    F --> G[cursor.hyperlink_id設定]

    D --> H[cursor.hyperlink_id = 0]

    G --> I[文字書き込み]
    I --> J[セルにhyperlink_id関連付け]

    K[マウスクリック] --> L{セルにリンクあり?}
    L -->|Yes| M[URI取得]
    M --> N[ブラウザで開く]
    L -->|No| O[通常処理]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-001 | 暗黙的ID | IDが未指定の場合は自動生成 | OSC 8でID省略時 |
| BR-002 | 同一リンク共有 | 同一ID/URIは同一ハイパーリンクとして扱う | 複数セル同一リンク時 |
| BR-003 | ページ内スコープ | ハイパーリンクはページ内でスコープ化 | ページ管理 |

### 計算ロジック

- 暗黙的ID: `cursor.hyperlink_implicit_id` をインクリメント

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

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

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| E-001 | メモリ不足 | ハイパーリンク登録時 | エラーを伝播 |

### リトライ仕様

リトライ機構は使用しない。

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

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

## パフォーマンス要件

- ハイパーリンク検索: O(1)（ハッシュマップ使用）

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

- 悪意のあるURIに対する対策（ユーザー確認等）

## 備考

- OSC 8はiterm2由来の拡張

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | hyperlink.zig | `src/terminal/hyperlink.zig` | Id、Map、Hyperlink、PageEntry構造体 |

**読解のコツ**: `Id`はセル数を超えない整数型。`Map`はセルオフセットからIDへのマッピング。`PageEntry`はページ内に格納される実際のリンクデータ。

#### Step 2: 主要処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | hyperlink.zig | `src/terminal/hyperlink.zig` | PageEntry.dupe()、PageEntry.hash()、PageEntry.eql() |
| 2-2 | Screen.zig | `src/terminal/Screen.zig` | cursor.hyperlink_id、cursor.hyperlink |

**主要処理フロー**:
- **29-74行目**: Hyperlink構造体 - deinit()、dupe()
- **80-141行目**: PageEntry構造体 - dupe()、hash()、eql()
- **149-153行目（Screen.zig）**: cursor.hyperlink_id

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

```
OSC 8シーケンス
    |
    +-- osc/parsers/hyperlink.zig
    |      +-- URI/ID解析
    |
    +-- Screen/Terminal
    |      +-- cursor.hyperlink_id設定
    |      +-- cursor.hyperlink保存
    |
    +-- Page
           +-- hyperlink_set追加
           +-- hyperlink_map更新
```

### データフロー図

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

OSC 8シーケンス ────> OSCパーサー
                           |
                           v
                    URI/ID抽出 ────────> PageEntry
                           |
                           v
                    cursor設定 ─────────> cursor.hyperlink_id
                           |
                           v
                    文字書込み ─────────> セル + hyperlink_id
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| hyperlink.zig | `src/terminal/hyperlink.zig` | ソース | ハイパーリンクデータ構造 |
| osc/parsers/hyperlink.zig | `src/terminal/osc/parsers/hyperlink.zig` | ソース | OSC 8パーサー |
| Screen.zig | `src/terminal/Screen.zig` | ソース | cursor.hyperlink_id管理 |
| page.zig | `src/terminal/page.zig` | ソース | ページ内ストレージ |
