# 機能設計書 67-非同期実行

## 概要

本ドキュメントは、space-vimにおける非同期実行機能の設計について記載する。asyncrun.vimプラグインによるコマンドの非同期実行機能を提供する。

### 本機能の処理概要

非同期実行機能は、外部コマンド（コンパイル、テスト、スクリプト実行等）をバックグラウンドで非同期に実行し、結果をQuickfixウィンドウに表示する機能を提供する。Vim操作を中断することなく、時間のかかる処理を実行できる。

**業務上の目的・背景**：従来のVimでは、外部コマンド実行中はVimの操作がブロックされ、長時間のコンパイルやテスト実行時に待ち時間が発生していた。非同期実行機能により、コマンド実行中も編集作業を継続でき、生産性が大幅に向上する。実行結果はQuickfixウィンドウに表示され、エラー箇所への即座のジャンプも可能である。

**機能の利用シーン**：
- ソースコードのコンパイルを行いながら編集を続ける場合
- テストスイートを実行しながら他のファイルを編集する場合
- スクリプトを実行して結果を確認する場合
- lintやコード検査を実行する場合

**主要な処理内容**：
1. `:AsyncRun` コマンドで外部コマンドを非同期実行
2. `<F5>` キーで言語に応じたコンパイル＆実行
3. 実行結果をQuickfixウィンドウに自動表示
4. エラー箇所への自動ジャンプ（errorformat連携）

**関連システム・外部連携**：
- skywind3000/asyncrun.vim プラグイン
- Vimのjob機能（Vim 8+）またはNeovimのjobstart機能
- Quickfixウィンドウ
- space-vimの+programming/programmingレイヤーの一部として提供

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

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 17 | Quickfix/Location List | 遷移先機能 | asyncrun.vimによるコマンド実行結果の表示 |
| 18 | Terminal（ターミナル画面） | 主機能 | Vim内蔵ターミナルエミュレータによるコマンド実行 |

## 機能種別

外部コマンド実行 / 非同期処理

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| command | String | Yes | 実行するコマンド | 有効なシェルコマンド |
| g:asyncrun_open | Number | No | Quickfixウィンドウの自動オープン時の高さ | 正の整数 |

### 入力データソース

- コマンドライン入力（`:AsyncRun`）
- キーマッピング（`<F5>`）
- 編集中のファイル（`%`でファイル名参照）

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| コマンド出力 | String | 外部コマンドの標準出力・標準エラー |
| 終了コード | Number | コマンドの終了ステータス |

### 出力先

- Quickfixウィンドウ
- ステータスライン（実行状態表示）

## 処理フロー

### 処理シーケンス

```
1. AsyncRunコマンド実行
   └─ :AsyncRun {command} または <F5>

2. ファイルタイプ判定（F5の場合）
   └─ spacevim#plug#asyncrun#CompileAndRun()で言語別コマンド選択

3. 非同期ジョブ開始
   └─ job_start()またはjobstart()でバックグラウンド実行

4. Quickfixウィンドウオープン
   └─ g:asyncrun_open設定値の高さで自動オープン

5. 出力のリアルタイム表示
   └─ コマンド出力をQuickfixに追加

6. 完了処理
   └─ 終了コードを表示、エラー時はエラー箇所にジャンプ可能
```

### フローチャート

