Shiopon Labo

しおぽん(@shiopon01)の個人ブログです

VSCodeの設定・拡張機能を環境間で共有する

追記

こんなものがあるらしい。この記事いらんやんけ!

github.com

本題

VSCodeの設定を環境間で共有するのはまあまあ面倒くさい(自分はMac/Ubuntuで設定を共有している)。この記事ではそのあたりについて言述する。

共有したい設定

VSCodeで共有しておきたい設定は次の2つ。

settings.json はOSによって保存場所が違うみたいで、例えば UbuntuLinux) だと .config の下とかに保存されているが、 Mac だともっと深いところに保存されている。

  • Windows %APPDATA%\Code\User\settings.json
  • Mac $HOME/Library/Application Support/Code/User/settings.json
  • Linux $HOME/.config/Code/User/settings.json

setting.json は bashrc のように dotfiles のリポジトリ等でファイルを管理して、上記の場所にシンボリックリンク等を張れば共有することができるので、難しくはない。

ln -s $HOME/rc/settings.json $HOME/.config/Code/User/settings.json

code.visualstudio.com

曲者なのが拡張機能で、拡張機能本体の容量がまあまあ大きいのでそのままリポジトリ等で管理するわけにはいかない。(できないこともないが、 push や clone にめっちゃ時間がかかったりする)

