# 画面設計書 7-F# Interactive ツールウィンドウ

## 概要

本ドキュメントは、Visual Studio 内で F# Interactive（FSI）セッションを実行するための「F# Interactive ツールウィンドウ」の設計仕様を記述するものです。

### 本画面の処理概要

この画面は、F# コードを対話的に実行するための REPL（Read-Eval-Print Loop）環境を提供するツールウィンドウです。エディタからコードを送信して実行したり、直接コードを入力して即座に結果を確認したりできます。

**業務上の目的・背景**：F# 開発者がコードを素早く試行・検証するために不可欠なツールです。コンパイル・ビルドのサイクルを経ずに、コードスニペットを即座に実行して結果を確認できるため、プロトタイピング、デバッグ、学習などの場面で広く活用されます。.NET Core/.NET 環境での F# スクリプト実行にも対応しています。

**画面へのアクセス方法**：Visual Studio のメニューバーから「表示」→「その他のウィンドウ」→「F# Interactive」を選択するか、エディタ上で F# コードを選択して Alt+Enter を押すことでアクセスできます。

**主要な操作・処理内容**：
1. F# コードの直接入力と実行
2. エディタからの選択コード送信（Alt+Enter）
3. エディタからの行送信
4. セッションの中断と再起動
5. デバッガのアタッチ・デタッチ
6. 履歴ナビゲーション（Up/Down キー）
7. ウィンドウのクリア

**画面遷移**：
- 遷移元：Visual Studio メニュー、エディタコンテキストメニュー
- 遷移先画面：なし（独立したツールウィンドウ）

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

## 関連機能

| 機能No | 機能名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 11 | F# Interactive（fsi） | 主機能 | F# コードの対話的実行、REPL 機能を提供するツールウィンドウ |
| 72 | FSI統合 | 主機能 | エディタから F# Interactive へコードを送信・実行（選択コード送信、行送信、デバッグ実行） |
| 12 | スクリプト実行 | 補助機能 | F# スクリプトファイル（.fsx）の実行 |
| 13 | 動的アセンブリ生成 | 補助機能 | F# Interactive 上でコードを動的にコンパイル・実行 |

## 画面種別

ツールウィンドウ（REPL インターフェース）

## URL/ルーティング

Visual Studio 内部ツールウィンドウのため、URLは存在しません。
- GUIDパス: `{Guids.guidFsiSessionToolWindow}`
- メニューパス: `表示` > `その他のウィンドウ` > `F# Interactive`

## 入出力項目

| 項目名 | 項目種別 | データ型 | 必須 | 説明 |
|--------|----------|----------|------|------|
| コード入力 | 入力（テキスト） | string | - | ユーザーが入力する F# コード |
| 実行結果 | 出力（テキスト） | string | - | F# Interactive から出力される結果やエラー |
| プロンプト | 出力（テキスト） | string | - | ">" プロンプト表示 |

## 表示項目

| 項目名 | 表示形式 | 説明 |
|--------|----------|------|
| テキストビュー | IVsTextView | コード入力と出力結果を表示するメインエリア |
| プロンプト | テキスト | ">" で表示される入力プロンプト |
| ReadOnly領域 | マーカー | 過去の出力結果（編集不可） |
| 入力領域 | テキスト | 現在入力中のコード（編集可能） |

## イベント仕様

### 1-RETURN（Enter キー）

ユーザーが Enter キーを押下すると、入力領域のコードが F# Interactive セッションに送信されて実行されます。セッションが未起動の場合は自動的に起動されます。

### 2-UP/DOWN（履歴ナビゲーション）

入力領域にカーソルがある状態で Up/Down キーを押すと、過去に入力したコードの履歴を遡って表示できます。

### 3-コード送信（Alt+Enter）

エディタで選択したコードを F# Interactive に送信して実行します。`sendSelectionToFSI` メソッドで処理されます。

### 4-行送信

