`fresco`：fish向けプラグインマネージャー

# まとめ
- [fresco]というプラグインマネージャーを作りました
- `fresco`では[ghq]を使ってプラグインを管理します
- [fisherman]と異なりシンボリックリンクは作りません

# これまでのあらすじ
fishを使う上で、`$HOME/.config/fish/functions/`配下のファイルの管理について下記の点が気になり始めました。

- `$HOME/.config/fish/functions/`配下にファイルがフラットに配置されている
- 複数の`function`が連携して別の機能を実現している場合に、どのファイルが連携しているのかわかりにくい

プラグインマネージャーを使うとプラグインという論理的な単位で管理することができますが、[fisherman]を使ってプラグインをインストールすると`$HOME/.config/fish/conf.d/`や`$HOME/.config/fish/functions/`といったディレクトリー配下にシンボリックリンクが配置されます。プラグインマネージャーは使いたいけれど、シンボリックリンクが作られるという点が肌に合いませんでした。

1ヶ月程度fishを使い慣れてたということで、fish自体の機能の勉強と各プラグインがどのような構造になっているのかの調査を兼ねて、シンプルなプラグインマネージャーを作ることに決めました。


# 開発にあたって

開発にあたっては開発方針を下記3点としました。

- シンボリックリンクを使わない
- プラグインは[ghq]で管理する
- [oh-my-fish]や[fisherman]向けのプラグインも管理できる

## シンボリックリンクを使わない

fishでは`$HOME/.config/fish/functions/`配下にファイルを配置しておくとオートロードされる仕様（[参考リンク](https://fishshell.com/docs/current/tutorial.html#tut_autoload)）ですので、`fisherman`が行っているシンボリックリンクを`functions/`配下に配置するというアプローチは合理的な方法です。しかし、これがどうしても気に入らなかったのです。

シンボリックリンクでオートロードというソリューションを使わずファイルを読み込む手段として`source`が使えそうです。ということで、各プラグインのファイルを`source`するコードを書くというアプローチを採用することにします。

## プラグインは`ghq`で管理する

普段からリポジトリーの管理には`ghq`という便利なツールを使っているので、GitHubに公開されているプラグインの管理にも`ghq`を使いたいと考えました。

`fresco`を使うために`ghq`が必要になってしまいますが、携わっているプロジェクトや普段使いのプラグインのリポジトリーを統一的に管理できるのはとてもスッキリします。

## `oh-my-fish`や`fisherman`向けのプラグインも管理できる

fishには既に多数のプラグインが存在します。

これらの資産を活用しない手はありませんので、下記仕様に対応することにします。

- `fishfile`に依存するプラグインが記載されている
- `uninstall.fish`という後始末スクリプトを準備しておくとプラグイン削除時に呼ばれる

見落としている仕様があれば教えていただけると助かります。


# `fresco`誕生

そんなわけで[fresco]ができました。

## インストール

`ghq`が入っている状態で下記コマンドを実行することで`fresco`をインストールすることができます。

```
$ curl https://raw.githubusercontent.com/masa0x80/fresco/master/install | fish
```

このコマンドは内部で下記を実行しているだけです。

1. `ghq`で`fresco`自体をダウンロード
2. `source (ghq root)/github.com/masa0x80/fresco/fresco.fish`を行う`$HOME/.config/fish/conf.d/fresco.fish`を作成

## `fresco`の使い方

### プラグインの追加

例として、[shark]をインストールしてみます。

```
$ fresco fisherman/shark
Download /Users/masa0x80/.ghq/github.com/fisherman/shark
Download /Users/masa0x80/.ghq/github.com/fisherman/getopts
Enable fisherman/shark
```

`fresco`でインストールされたプラグインは`$HOME/.config/fish/plugins.fish`ファイルに記録されるので、確認してみましょう。

```
$ cat $HOME/.config/fish/plugins.fish
fisherman/getopts
fisherman/shark
```

`fresco list`でも`fresco`管理下のプラグインを確認できます。

```
$ fresco list
fisherman/getopts
fisherman/shark
```

インストールができたようなので`shark`コマンドを試してみます。

```
$ seq 8 | shark
▁▂▃▄▅▆▇█
```

無事インストールできたようです。

### プラグインの更新

プラグイン名を指定して`fresco update`を実行することで、特定のプラグインを更新することができます。

```
$ fresco update fisherman/shark
```

`fresco`管理下のプラグインすべてを更新することもできます。

```
$ fresco update --all
```

`fresco`自体を更新したい場合は`--self`オプションを指定してください。

```
$ fresco update --self
```

### プラグインの無効化・削除

プラグインが不要になった場合は下記コマンドで無効化できます。

```
$ fresco remove fisherman/shark
```

なお、`--force`オプションを付けて実行することで、`ghq`管理のリポジトリーごと削除することができます。

```
$ fresco remove --force fisherman/shark
```

# おわりに

`fresco`はイタリア語で「新鮮な」という意味です。

よろしければ[鮮魚](fresco)をご賞味ください。


[fresco]: https://github.com/masa0x80/fresco
[oh-my-fish]: https://github.com/oh-my-fish/oh-my-fish
[fisherman]: http://fisherman.sh/
[ghq]: https://github.com/motemen/ghq
[shark]: https://github.com/fisherman/shark