日々是好日

プログラミングについてのあれこれ、ムダ知識など

sushi-buffetを支える技術

VSCode の背景にたくさんのお寿司を流す拡張機能を作りました。

twitter.com

言うまでもありませんが、完全なネタ拡張機能です。寿司だけに。

マーケットプレイスはこちら。

marketplace.visualstudio.com

Sushi Buffet とは

お寿司大好きな IT エンジニアの皆様が、コーディング中でも常にお寿司のことを 忘れないようにするための拡張機能です。

f:id:kcpoipoi:20190503171545g:plain

大量のお寿司を VSCode の背景に流す。ただそれだけ。

アニメーションはすべて CSS で表現しています。

github.com

お寿司を流すのに必要な技術

  • Node.js
  • TypeScript
  • CSS
  • ちょっとしたシェルコマンドの知識

どうやってお寿司を流しているのか

VSCode では、背景を操作できる API が提供されていません。

そのため背景を編集するには、VSCode の画面を構成するworkbench.main.cssを直接編集する必要があります。

workbench.main.css とは

VSCode の各種パーツの表現を担当しています。 Windows における標準的なパスは次の場所のようです。

C:\Users\user\AppData\Local\Programs\Microsoft VS Code\resources\app\out\vs\workbench\workbench.main.css

記述が圧縮されているので、解読はあまりおすすめできません。

何をしたのか

シェルコマンド(sed)でworkbench.main.cssの末尾に次のような記述を追加しました。

/*ext-sushi-buffet-start*/
body{
  background-image:
  url(sushi_akami.png),
  ... /*寿司25種分のURIを列挙*/
  url(sushi_uni.png);
  background-position:
  left top, 25% top, 50% top, 75% top, right top,
  ... /*25種それぞれの寿司についてポジションを設定*/
  right 75%,left bottom, 25% bottom, 50% bottom, 75% bottom, right bottom;
  background-repeat:no-repeat;
  background-attachment:fixed;
  background-size:auto 20%;
  opacity:0.8;
  animation:slideIn 2.5s ease-in-out 1s 1 normal
}

@keyframes slideIn {
  0% {
    opacity: 0.8;
    background-position:
    100% top, 150% top, 150% top, 150% top, 150% top,
    ... /*25種それぞれの寿司についてポジションを設定*/
    150% bottom, 150% bottom, 150% bottom, 150% bottom, 200% bottom;
  50% {
    opacity: 0.8;
    background-position:
    -200% top, 150% top, 150% top, 150% top, 150% top, 150% 25%,
    ... /*25種それぞれの寿司についてp(ry*/
    150% bottom, 150% bottom, 150% bottom, 150% bottom, -100% bottom;
  }
  100% {
    opacity: 0.8;
    background-position:
    left top, 25% top, 50% top, 75% top, right top,
    ... /*25種それz(ry*/
    left bottom, 25% bottom, 50% bottom, 75% bottom, right bottom;
  }
}
/*ext-sushi-buffet-end*/

シェルコマンドはどう記述したか

拡張機能開発は Node.js 上で行っているため、child-processパッケージのexecメソッドで実行しました。

import * as cp from 'child-process';

const delContent = `/\\*ext-${this.extName}-start\\*/.*/\\*ext-${this.extName}-end\\*/`;

//1. 既に workbench.main.css が編集されている場合、一度追加部分を消す(s|${delContent}||)
//2. 新しく文を追加する($a ${content})
//3. 空白行が発生するので消す(/^[<space><tab>]*$/d)
//4. -i オプションを付加しているのでそのまま上書き(${this.mainCssPath})
cp.exec(`sed -i -e "s|${delContent}||g" -e "$a ${content}" -e "/^[<space><tab>]*$/d" "${this.mainCssPath}"`, (err, stdout, stderr) => {
  if (err) {
    console.log(err);
  } else {
    console.log(stdout);
  }
});

${content}には、先ほど提示した CSS の文字列を突っ込みます。 -eで複数の条件を付けられるので便利ですね。

大変だったところ

  • シェルコマンド全然わからん(cdとかlsくらいしかわからん)
    • workbench.main.cssのパスをシェルコマンドの引数にしたら、Microsoft VS Codeの半角スペースで分割されてエラー吐いて詰む
  • $aで挿入すると余計な改行コード入って反映されへん
  • 空白行の消し方わからん
    • workbench.main.cssに空白行が入るとちゃんと反映されない
  • 拡張機能にリソースファイルを置いたときの取得方法わからん
  • CSS 触ったことない
  • ネット上に情報が無さすぎる

全体的に初めての試みが多すぎた開発でした。

感想

なんでわざわざシェルコマンドで挿入したのかといえば、 workbench.main.cssがあまりにも長く、

「末尾に追記するだけなのに、プログラム上で中身取得する必要ないのでは?」

というイキり発想が降りてきたためです。

結果的にコマンドだけでコンパクトに構成できたので、 開発者的には満足です。

あと CSS アニメーションを Infinite とかにすれば永遠にお寿司流せるかも。

参考にさせてもらったサイトなど

bachground-cover

marketplace.visualstudio.com

ラブライブ!仕様開発環境 Visual Studio Code

learn-with-muse.sato-t.net

Visual Studio Code(Ver. 0.5.0以降)でプロ生ちゃんを召喚する方法

chronoir.net