現在のカーソル行を F# Interactive に送信して実行します。行全体が選択されて送信されます。

### 5-デバッグ実行

選択したコードをデバッグモードで実行します。デバッガが自動的にアタッチされ、ブレークポイントで停止できます。

### 6-セッション中断（Ctrl+Break）

実行中のコードを中断します。`sessions.Interrupt()` メソッドで処理されます。

### 7-セッション再起動

F# Interactive セッションを終了して新しいセッションを開始します。出力がクリアされます。

### 8-ペインクリア

出力領域をクリアしますが、セッションは維持されます。

## データベース更新仕様

本画面はデータベースを使用しません。

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

該当なし

## メッセージ仕様

| メッセージID | 種別 | メッセージ内容 | 表示条件 |
|--------------|------|----------------|----------|
| sessionTerminationDetected | 情報 | セッション終了の検出メッセージ | セッション終了時 |
| sessionInitialMessageNetCore | 情報 | .NET Core セッション開始メッセージ | .NET Core 使用時 |
| couldNotObtainFSharpLS | エラー | F# 言語サービス取得失敗 | 初期化失敗時 |
| sessionIsNotDebugFriendly | 警告 | デバッグ最適化されていない設定の警告 | デバッグ実行時 |

## 例外処理

| 例外状況 | 処理内容 |
|----------|----------|
| 言語サービス取得失敗 | エラーメッセージを表示してツールウィンドウの初期化を中断 |
| セッション終了 | 終了メッセージを表示し、次の入力で自動再起動 |
| デバッグ設定警告 | 警告ダイアログを表示し、ユーザーの確認を求める |

## 備考

- 本画面は F# で実装されたツールウィンドウです（`fsiSessionToolWindow.fs`）
- `FsiToolWindow` クラスは `ToolWindowPane` を継承し、`IVsWindowPane`、`IVsUIElementPane`、`IOleCommandTarget` インターフェースを実装
- テキストバッファとテキストビューは Visual Studio の標準コンポーネント（`VsTextBufferClass`、`VsTextViewClass`）を使用
- 入力履歴は `HistoryBuffer` クラスで管理
- セッション管理は `FsiSessions` クラスで行われ、stdout/stderr の出力をバッファリングして表示
- .NET Core/.NET 環境では、セッションは自動起動せず、最初の入力またはコード送信時に起動されます
- フォント・カラー設定は専用のカテゴリ GUID（`fsiFontsAndColorsCategory`）で管理

---

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

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

### 推奨読解順序

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

まず、セッション管理やイベント処理に使用されるデータ構造を理解することが重要です。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | fsiSessionToolWindow.fs | `vsintegration/src/FSharp.VS.FSI/fsiSessionToolWindow.fs` | `FsiDebuggerState` 型（69-72行目）- デバッガ状態の3つの値 |
| 1-2 | fsiSessionToolWindow.fs | `vsintegration/src/FSharp.VS.FSI/fsiSessionToolWindow.fs` | `FsiEditorSendAction` 型（74-77行目）- エディタからの送信アクション種別 |
| 1-3 | fsiSessionToolWindow.fs | `vsintegration/src/FSharp.VS.FSI/fsiSessionToolWindow.fs` | `Locals` モジュール（36-65行目）- ユーティリティ関数とプロンプト処理 |

**読解のコツ**: F# の判別共用体型を使って状態管理を行っています。

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

ツールウィンドウのクラス定義と初期化処理を理解します。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | fsiSessionToolWindow.fs | `vsintegration/src/FSharp.VS.FSI/fsiSessionToolWindow.fs` | `FsiToolWindow` クラス（79-897行目）- ツールウィンドウ本体 |

**主要処理フロー**:
1. **79-80行目**: `[<Guid(Guids.guidFsiSessionToolWindow)>]` 属性と `ToolWindowPane` 継承
2. **83-126行目**: 初期化処理（サービスプロバイダ取得、テキストバッファ/ビュー作成）
3. **194-196行目**: セッションと履歴バッファの初期化
4. **680-739行目**: `OnToolWindowCreated()` でコマンドハンドラ登録

