# 機能設計書 110-コマンドライン引数処理

## 概要

本ドキュメントは、wt.exe のコマンドライン引数解析機能について記述する。CLI11ライブラリを使用して、new-tab、split-pane、focus-tab、move-focus、move-pane、swap-pane、focus-pane、x-save等のサブコマンドを解析し、対応するActionAndArgsオブジェクトに変換する。セミコロン(;)区切りによる複数コマンドの連結にも対応する。

### 本機能の処理概要

**業務上の目的・背景**：Windows Terminalはコマンドラインから起動時の構成を指定できる。複数タブやペインの同時起動、ウィンドウサイズの指定、既存ウィンドウへのコマンド送信など、スクリプトやショートカットからの自動化を可能にする。

**機能の利用シーン**：ユーザーが `wt new-tab -p "PowerShell" ; split-pane -V -p "Ubuntu"` のようにコマンドラインを指定してTerminalを起動する。コマンドパレットのコマンドラインモードや、ExecuteCommandlineアクションからも利用される。

**主要な処理内容**：
1. コマンドライン引数のセミコロン区切り分割（BuildCommands）
2. 各サブコマンドの解析とActionAndArgs生成（ParseCommand）
3. グローバルフラグの処理（-M最大化、-F全画面、-f フォーカス、--pos位置、--size サイズ、-wウィンドウ指定）
4. サブコマンドのないコマンドラインは暗黙のnew-tabとして処理
5. ヘルプ/バージョン表示の処理

**関連システム・外部連携**：CLI11パーサーライブラリ、TerminalSettingsModel（ActionAndArgs, NewTabArgs等）。

**権限による制御**：特段の権限制御はない。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | コマンドライン（外部） | 主機能 | wt.exeの起動引数 |
| 10 | CommandPalette（コマンドパレット） | 補助機能 | コマンドラインモードでWTコマンドを実行 |

## 機能種別

コマンドライン解析 / アクション変換

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| args | array_view<hstring> | Yes | コマンドライン引数配列 | 空でないこと |
| -v, --version | フラグ | No | バージョン表示 | - |
| -M, --maximized | フラグ | No | 最大化起動 | -Fと排他 |
| -F, --fullscreen | フラグ | No | 全画面起動 | -Mと排他 |
| -f, --focus | フラグ | No | フォーカスモード起動 | -Fと排他 |
| --pos | string | No | ウィンドウ位置 | - |
| --size | string | No | ウィンドウサイズ | - |
| -w, --window | string | No | ターゲットウィンドウ | - |
| -s, --saved | int | No | 保存レイアウトインデックス | - |

### サブコマンド

| サブコマンド | 短縮形 | 説明 | 主要オプション |
|-------------|--------|------|---------------|
| new-tab | nt | 新しいタブ | -p プロファイル, -d ディレクトリ, --title タイトル |
| split-pane | sp | ペイン分割 | -H 水平, -V 垂直, -D 複製, -s サイズ |
| focus-tab | ft | タブフォーカス | -t インデックス, -n 次, -p 前 |
| move-focus | mf | フォーカス移動 | direction (left/right/up/down等) |
| move-pane | mp | ペイン移動 | -t タブインデックス |
| swap-pane | - | ペイン入替 | direction |
| focus-pane | fp | ペインフォーカス | -t ターゲット |
| x-save | - | スニペット保存 | --name, --keychord, command |

### 入力データソース

- プロセス起動時のコマンドライン引数
- ExecuteCommandlineアクションからの文字列
- コマンドパレットのコマンドラインモード

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| _startupActions | vector<ActionAndArgs> | 生成されたアクションのリスト |
| _exitMessage | string | 終了メッセージ（ヘルプ/バージョン/エラー） |
| _shouldExitEarly | bool | 早期終了フラグ |
| _launchMode | optional<LaunchMode> | 起動モード |
| _position | optional<LaunchPosition> | ウィンドウ位置 |
| _size | optional<til::size> | ウィンドウサイズ |

### 出力先

- Terminal起動処理へのアクションリスト提供
- エラー/ヘルプメッセージの表示

## 処理フロー

### 処理シーケンス

