QuickInputとInputBoxを利用してユーザー入力を受け付ける - Visual Studio Codeの拡張機能を開発する

この記事ではVSCodeの拡張機能で、QuickInputとInputBoxを利用してユーザー入力を受け付ける方法について説明します。

QuickInputとは?

VSCode標準で提供されている要素選択のUIで、たとえばコマンドパレットなどもこのUIで実装されています。

QuickInputの例: コマンドパレット

QuickInputの使い方

まずは、QuickInputの実装を示します。

// vscode.window.showQuickPickでQuickPickを表示する

// 戻り値はThenable<T>で、Promiseと同様に扱える
// この例ではawaitで結果を待つ
// then/rejectでもOK
const result = await vscode.window.showQuickPick(['one', 'two', 'three'], {
    placeHolder: 'one, two or three',
    // QuickItemでフォーカスがあたった際に呼び出されるコールバック
	onDidSelectItem: item =>
        vscode.window.showInformationMessage(`Focus ${++i}: ${item}`)
});

// 結果を表示する
if (result) {
    // 入力完了
    vscode.window.showInformationMessage(`Got: ${result}`);
} else {
    // 入力がキャンセルされた
    vscode.window.showInformationMessage(`Failed to get`);
}

vscode.window.showQuickInputを実行するとQuickInputを呼びだします。戻り値はThenable<T>で、awaitと組み合わせると入力の完了(または入力のキャンセル)を待って、その入力値を受け取ることができます。

showQuickInputの第1引数は選択する要素をstringQuickPickItemの配列を、第2引数にはQuickInputの挙動を制御するQuickItemOptionsを指定することができます。

QuickPickItem

第1引数には選択する要素をstringQuickPickItemの配列で渡します。QuickPickItemは下記のインターフェイスで定義されています。

export interface QuickPickItem {
    label: string;
    description?: string;
    detail?: string;
    picked?: boolean;
    alwaysShow?: boolean;
}

要素をstring[]で指定した場合は、QuickPickItemlabelのみ指定した表示および挙動となります。QuickPickItemdescriptiondetailを指定すると下記のような表示となります。

labelとdescription、detailを指定した場合のQuickInputの表示

labelとdescription、detailを指定した場合のQuickInputの表示

詳細は後述しますが、QuickPickの絞り込み検索はデフォルトでlabelのみを対象とします。この挙動はQuickPickOptionsで変更することができます。

下記のようにQuickPickItemalwaysShowtrueとして指定すると、絞り込み結果に関わらず必ずその要素が表示されるようになります。

const items : vscode.QuickPickItem[] = [
    {
        label: "item 1",
        description: "item 1(alwaysShow = false)",
        alwaysShow : false,
    },
    // ...item2 ~ 4もalwaysShow=falseで指定
    {
        label: "item 5",
        description: "item 5(alwaysShow = true)",
        alwaysShow : true,
    },
];

const result = await vscode.window.showQuickPick(items);
if (result) {
    vscode.window.showInformationMessage(`Got: ${result.label}`);
} else {
    vscode.window.showWarningMessage(`Failed to get`);
}

上記の指定で、下記のような挙動になります。

item 5にalwaysShowを指定した様子。絞り込めなくても必ず結果に表示されている。

InputBoxとは?

VSCode標準で提供されているテキスト入力UIで、こちらもVSCodeの各種機能で利用されています。

InputBox

InputBoxの使い方

まず上記動画の実装コードを示します。

// InputBoxを呼び出す。awaitで完了を待つ。
const result = await vscode.window.showInputBox();
// ここで入力を処理する
if (result) {
    // 入力が正常に行われている
    vscode.window.showInformationMessage(`Got: ${result}`);
} else {
    // 入力がキャンセルされた
    vscode.window.showWarningMessage(`Failed to get`);
}

vscode.window.showInputBoxを呼び出すことでInputBoxを表示します。戻り値はshowQuickInput同様Thenableなので、awaitで入力の完了を待って、その結果を元に次の処理をおこないます。

この例では指定していないですが、第1引数にInputBoxOptionsを指定することでInputBoxの挙動を指定することができます。

InputBoxOptions

InputBoxの挙動を指定するオプションで、下記のインターフェイスで定義されています。

export interface InputBoxOptions {
    value?: string;
    valueSelection?: [number, number];
    prompt?: string;
    placeHolder?: string;
    password?: boolean;
    ignoreFocusOut?: boolean;
    validateInput?(value: string):
        string | undefined | null |
        Thenable<string | undefined | null>;
}

下記のようにvalueを指定すると、InboxBoxのデフォルト値を指定することができます。

const result = await vscode.window.showInputBox({
    value: "default value"
});
if (result) {
    vscode.window.showInformationMessage(`Got: ${result}`);
} else {
    vscode.window.showWarningMessage(`Failed to get`);
}

InputBoxでvalueを指定する

また下記のようにvalueSelectionを指定すると、valueに対して選択済みの範囲を指定することができます。

valueでプレフィックスやサフィックスを定義しつつ、入力させたい要素を選択済みにすることで、ユーザー入力をよりスムーズにさせることができます。

const result = await vscode.window.showInputBox({
    value: 'abcdef',
    valueSelection: [2, 4],
});

if (result) {
    vscode.window.showInformationMessage(`Got: ${result}`);
} else {
    vscode.window.showWarningMessage(`Failed to get`);
}

valueSelectionをするとデフォルト値に対して選択済み範囲を指定することができる

validateInputはInputBoxの入力値を検証することができます。

validateInputには関数を指定します。この関数の検証が通らない限り入力を確定することができません。

検証関数はstringを引数に受け取ります。入力値が正常であればnullを、異常値であればその理由をstringで返却します。

const result = await vscode.window.showInputBox({
    validateInput: (text) => {
        return text.length >= 6 ? null: "6 or more characters";
    },
});

if (result) {
    vscode.window.showInformationMessage(`Got: ${result}`);
} else {
    vscode.window.showWarningMessage(`Failed to get`);
}

InputBoxの入力を検証する

まとめ

VSCodeの拡張実装でよく利用する、QuickInputおよびInputBoxについて、その利用方法を紹介しました。

ちなみに、MicroSoft公式がサンプル実装はvscode-extension-samples/quickinput-sample at main · microsoft/vscode-extension-samplesで確認できます。