孤独のグルメ風にプログラミングがしたかったからVSCodeの拡張機能を作った

> 「時間や社会にとらわれず、幸福に空腹を満たすとき、彼はつかの間自分勝手になり、「自由」になる。孤独のグルメ―。それは、誰にも邪魔されず、気を使わずものを食べるという孤高の行為だ。そして、この行為こそが現代人に平等に与えられた、最高の「癒し」といえるのである。」
(孤独のグルメ 第一巻より)

『孤独のグルメ』をご存知だろうか。
1994年から連載され、1997年に単行本化、その後TVドラマシリーズ化もされた、ロングセラーの漫画である。

この漫画の中で主人公である井之頭五郎（いのがしら ごろう）はとにかく食べる。食べて食べて食べまくる。
そこにTV番組のような詳細な食レポは一切ない。
一人で食べるので感想を言い合うこともない。

しかし、頭の中は一口ごとに幸せに満ち溢れ、つい気持ちが心の声として零れ出る。
「...」（いいぞいいぞ）
「...」(こういうのでいいんだよ)
「...」(良いセンスしてるなあ)

それはなんて幸せで満ち足りている食事体験なんだろう。
静寂の中でありながら、至極の一皿を前に対話をせずにはいられない。

そこで私は気づいたのだ。
それは、我々プログラマにとって見習うべき姿勢なのではないか、と。

プログラマにとってプログラムを書くことは食事をするにも等しい欲求であろう。
であれば、彼の生き様をプログラミングに当てはめることで、より高みへと至ることができるのではなかろうか。

よし、私も井之頭五郎のようにプログラミングをしよう。

（ポエム終了）

# 何を作るのか

井之頭五郎は食べるときは無言でも、頭の中では食事を後押しするように「うまい！」「いいぞ〜」とコメントが浮かんでいます。
![shokuji.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/401312/4f3989ba-4fd0-30bb-afe7-da4b3adfa12d.png)

そのため、自分もプログラムを書いているときに「うまい！」「いいぞ〜」と考えれば良いわけです。

![computer.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/401312/3eb38e20-cdfa-44bf-722a-e00d9f7b0743.png)

ただ、そんな事をずっと考えていたらプログラム書けなくなっちゃいます。
なので、自分の頭の代わりに画面に表示すれば良いのかなと考えました。

つまり、タイピングが捗ってきたら画面に井之頭五郎風コメントを表示するわけです。
私は普段プログラムを書くときはVSCodeをよく使っています。そのため、今回はVSCode向けの拡張機能でタイピング体験を幸せにする「InogashiraMode(井之頭モード)」を作ってみようと思います。

# 開発

