# 通知設計書 9-spacevim#github#CommitRef

## 概要

本ドキュメントは、space-vimにおけるGitHub コミットURL通知関数 `spacevim#github#CommitRef` の通知仕様を定義するものである。

### 本通知の処理概要

`spacevim#github#CommitRef` は、現在編集中のファイルの該当行に対応するGitHub上のコミットURLを生成し、クリップボードにコピーしてユーザーに通知する関数である。コードレビューや問題報告時に、特定の行を参照するためのURLを簡単に共有できる。

**業務上の目的・背景**：開発チームでコードをレビューする際や、バグ報告時に「このファイルのこの行」を正確に指し示す必要がある。しかし、GitHubのURLを手動で構築するのは面倒であり、間違いも起こりやすい。この関数により、現在のカーソル位置に対応するGitHub URLをワンクリックで生成でき、Slack、メール、issueなどで即座に共有できる。これにより、コミュニケーションの効率が大幅に向上する。

**通知の送信タイミング**：ユーザーがこの関数を呼び出した際に、URLの生成とクリップボードへのコピーが完了した直後に通知が送信される。

**通知の受信者**：Vimエディタを操作しているユーザー本人がメッセージの受信者となる。メッセージはVimのコマンドライン領域に表示される。

**通知内容の概要**：生成されたGitHub URLが警告色（黄色）で表示され、「copied to your clipboard」というメッセージが続けて表示される。

**期待されるアクション**：ユーザーはクリップボードの内容をSlack、GitHub issue、メールなどに貼り付けて、コードの特定行を他の開発者と共有する。

## 通知種別

アプリ内通知（Vimコマンドライン表示）

## 送信仕様

### 基本情報

| 項目 | 内容 |
|-----|------|
| 送信方式 | 同期 |
| 優先度 | 低 |
| リトライ | 無し |

### 送信先決定ロジック

現在Vimエディタを操作しているユーザーのコマンドライン領域に直接表示される。特別な送信先決定ロジックは存在しない。

## 通知テンプレート

### アプリ内通知の場合

| 項目 | 内容 |
|-----|------|
| 表示位置 | Vimコマンドライン領域 |
| ハイライト | WarningMsg（URL）、Normal（メッセージ本文） |
| プレフィックス | なし |
| 形式 | テキスト |

### 本文テンプレート

```
{GitHub URL} copied to your clipboard
```

URL形式：
```
https://github.com/{owner}/{repo}/blob/{commit_hash}/{relative_path}#L{line_number}
```

### 添付ファイル

該当なし

## テンプレート変数

| 変数名 | 説明 | データ取得元 | 必須 |
|--------|------|-------------|-----|
| GitHub URL | 生成されたGitHub コミットURL | プロジェクト情報から構築 | Yes |
| owner/repo | リポジトリのオーナーとリポジトリ名 | git remote -v から抽出 | Yes |
| commit_hash | 現在のコミットハッシュ | git rev-parse HEAD | Yes |
| relative_path | リポジトリルートからの相対パス | abs_path - root_dir | Yes |
| line_number | 現在のカーソル行番号 | line('.') | Yes |

## 送信トリガー・条件

### トリガー一覧

| トリガー種別 | トリガーイベント | 送信条件 | 説明 |
|------------|----------------|---------|------|
| 関数呼び出し | spacevim#github#CommitRef()の呼び出し | Gitリポジトリ内かつorigin remoteが存在する場合 | ユーザーが手動で関数を呼び出し |

### 送信抑止条件

| 条件 | 説明 |
|-----|------|
| Gitリポジトリ外 | root_dirが空の場合、処理を中断（エラー通知なし） |
| パス不一致 | abs_pathがroot_dirで始まらない場合、エラー通知（No.10） |
| origin remoteなし | origin remoteが見つからない場合、エラー通知（No.10） |

## 処理フロー

### 送信フロー

```mermaid
flowchart TD
    A[CommitRef呼び出し] --> B[プロジェクトルート取得]
    B --> C{root_dirが空?}
    C -->|Yes| D[終了（通知なし）]
    C -->|No| E[abs_path取得]
    E --> F{abs_pathがroot_dirで始まる?}
    F -->|No| G[echoerr パス不一致エラー]
    F -->|Yes| H[相対パス計算]
    H --> I[git remote -v 実行]
    I --> J{origin remoteあり?}
    J -->|No| K[echoerr origin不在エラー]
    J -->|Yes| L[remote URL抽出・整形]
    L --> M[git rev-parse HEAD 実行]
    M --> N[コミットURL構築]
    N --> O[クリップボードにコピー]
    O --> P[URL表示 + コピー完了通知]
    P --> Q[終了]
    G --> Q
    K --> Q
    D --> Q
```

## データベース参照・更新仕様

### 参照テーブル一覧

該当なし（Gitコマンドを使用）

### 更新テーブル一覧

| テーブル名 | 操作 | 概要 |
|-----------|------|------|
| @+ | UPDATE | クリップボードレジスタにURLを書き込み |

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 対処方法 |
|----------|---------|---------|
| Gitリポジトリ外 | プロジェクトルートが見つからない | 処理を中断（エラー通知なし） |
| パス不一致 | ファイルパスがリポジトリ内にない | echoerr でエラーメッセージ表示 |
| origin remoteなし | origin remoteが設定されていない | echoerr でエラーメッセージ表示 |

