## Issue
<div class="link-card-v2">
<div class="link-card-v2-site">
<img class="link-card-v2-site-icon" src="https://github.githubassets.com/favicons/favicon.svg" />
<span class="link-card-v2-site-name">GitHub</span>
</div>
<div class="link-card-v2-title">
[Feature Request] return value for pickers · Issue #319 · tadashi-aikawa/obsidian-another-quick-switcher
</div>
<div class="link-card-v2-content">
As far as I know, any picker (say File Name Search) does not return a value ( I tested this and it returns a boo ...
</div>
<img class="link-card-v2-image" src="https://opengraph.githubassets.com/6fedf55cf55cf6b85c59b782a6b287c4bf02d380f9d5725d4f12f83cb9ba356c/tadashi-aikawa/obsidian-another-quick-switcher/issues/319" />
<a href="https://github.com/tadashi-aikawa/obsidian-another-quick-switcher/issues/319"></a>
</div>
## Plan: ピッカーAPIの実装(外部スクリプト連携用)
TemplaterなどのスクリプトからAQSのピッカーを呼び出し、選択結果を取得できるPromise-base APIを実装します。各モーダルに `openAndGetValue()` メソッドを追加し、プラグインの `api` プロパティ経由で公開します。
### Steps
1. src/api.ts を新規作成し、`AnotherQuickSwitcherAPI` クラスと各ピッカーの返り値型(`FilePickResult`, `HeaderPickResult` など)を定義する
2. [AbstractSuggestionModal.ts](vscode-file://vscode-app/Applications/Visual%20Studio%20Code.app/Contents/Resources/app/out/vs/code/electron-browser/workbench/workbench.html) に `resolvePromise`/`rejectPromise` プロパティと `apiMode` フラグを追加し、`onClose` でキャンセル時の reject 処理を実装する
3. 各モーダル([AnotherQuickSwitcherModal.ts](vscode-file://vscode-app/Applications/Visual%20Studio%20Code.app/Contents/Resources/app/out/vs/code/electron-browser/workbench/workbench.html), [HeaderModal.ts](vscode-file://vscode-app/Applications/Visual%20Studio%20Code.app/Contents/Resources/app/out/vs/code/electron-browser/workbench/workbench.html), [BacklinkModal.ts](vscode-file://vscode-app/Applications/Visual%20Studio%20Code.app/Contents/Resources/app/out/vs/code/electron-browser/workbench/workbench.html), [LinkModal.ts](vscode-file://vscode-app/Applications/Visual%20Studio%20Code.app/Contents/Resources/app/out/vs/code/electron-browser/workbench/workbench.html), [InFileModal.ts](vscode-file://vscode-app/Applications/Visual%20Studio%20Code.app/Contents/Resources/app/out/vs/code/electron-browser/workbench/workbench.html), [GrepModal.ts](vscode-file://vscode-app/Applications/Visual%20Studio%20Code.app/Contents/Resources/app/out/vs/code/electron-browser/workbench/workbench.html))に `openAndGetValue(): Promise<T | null>` メソッドを追加し、選択時に `resolve` を呼び出すよう `chooseCurrentSuggestion` を修正する
4. [main.ts](vscode-file://vscode-app/Applications/Visual%20Studio%20Code.app/Contents/Resources/app/out/vs/code/electron-browser/workbench/workbench.html) の `AnotherQuickSwitcher` クラスに `api` プロパティを追加し、`onload()` で `AnotherQuickSwitcherAPI` インスタンスを生成・公開する
5. README または docs にAPI使用例(Templater連携サンプル)を追記する
### Further Considerations
1. **APIモード時のファイルオープン動作**: APIから呼び出された場合、ファイルを自動で開くべきか? → オプション引数 `{ openFile: boolean }` で制御する / 開かない(純粋に値を返す)/ 常に開く
2. **キャンセル時の挙動**: キャンセル時に `null` を返す vs エラーを throw する → `throw_on_cancel` オプションで選択可能にするか
3. **FolderModal/MoveModal のAPI化**: これらもAPI化するか、まずは検索系モーダルのみに絞るか
## 回答
対象は AnotherQuickSwitcherModal だけでいいです。
その上で回答です。
1. 『純粋に値を返す』で良い。他のスクリプトと連携できるのが今回の趣旨であり、ファイルを開いてしまったら本末転倒
2. nullを返す
3. しない。AnotherQuickSwitcherModalだけ。
## Plan: AnotherQuickSwitcherModal ピッカーAPI実装
Templater等のスクリプトから `app.plugins.plugins['obsidian-another-quick-switcher'].api.pickFile()` で呼び出し、選択されたTFileを返すPromise-base APIを実装します。APIモード時はファイルを開かず純粋に値のみ返し、キャンセル時は `null` を返します。
### Steps
1. src/api.ts を新規作成し、`AnotherQuickSwitcherAPI` クラスと `pickFile(options?)` メソッドを定義。オプションで `inputQuery` や `searchTarget` を渡せるようにする
2. [AnotherQuickSwitcherModal.ts](vscode-file://vscode-app/Applications/Visual%20Studio%20Code.app/Contents/Resources/app/out/vs/code/electron-browser/workbench/workbench.html) に `apiMode` フラグと `resolveApiPromise` / `rejectApiPromise` を追加。`openAndGetValue(): Promise<TFile | null>` メソッドを新設する
3. `chooseCurrentSuggestion` を修正し、`apiMode` が `true` の場合は `appHelper.openFile()` をスキップして `resolveApiPromise(fileToOpened)` を呼ぶ
4. `onClose` を修正し、`apiMode` が `true` かつ未解決の場合に `resolveApiPromise(null)` を呼ぶ(キャンセル時)
5. [main.ts](vscode-file://vscode-app/Applications/Visual%20Studio%20Code.app/Contents/Resources/app/out/vs/code/electron-browser/workbench/workbench.html) の `AnotherQuickSwitcher` クラスに `public api: AnotherQuickSwitcherAPI` を追加し、`onload()` でインスタンス化・公開する
### Further Considerations
1. **pickFile のオプション引数**: デフォルトの `SearchCommand` をどう決めるか → `file` をデフォルトに / ユーザーが `searchTarget` を指定可能にする / 設定から読み込む
## 回答
> 1. src/api.ts を新規作成し、`AnotherQuickSwitcherAPI` クラスと `pickFile(options?)` メソッドを定義。オプションで `inputQuery` や `searchTarget` を渡せるようにする
クエリやsearthTargetなどを渡すのではなく、**Another Quick SwitcherのSearch Commandsで登録されたコマンドタイトル(ex: Recent search)** を指定したら、そのモードでモーダルを表示するようにしてください。
## Plan: AnotherQuickSwitcherModal ピッカーAPI実装
Templater等のスクリプトから `app.plugins.plugins['obsidian-another-quick-switcher'].api.pickFile("Recent search")` のようにSearch Command名を指定して呼び出し、選択されたTFileを返すPromise-base APIを実装します。APIモード時はファイルを開かず純粋に値のみ返し、キャンセル時は `null` を返します。
### Steps
1. src/api.ts を新規作成し、`AnotherQuickSwitcherAPI` クラスを定義。`pickFile(commandName: string): Promise<TFile | null>` メソッドを実装し、`settings.searchCommands` から `name` が一致する `SearchCommand` を検索してモーダルを表示する
2. [AnotherQuickSwitcherModal.ts](vscode-file://vscode-app/Applications/Visual%20Studio%20Code.app/Contents/Resources/app/out/vs/code/electron-browser/workbench/workbench.html) に `apiMode` フラグと `resolveApiPromise: ((file: TFile | null) => void) | null` を追加。`openAndGetValue(): Promise<TFile | null>` メソッドを新設する
3. `chooseCurrentSuggestion` を修正し、`apiMode` が `true` の場合は `appHelper.openFile()` をスキップして `resolveApiPromise(fileToOpened)` を呼び、`close()` する
4. `onClose` を修正し、`apiMode` が `true` かつ `resolveApiPromise` が未呼び出しの場合に `resolveApiPromise(null)` を呼ぶ(キャンセル時)
5. [main.ts](vscode-file://vscode-app/Applications/Visual%20Studio%20Code.app/Contents/Resources/app/out/vs/code/electron-browser/workbench/workbench.html) の `AnotherQuickSwitcher` クラスに `public api: AnotherQuickSwitcherAPI` を追加し、`onload()` でインスタンス化・公開する
### Further Considerations
1. **存在しないコマンド名の指定時**: `null` を即座に返す / エラーをthrowする / 利用可能なコマンド名リストを返すヘルパーメソッド `listCommands()` を追加する
## 回答
>1. **存在しないコマンド名の指定時**: `null` を即座に返す / エラーをthrowする / 利用可能なコマンド名リストを返すヘルパーメソッド `listCommands()` を追加する
エラーをthrowする。
SearchCommandはCheck/Uncheck機能(multi select)で複数の `TFile` を選択することができるため、戻り値は `Promise<TFile|null>` ではなく `Promise<TFile[]|null>` になるのでは?
## Plan: AnotherQuickSwitcherModal ピッカーAPI実装
Templater等のスクリプトから `app.plugins.plugins['obsidian-another-quick-switcher'].api.pickFile("Recent search")` のようにSearch Command名を指定して呼び出し、選択されたTFile配列を返すPromise-base APIを実装します。APIモード時はファイルを開かず純粋に値のみ返し、キャンセル時は `null` を返します。存在しないコマンド名の場合はエラーをthrowします。
### Steps
1. src/api.ts を新規作成し、`AnotherQuickSwitcherAPI` クラスを定義。`pickFile(commandName: string): Promise<TFile[] | null>` メソッドを実装し、`settings.searchCommands` から `name` が一致する `SearchCommand` を検索してモーダルを表示する。コマンド名が見つからない場合は `Error` をthrowする
2. [AnotherQuickSwitcherModal.ts](vscode-file://vscode-app/Applications/Visual%20Studio%20Code.app/Contents/Resources/app/out/vs/code/electron-browser/workbench/workbench.html) に `apiMode` フラグと `resolveApiPromise: ((files: TFile[] | null) => void) | null` を追加。`openAndGetValue(): Promise<TFile[] | null>` メソッドを新設する
3. `chooseCurrentSuggestion` を修正し、`apiMode` が `true` の場合は `appHelper.openFile()` をスキップ。`checkedItems` があれば複数ファイル、なければ単一ファイルを配列として `resolveApiPromise([...files])` を呼び、`close()` する
4. `onClose` を修正し、`apiMode` が `true` かつ `resolveApiPromise` が未呼び出しの場合に `resolveApiPromise(null)` を呼ぶ(キャンセル時)
5. [main.ts](vscode-file://vscode-app/Applications/Visual%20Studio%20Code.app/Contents/Resources/app/out/vs/code/electron-browser/workbench/workbench.html) の `AnotherQuickSwitcher` クラスに `public api: AnotherQuickSwitcherAPI` を追加し、`onload()` でインスタンス化・公開する
### Further Considerations
1. **APIの型定義の公開**: Templater等から型補完を受けられるよう、型定義を別ファイル(`src/types.ts` など)にエクスポートするか、READMEに型情報を記載するか
## 回答
> 1. **APIの型定義の公開**: Templater等から型補完を受けられるよう、型定義を別ファイル(`src/types.ts` など)にエクスポートするか、READMEに型情報を記載するか
READMEでよい。
> 3. `chooseCurrentSuggestion` を修正し、`apiMode` が `true` の場合は `appHelper.openFile()` をスキップ。`checkedItems` があれば複数ファイル、なければ単一ファイルを配列として `resolveApiPromise([...files])` を呼び、`close()` する
`resolveApiPromise` の処理は `appHelper.openFile()` の中に書くのか? それとも呼び出し元でif文により分岐するのか?
## Plan: AnotherQuickSwitcherModal ピッカーAPI実装
Templater等のスクリプトから `app.plugins.plugins['obsidian-another-quick-switcher'].api.pickFile("Recent search")` のようにSearch Command名を指定して呼び出し、選択されたTFile配列を返すPromise-base APIを実装します。APIモード時はファイルを開かず純粋に値のみ返し、キャンセル時は `null` を返します。存在しないコマンド名の場合はエラーをthrowします。
### Steps
1. src/api.ts を新規作成し、`AnotherQuickSwitcherAPI` クラスを定義。`pickFile(commandName: string): Promise<TFile[] | null>` メソッドを実装し、`settings.searchCommands` から `name` が一致する `SearchCommand` を検索してモーダルを表示する。コマンド名が見つからない場合は `Error` をthrowする
2. [AnotherQuickSwitcherModal.ts](vscode-file://vscode-app/Applications/Visual%20Studio%20Code.app/Contents/Resources/app/out/vs/code/electron-browser/workbench/workbench.html) に `apiMode` フラグと `resolveApiPromise: ((files: TFile[] | null) => void) | null` を追加。`openAndGetValue(): Promise<TFile[] | null>` メソッドを新設する
3. `chooseCurrentSuggestion` を修正し、呼び出し元で `if (this.apiMode)` 分岐を追加。`true` の場合は `appHelper.openFile()` を呼ばず、`checkedItems` があれば複数ファイル、なければ単一ファイルを配列として `resolveApiPromise([...files])` を呼び `close()` して早期リターン。`false` の場合は既存の `appHelper.openFile()` 処理を実行
4. `onClose` を修正し、`apiMode` が `true` かつ `resolveApiPromise` が未呼び出しの場合に `resolveApiPromise(null)` を呼ぶ(キャンセル時)
5. [main.ts](vscode-file://vscode-app/Applications/Visual%20Studio%20Code.app/Contents/Resources/app/out/vs/code/electron-browser/workbench/workbench.html) の `AnotherQuickSwitcher` クラスに `public api: AnotherQuickSwitcherAPI` を追加し、`onload()` でインスタンス化・公開する
6. [README.md](vscode-file://vscode-app/Applications/Visual%20Studio%20Code.app/Contents/Resources/app/out/vs/code/electron-browser/workbench/workbench.html) にAPI使用例(Templater連携サンプル)と型情報を追記する
```
いくつか修正・整理を加える。
```
## デグレリスク(影響範囲と理由)
1. **[silentClose()](vscode-file://vscode-app/Applications/Visual%20Studio%20Code.app/Contents/Resources/app/out/vs/code/electron-browser/workbench/workbench.html) 経由のモーダル遷移の挙動**
- [onClose](vscode-file://vscode-app/Applications/Visual%20Studio%20Code.app/Contents/Resources/app/out/vs/code/electron-browser/workbench/workbench.html) の [willSilentClose](vscode-file://vscode-app/Applications/Visual%20Studio%20Code.app/Contents/Resources/app/out/vs/code/electron-browser/workbench/workbench.html) 判定位置を変更したため、モーダル遷移時に「履歴・プレビュー復元」系の後処理がスキップされる条件が変わっています。
- 該当箇所: [AnotherQuickSwitcherModal.ts:290-323](vscode-file://vscode-app/Applications/Visual%20Studio%20Code.app/Contents/Resources/app/out/vs/code/electron-browser/workbench/workbench.html)
- リスク: ナビゲーション(show links/backlinks、navigate back/forward)で履歴・状態復元のタイミングが微妙に変わる可能性。
2. **APIモードの引き回し**
- 新しいモーダル生成時に [apiMode](vscode-file://vscode-app/Applications/Visual%20Studio%20Code.app/Contents/Resources/app/out/vs/code/electron-browser/workbench/workbench.html) と [resolveApiPromise](vscode-file://vscode-app/Applications/Visual%20Studio%20Code.app/Contents/Resources/app/out/vs/code/electron-browser/workbench/workbench.html) を引き継ぐように変更しました。
- 該当箇所: [AnotherQuickSwitcherModal.ts:1333-1381](vscode-file://vscode-app/Applications/Visual%20Studio%20Code.app/Contents/Resources/app/out/vs/code/electron-browser/workbench/workbench.html), [AnotherQuickSwitcherModal.ts:1406-1444](vscode-file://vscode-app/Applications/Visual%20Studio%20Code.app/Contents/Resources/app/out/vs/code/electron-browser/workbench/workbench.html)
- リスク: 既存のモーダル遷移で「本来はAPIモードでないのに、引き継ぎが発生する」可能性は低いですが、引数が間違って渡ると全体に影響します。
3. **[open](vscode-file://vscode-app/Applications/Visual%20Studio%20Code.app/Contents/Resources/app/out/vs/code/electron-browser/workbench/workbench.html) キー操作時の分岐**
- APIモード時、[open](vscode-file://vscode-app/Applications/Visual%20Studio%20Code.app/Contents/Resources/app/out/vs/code/electron-browser/workbench/workbench.html) キー押下でファイルを開かずに [resolveApiWithFiles](vscode-file://vscode-app/Applications/Visual%20Studio%20Code.app/Contents/Resources/app/out/vs/code/electron-browser/workbench/workbench.html) を呼ぶ分岐を追加。
- 該当箇所: [AnotherQuickSwitcherModal.ts:1099-1135](vscode-file://vscode-app/Applications/Visual%20Studio%20Code.app/Contents/Resources/app/out/vs/code/electron-browser/workbench/workbench.html)
- リスク: 通常モードで [apiMode](vscode-file://vscode-app/Applications/Visual%20Studio%20Code.app/Contents/Resources/app/out/vs/code/electron-browser/workbench/workbench.html) が誤って true になると、既存の「openでファイルを開く」動作が失われます。
4. **[initialLeaf](vscode-file://vscode-app/Applications/Visual%20Studio%20Code.app/Contents/Resources/app/out/vs/code/electron-browser/workbench/workbench.html) の取り扱い**
- API側で [activeFileLeaf](vscode-file://vscode-app/Applications/Visual%20Studio%20Code.app/Contents/Resources/app/out/vs/code/electron-browser/workbench/workbench.html) を渡すように変更。
- 該当箇所: [api.ts:38-73](vscode-file://vscode-app/Applications/Visual%20Studio%20Code.app/Contents/Resources/app/out/vs/code/electron-browser/workbench/workbench.html)
- リスク: 低。むしろ従来と同等の挙動に揃えた改善。
5. **[onClose](vscode-file://vscode-app/Applications/Visual%20Studio%20Code.app/Contents/Resources/app/out/vs/code/electron-browser/workbench/workbench.html) のAPIキャンセル処理**
- [resolveApiPromise(null)](vscode-file://vscode-app/Applications/Visual%20Studio%20Code.app/Contents/Resources/app/out/vs/code/electron-browser/workbench/workbench.html) が [silentClose](vscode-file://vscode-app/Applications/Visual%20Studio%20Code.app/Contents/Resources/app/out/vs/code/electron-browser/workbench/workbench.html) で走らないように移動。
- 該当箇所: [AnotherQuickSwitcherModal.ts:290-323](vscode-file://vscode-app/Applications/Visual%20Studio%20Code.app/Contents/Resources/app/out/vs/code/electron-browser/workbench/workbench.html)
- リスク: 低。ただし [silentClose](vscode-file://vscode-app/Applications/Visual%20Studio%20Code.app/Contents/Resources/app/out/vs/code/electron-browser/workbench/workbench.html) 以外のケースで [resolveApiPromise](vscode-file://vscode-app/Applications/Visual%20Studio%20Code.app/Contents/Resources/app/out/vs/code/electron-browser/workbench/workbench.html) が残存すると、複数回解決の可能性が理論上あるため、他の閉じ方との組み合わせは確認が必要。
## 重点確認ポイント(手動)
- [show links](vscode-file://vscode-app/Applications/Visual%20Studio%20Code.app/Contents/Resources/app/out/vs/code/electron-browser/workbench/workbench.html) / `show backlinks` / [navigate back](vscode-file://vscode-app/Applications/Visual%20Studio%20Code.app/Contents/Resources/app/out/vs/code/electron-browser/workbench/workbench.html) / [navigate forward](vscode-file://vscode-app/Applications/Visual%20Studio%20Code.app/Contents/Resources/app/out/vs/code/electron-browser/workbench/workbench.html) の後に:
- 返り値が `null` にならない
- 既存の履歴復元やプレビュー復帰の動作が保たれる
- 通常利用で [open](vscode-file://vscode-app/Applications/Visual%20Studio%20Code.app/Contents/Resources/app/out/vs/code/electron-browser/workbench/workbench.html) / [open in new tab](vscode-file://vscode-app/Applications/Visual%20Studio%20Code.app/Contents/Resources/app/out/vs/code/electron-browser/workbench/workbench.html) などが従来通り動く
## 結論
デグレリスクは **低〜中**。特にモーダル遷移と [onClose](vscode-file://vscode-app/Applications/Visual%20Studio%20Code.app/Contents/Resources/app/out/vs/code/electron-browser/workbench/workbench.html) まわりが中心的な影響範囲です。上記ポイントの手動確認で十分に検知可能な範囲です。