GWの趣味プロ：vs code extension をつくって作業効率化する話

## はじめに
大量のファイルの中に大量の置換文字列を含むプロジェクトってありますよね？
全置換するツールを作りたいけれども、完全に機械的に置換できない微妙なファイル。

機械的に置換できそうな部分（正規表現で表現できそうな部分）をぐいっと選択してコマンドパレットからコマンド一撃で置換できたら瞬殺じゃない？しかも**vs code の extension 作成めちゃんこ簡単そう**ってことで作りました。


## 事前準備

- nodist + node 16.15.0
- yo
- genarator-code

```
# nodist のページからインストーラーをダウンロードしてインストール
# choco でインストールすると深いフォルダにインストールされるので手動で浅いフォルダにインストールした方がよさそう
https://github.com/nullivex/nodist/releases

# npm が動作しない時に実行
nodist npm match
# yo, generator-code をインストール
npm install yo generator-code -g
```

※node 環境があれば nodist ではなくてもよいです。(nvm-windows, volta, ...)


## プロジェクトを作成する

`yo code` を実行していつものおじさんの質問に答えてプロジェクトを作成しましょう。

```
yo code


     _-----_     ╭──────────────────────────╮
    |       |    │   Welcome to the Visual  │
    |--(o)--|    │   Studio Code Extension  │
   `---------´   │        generator!        │
    ( _´U`_ )    ╰──────────────────────────╯
    /___A___\   /
     |  ~  |
   __'.___.'__
 ´   `  |° ´ Y `

? What type of extension do you want to create? New Extension (TypeScript)
? What's the name of your extension? {your project name}
? What's the identifier of your extension? {your identifier name}
? What's the description of your extension? 
? Initialize a git repository? Yes
? Bundle the source code with webpack? No       
? Which package manager to use? yarn
```

プロジェクトができたら `F5`で実行します。
エクステンションがインストールされた状態の vs code が起動してデバッグできます。


## extension.ts を見る

主にコードを書くのは extension.ts になります。
作成した時点では、コマンドを実行すると hello と表示されるだけの extension になっています。
register command の中身を変更すれば良さそうなことが分かると思います。

```
// The module 'vscode' contains the VS Code extensibility API
// Import the module and reference it with the alias vscode in your code below
import * as vscode from 'vscode';

// this method is called when your extension is activated
// your extension is activated the very first time the command is executed
export function activate(context: vscode.ExtensionContext) {
	
	// Use the console to output diagnostic information (console.log) and errors (console.error)
	// This line of code will only be executed once when your extension is activated
	console.log('Congratulations, your extension "{your project name}" is now active!');

	// The command has been defined in the package.json file
	// Now provide the implementation of the command with registerCommand
	// The commandId parameter must match the command field in package.json
	let disposable = vscode.commands.registerCommand('{your project name}.hello', () => {
		// The code you place here will be executed every time your command is executed
		// Display a message box to the user
		vscode.window.showInformationMessage('Hello World from {your project name}!');
	});

	context.subscriptions.push(disposable);
}

// this method is called when your extension is deactivated
export function deactivate() {}

```

とりあえずは、Hello というコマンド名を変えてみると理解が深まると思います。


## サンプルを見る

しかしそれだけでは、選択したテキストを操作する方法はさっぱりわからないので、以下のサイトよりサンプルを取得しよう。

https://github.com/microsoft/vscode-extension-samples/

```
git clone https://github.com/Microsoft/vscode-extension-samples
```

今回やりたいことに近いのは、`document-editing-sample` っぽいのでそのプロジェクトの、`extension.ts` を見ることにしました。

https://github.com/microsoft/vscode-extension-samples/blob/main/document-editing-sample/src/extension.ts
```
'use strict';

import * as vscode from 'vscode';

export function activate(context: vscode.ExtensionContext) {
	const disposable = vscode.commands.registerCommand('extension.reverseWord', function () {
		// Get the active text editor
		const editor = vscode.window.activeTextEditor;

		if (editor) {
			const document = editor.document;
			const selection = editor.selection;

			// Get the word within the selection
			const word = document.getText(selection);
			const reversed = word.split('').reverse().join('');
			editor.edit(editBuilder => {
				editBuilder.replace(selection, reversed);
			});
		}
	});

	context.subscriptions.push(disposable);
}
```

驚く程簡単。
word を reversed にしている部分を書き換えればよさそうだ。
修正したらエクステンションを実行している vscode を閉じて、`F5`で再実行。


## まとめ

ということで小一時間でエクステンションが書けました。

新人さん向け課題としてもちょうどよさそうだし、脳死反復作業をプログラムの力で解決するのはよいことなだと思います。
プロジェクトメンバーに配布すれば、アウトプットが均質化されるのも魅力的です。

もしも身の回りに反復作業があるようなら、extension 作成してみてはいかがでしょうか？