```
1. コマンドライン分割 (BuildCommands)
   |-- 引数配列を走査
   |-- セミコロン";"で区切り（エスケープ"\;"は無視）
   |-- 各セグメントにwt.exeプレースホルダーを先頭に付加
   +-- Commandlineオブジェクトのvectorを返却

2. 各コマンドの解析 (ParseCommand)
   |-- _currentCommandlineポインタをセット
   |-- 引数を逆順にしてCLI11に渡す（CLI11の仕様）
   |-- _resetStateToDefaultで状態リセット
   |-- "/?" or "-?" なら CallForHelp 例外
   |-- _app.parse() で prefix command を解析
   |-- サブコマンドが未指定なら暗黙の new-tab として解析
   |-- 未解析の引数があれば ExtrasError
   +-- コールバックでActionAndArgsを_startupActionsに追加

3. アクション生成（各サブコマンドのコールバック）
   |-- new-tab: NewTabArgs → ShortcutAction::NewTab
   |-- split-pane: SplitPaneArgs → ShortcutAction::SplitPane
   |-- focus-tab: SwitchToTabArgs / NextTabArgs / PrevTabArgs
   |-- move-focus: MoveFocusArgs → ShortcutAction::MoveFocus
   |-- move-pane: MovePaneArgs → ShortcutAction::MovePane
   |-- swap-pane: SwapPaneArgs → ShortcutAction::SwapPane
   |-- focus-pane: FocusPaneArgs → ShortcutAction::FocusPane
   +-- x-save: SaveSnippetArgs → ShortcutAction::SaveSnippet
```

### フローチャート

```mermaid
flowchart TD
    A[wt.exe引数] --> B[BuildCommands]
    B --> C[セミコロンで分割]
    C --> D[各Commandline]
    D --> E[ParseCommand]
    E --> F{ヘルプ/バージョン?}
    F -->|Yes| G[_exitMessage設定]
    F -->|No| H[_app.parse]
    H --> I{サブコマンドあり?}
    I -->|No| J[暗黙のnew-tab解析]
    I -->|Yes| K[サブコマンドコールバック]
    J --> K
    K --> L[ActionAndArgs生成]
    L --> M[_startupActionsに追加]
    G --> N[_shouldExitEarly = true]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-110-1 | セミコロン区切り | ";"で複数コマンドを連結。"\;"はエスケープ | BuildCommands時 |
| BR-110-2 | 暗黙のnew-tab | サブコマンドなしの場合はnew-tabとして解析 | ParseCommand時 |
| BR-110-3 | 最大化/全画面排他 | -Mと-Fは排他。-Mと-fは組み合わせ可（MaximizedFocusMode） | グローバルフラグ |
| BR-110-4 | 引数逆順 | CLI11のparse()は引数を逆順で受け取る | ParseCommand時 |
| BR-110-5 | 先頭引数スキップ | 各コマンドの先頭引数（実行ファイル名）はスキップ | ParseCommand時 |
| BR-110-6 | split-paneサイズ | -sオプションの範囲は0.01~0.99 | split-pane解析時 |
| BR-110-7 | focus-tab排他 | -t(インデックス)、-n(次)、-p(前)は排他 | focus-tab解析時 |
| BR-110-8 | MRU無効 | コマンドラインからのタブ切り替えではMRU順序を無効化 | focus-tab時 |

### 計算ロジック

特殊な計算ロジックはない。

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

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

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| CLI::CallForHelp | ヘルプ要求 | -? or /? | ヘルプテキストを_exitMessageに設定 |
| CLI::ExtrasError | 未解析引数 | サブコマンド後に不明な引数 | エラーメッセージを_exitMessageに設定 |
| CLI::ParseError | パースエラー | 不正な引数形式 | _handleExitでエラー処理 |

### リトライ仕様

リトライは不要。

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

- scope_exitパターンで_currentCommandlineポインタのクリーンアップを保証

## パフォーマンス要件

- コマンドライン解析はアプリケーション起動時に1回実行されるため、特段のパフォーマンス要件はない

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

- コマンドライン引数はプロセス起動元からの入力であり、信頼できる前提
- 文字列のエスケープ処理（QuoteAndEscapeCommandlineArg）は適切に実装されている必要がある

## 備考

- Commandlineクラスは引数をワイド文字列で受け取り、ナロー文字列に変換して保持する（CLI11がナロー文字列を要求するため）
- `_commandDelimiterRegex` は `^;|[^\\];` パターンで、行頭のセミコロンまたはバックスラッシュ以外に続くセミコロンにマッチ
- prefix_command()モードにより、グローバルオプション→サブコマンドの2段階解析が可能
- -Mと-fの組み合わせはMaximizedFocusModeとなる

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | Commandline.h | `src/cascadia/TerminalApp/Commandline.h` | Commandlineクラス(31-46行目)。セミコロンデリミタ定数(34-35行目)、_args(43行目) |
| 1-2 | AppCommandlineArgs.h | `src/cascadia/TerminalApp/AppCommandlineArgs.h` | AppCommandlineArgsクラス(20-162行目)。CLI::App(55行目)、NewTerminalSubcommand(59-72行目)、各サブコマンドメンバ(82-95行目) |

**読解のコツ**: NewTerminalSubcommand構造体(59-72行目)はnew-tabとsplit-paneで共通のオプション（プロファイル名、作業ディレクトリ、タイトル等）をまとめている。NewPaneSubcommand(74-79行目)はこれを継承し、分割方向オプションを追加している。

#### Step 2: パーサー構築を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | AppCommandlineArgs.cpp | `src/cascadia/TerminalApp/AppCommandlineArgs.cpp` | _buildParser(136-212行目) |

**主要処理フロー**:
1. **145行目**: prefix_command()で2段階解析モードを設定
2. **148-158行目**: -v/--versionフラグの登録
3. **166-184行目**: -M, -F, -f の起動モードフラグ（相互排他設定あり）
4. **186-197行目**: --pos, --size, -w, -sのグローバルオプション
5. **203-211行目**: 各サブコマンドのパーサー構築呼び出し

#### Step 3: サブコマンド解析を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | AppCommandlineArgs.cpp | `src/cascadia/TerminalApp/AppCommandlineArgs.cpp` | _buildNewTabParser(221-247行目)、_buildSplitPaneParser(256-314行目)、_buildFocusTabParser(360-409行目)、_buildMoveFocusParser(429-461行目) |

**読解のコツ**: 各サブコマンドにはlong/shortの2形式がある（例: new-tab/nt, split-pane/sp）。コールバック内で_getNewTerminalArgsを呼び出し、ActionAndArgsを_startupActionsに追加する。

#### Step 4: メイン解析フローを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | AppCommandlineArgs.cpp | `src/cascadia/TerminalApp/AppCommandlineArgs.cpp` | ParseCommand(31-96行目)、_handleExit(107-128行目) |

**主要処理フロー**:
1. **42-43行目**: _currentCommandlineポインタ設定とscope_exitでのクリーンアップ
2. **57行目**: 先頭の実行ファイル名をスキップし、引数を逆順に
3. **67-70行目**: -? / /? のヘルプフラグ手動チェック
4. **73行目**: _app.parse()でプレフィックスコマンドを解析
5. **78-81行目**: サブコマンド未指定時に暗黙のnew-tabとして再解析
6. **86-89行目**: 未解析パラメータがあればExtrasErrorをthrow

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

```
アプリケーション起動 / ExecuteCommandlineアクション
    |
    +-- AppCommandlineArgs::BuildCommands    ... セミコロン分割
    |       +-- _addCommandsForArg           ... 各引数を処理
    |       +-- Commandline::AddArg           ... 引数追加
    |
    +-- AppCommandlineArgs::ParseCommand     ... 各コマンド解析
    |       +-- _resetStateToDefault          ... 状態リセット
    |       +-- CLI::App::parse               ... CLI11パース
    |       +-- サブコマンドコールバック
    |       |   +-- new-tab:    _getNewTerminalArgs → NewTabArgs
    |       |   +-- split-pane: _getNewTerminalArgs → SplitPaneArgs
    |       |   +-- focus-tab:  SwitchToTabArgs / NextTabArgs / PrevTabArgs
    |       |   +-- move-focus: MoveFocusArgs
    |       |   +-- move-pane:  MovePaneArgs
    |       |   +-- swap-pane:  SwapPaneArgs
    |       |   +-- focus-pane: FocusPaneArgs
    |       |   +-- x-save:    SaveSnippetArgs
    |       +-- _handleExit                   ... エラー/ヘルプ処理
    |
    +-- AppCommandlineArgs::ValidateStartupCommands ... 検証
    +-- AppCommandlineArgs::GetStartupActions       ... アクション取得
