# 機能設計書 85-言語固有設定

## 概要

本ドキュメントは、space-vimの言語固有設定機能（ftplugin）の設計について記述する。この機能は、プログラミング言語ごとに最適化されたVim設定を自動的に適用する仕組みを提供する。

### 本機能の処理概要

**業務上の目的・背景**：異なるプログラミング言語はそれぞれ異なるコーディング規約やベストプラクティスを持つ。Pythonは4スペースインデント、JavaScriptは2スペースインデント、Goはタブインデントなど、言語ごとに推奨される設定が異なる。本機能は、ファイルタイプを自動検出し、各言語に最適な設定（インデント、リンター、フォーマッター、キーバインド等）を自動的に適用することで、開発者が手動で設定を切り替える手間を省き、一貫したコーディング体験を提供する。

**機能の利用シーン**：Pythonファイルを開いた際の4スペースインデント自動設定、JavaScriptファイルを開いた際のESLintリンター設定、Goファイルを開いた際のgoimportsコマンドバインディング設定など、ファイルを開くだけで言語固有の最適設定が適用される。

**主要な処理内容**：
1. Vimのファイルタイプ検出機能によるファイルタイプ判定
2. 対応するftpluginファイルの自動読み込み
3. 言語固有のインデント設定、タブ設定の適用
4. 言語固有のALEリンター・フィクサー設定
5. 言語固有のキーバインディング設定
6. 遅延ロードによる言語固有プラグインのロード