### リトライ仕様

| 項目 | 内容 |
|-----|------|
| リトライ回数 | なし |
| リトライ間隔 | なし |
| リトライ対象エラー | なし |

## 配信設定

### レート制限

| 項目 | 内容 |
|-----|------|
| 1分あたり上限 | 制限なし |
| 1日あたり上限 | 制限なし |

### 配信時間帯

制限なし（Vimが起動している間は常に表示可能）

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

- 生成されるURLにはリポジトリのコミットハッシュが含まれる
- プライベートリポジトリの場合、URLを共有する相手がアクセス権を持っている必要がある
- GitHub Personal Access Tokenを含むURLは自動的に除去される（セキュリティ対策）
- クリップボードは他のアプリケーションからもアクセス可能

## 備考

- `clap#path#find_project_root` 関数を使用してプロジェクトルートを検出する（vim-clapプラグインに依存）
- `https://ghp_TOKEN@github.com` 形式のURLからトークン部分を自動除去する
- `.git` で終わるURLは自動的にサフィックスを除去する
- URLにはハッシュフラグメント `#L{行番号}` が付与され、GitHub上で該当行がハイライトされる

---

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

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

### 推奨読解順序

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

本関数は複数の文字列変数を組み合わせてURLを構築する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | github.vim | `core/autoload/spacevim/github.vim` | 使用される主要な変数（root_dir, abs_path, relative_path, remote_url, rev, commit_url）を確認 |

**読解のコツ**: この関数はGitコマンドの出力を解析してURLを構築するため、systemlist()の使用箇所に注目する。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | github.vim | `core/autoload/spacevim/github.vim` | spacevim#github#CommitRef関数の定義（1-52行目） |

**主要処理フロー**:
1. **1行目**: `function! spacevim#github#CommitRef() abort` - 関数定義
2. **2行目**: `let root_dir = clap#path#find_project_root(bufnr(''))` - プロジェクトルート取得
3. **5-7行目**: root_dirが空なら早期リターン
4. **9行目**: `let abs_path = expand('%:p')` - 現在のファイルの絶対パス取得
5. **11-16行目**: abs_pathがroot_dirで始まるか検証、相対パス計算
6. **20行目**: `let output = systemlist('git remote -v')` - リモート情報取得
7. **21行目**: `let origin = filter(output, 'v:val =~ "^origin"')` - originフィルタ
8. **22-25行目**: origin不在の場合エラー
9. **28-37行目**: remote URL整形（.git除去、トークン除去）
10. **39行目**: `let rev = systemlist('git rev-parse HEAD')[0]` - コミットハッシュ取得
11. **41行目**: `let commit_url = printf(...)` - URL構築
12. **43行目**: `let @+ = commit_url` - クリップボードにコピー
13. **45-51行目**: 成功メッセージ表示

#### Step 3: URL整形処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | github.vim | `core/autoload/spacevim/github.vim` | remote URL整形（28-37行目） |

**主要処理フロー**:
- **28行目**: `let remote_url = split(origin[0])[1]` - originの2番目の要素（URL）を取得
- **30-32行目**: `.git$` サフィックスを除去
- **35-37行目**: `https://ghp_...@github.com` 形式のトークンを除去

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

```
spacevim#github#CommitRef()
    │
    ├─ clap#path#find_project_root(bufnr(''))
    │      └─ プロジェクトルートディレクトリを検出
    │
    ├─ expand('%:p')
    │      └─ 現在のファイルの絶対パスを取得
    │
    ├─ systemlist('git remote -v')
    │      └─ Gitリモート情報を取得
    │
    ├─ filter(..., 'v:val =~ "^origin"')
    │      └─ origin remoteをフィルタ
    │
    ├─ split(origin[0])[1]
    │      └─ remote URLを抽出
    │
    ├─ substitute() x 2
    │      ├─ .git サフィックス除去
    │      └─ トークン除去
    │
    ├─ systemlist('git rev-parse HEAD')
    │      └─ 現在のコミットハッシュを取得
    │
    ├─ printf('%s/blob/%s%s#L%d', ...)
    │      └─ GitHub URLを構築
    │
    ├─ let @+ = commit_url
    │      └─ クリップボードにコピー
    │
    └─ echohl + echon
           └─ 成功メッセージ表示
```

### データフロー図

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

bufnr('') ───────▶ find_project_root() ───▶ root_dir
                                                │
expand('%:p') ─────────────────────────────▶ abs_path
                                                │
                                                ▼
                                        相対パス計算
                                                │
'git remote -v' ─────────▶ systemlist() ───▶ origin remote URL
                                                │
                                                ▼
                                        URL整形（.git除去、トークン除去）
                                                │
'git rev-parse HEAD' ────▶ systemlist() ───▶ commit_hash
                                                │
line('.') ──────────────────────────────────▶ line_number
                                                │
                                                ▼
                                        printf() でURL構築
                                                │
                          ┌─────────────────────┴─────────────────────┐
                          │                                           │
                          ▼                                           ▼
                   @+ レジスタ                                成功メッセージ
                （クリップボード）                           （コマンドライン）
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| github.vim | `core/autoload/spacevim/github.vim` | ソース | CommitRef関数の実装 |
