序章

Visual Studio Code は、Windows、Linux、およびmacOSで使用できるMicrosoftのコードエディターです。 Visual Studio Code Marketplace からインストールして、エディターの追加機能を利用できる拡張機能を提供します。 必要な機能を正確に実行する拡張機能が見つからない場合は、独自の拡張機能を作成することができます。

この記事では、最初のVisualStudioCode拡張機能を作成します。

前提条件

このチュートリアルを完了するには、次のものが必要です。

このチュートリアルは、ノードv14.4.0、npm v6.14.5、yo v3.1.1、およびgenerator-codev1.2.16で検証されました。

ステップ1—ツールのインストール

Visual Studio Codeチームは、拡張機能を作成するためのジェネレーターを作成しました。このジェネレーターは、拡張機能の作成を開始するために必要なすべてのスターターファイルを生成します。

VS Code Extensionsの開発を開始するには、2つの異なるnpmパッケージが必要です。

  • yo Yoomanのコマンドラインインターフェイス。
  • generator-code -VisualStudioCode拡張機能を作成するためのYeomanジェネレーター。

Visual Studio Codeの組み込みターミナルを使用して、 npxを使用してyoおよびgenerator-codeのローカルコピーを実行してから、コマンドyo codeを実行できます。新しいプロジェクトを初期化するには:

  1. npx -p yo -p generator-code yo code

この時点で、Yeomanはコードジェネレーターを実行します。

ステップ2—最初の拡張機能を作成する

これで、最初の拡張機能を作成する準備が整いました。

次に、プロジェクトに関するいくつかの質問に答えます。 作成する拡張機能の種類と、「TypeScript」と「JavaScript」のどちらかを選択する必要があります。 このチュートリアルではJavaScriptを選択します。

Output of questions to answer

次に、さらにいくつかの質問が表示されます。 このチュートリアルでは、次の選択肢が選択されました。

? What type of extension do you want to create? New Extension (JavaScript)
? What's the name of your extension? testytest
? What's the identifier of your extension? testytest
? What's the description of your extension? This is a test extension
? Enable JavaScript type checking in 'jsconfig.json'? Yes
? Initialize a git repository? Yes
? Which package manager to use? npm

このプロセスが完了すると、開始するために必要なすべてのファイルが作成されます。 最も重要な2つのファイルは次のとおりです。

  • package.json
  • extension.js

package.jsonを開いて、見てみましょう。 名前、説明などが表示されます。 非常に重要なセクションがさらに2つあります。

  • activationEvents:これは拡張機能をアクティブにするイベントのリストです。 拡張機能は遅延読み込みされるため、これらのアクティブ化イベントのいずれかが発生するまでアクティブ化されません。
  • commands:拡張機能を介して実行するためにユーザーに提供するコマンドのリスト。

すぐにこれらに戻ります。

package.json
{
  // ...
  "activationEvents": [
    "onCommand:testytest.helloWorld"
  ],
  "main": "./extension.js",
  "contributes": {
    "commands": [
      {
        "command": "testytest.helloWorld",
        "title": "Hello World"
      }
    ]
  },
  // ...
}

extension.jsファイルもご覧ください。 ここで、拡張機能のコードを記述します。 ここにいくつかの定型コードがあるので、それを分解してみましょう。

以下の強調表示された行は、コマンドがVSCodeに登録されている場所です。 この名前helloWorldは、package.jsonのコマンドと同じであることに注意してください。 これは意図的なものです。 package.jsonは、ユーザーが使用できるコマンドを定義しますが、extension.jsファイルはそのコマンドのコードを登録します。

extension.js
// ...

/**
 * @param {vscode.ExtensionContext} context
 */
function activate(context) {
  console.log('Congratulations, your extension "testytest" is now active!');

  let disposable = vscode.commands.registerCommand('testytest.helloWorld', function () {
    vscode.window.showInformationMessage('Hello World from testytest!');
  });

  context.subscriptions.push(disposable);
}

// ...

このHello Worldの例では、このコマンドが実行するのは、ユーザーに「HelloWorld」メッセージを表示することだけです。

ステップ3—拡張機能のデバッグ

必要なファイルがすべてインストールされたので、拡張機能を実行できます。

.vscodeフォルダーは、VSCodeがプロジェクトのある種の構成ファイルを格納する場所です。 この場合、デバッグ構成を含むlaunch.jsonが含まれています。

.vscode / launch.json
// ...
{
  // ...
  "configurations": [
    {
      "name": "Run Extension",
      "type": "extensionHost",
      "request": "launch",
      "runtimeExecutable": "${execPath}",
      "args": [
        "--extensionDevelopmentPath=${workspaceFolder}"
      ]
    },
    // ...
  ]
}

ここから、デバッグできます。 画面左側の左側にあるdebugタブを開き、「再生」アイコンをクリックします。

Debug mode on

これにより、VS Codeの新しい(デバッグ)インスタンスが開きます。

Debug instance opened up

このVSCodeのデバッグインスタンスを開いた状態で、Macの場合はCOMMAND+SHIFT+P、Windowsの場合はCTRL+SHIFT+Pでコマンドパレットを開き、 HelloWorldを実行できます。