そのため、拡張機能拡張機能の名前のリストのみ管理することにする。これには code --list-extensions コマンドが利用でき、これでインストールされている拡張機能のリストを出力することができる。(Maccode コマンドを使うのに少し設定が必要らしい https://code.visualstudio.com/docs/setup/mac

$ code --list-extensions
bungcip.better-toml
codezombiech.gitignore
Compulim.vscode-clock
dbaeumer.vscode-eslint
...

この出力結果をファイルに保存してリポジトリとかで管理して共有する。

code --list-extensions > $HOME/rc/extensions

このファイルから1発でインストールできたらいいけど、ドキュメント見たかんじ欲しいコマンドは無さそう…。

code.visualstudio.com

出力した拡張機能リストからのダウンロードには code --install-extension を使う。ただし、ドキュメントにあるように1つづつしかダウンロードできないため、ファイルの行をループして1つづつインストールしていく。このスクリプトも extensions のファイルと一緒に管理しておこう。

while read ext; do
  code --install-extension $ext
done <$HOME/rc/extensions

一応、実行したらこんなかんじ。

$ sh install.sh 
Found 'bungcip.better-toml' in the marketplace.
Installing...
Extension 'bungcip.better-toml' v0.3.2 was successfully installed!
Found 'codezombiech.gitignore' in the marketplace.
Installing...
Extension 'codezombiech.gitignore' v0.6.0 was successfully installed!
Found 'compulim.vscode-clock' in the marketplace.
Installing...
Extension 'compulim.vscode-clock' v0.0.1 was successfully installed!
Found 'dbaeumer.vscode-eslint' in the marketplace.
Installing...
...

まとめ

環境の共有には次の手順が必要。

$HOME/rc/vscode/settings.json$HOME/rc/vscode/extensions が存在している状態なら次のスクリプトでなんとかなる。(Windowsなし)

# setting.json

if [ "$(uname)" == 'Darwin' ]; then
  SETTINGS_PATH="$HOME/Library/Application Support/Code/User/settings.json"
elif [ "$(expr substr $(uname -s) 1 5)" == 'Linux' ]; then
  SETTINGS_PATH="$HOME/.config/Code/User/settings.json"
elif [ "$(expr substr $(uname -s) 1 10)" == 'MINGW32_NT' ]; then                                                                                           
  echo "Windows is not supported."
  exit 1
else
  echo "Your platform ($(uname -a)) is not supported."
  exit 1
fi

ln -s $HOME/rc/vscode/settings.json $SETTINGS_PATH

# install extensions

while read ext; do
  code --install-extension $ext
done <$HOME/rc/vscode/extensions

echo 'done.'

Homebrew を使うなら brew bundle を使っていくべきだ

Homebrew はMacユーザーなら知らぬものはいないレベルで有名なパッケージマネージャーだ。
きのこたけのこのように MacPorts と戦わされがちなポジション。僕はたけのこ派

Homebrew でパッケージをインストールするときは通常 brew install を使うが、実は Brewfile というものを使って複数パッケージをまとめてインストールすることもできる。RubyでのGemfile、Nodeでのpackage.jsonみたいなもので、使ってない人はとりあえず使ったほうが良い。

とりあえずHomebrewのインストール。公式のやつをコピペしよう。

/usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"

brew.sh

この後すぐBrewfileを用意して brew bundle を行う。

自分が普段使っているBrewfileはこちら。こう見るとぜんぜん使ってないものばっかりだ。(人のこういうファイルを見るのが好きなのでみんな晒してくれ)

gist.github.com

追加で brew install したくなった時は気持ちをぐっとこらえ、このファイルに追記して brew bundle を行う。

使い方としては、このファイルをローカルに落として brew bundle を実行するだけ。App Storeのアプリを落としてくれる mas では初回の警告が出るかもしれない。また、 ## mas kakin 以下の行は課金アプリで購入していないと普通にエラーを吐くと思うので、そのまま使う場合はコメントアウトするなりしてもらいたい。

$ curl https://gist.githubusercontent.com/shiopon01/a584cc20552cf3eed3012865c0b020c5/raw/298d9ff2a48783ac64ac4f2bd5c40177213b47c3/Brewfile > Brewfile
$ brew bundle

インストール後はインストールした Alfred 3Karabiner-Elements などいくつかの常駐アプリの起動と設定、 nodenvgoenv でのプログラミング言語インストールを行う。

ショートカット

SkitchのスクショのショートカットがMacOSのものと被るので注意。自分はMacOSの方をOFFにしている。

f:id:shiopon01:20190102024539p:plain

明けましておめでとうございます。抱負など

明けましておめでとうございます!

1995年生まれ男の自分は今年は猪年の年男でもあり、本厄の年でもあります。厄年でもあるので慎重に、しかし猪年らしく 一意専心 に何事にも取り組んでいける年にできたらなと思います。

ちなみにFGO福袋は酒呑童子が出ました。はじめての★5アサシンありがとう!

f:id:shiopon01:20190101013631j:plain

新年の抱負

抱負なのであんまり公言するものでもありませんが、2019年は何かまじめなサービスをリリースすることを考えています。ユーザー○人獲得とかではなくて、単純にリリースすることが目標です。

これは実は2018年後半から考えていて、せっかく個人のサービスなら流行りのアーキテクチャとか技術をもりもり積んでいこうということで、そういうインプットをなんやかんや去年からやっています。(勉強すればするほど学ばないといけないことが増える辛さ)

具体的に自分がずっと学生時代から作りたいともんもんと考えていたアプリは次の2つ。

どちらも設計の段階で他のアプリの劣化のように思えてきて何度か挫折してきたものです。

学生の頃はOICのメディアフロンティアのためにRailsとかでこれらのプロトタイプを作成したりしましたが、こういう挫折もあって方向性を見失い、結局お蔵入りとなったり…。

どちらも大きくシェアを取っているアプリがすでに存在している分野でもあるので、今更同じ土俵にあがるのも…と気負いするところでもありますが、まあ個人アプリなんで、そのあたりは気にせず良い所はパクる精神で今年はゆるゆる作っていけたらなと思います。

他の抱負で言うと、最近練習し始めた絵描きでマシな絵を書けるようになるとか、結局学ぶだけ学んで大したものを生み出せてないAfter Effectsで映像作品を作るなど。文字だけでなく動画や音声でのアウトプットを行ってみたいという気持ちもあるので、そういうのもあります。

あ、あとIIDXで十段を取りたい!(PEN以来まともにやってないブランクもあって現在悲しみの1曲目落ち)

f:id:shiopon01:20190101021149j:plain

以下まとめです。2019年の shiopon01 の活躍にご期待ください。

  • サービスをリリース
  • After Effectsで映像作品を作る
  • マシな絵を書けるようになる
  • 映像や音声でのアウトプット手段の模索
  • IIDX十段取得
  • TOEIC 500点
  • etc(考え中)

(絵の練習はPixivのSenseiがまじで良いです)

sensei.pixiv.net

2018/1/1のステータス

  • 身長:174cm
  • 体重:77.2kg
  • TOEIC:310点くらい

今年は体重を減らすか、キープか増えるにしても筋肉で……が目標…。

Node.jsの初見殺し (x) => (y) => { ... }

引数定義する部分が2つある関数定義、まさに初見殺し。

const a = (x) => (y) => {
 console.log(x * y)
}

ただでさえ function (x) { ... }シンタックスシュガーみたいな (x) => { ... } (アロー関数)があったりするのに、アロー関数には引数定義が2つ付いた (x) => (y) => { ... } みたいな定義方法もある。調べても情報が多くないように思うし、そもそも調べ方もよく分からないかんじがある。この記事はこれの話。( this とかには触れない)

カリー化

さて、結論から言うとこれは カリー化 と呼ばれるもので、先述した関数定義は次の構文のシンタックスシュガーみたいなものである。カリー化についてはいろいろ記事があると思うので 部分適応カリー化 で検索してもらえたらと思う。

const a = function (x) {
  return function (y) {
    console.log(x * y)
  }
}

これは見たとおり、定義した a は引数 x を受け取って新しい関数を生成する関数だ。ここで生成される関数は最初に渡される x を保持しているので、 function (y) の中でも x を利用できる。

実際に 2 を渡して実行してみても、関数が生成されていることが分かる。この関数はもちろん 2 を保持している。

$ node
> const a = (x) => (y) => {
... console.log(x * y)
... }
undefined
> a (2)
[Function]

生成された関数は引数 y を受け取って console.log するだけのものだ。計算に使う x は最初の a (2) で渡したものが引き継がれている。

次の2つは呼び出し方は違うが、結果は同じものである。これは生成された関数に 3 を渡してそのまま実行するパターン。

> a (2)(3)
6

そしてこれが、関数を一旦変数にいれてから 3 を渡して実行するパターン。そのまま実行するパターンではカリー化するメリットが無いので、ふつうはこうやって使う。

> const b = a(2)
[Function]
> b (3)
6

ちなみに関数定義ではいくらでも引数の定義をアローで繋げることができて、つなげた分だけ階層を深くすることができる。好きなだけ繋げるべし。

> const c = (x) => (y) => (z) => {
... console.log (x + y + z)
... }
undefined
> c (1)(2)(3)
6

使い方

この構文を使うタイミングについて少し言述する。

カリー化とはつまり、新たな関数を生み出して処理の共通化を行うためのアプローチだ。関数を生成する際に様々な設定値などを渡すことで、最適な新たな関数を生み出すことができる。この結果、何度も呼び出すが決め打ちの引数が入る煩わしい関数のをスマートに定義することができるようになる。

ありがちだが、例えば次のプログラムは消費税を計算するものだ。ここでは calcJPTax という日本の消費税を計算する新しい関数を生成している。この関数を生成する際に渡す数値を変えて複数定義すれば、国に対応した消費税計算関数を簡単に作成することができる。

const product = (tax) => (value) => {
  return (value * tax)
}

const calcJPTax = product (1.08)

console.log(calcJPTax(100)) //=> 108

少し難しいが、カリー化する際に関数を渡すこともできる。これを使うことで好きな処理を関数に差し込むことができる。

これはコンソールに値を出力する関数で、最初に渡す関数の返り値によって内容を変更できる。

const say = (func) => (value) => {
  return console.log(func(value))
}

const sayHello = say ((name) => {
  return 'Hello, ' + name
})

sayHello('Mario') //=> 'Hello, Mario'

などなど。様々な場面で使いみちがある。

E: パッケージ ○○ を再インストールする必要がありますが、そのためのアーカイブを見つけることができませんでした。

E: パッケージ virtualbox-6.0 を再インストールする必要がありますが、そのためのアーカイブを見つけることができませんでした。

こいつに時間食われたのでシェア。

やりたいこと

こいつを消したい。

$ sudo dpkg -l | grep virtualbox-6.0
iFR virtualbox-6.0        6.0.0-127566~Ubuntu~bionic        amd64    Oracle VM VirtualBox

minikube start したらVirtualBoxでエラーが出たので、 dpkg -i virtualbox〜〜 とかやってたらますますおかしくなったパターン)