VSCode拡張機能を作るので、セオリー通り[公式ドキュメント](https://code.visualstudio.com/api/get-started/your-first-extension)を参考にしました。
Node.jsとGitが入っている前提でYeomenとVSCode拡張機能ジェネレータをインストールするらしいです。

```sh
npm install -g yo generator-code
```

下記でまずはプロジェクトを作ります。

```sh
% yo code
? ==========================================================================
We're constantly looking for ways to make yo better!
May we anonymously report usage statistics to improve the tool over time?
More info: https://github.com/yeoman/insight & http://yeoman.io
========================================================================== No

     _-----_     ╭──────────────────────────╮
    |       |    │   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? InogashiraMode
? What's the identifier of your extension? inogashiramode
? What's the description of your extension?
? Initialize a git repository? Yes
? Bundle the source code with webpack? No
? Which package manager to use? npm
   create inogashiramode/.vscode/extensions.json
   create inogashiramode/.vscode/launch.json
   create inogashiramode/.vscode/settings.json
   create inogashiramode/.vscode/tasks.json
   create inogashiramode/src/test/runTest.ts
   create inogashiramode/src/test/suite/extension.test.ts
   create inogashiramode/src/test/suite/index.ts
   create inogashiramode/.vscodeignore
   create inogashiramode/.gitignore
   create inogashiramode/README.md
   create inogashiramode/CHANGELOG.md
   create inogashiramode/vsc-extension-quickstart.md
   create inogashiramode/tsconfig.json
   create inogashiramode/src/extension.ts
   create inogashiramode/package.json
   create inogashiramode/.eslintrc.json

I'm all done. Running npm install for you to install the required dependencies. If this fails, try running the command yourself.
```

プロジェクトができあがります。
この状態で左側のデバッグビューからデバッグを実行すると、その拡張機能がインストールされた状態のVSCodeウィンドウが立ち上がり、挙動を確認できます。

そのサンプルプロジェクトを元にして下記のようにプログラムを書いてみました。
仕様としては、1.5秒以内にタイピングをし続けるとコンボが貯まり、20コンボごとに配列に指定した文字がランダムに表示されるというものです。

```typescript:src/extension.ts
import * as vscode from 'vscode';

const comboThreshold = 20;
const timeThreshold = 1.5;

const words:string[] = [
	'いいぞ〜',
	'いいぞいいぞ',
	'ふむふむ',
	'こういうの結構難しいんだよな',
	'いいじゃないか',
	'そういうことだよな',
	'うんうん',
	'こういうのでいいんだよ',
	'大正解だ',
	'問答無用のうまさだなあ',
	'素晴らしい',
	'良いセンスしてるなあ',
	'これは良い',
	'心憎いなぁ',
	'うますぎる',
	'最高だ',
];

let combo = 0;
let lastTime = new Date().getTime();

export function activate(context: vscode.ExtensionContext) {

	console.log('Congratulations, your extension "inogashiramode" is now active!');

    vscode.workspace.onDidChangeTextDocument(event => {

		let nowTime = new Date().getTime();
		var diffTime = nowTime - lastTime;

		if (diffTime / 1000 < timeThreshold){
			combo++;

			if(combo % comboThreshold === 0){
				vscode.window.showInformationMessage(words[Math.floor(Math.random() * words.length)]);
			}
		} else {
			combo = 0;
		}

		lastTime = nowTime;

	}, null, context.subscriptions);
}

export function deactivate() {
	console.log('"inogashiramode" is now deactive! Thank you for using!');
}
```

下記はプロジェクト設定用のファイルです。

```json:package.json
{
	"name": "inogashiramode",
	"publisher": "ayatothos",
	"displayName": "InogashiraMode",
	"description": "Make your typing experience happy.",
	"version": "0.0.1",
	"engines": {
		"vscode": "^1.52.0"
	},
	"categories": [
		"Other"
	],
	"activationEvents": [
		"*"
	],
	"main": "./out/extension.js",
	"contributes": {
	},
	"scripts": {
		"vscode:prepublish": "npm run compile",
		"compile": "tsc -p ./",
		"watch": "tsc -watch -p ./",
		"pretest": "npm run compile && npm run lint",
		"lint": "eslint src --ext ts",
		"test": "node ./out/test/runTest.js"
	},
	"devDependencies": {
		"@types/vscode": "^1.52.0",
		"@types/glob": "^7.1.3",
		"@types/mocha": "^8.0.4",
		"@types/node": "^12.11.7",
		"eslint": "^7.15.0",
		"@typescript-eslint/eslint-plugin": "^4.9.0",
		"@typescript-eslint/parser": "^4.9.0",
		"glob": "^7.1.6",
		"mocha": "^8.1.3",
		"typescript": "^4.1.2",
		"vscode-test": "^1.4.1"
	},
	"repository": {
		"type": "git",
		"url": "https://github.com/ayatothos/inogashiramode.git"
	}
}
```

# 完成

井之頭モードが完成しました！
文章を打っていくと右下にコメントが出るようになっています。
テキストの変更を検知しているだけなので削除でも反応します。

![inogashira.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/401312/9923c9db-7d6b-2d6b-f320-fd32b3cd5a0d.gif)

# 公開

[公式の手順](https://code.visualstudio.com/api/working-with-extensions/publishing-extension)を参考にマーケットプレースにも上げて公開してみました。

リポジトリ：https://github.com/ayatothos/inogashiramode
マーケットプレース：https://marketplace.visualstudio.com/items?itemName=ayatothos.inogashiramode

VSCodeの拡張機能ビューから`InogashiraModeで`検索すると出てくるかと思います。

孤独のグルメファンの方や酔狂な方は入れてみてください。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/401312/b2a80b14-ea59-281a-35fc-3e99fce480d3.png)

それでは！