```mermaid
flowchart TD
    A[AsyncRunコマンド] --> B{F5?}
    B -->|Yes| C[ファイルタイプ判定]
    B -->|No| D[コマンド直接実行]
    C --> E{対応言語?}
    E -->|Yes| F[言語別コマンド選択]
    E -->|No| G[エラー表示]
    F --> H[ファイル保存]
    H --> D
    D --> I[非同期ジョブ開始]
    I --> J[Quickfixウィンドウオープン]
    J --> K[出力をQuickfixに追加]
    K --> L{コマンド終了?}
    L -->|No| K
    L -->|Yes| M[終了処理]
    M --> N[完了]
    G --> N
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-01 | Quickfix自動オープン | 実行開始時にウィンドウ高さの30%でQuickfixを表示 | AsyncRun実行時 |
| BR-02 | 言語別コマンド | F5押下時はファイルタイプに応じたコンパイル・実行コマンドを使用 | サポート言語のファイル編集時 |
| BR-03 | 自動保存 | F5実行時は自動的にファイルを保存 | F5キー押下時 |

### 計算ロジック

- Quickfixウィンドウ高さ: `float2nr(round(winheight('%') * 0.3))`

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

該当なし（外部コマンド実行のみ）

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | 未対応ファイルタイプ | F5で未対応言語のファイルを実行 | エラーメッセージ表示 |
| - | コマンド実行エラー | 外部コマンドが異常終了 | Quickfixにエラー出力を表示 |

### リトライ仕様

再度コマンドを実行することで再試行可能

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

該当なし（外部コマンド実行のみ）

## パフォーマンス要件

- 非同期実行のため、コマンド実行中もVim操作が可能
- 出力はリアルタイムでQuickfixに反映

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

外部コマンドを実行するため、信頼できるコマンドのみを実行すること

## 備考

- asyncrun.vimは遅延ロードで設定されている
- 対応言語: C, C++, Shell, Go, Ruby, Java, Rust, Python, Haskell
- vim-polyglotとの連携でerrorformatがリセットされる場合がある

---

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

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

### 推奨読解順序

#### Step 1: プラグイン登録を理解する

asyncrun.vimプラグインの登録を確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | packages.vim | `layers/+programming/programming/packages.vim` | asyncrun.vimの登録を確認 |

**読解のコツ**: asyncrun.vimは遅延ロード設定で、`:AsyncRun`または`:AsyncRun!`コマンド実行時にロードされる。

**主要処理フロー**:
1. **33行目**: `MP 'skywind3000/asyncrun.vim', { 'on': ['AsyncRun!', 'AsyncRun'] }` - 遅延ロード登録

#### Step 2: 設定とキーマッピングを理解する

asyncrunの設定とF5キーマッピングを確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | config.vim | `layers/+programming/programming/config.vim` | asyncrun設定とキーマッピングを確認 |

**主要処理フロー**:
- **75-78行目**: asyncrun.vim設定セクション
- **76行目**: `let g:asyncrun_open = float2nr(round(winheight('%') * 0.3))` - Quickfixウィンドウ高さ設定
- **77行目**: `nnoremap <F5> :call spacevim#plug#asyncrun#CompileAndRun()<CR>` - F5キーマッピング

#### Step 3: 言語別コンパイル関数を理解する

F5実行時の言語別処理を確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | asyncrun.vim | `core/autoload/spacevim/plug/asyncrun.vim` | CompileAndRun関数の実装を確認 |

**主要処理フロー**:
- **1行目**: `function! spacevim#plug#asyncrun#CompileAndRun()` - 関数定義開始
- **2-12行目**: `let l:cmd = {...}` - 言語別コマンド辞書
  - **3行目**: `'c': "gcc % -o %<; time ./%<"` - Cコンパイル＆実行
  - **4行目**: `'sh': "time bash %"` - シェルスクリプト実行
  - **5行目**: `'go': "go run %"` - Go実行
  - **6行目**: `'cpp': "g++ -std=c++11 % -o %<; time ./%<"` - C++コンパイル＆実行
  - **7行目**: `'ruby': "time ruby %"` - Ruby実行
  - **8行目**: `'java': "javac %; time java %<"` - Javaコンパイル＆実行
  - **9行目**: `'rust': "rustc % -o %<; time ./%<"` - Rustコンパイル＆実行
  - **10行目**: `'python': "time python %"` - Python実行
  - **11行目**: `'haskell': "ghc % -o %< && ./%<"` - Haskellコンパイル＆実行
- **13行目**: `let l:ft = &filetype` - 現在のファイルタイプ取得
- **14-19行目**: 対応言語判定と実行
  - **15行目**: `exec 'w'` - ファイル保存
  - **16行目**: `exec "AsyncRun! ".l:cmd[l:ft]` - 非同期実行
  - **18行目**: エラー表示（未対応ファイルタイプ）

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

```
<F5> キー押下
    │
    └─ spacevim#plug#asyncrun#CompileAndRun()
           │
           ├─ ファイルタイプ判定
           │      └─ &filetype
           │
           ├─ 言語別コマンド選択
           │      └─ l:cmd 辞書参照
           │
           ├─ ファイル保存
           │      └─ :w
           │
           └─ 非同期実行
                  │
                  └─ :AsyncRun! {command}
                         │
                         └─ asyncrun.vim
                                │
                                ├─ job_start() / jobstart()
                                │
                                └─ Quickfixウィンドウ更新
```

### データフロー図

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

<F5> キー               spacevim#plug#asyncrun           Quickfixウィンドウ
     +            ───▶   #CompileAndRun()    ───▶        実行結果表示
バッファ内容                   │
                              ▼
                         ファイルタイプ判定
                              │
                              ▼
                         言語別コマンド選択
                              │
                              ▼
                         :AsyncRun! 実行
                              │
                              ▼
                         バックグラウンド
                         ジョブ実行
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| packages.vim | `layers/+programming/programming/packages.vim` | 設定 | プラグイン登録 |
| config.vim | `layers/+programming/programming/config.vim` | 設定 | 設定とキーマッピング |
| asyncrun.vim | `core/autoload/spacevim/plug/asyncrun.vim` | ソース | 言語別コンパイル関数 |
| LAYERS.md | `layers/LAYERS.md` | ドキュメント | レイヤー一覧 |
| asyncrun.vim | 外部プラグイン（skywind3000/asyncrun.vim） | プラグイン | 非同期実行機能本体 |
