8
1

More than 3 years have passed since last update.

VSCode拡張機能を作ってみる2 - 入力補完

Last updated at Posted at 2021-06-23

はじめに

公式サンプルにVSCode APIを使ったサンプルがあるので、いくつか使いそうなものをピックアップしてみました。

今回は、CompletionItemProvider API を使って入力補完する機能を付けます。

前回
VSCode拡張機能を作ってみる1 - インストールとHelloWorld!

事前準備

まず、空のcompletion.tsファイルを作成し、extension.ts で読み込んでおきます。

completion.ts
import * as vscode from 'vscode';

export default class Completions implements vscode.CompletionItemProvider
{
    public provideCompletionItems(): vscode.ProviderResult<vscode.CompletionItem[]>
    {
        // ここに補完機能を追加していきます
        return [];
    }
}

plaintextにしているので対応したい言語に変更してください。

extension.ts
import * as vscode from 'vscode';

import Completions from "./completions";

export function activate(context: vscode.ExtensionContext)
{
    const provider = vscode.languages.registerCompletionItemProvider('plaintext', new Completions());
    context.subscriptions.push(provider);
}

export function deactivate() {}

Hello World!

シンプルにHello World!を自動補完してみます。

image.png

completion.ts
    public provideCompletionItems(): vscode.ProviderResult<vscode.CompletionItem[]>
    {
        const simpleCompletion = new vscode.CompletionItem('Hello World!');
        return [simpleCompletion];
    }

insertText

挿入テキストを指定できます。
insertTextがない場合はvscode.CompletionItemのラベルが挿入されます。

completion.ts
    public provideCompletionItems(): vscode.ProviderResult<vscode.CompletionItem[]>
    {
        const simpleCompletion = new vscode.CompletionItem('Hello World!');
        simpleCompletion.insertText = 'Change the World!';

        return [simpleCompletion];
    }

documentation

補完候補に説明を追加できます。

image.png

completion.ts
    public provideCompletionItems(): vscode.ProviderResult<vscode.CompletionItem[]>
    {
        const snippetCompletion = new vscode.CompletionItem('Good part of the day');
        snippetCompletion.documentation = new vscode.MarkdownString("Inserts a snippet that lets you select the _appropriate_ part of the day for your greeting.");

        return [snippetCompletion];
    }

Snippet

SnippetStringを使って挿入テキストにスニペットを追加できます。

image.png

completion.ts
    public provideCompletionItems(): vscode.ProviderResult<vscode.CompletionItem[]>
    {
        const snippetCompletion = new vscode.CompletionItem('Good part of the day');
        snippetCompletion.insertText = new vscode.SnippetString('Good ${1|morning,afternoon,evening|}. It is ${1}, right?');

        return [snippetCompletion];
    }

commitCharacters

補完候補が1つまたは選択している場合、特定の文字を入力すると自動で補完が完了します。

この状態で「.」を入力すると「console.」と補完されます。
image.png

completion.ts
    public provideCompletionItems(): vscode.ProviderResult<vscode.CompletionItem[]>
    {
        const commitCharacterCompletion = new vscode.CompletionItem('console');
        commitCharacterCompletion.commitCharacters = ['.'];
        commitCharacterCompletion.documentation = new vscode.MarkdownString('Press `.` to get `console.`');

        return [commitCharacterCompletion];
    }

command

IntelliSenseを再トリガーする補完アイテムを使ってみます。

「new」を自動補完した後、続けて同じ入力補完を実行できるようになります。
insertTextでは「new」の後ろにスペースを追加しています。
Enterを押し続けると「new new new...」と連続で挿入できます。

image.png

completion.ts
    public provideCompletionItems(): vscode.ProviderResult<vscode.CompletionItem[]>
    {
        const commandCompletion = new vscode.CompletionItem('new');
        commandCompletion.insertText = 'new ';
        commandCompletion.command = { command: 'editor.action.triggerSuggest', title: 'Re-trigger completions...' };

        return [commandCompletion];
    }

triggerCharacters

特定の文字が入力されたときだけ入力補完する場合は、CompletionItemProviderの3引数目以降に追加していきます。
「.」が入力された場合だけ実行する場合は
registerCompletionItemProvider('plaintext', new Completions(), '.');
となります。

extension.ts
export function activate(context: vscode.ExtensionContext)
{
    const provider = vscode.languages.registerCompletionItemProvider('plaintext', new Completions(), '.');
    context.subscriptions.push(provider);
}

icon

completionsのtypeを指定することで補完候補のアイコンを指定することができます。

const commandCompletion = new vscode.CompletionItem('new');
commandCompletion.kind = vscode.CompletionItemKind.Keyword;

TextDocument

入力した内容を取得し処理を追加することができます。

provideCompletionItemsの引数にvscode.TextDocumentvscode.Positionを追加し、挿入した行を取得します。
「console.」で終わる文字だった場合にのみ、log,warn,errorの入力補完を追加します。

completion.ts
    public provideCompletionItems(document: vscode.TextDocument, position: vscode.Position): vscode.ProviderResult<vscode.CompletionItem[]>
    {
        const linePrefix = document.lineAt(position).text.substr(0, position.character);
        if (!linePrefix.endsWith('console.')) {
            return undefined;
        }

        return [
            new vscode.CompletionItem('log', vscode.CompletionItemKind.Method),
            new vscode.CompletionItem('warn', vscode.CompletionItemKind.Method),
            new vscode.CompletionItem('error', vscode.CompletionItemKind.Method),
        ];
    }

まとめ

入力文字取得してごにょごにょしてinsertTextするだけで便利なことできそう!

次回
SCode拡張機能を作ってみる3 - 文字の装飾

8
1
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
8
1