\\\\ ٩( 'ω' )و ////

いろんな形がなかったりするものをこねてこねてこねまくります

preztoのExternal Modulesを使ってdotfilesを綺麗に保つ

prezto使ってますか。軽くていい感じに module が揃っていて最高ですね。

ところで prezto で自分で魔改造したカスタムプロンプトを使っている方はどうやって適用しているでしょうか。 更新なんかしないから zip で落としてきて modules の prompt フォルダに突っ込んで終わりの人や、submodule にしてシンボリックリンクを貼ったりするでしょうか。

更新なんかせんわ〜って人はいいでしょうが、メンテナンス性を考えてせっかく更新できるように submodule にしたのに unstaged changes に自分の追加したファイルが残っていたり、更新したらシンボリックリンクが消えて貼り直しみたいなことが多くあると思います。

そこで、prezto の機能であるExternal Modulesを使って自分が追加したいプロンプトを module 化してしまうことで、prezto 本体と疎結合にすることができメンテナンス性が増します。

今回はプロンプトの分離を例にとりますが、iterm2 の拡張など、様々な拡張機能を自分で作ることもできます。

External Modules is なに

External Modules は一言で言うと prezto に PR を送らなくても module を作ることができる機能です。

prezto はデフォルトで $ZPREZTODIR/modules$ZPREZTODIR/contrib の中にある module を読み込みます。それに加えてユーザーが拡張したい module が指定されていた場合にそのディレクトリも読み込みます。

有効にする方法はzpreztorc にある zstyle ':prezto:load' pmodule-dirs $HOME/.zprezto-contrib と言う設定のコメントを外すだけです。ここの path を module を置いておくディレクトリに変えておくことで起動時に prezto が指定した path にある module を読み込んでくれます。

module を作る

module の構成は以下のようにします。

sample-module
├── functions
│   └── hoge.sh
└── init.zsh # or sample-module.plugin.zsh

ここで重要なのが init.zshfunctions です。

prezto は module 読み込み時に init.zsh もしくは <モジュール名>.plugin.zsh と名前がついたファイルを探して初期化します。なのでこのファイル もう1つのfunctionsというディレクトリはこの中にある shell script を全て autoload します。functions ディレクトリはなくても動きます。用途に合わせて作ってください。

なお module の名前はユニークなものにしなければなりません。被らせてしまうと conflicting module locations と怒られます。

その後、 preztorczstyle ':prezto:load' に自分の作った module の名前を追加すると次回起動時に自動で読み込まれます。

実際に読み込まれたかどうかを確認するには zstyle -t ":prezto:module:<モジュール名>" loaded 'yes' 'no' が正常に終了すれば読み込まれています。

プロンプトを分離してみる

一番簡単な方法は prezto にある prompt ディレクトリを丸々コピーしてきて追加する方法です。 ですが 自分の使わないプロンプトを読み込んでも仕方がないので使わないものは消しましょう。

消すとこんな感じになるはずです。

custom-prompt
├── functions
│   ├── prompt-pwd
│   └── prompt_xxxxxx_setup
└── init.zsh

init.zsh は prezto の prompt ディレクトリにあるものをそのまま持ってきて大丈夫ですが、一部だけ変更しなければならない箇所があります。

# Load and execute the prompt theming system.
autoload -Uz promptinit && promptinit

# Load the prompt theme.
zstyle -a ':prezto:module:prompt' theme 'prompt_argv'
if [[ "$TERM" == (dumb|linux|*bsd*) ]] || (( $#prompt_argv < 1 )); then
  prompt 'off'
else
  prompt "$prompt_argv[@]"
fi
unset prompt_argv

にある zstyle -a ':prezto:module:prompt' theme 'prompt_argv':prezto:module:prompt を自分のモジュール名に書き換える必要があります。これをしないと正常にプロンプトが読み込めなくなります。

さらに、prompt-pwdはなんのためにあるのかというと、今いるディレクトリを短縮して表示してくれる関数なので使わないひとは消してもいいです。 他にも powerline だったり pure だったりを使う人は external に submodule add してあげると使えます。

あとは作った module を preztorczstyle ':prezto:load' に追加して、zpreztorc の zstyle ':prezto:module:prompt' theme 'sorin' のモジュール名とプロンプトテーマを書きかえれば完了です。

今回やった方法で作った dotfiles はここに置いてあるので参考にしてみてください

github.com