vscodeの拡張機能(Extension)を自作するためのTips


開発を進める時、「やりたいこと」をAPIのドキュメントから探すのは時間がかかります。
ですので、その時間を短縮するために、よく使いそうな記法をまとめてみたいと思います。
(より詳しく知りたい方は、[公式ドキュメント](https://code.visualstudio.com/api)をご覧ください)

# 拡張機能開発

## 始め方

https://code.visualstudio.com/api/get-started/your-first-extension

### 概略

npmで「[yo](https://www.npmjs.com/package/yo)」と「[generator-code](https://www.npmjs.com/package/generator-code)」 をインストールして、`$ yo code` を実行する。

<details><summary>環境用のDockerfile</summary>

```Dockerfile
FROM node:latest

RUN npm install -g yo generator-code vsce

USER node
```
</details>

## 入力を受け付ける
```typescript
const answer = await vscode.window.showInputBox({
    title: 'question is here.'
});
```

https://code.visualstudio.com/api/references/vscode-api#InputBoxOptions


## メッセージを表示する
```typescript
vscode.window.showInformationMessage(`show message`);
```


## 結果を別ページとして表示する

```typescript
    const panel = vscode.window.createWebviewPanel(
    'webViewの一意となる識別子',
    `WebViewTitle`,
    vscode.ViewColumn.One,
    {}
    );
    panel.webview.html = "";
```

https://code.visualstudio.com/api/extension-guides/webview


## 選択箇所を取得し、置換する

```typescript
const editor: vscode.TextEditor | undefined = vscode.window.activeTextEditor;
if (editor) {
    let text = editor.document.getText(editor.selection);
    editor.edit((editBuilder) => {
        editBuilder(editor.selection, "replaced");
    });
}
```


## 改行コードを取得する

```typescript
const lineSeparator: string = () => {
  const LF = 1;
  const CRLF = 2;
  const editor: vscode.TextEditor | undefined = vscode.window.activeTextEditor;
  if (editor) {
    if (editor.document.eol == LF) {
      return '\n'
    }
    if (editor.document.eof == CRLF) {
      return '\r\n';
    }
    return '\n';
  }
  return '';
};
```

# 拡張機能の設定

## 実装したExtensionを登録する

package.json
```json
{
  "activationEvents": [
    "onCommand:vscode.commands.registerCommand() で定義したcommand文字列"
	],
  "contributes": {
    "commands": [
      {
        "command": "vscode.commands.registerCommand() で定義したcommand文字列",
        "category": "「Git:clone」の「Git」の部分",
        "title": "「Git:clone」の「clone」の部分",
      }
    ]
  },
}
```

* https://code.visualstudio.com/api/references/contribution-points#contributes.commands
* https://code.visualstudio.com/api/references/activation-events

## 右クリックのメニューに追加する

package.json
```json
{
  "contributes": {
    "commands": [
      {
        "command": "vscode.commands.registerCommand() で定義したcommand文字列",
        "category": "「Git:clone」の「Git」の部分",
        "title": "「Git:clone」の「clone」の部分",
      }
    ],
    "menus": {
      "editor/context": [
        {
          "command": "vscode.commands.registerCommand() で定義したcommand文字列",
          "when": "editorHasSelection",
        }
      ]
    }
  }
}
```

※ 「"when": "editorHasSelection"」を設定した場合、選択している時のみ表示される
※ 右クリックメニューには、commands > title が表示される

* https://code.visualstudio.com/api/references/contribution-points#contributes.menus

## Explorer内での右クリックメニュー

package.json
```json
{
  "contributes": {
    "commands": [
      {
        "command": "vscode.commands.registerCommand() で定義したcommand文字列",
        "category": "「Git:clone」の「Git」の部分",
        "title": "「Git:clone」の「clone」の部分",
      }
    ],
    "menus": {
      "explorer/context": [
        {
          "command": "vscode.commands.registerCommand() で定義したcommand文字列",
        }
      ]
    }
  }
}
```

## コマンドパレット(Ctrl+Shift+P or F1)

※ contributes > commands に記載していれば自動的に登録される。細かい制御をしたい場合に追加することになる。

package.json
```json
{
  "contributes": {
    "commands": [
      {
        "command": "vscode.commands.registerCommand() で定義したcommand文字列",
        "category": "「Git:clone」の「Git」の部分",
        "title": "「Git:clone」の「clone」の部分",
      }
    ],
    "menus": {
      "commandPalette": [
        {
          "command": "vscode.commands.registerCommand() で定義したcommand文字列"
        }
      ]
    }
  }
}
```

* https://code.visualstudio.com/api/references/contribution-points#Context-specific-visibility-of-Command-Palette-menu-items


## settings.json でユーザーが設定できるようにする

package.json
```json
{
  "contributes": {
    "configuration": {
      "title": "Extension 内のサイドメニュー名",
      "properites": {
        "settings.json で設定する時のkey名(「title(lower camel case).設定する内容」が望ましい)": {
           "type": "number or string or boolean or null から設定。[] で囲えば、複数設定可能",
           "default": "デフォルト値があれば、設定する",
           "enum": ["selectで選択してほしい場合は、選択肢の値を設定"],
           "description": "説明を入力する。descriptionではなく、markdownDescription を使うことで、markdown形式も可能。"
        }
      }
    }
  }
}
```

* https://code.visualstudio.com/api/references/contribution-points#contributes.configuration

### Extension内で取得する

```typescript
const extensionConfig: vscode.WorkspaceConfiguration = vscode.workspace.getConfiguration('titleの値');

const settingValue: string = extensionConfig.get<string>("properties直下の(title.を除いた)キー名");
```

# さいごに

まだまだ設定できる内容もありますが、「作りたい！」と思い立った時に、とりあえず始めることができる情報をまとめることができたかな…と思います。(他にも、必要な情報がありましたら、ご意見いただけると嬉しいです)
また、公開されている拡張機能がどのように作られていて、どのように設定ができるのか・使えるのかを調べるための索引にもなれれば幸いです。

作成したものの公開や配布・個人利用をしたい方は、下記にまとめていますので、よろしければご覧ください。

https://qiita.com/tkts_knr/items/92a15a9fe7475418b333