```

### データフロー図

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

コマンドライン文字列            AppCommandlineArgs             起動アクション
  "wt nt -p PS ; sp -V"
        |
        v
  BuildCommands ---------> Commandline[] (セミコロン分割)
        |                      |
        v                      v
  ParseCommand(1) -------> "nt -p PS" → NewTabArgs
  ParseCommand(2) -------> "sp -V"   → SplitPaneArgs
        |                                    |
        v                                    v
  _startupActions -------> [NewTab, SplitPane]
        |
        v
  GetStartupActions -----> Terminal起動処理
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| AppCommandlineArgs.h | `src/cascadia/TerminalApp/AppCommandlineArgs.h` | ソース(ヘッダ) | コマンドライン解析クラス宣言 |
| AppCommandlineArgs.cpp | `src/cascadia/TerminalApp/AppCommandlineArgs.cpp` | ソース(実装) | パーサー構築・コマンド解析 |
| Commandline.h | `src/cascadia/TerminalApp/Commandline.h` | ソース(ヘッダ) | 個別コマンドライン表現 |
| Commandline.cpp | `src/cascadia/TerminalApp/Commandline.cpp` | ソース(実装) | Commandlineクラス実装 |
| ActionAndArgs | TerminalSettingsModel | WinRT | アクション+引数の組み合わせ |
| NewTabArgs | TerminalSettingsModel | WinRT | new-tabサブコマンドの引数 |
| SplitPaneArgs | TerminalSettingsModel | WinRT | split-paneサブコマンドの引数 |