#### Step 3: コマンドハンドラを理解する

各ユーザー操作に対応するコマンドハンドラを理解します。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | fsiSessionToolWindow.fs | `vsintegration/src/FSharp.VS.FSI/fsiSessionToolWindow.fs` | コマンドハンドラ群（357-620行目） |

**主要処理フロー**:
- **358-364行目**: `onHome` - Home キー処理
- **378行目**: `onNoAction` - 無操作（ReadOnly 領域保護）
- **382-399行目**: `onClearPane` - ペインクリア
- **409-410行目**: `onInterrupt` - セッション中断
- **412-425行目**: `onRestart` - セッション再起動
- **428-436行目**: `onReturn` - Enter キー処理
- **563-600行目**: `sendSelectionToFSI` - コード送信処理
- **603-619行目**: `onHistory` - 履歴ナビゲーション

#### Step 4: セッション管理を理解する

F# Interactive セッションのライフサイクル管理を理解します。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | fsiSessionToolWindow.fs | `vsintegration/src/FSharp.VS.FSI/fsiSessionToolWindow.fs` | セッション関連処理（194-247行目） |

**主要処理フロー**:
- **195行目**: `sessions = Session.FsiSessions()` - セッションインスタンス
- **198-208行目**: `writeText` - 出力テキストの書き込み
- **211-225行目**: stdout/stderr イベントのマージとバッファリング
- **231-240行目**: `recordTermination` - セッション終了検出

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

```
FsiToolWindow
    │
    ├─ 初期化
    │      ├─ ServiceProvider 取得
    │      ├─ VsTextBufferClass / VsTextViewClass 作成
    │      ├─ FsiLanguageService 取得
    │      ├─ FsiSessions 初期化
    │      └─ HistoryBuffer 初期化
    │
    ├─ コマンドハンドラ登録 (OnToolWindowCreated)
    │      ├─ RETURN → onReturn
    │      ├─ UP/DOWN → onHistory
    │      ├─ HOME → onHome
    │      ├─ ClearPane → onClearPane
    │      ├─ Interrupt → onInterrupt
    │      ├─ Restart → onRestart
    │      ├─ SendSelection → onMLSendSelection
    │      ├─ SendLine → onMLSendLine
    │      └─ DebugSelection → onMLDebugSelection
    │
    └─ 出力処理
           ├─ sessions.Output イベント → StdOut
           ├─ sessions.Error イベント → StdErr
           └─ writeTextAndScroll → TextBufferStream
```

### データフロー図

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

エディタ選択 ───▶ sendSelectionToFSI ───▶ FsiSessions.SendInput
                        │
                        ▼
直接入力 ─────▶ executeUserInput ───────▶ FsiSessions.SendInput
                        │
                        ▼
                 FsiSessions (fsi.exe) ───▶ stdout/stderr イベント
                        │
                        ▼
                 responseBufferE ─────────▶ writeTextAndScroll
                        │
                        ▼
                 TextBufferStream ────────▶ テキストビュー表示
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| fsiSessionToolWindow.fs | `vsintegration/src/FSharp.VS.FSI/fsiSessionToolWindow.fs` | ソース | ツールウィンドウ本体 |
| Session.fs | `vsintegration/src/FSharp.VS.FSI/Session.fs` | ソース | F# Interactive セッション管理 |
| HistoryBuffer.fs | `vsintegration/src/FSharp.VS.FSI/HistoryBuffer.fs` | ソース | 入力履歴管理 |
| FsiLanguageService.fs | `vsintegration/src/FSharp.VS.FSI/FsiLanguageService.fs` | ソース | 言語サービス統合 |
| Guids.fs | `vsintegration/src/FSharp.VS.FSI/Guids.fs` | ソース | GUID 定数定義 |