Running Hello World

右下隅に「HelloWorld」メッセージがポップアップ表示されます。

ステップ4—拡張機能を編集する

コードに取り組む前に、package.jsonファイルのactivationEventsセクションをもう一度見てみましょう。 繰り返しになりますが、このセクションには、発生するたびに拡張機能をアクティブ化するイベントのリストが含まれています。 デフォルトでは、コマンドの実行時にアクティブになるように設定されています。

理論的には、このイベントは何でもかまいません。より具体的には、*何でもかまいません。 アクティベーションイベントを*に設定すると、VSCodeの起動時に拡張機能が読み込まれることを意味します。 これは決して必要ではなく、メモだけです。

package.json
{
  // ...
  "activationEvents": [
    "*"
  ],
  // ...
}

必要なファイルがあり、デバッグ方法を知っています。 それでは、拡張機能の構築を始めましょう。 この拡張機能で、ボイラープレートコードがすでに含まれていて、プロジェクトに追加されているHTMLファイルを作成できるようにしたいとします。

まず、コマンドの名前を更新しましょう。 extension.jsで、コマンド名をextension.helloworldからextension.createBoilerplateに更新します。

extension.js
// ...

/**
 * @param {vscode.ExtensionContext} context
 */
function activate(context) {
  console.log('Congratulations, your extension "testytest" is now active!');

  let disposable = vscode.commands.registerCommand('testytest.createBoilerplate', function () {
    vscode.window.showInformationMessage('Hello World from testytest!');
  });

  context.subscriptions.push(disposable);
}

// ...

次に、コマンドの変更に応じてpackage.jsonファイルを更新します。

package.json
{
  // ...
  "activationEvents": [
    "onCommand:testytest.createBoilerplate"
  ],
  "main": "./extension.js",
  "contributes": {
    "commands": [
      {
        "command": "testytest.createBoilerplate",
        "title": "Create Boilerplate"
      }
    ]
  },
  // ...
}

それでは、機能を書いてみましょう。 最初に行うことは、いくつかのパッケージを必要とすることです。 fs(ファイルシステム)およびpathモジュールを使用します。

extension.js
const fs = require('fs');
const path = require('path');

また、現在のフォルダーへのパスを取得する必要があります。 コマンド内に、次のスニペットを追加します。

extension.js
if (!vscode.workspace) {
  return vscode.window.showErrorMessage('Please open a project folder first');
}

const folderPath = vscode.workspace.workspaceFolders[0].uri
  .toString()
  .split(':')[1];

また、ボイラープレートHTMLコードを変数に格納して、ファイルに書き込むことができるようにする必要があります。 ボイラープレートHTMLは次のとおりです。

extension.js
const htmlContent = `<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  <meta http-equiv="X-UA-Compatible" content="ie=edge" />
  <title>Document</title>
  <link rel="stylesheet" href="app.css" />
</head>
<body>
  <script src="app.js"></script>
</body>
</html>`;

次に、ファイルに書き込む必要があります。 ファイルシステムモジュールのwriteFile関数を呼び出して、フォルダーパスとHTMLコンテンツに渡すことができます。

パスモジュールを使用して、フォルダーパスを作成するファイルの名前と組み合わせることに注意してください。 次に、コールバック内でエラーが発生した場合、それをユーザーに表示します。 それ以外の場合は、ボイラープレートファイルが正常に作成されたことをユーザーに通知します。

extension.js
fs.writeFile(path.join(folderPath, 'index.html'), htmlContent, (err) => {
  if (err) {
    return vscode.window.showErrorMessage('Failed to create boilerplate file!');
  }
  vscode.window.showInformationMessage('Created boilerplate files');
});

完全な関数は次のようになります。

extension.js
//...
  let disposable = vscode.commands.registerCommand(
    'testytest.createBoilerplate', async function () {
    // The code you place here will be executed every time your command is executed

    if (!vscode.workspace) {
      return vscode.window.showErrorMessage('Please open a project folder first');
    }

    const folderPath = vscode.workspace.workspaceFolders[0].uri
      .toString()
      .split(':')[1];

    const htmlContent = `<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  <meta http-equiv="X-UA-Compatible" content="ie=edge" />
  <title>Document</title>
  <link rel="stylesheet" href="app.css" />
</head>
<body>
  <script src="app.js"></script>
</body>
</html>`;

    fs.writeFile(path.join(folderPath, 'index.html'), htmlContent, (err) => {
      if (err) {
        return vscode.window.showErrorMessage(
          'Failed to create boilerplate file!'
        );
      }
      vscode.window.showInformationMessage('Created boilerplate files');
    });

    // ...
  }
// ...

先に進み、新しく開発した拡張機能をデバッグします。 次に、コマンドパレットを開き、ボイラープレートの作成を実行します(名前を変更したことを思い出してください)。

Running Create Boilerplate in the Command palette

コマンドを実行すると、新しく生成されたindex.htmlファイルと、ユーザーに通知するメッセージが表示されます。

The newly generated index.html file

結論

使用するAPIとその使用方法の詳細については、Visual Studio Code ExtensionAPIのドキュメントをお読みください。

このチュートリアルのコードは、GitHubで入手できます。