**関連システム・外部連携**：各言語レイヤー（+lang/*）との連携。ALEリンターとの連携。各言語固有プラグイン（vim-go、python-mode等）との連携。

**権限による制御**：特になし。ftpluginはVimの標準機能として動作し、すべてのユーザーに適用される。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 20 | Help（ヘルプ画面） | 補助機能 | ftpluginによるヘルプ画面固有のキーバインド設定 |

## 機能種別

設定自動適用 / ファイルタイプ連動

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| &filetype | String | Yes | Vimが検出したファイルタイプ | vim/python/go/javascript等 |
| spacevim#load() | Function | No | レイヤーロード状態の確認 | true/false |
| g:spacevim.timer | Boolean | No | タイマー機能の有効状態 | true/false |

### 入力データソース

- Vimのファイルタイプ検出（拡張子、シェバン等から判定）
- space-vimのレイヤー設定状態

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| インデント設定 | Number | tabstop, shiftwidth, softtabstop等 |
| ALEリンター設定 | List | b:ale_linters, b:ale_fixers |
| キーバインド | Mapping | LocalLeaderベースの言語固有マッピング |

### 出力先

- バッファローカル設定（setlocal）
- バッファローカル変数（b:変数）
- バッファローカルキーマッピング

## 処理フロー

### 処理シーケンス

```
1. ファイルオープン
   └─ Vimがファイルタイプを検出
2. ftplugin検索
   └─ core/ftplugin/{filetype}.vimを検索
3. 重複実行チェック
   └─ b:did_spacevim_{ft}_ftpluginをチェック
4. レイヤー確認
   └─ spacevim#load()で対応レイヤーの有効性確認
5. 設定適用
   └─ setlocalでインデント等を設定
   └─ b:ale_linters/b:ale_fixersを設定
   └─ キーバインディングを設定
6. 遅延ロード
   └─ timer_startで言語固有プラグインをロード
```

### フローチャート

```mermaid
flowchart TD
    A[ファイルオープン] --> B[ファイルタイプ検出]
    B --> C{ftpluginファイル存在?}
    C -->|Yes| D{既に読み込み済み?}
    C -->|No| Z[処理終了]
    D -->|Yes| Z
    D -->|No| E{対応レイヤー有効?}
    E -->|No| Z
    E -->|Yes| F[インデント設定適用]
    F --> G[ALEリンター設定]
    G --> H[キーバインド設定]
    H --> I{timer機能有効?}
    I -->|Yes| J[遅延プラグインロード]
    I -->|No| Z
    J --> Z
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-85-1 | 重複読み込み防止 | b:did_spacevim_{ft}_ftplugin変数で重複を防止 | ftplugin読み込み時 |
| BR-85-2 | レイヤー依存 | spacevim#load()でレイヤーが無効なら処理スキップ | 言語レイヤー依存のftplugin |
| BR-85-3 | バッファローカル | 設定はバッファローカルに適用 | setlocal, b:変数使用 |
| BR-85-4 | タイマー遅延ロード | 重いプラグインはtimer_startで遅延ロード | g:spacevim.timer == true |

### 計算ロジック

特になし

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

本機能はデータベース操作を行わない。

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

該当なし

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | レイヤー無効 | 言語レイヤーが有効化されていない | ~/.spacevimで対応レイヤーを追加 |
| - | プラグイン未インストール | 言語固有プラグインがない | :PlugInstallを実行 |
| - | ALEエラー | リンターが見つからない | 対応リンターをシステムにインストール |

### リトライ仕様

リトライは不要。エラー発生時はユーザーが設定を修正して再度ファイルを開く。

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

該当なし（ファイルシステムやDBへの永続化を伴わない）

## パフォーマンス要件

- ftplugin読み込みは即座に完了すること
- 遅延ロードにより起動時間への影響を最小化

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

- 外部コマンド実行（リンター、フォーマッター）はユーザー設定に基づく
- 悪意のあるファイルタイプ設定のリスクは最小限

## 備考

- core/ftpluginディレクトリに25種類の言語固有設定ファイルが存在
- LocalLeader（デフォルト:カンマ）を使用した言語固有キーバインド
- 各ftpluginファイルは独立しており、必要な言語のみがロードされる

---

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

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

### 推奨読解順序

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

ftpluginはVimの標準機能。各言語のftpluginファイルはバッファローカル変数を使用。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | python.vim | `core/ftplugin/python.vim` | ftpluginの典型的な構造 |

**読解のコツ**: `b:did_spacevim_{ft}_ftplugin`は重複読み込み防止のためのガード変数。`setlocal`はバッファローカルな設定。

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

Vimがファイルタイプを検出すると、自動的に対応するftpluginが読み込まれる。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | python.vim | `core/ftplugin/python.vim` | Pythonファイルの設定 |
| 2-2 | javascript.vim | `core/ftplugin/javascript.vim` | JavaScriptファイルの設定 |
| 2-3 | go.vim | `core/ftplugin/go.vim` | Goファイルの設定 |

**主要処理フロー（python.vim）**:
1. **1-4行目**: ガード処理（重複・レイヤー確認）
2. **6行目**: `setlocal foldmethod=indent tabstop=4 textwidth=79` - インデント設定
3. **8-10行目**: タイマーによる遅延ロード
4. **12-17行目**: ALEリンター・フィクサー設定
5. **19-24行目**: キーバインド設定

#### Step 3: 各言語のftpluginを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | markdown.vim | `core/ftplugin/markdown.vim` | Markdown特有の設定（emoji補完含む） |
| 3-2 | rust.vim | `core/ftplugin/rust.vim` | Rust特有の設定 |
| 3-3 | help.vim | `core/ftplugin/help.vim` | ヘルプ画面特有の設定 |

**主要処理フロー**:
- **help.vim 1行目**: `nnoremap <buffer> q :helpclose<CR>` - qキーでヘルプを閉じる

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

```
ファイルオープン（例: test.py）
    │
    ├─ Vimファイルタイプ検出
    │      └─ filetype=python
    │
    └─ ftplugin読み込み
           └─ core/ftplugin/python.vim
                  ├─ ガード処理
                  │      └─ b:did_spacevim_py_ftplugin確認
                  │      └─ spacevim#load('python')確認
                  ├─ setlocal設定
                  │      └─ foldmethod=indent
                  │      └─ tabstop=4
                  │      └─ textwidth=79
                  ├─ ALE設定
                  │      └─ b:ale_linters = ['flake8']
                  │      └─ b:ale_fixers = [...]
                  ├─ キーバインド
                  │      └─ <LocalLeader>cc → run
                  │      └─ <F5> → run
                  └─ 遅延ロード
                         └─ timer_start(300, 'spacevim#defer#python')
                                └─ python-modeロード
```

### データフロー図

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

ファイル拡張子      Vimファイルタイプ検出           &filetype設定
(.py, .js等)  ──▶                          ──▶
                                                           │
&filetype       ftplugin読み込み                 バッファ設定
              ──▶  core/ftplugin/{ft}.vim  ──▶  &tabstop等
                                                  b:ale_linters
                                                  キーバインド
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| python.vim | `core/ftplugin/python.vim` | ソース | Python設定 |
| javascript.vim | `core/ftplugin/javascript.vim` | ソース | JavaScript設定 |
| go.vim | `core/ftplugin/go.vim` | ソース | Go設定 |
| rust.vim | `core/ftplugin/rust.vim` | ソース | Rust設定 |
| markdown.vim | `core/ftplugin/markdown.vim` | ソース | Markdown設定 |
| vim.vim | `core/ftplugin/vim.vim` | ソース | Vim script設定 |
| help.vim | `core/ftplugin/help.vim` | ソース | ヘルプ画面設定 |
| qf.vim | `core/ftplugin/qf.vim` | ソース | Quickfix設定 |
| html.vim | `core/ftplugin/html.vim` | ソース | HTML設定 |
| css.vim | `core/ftplugin/css.vim` | ソース | CSS設定 |
| java.vim | `core/ftplugin/java.vim` | ソース | Java設定 |
| cpp.vim | `core/ftplugin/cpp.vim` | ソース | C++設定 |
| c.vim | `core/ftplugin/c.vim` | ソース | C設定 |
| cs.vim | `core/ftplugin/cs.vim` | ソース | C#設定 |
| tex.vim | `core/ftplugin/tex.vim` | ソース | LaTeX設定 |
| php.vim | `core/ftplugin/php.vim` | ソース | PHP設定 |
| sh.vim | `core/ftplugin/sh.vim` | ソース | シェルスクリプト設定 |
| vue.vim | `core/ftplugin/vue.vim` | ソース | Vue設定 |
| dot.vim | `core/ftplugin/dot.vim` | ソース | Graphviz設定 |
| nerdtree.vim | `core/ftplugin/nerdtree.vim` | ソース | NERDTree設定 |
| fzf.vim | `core/ftplugin/fzf.vim` | ソース | FZF設定 |
| which_key.vim | `core/ftplugin/which_key.vim` | ソース | which-key設定 |
| fugitiveblame.vim | `core/ftplugin/fugitiveblame.vim` | ソース | Fugitive blame設定 |
| gitrebase.vim | `core/ftplugin/gitrebase.vim` | ソース | Git rebase設定 |
| netrw.vim | `core/ftplugin/netrw.vim` | ソース | netrw設定 |