いけたやつ

もし debconf: DbDriver "config": /var/cache/debconf/config.dat is locked by another process: Resource temporarily unavailable のエラーが出たらとりあえず rm /var/cache/debconf/*.dat したらなんとかなる。

自分の場合はこれでいけた。

$ sudo rm /var/cache/debconf/*.dat 

$ sudo dpkg -P --force-remove-reinstreq virtualbox-6.0
dpkg: 警告: --force が有効なので、問題を無視します:
dpkg: 警告: パッケージが非常に矛盾した状態に陥りました。
削除を行う前にこのパッケージを再インストールすべきです
(データベースを読み込んでいます ... 現在 223431 個のファイルとディレクトリがインストールされています。)
virtualbox-6.0 (6.0.0-127566~Ubuntu~bionic) を削除しています ...
virtualbox-6.0 (6.0.0-127566~Ubuntu~bionic) の設定ファイルを削除しています ...
dpkg: 警告: virtualbox-6.0 の削除中、ディレクトリ '/usr/lib/virtualbox/sdk/bindings/xpcom/python/xpcom/server' が空でないため削除できませんでした
dpkg: 警告: virtualbox-6.0 の削除中、ディレクトリ '/usr/lib/virtualbox/sdk/bindings/xpcom/python/xpcom/client' が空でないため削除できませんでした
shared-mime-info (1.9-2) のトリガを処理しています ...
hicolor-icon-theme (0.17-2) のトリガを処理しています ...
desktop-file-utils (0.23-1ubuntu3.18.04.2) のトリガを処理しています ...
mime-support (3.60ubuntu1) のトリガを処理しています ...

一応、こうしてVirtualBoxをインストールできたのであった。

$ sudo dpkg -i virtualbox-6.0_6.0.0-127566_Ubuntu_bionic_amd64.deb

Minikubeも動いた。

$ minikube start
Starting local Kubernetes v1.10.0 cluster...
Starting VM...
Getting VM IP address...
Moving files into cluster...
Setting up certs...
Connecting to cluster...
Setting up kubeconfig...
Starting cluster components...
Kubectl is now configured to use the cluster.
Loading cached images from config file.

いけなかったやつ

$ sudo dpkg -r virtualbox-6.0
dpkg: パッケージ virtualbox-6.0 の処理中にエラーが発生しました (--remove):
 パッケージが非常に矛盾した状態に陥りました。
削除を行う前にこのパッケージを再インストールすべきです
処理中にエラーが発生しました:
 virtualbox-6.0
$ sudo dpkg -p virtualbox-6.0
dpkg-query: パッケージ 'virtualbox-6.0' はまだ利用可能でありません
アーカイブファイルを調べるためには dpkg --info (= dpkg-$ sudo dpkg -p virtualbox-6.0
dpkg-query: パッケージ 'virtualbox-6.0' はまだ利用可能でありません
アーカイブファイルを調べるためには dpkg --info (= dpkg-deb --info) を、
その内容一覧を表示するには dpkg --contents (= dpkg-deb --contents) を使います。deb --info) を、
その内容一覧を表示するには dpkg --contents (= dpkg-deb --contents) を使います。
$ sudo apt install --reinstall dpkg
パッケージリストを読み込んでいます... 完了
依存関係ツリーを作成しています                
状態情報を読み取っています... 完了
E: パッケージ virtualbox-6.0 を再インストールする必要がありますが、そのためのアーカイブを見つけることができませんでした。
$ sudo apt install -f
パッケージリストを読み込んでいます... 完了
依存関係ツリーを作成しています                
状態情報を読み取っています... 完了
E: パッケージ virtualbox-6.0 を再インストールする必要がありますが、そのためのアーカイブを見つけることができませんでした。