0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

`createQuickPick`で「プリセット選択」と「自由入力」を同じダイアログに両立させる

0
Posted at

背景

「現在行から任意の文字列を含む行まで一括選択・コピーする」VSCodeマクロを作る際、「よく使う検索対象(空行・EOFなど)はプリセットからすぐ選びたい」が「たまに任意の文字列も検索したい」という2つの要求を1つのダイアログで両立させる必要がありました。

1. showQuickPickではなくcreateQuickPickを使う

const quickPick = vscode.window.createQuickPick();
quickPick.items = PRESET_PATTERNS;
quickPick.placeholder = '終了位置を選択または直接入力してください';
quickPick.ignoreFocusOut = true;

vscode.window.showQuickPick()は選択肢からの選択専用で、自由入力を受け付けません。createQuickPick()で低レベルAPIを直接扱うことで、入力欄にテキストを打った状態でEnterを押すという操作も拾えるようになります。

2. 選択 or 入力をイベントハンドラで分岐

quickPick.onDidAccept(() => {
    const selected = quickPick.selectedItems[0];
    const inputValue = quickPick.value.trim();

    if (selected) {
        // プリセットの選択肢をハイライトした状態でEnter
        resolve(pattern?.value || null);
    } else if (inputValue) {
        // プリセットを選ばずテキストを入力してEnter
        resolve(inputValue);
    } else {
        resolve(null);
    }
    quickPick.hide();
});

onDidAcceptが発火した時点でselectedItems[0]があるかどうかで、「候補をハイライトして選んだ」のか「そのまま自由入力した」のかを判別できます。同じイベントの中で両方のケースを吸収できるため、ダイアログを分ける必要がありません。

3. Promiseでラップしてasync/awaitに乗せる

return new Promise((resolve) => {
    quickPick.onDidAccept(() => { /* ... */ resolve(value); });
    quickPick.onDidHide(() => { resolve(null); quickPick.dispose(); });
    quickPick.show();
});

createQuickPickはイベント駆動のAPIなので、そのままでは呼び出し側でawaitできません。Promiseでラップし、onDidAcceptとonDidHide(Escでキャンセルした場合)の両方でresolveすることで、呼び出し元はawait showPatternDialog()と書くだけで済みます。onDidHide側でquickPick.dispose()を呼び、リソースの解放も忘れずに行います。

4. 改行を含む選択範囲の作り方

const endPos = endLine < document.lineCount - 1
    ? new vscode.Position(endLine + 1, 0)
    : new vscode.Position(endLine, document.lineAt(endLine).text.length);

選択範囲の終端を「対象行の行末」ではなく「次の行の先頭(0文字目)」にすることで、コピー時に末尾の改行までまとめて含められます。最終行の場合は次の行が存在しないため、行末位置にフォールバックします。

まとめ

createQuickPickのイベントハンドラで選択と自由入力を1つのダイアログに統合するパターンは、この機能に限らず「プリセット+カスタム値」を扱うUIで汎用的に使えます。空行検出や文字列検索を含む完全なコードは元記事にまとめています。

→ 任意行までの一括選択・コピーを実現するTypeScriptマクロ(ブログ)

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?