Nix学習備忘録Part 2-1: Home ManagerでZ Shellを導入する
1 はじめに
本記事ではHome Managerを用いてZ Shellを導入し、各種設定を行います。 先にhome.nix
の記述を載せているので、筆者と同じ設定で取り敢えず済ませたい方は、 2.1、 2.2、 3.1 だけ読めば設定できます。残りは各種設定の解説です。
zshの設定に詳しい方は、Home Managerのzsh.nix を見て、ご自身の.zshrc
と見比べながら設定すれば、簡単に移行できると思います。
Z shell(ズィーシェル、zsh)はUnixのコマンドシェルの1つです。
そのため、先に軽くシェルの説明を行います。ご存じの方は読み飛ばして頂いて構いません。
1.1 シェルとは
Unix系のOSを操作するにはカーネル(kernel)と呼ばれる場所に命令を出す必要がありますが、 ユーザーが直接カーネルに命令を出すことはできません。 カーネルの周りを覆う殻、すなわちシェル(shell)を介して命令を出す必要があります。 このシェルを起動し、使用するためのソフトが端末(terminal)です。
シェルにも色々な種類があり、bashやzshの他、fishやeshellなど、数多くあります。 Linuxの場合、標準はほとんどがbashというシェルになっています。 MacOSの場合、10.15 Catalinaからデフォルトのシェルはzshとなっています。
個人的に調べた感じだと、bash以外のシェルだと、zshとfishが人気だと感じました。 本記事では、bashより柔軟で使いやすいと言われており、設定に関する記事も豊富なzshを導入していきます。
2 今回行うHome Managerを用いたzshの設定
「細々した設定の説明は良いから、取り敢えず筆者と同じ設定使ってみて、後で適当に自分で弄るわ!」 って方もいらっしゃると思うので、今回作る完成形を先に載せておきます。
2.1 home.nixの記述
今回行うzshの設定
以下の記述を~/.config/nixpkgs/home.nix
内の前回の記事 のひな形に書いたprograms = {};
の中に記述します。
zsh = {
autocd = true;
defaultKeymap = "emacs";
dotDir = ".config/zsh";
enable = true;
enableAutosuggestions = true;
enableCompletion = true;
enableSyntaxHighlighting = true;
envExtra = ''
if [ -e ~/.nix-profile/etc/profile.d/nix.sh ]; then
. ~/.nix-profile/etc/profile.d/nix.sh
fi
'';
initExtra =''
setopt no_beep
setopt auto_pushd
setopt pushd_ignore_dups
setopt inc_append_history
'';
history = {
extended = true;
ignoreDups = true;
save = 1000000;
share = true;
size = 1000000;
};
oh-my-zsh = {
enable = true;
plugins = [
"extract"
"fzf"
"git"
"web-search"
];
};
shellAliases =
{
h = "history";
hs = "history | grep";
hsi = "history | grep -i";
ll = "ls -alF";
la = "ls -A";
l = "ls -CF";
vi = "nvim";
view = "nvim -R";
vim = "nvim";
};
zplug = {
enable = true;
plugins = [
{ name = "romkatv/powerlevel10k"; tags = [ as:theme depth:1 ]; }
];
};
};
2.2 既定のシェルをzshへ変更する
home-manager switch
で上のzshの設定が反映されたhome.nix
を読み込みます。 しかし、これだけでは再びターミナルを開き直しても、いつも通りのシェルが起動します。 現在のシェルを変更するために、chsh
コマンドを使って設定します。
$ echo $SHELL
/bin/bash
$ command -v zsh
/home/username/.nix-profile/bin/zsh
$ sudo chsh -s "$(command -v zsh)" "${USER}"
これでターミナルを起動し直すと(なぜか私は2回起動し直す必要がありました)、 後述しますが、初回起動時のみ、powerlevel10k というシェルの見た目を簡単に設定できるものが起動します。
質問に答えていくだけですが、わからない場合は次で紹介するpowerlevel10kのパートで設定方法を確認してください。
Visual Studio Codeでの既定のシェルの設定
Ctrl+Shift+@
でターミナルを起動し、+ボタンの右にあるをクリックし、 既定のプロファイルの選択をクリックして、zsh
を選択する。
3 zshのカスタマイズ
前節で設定したものについて細かく見ていきます。 本来なら基本設定から解説した方が良いですが、上の設定をコピペでスタートした人のために、まずpowerlevel10kから解説します。
3.1 powerlevel10k: ターミナルの見た目を簡単に設定する
GitHubのリポジトリはこちら(https://github.com/romkatv/powerlevel10k)
3.1.1 home.nixへの記述
home.nix
のprograms.zsh
内の以下の部分で導入しています:
zplug = {
enable = true;
plugins = [
{ name = "romkatv/powerlevel10k"; tags = [ as:theme depth:1 ]; }
];
};
ちなみに、Home Managerを使わずにやると、手動で設定すること(ZSH_THEME
の設定等)が少しだけ多いのですが、 その辺りの細々した作業も全部やってくれます。有難い。。。
3.1.2 フォントの設定
ただし、このフォント設定を行わないと、アイコンが上手く表示されなかったりします。 別に気にしない方や、ターミナルのフォントを変更したくない場合はこちらのステップは省略可能なので、次のステップに進んでください。
- powerlevel10kのGitHubリポジトリにアクセスする。
README.md
の1/4くらいにあるFontsを見つける(「Fonts」でページ内検索するなどして見つけてください)。- Manual font installationにある、以下の4つのフォント(
ttf
ファイル)をダウンロードする:
MesloLGS NF Regular.ttf
MesloLGS NF Bold.ttf
MesloLGS NF Italic.ttf
MesloLGS NF Bold Italic.ttf
- 各ファイルを開くと、「インストール(Install)」または「フォントをインストール(Install Font)」というボタンがあるので、クリックしてインストールする。
以下、ターミナルごとにフォントの設定を行う:
3.1.3 powershell10kの設定について
powershell10kを設定した後、初めてシェルを起動すると、設定が始まります。 基本的には、質問に対して答えていくだけですが、一応英語が苦手な方のためにも質問の内容を記載します。 ちなみに、次の節で解説するように、設定を変えたい場合はいつでも簡単に再設定できるので、忙しい方は適当に答えてても問題ありません。
最初の4つの質問は、アイコンフォントが文字化けするかどうかの質問です。 前のフォントの設定を飛ばしている場合、いくつかn
で答える箇所が出るかもしれません。
--->
と<---
の間にある文字がダイヤモンド(◆)に見えているか?という質問です。 ダイヤモンドが表示されていればy
、文字化けしていればn
を入力してください。- 同様に、次は南京錠()が表示されているか?という質問です。 南京錠が表示されていれば
y
、文字化けしていればn
を入力してください。 - 次はDebianのロゴである渦巻き模様が見えているかという質問です。 渦巻き模様が表示されていれば
y
、文字化けしていればn
を入力してください。 - 次は
X
を間に挟んで、様々な色の様々なアイコンが表示されているかという質問です。 恐らく、X(赤色でgit
の文字)X(緑でGitHubのアイコン)X(黄色で時計)X(青でダイヤモンド)X(紫で家アイコン)X(水色でファイルアイコン)X(赤色で白抜きファイルアイコン)X(緑でよくわからないもの)Xが表示されると思います(違うかもしれません)。 文字化けしていなければy
、していればn
を入力してください。
ここから先は好みでプロンプトの見た目を設定していきます。 どのプロンプトを選ぶかによって、質問の量や内容は変わりますが、一応自分の設定の分だけ載せておきます。 一応選定理由も載せていますが、個人の好みなので、好きなように設定してください。
- プロンプトの見た目です。情報がごちゃごちゃし過ぎるのはあまり好きではないので、私は
Lean
にします。1
を選択します。 - 文字セットの設定です。Unicodeが良いので、
1
を選択します。 - プロンプトに使う色の数です。256色で
1
を選択します。 - プロンプトの右側に表示する現在時刻の表示設定です。時刻くらいなら表示してても良いかなと思うので、
24-hours format
の2
を選択します。 - 入力行を改行するか否かの設定です。カレントディレクトリへのパスが長くなると、かなり窮屈になってしまうので、
Two Lines
の2
を選択します。 - ディレクトリ情報と時刻情報の間にラインを引くか否かの設定です。シンプルに
Disconnected
の1
を選択します。 - 改行に付けるフレームの設定です。ここもシンプルに
No frame
の1
を選択します。 - コマンドの実行後に空行を入れるかどうかの設定です。前に実行したコマンドができるだけ多く表示されていた方が好きなので、
Compact
の1
を選択します。 - アイコンを表示するかどうかの設定です。直感的にわかりやすいと思うので、
Many icons
の2
を選択します。 - 表示により詳しい説明を加えるかどうかの設定です。流石に長くなり過ぎるので、
Concise
の1
を選択します。 - コマンド実行後に、以前のコマンドの部分にもディレクトリ情報等を残すか否かの設定です。よく考えれば要らないなと思ったので、
No
のn
を選択します。 - インスタントプロンプトに関する設定と出ていますが、よくわからないので、推奨されているVerboseの
1
を選択します。 - 設定を完了して保存するかの質問です。
Yes
のy
を選択します。
これで設定が完了しました!個人的にプロンプトの見た目が自分好みだと、モチベーションにも繋がります。
3.1.4 powerlevel10kの設定をやり直す
ここまで行った設定はいつでも設定し直すことができます。 やり方はコマンド一つです。p10k configure
を実行すると、再度設定画面が開き、再設定できます。 飽きたら別の見た目にいつでもカスタマイズできるということですね。
3.2 zshの便利なコマンド
色々ありますが、便利だなと思った2つだけピックアップします。 自分自身入門したてなので、他にも便利なショートカットがあれば教えて頂けると幸いです。
Ctrl+k
: カーソル位置から行末まで削除Ctrl+r
: 以前実行したコマンドの検索
3.3 基本設定
Home Managerで準備されている設定と、されていない設定があります。 準備されていない設定に関してはzsh
のinitExtra
で設定されています。
まず、
enableAutosuggestions = true;
でサジェストを有効化、enableCompletion = true;
で補完の有効化、enableSyntaxHighlighting = true;
でシンタックスハイライトの有効化
を行っています。
envExtra
に記述している内容はNixを使う上で必要な設定なので、 あまり気にしなくてOKです。
3.3.1 auto_cd: ディレクトリ名の入力だけでそのディレクトリに移動する
zsh
内の以下の行で設定しています(通常は.zshrc
にsetopt auto_cd
と記述します):
autocd = true;
これを設定しておくと、cd
と入力しなくても、ディレクトリの名前だけで移動できます。
3.3.2 no_beep: ビープ音を消す
initExtra
内の以下の行で設定しています。
setopt no_beep
できない操作を試みたときにビープ音を鳴らさないようにする設定です。 私はいちいちうるさいと感じるので、設定しています。
3.3.3 auto_pushdとpushd_ignore_dups: ディレクトリ移動をスタックで管理する
次の2つは少し難しいですが、pushd
とpopd
というディレクトリの移動に便利な操作に関する設定です。 先にpushd
とpopd
について説明します。 スタック(stack)でディレクトリの移動を管理できるというものです。
スタック(stack)って何?
push
で最後に入れた(last-in)ものを、 pop
で頭から取り出す(first-out)ことができるLIFO(last-in first-out)のデータ構造です。 よく挙げられる例が、本を机の上に積み上げる例です。1冊1冊本を積み上げたとき、 最初に取り出せるもの(first-out)は一番上にある本ですが、 これは最後に積んだ本(last-out)ですね。 本を積む操作がpush
、本を取り出す操作がpop
と考えて頂ければOKです。
pushd
とpopd
の「d
」はディレクトリ(directory)の頭文字です。
pushd
とpopd
のデモ
以下、コマンドの状況の説明を#
以降で説明しています。 自分で動作確認をする場合は、#
以降は入力せずに行ってください。
$ cd ~ # ホームディレクトリに移動
$ mkdir tmp # デモ用のディレクトリ作成
$ mkdir tmp/hoge # デモ用のディレクトリ作成
$ mkdir tmp/hoge/fuga # デモ用のディレクトリ作成
$ pwd # 現在位置の確認
/home/username
$ pushd tmp/hoge # スタックにtmp/hogeを追加
~/tmp/hoge ~ # 最後に移動した~/tmp/hogeがスタックの先頭に追加されている
$ pwd # 現在位置の確認
/home/username/tmp/hoge # 移動できている
$ pushd fuga # スタックにfugaを追加
~/tmp/hoge/fuga ~/tmp/hoge ~ # ~/tmp/hoge/fugaがスタックの先頭に追加されている
$ pwd
/home/username/tmp/hoge/fuga # 移動できている
$ popd
~/tmp/hoge ~ # ~/tmp/hoge/fugaがスタックから取り出された
$ pwd
/home/username/tmp/hoge # ~/tmp/hogeに移動している
$ popd
~ # ~/tmp/hogeがスタックから取り出された
$ pwd
/home/username # ~に移動している
$ rm -r tmp # 掃除
このような形で、pushd
で移動の履歴を残しながら、 戻りたいときにはpopd
で戻ることができます。 ちょっと別のディレクトリに用事があるけど、すぐ戻りたいとき等に便利そうですね。
さて、前置きが長くなりましたが、setopt auto_pushd
と記述しておくと、 普段のcd
コマンドがpushd
として実行され、普段通りcd
で移動した場合でも、 popd
で辿って来た道のりを戻ることができます。
これはinitExtra
内の以下の行で設定しています:
setopt auto_pushd
次に、setopt pushd_ignore_dups
ですが、これを設定していない状態で、 例えばcd ~
を連続して何度も行うと、スタックにずっと~
が溜まり続け、 popd
をやってもやってもホームディレクトリから動けないという状態に陥ってしまいます。 これを避けるために、重複したディレクトリはスタックに追加しないというのが、 このsetopt pushd_ignore_dups
の設定です。
これはinitExtra
内の以下の行で設定しています:
setopt pushd_ignore_dups
3.3.4 historyを使いやすくする
history
というコマンドで、以前実行したコマンドをチェックすることができ、 !
に履歴の番号を添えて実行することで、そのコマンドを再度実行することができます。 このhistory
の機能を使いやすくする設定を行います。
home.nix
のzsh
内にある以下の記述で設定しています:
history = {
extended = true;
ignoreDups = true;
save = 1000000;
share = true;
size = 1000000;
};
extended = true;
は、history
ファイルにタイムスタンプを保存するという設定です (通常は.zshrc
でsetopt EXTENDED_HISTORY
と記述します)。
ignoreDups = true;
は、history
コマンドで重複するコマンドは保存しないというものです (通常は.zshrc
でsetopt hist_ignore_dups
と記述します)。 例えば、癖でls
コマンドを何回も実行したりしてしまうことがよくありますが、 そういったものでコマンド履歴を汚さなくてすむようになります。
share = true;
は、新しく開いたzshにも履歴をシェアするという設定です (通常は.zshrc
でsetopt share_histroy
と記述します)。
save = 10000000;
は、履歴ファイルに保存する履歴の件数の設定です (通常は.zshrc
でexport SAVEHIST=1000000
と記述します)。
size = 10000000;
は、メモリに保存する履歴の件数の設定です (通常は.zshrc
でexport HISTSIZE=1000000
と記述します)。
また、通常history
にコマンドの履歴が保存されるのは、 再度コマンドが入力可能になるタイミングですが、 この設定だと、サーバーにアクセスするような、 しばらく結果がかえって来ないようなコマンドを実行して、 そのままターミナルを閉じてしまった場合などに、履歴にコマンドが残らなくなります。 この保存のタイミングを、実行したとき即座に行うようにする設定が、initExtra
にある以下の記述です:
setopt inc_append_history
3.4 oh my zshによるプラグインの設定
zsh
内の以下の行で有効にしています:
oh-my-zsh = {
enable = true;
以下、plugins = [];
の中身に欲しいoh my zshのプラグインを書いていくだけです。
3.4.1 extract: ファイルを展開する
oh-my-zsh
のplugins
内の以下の行で設定しています:
"extract"
圧縮ファイルの種類はたくさんありますが、このextract
を入れておくと、 extract <ファイル名>
で大抵のファイルを展開することができるようになります。 展開できるファイルはoh-my-zshのextractプラグインで見ることができます。
3.4.2 fzf: ファイルを高速に検索する
oh-my-zsh
のplugins
内の以下の行で設定しています:
"fzf"
これにより、ターミナル上でCtrl+t
というショートカットでFuzzy Finderというファイル検索が起動し、 ファイル名やディレクトリ名を入れてそこに移動することが可能になります。
3.4.3 git: gitのaliasとfunctionを利用する
oh-my-zsh
のplugins
内の以下の行で設定しています:
"git"
正直、oh-my-zshの設定でデフォルトで入るものなので入れてるというだけです。 aliasについては、oh-my-zshのgitプラグイン を参照すれば良いかと思います。ga
でgit add
、gb
でgit branch
など、 たくさんaliasが設定されています。使わないなら削除しても良いかと思います。
3.4.4 web-search: コマンドラインから検索を行う
oh-my-zsh
のplugins
内の以下の行で設定しています:
"web-search"
これにより、コマンドラインからgoogle
というコマンドでGoogle Chromeを立ち上げて検索することができるようになります。 何が嬉しいかというと、ターミナルでプログラムを実行したときに出たエラーメッセージを、 そのままターミナル内でコピーして、 例えばgoogle python command not found
などと入力するだけで、 「python command not found」に関するエラーをGoogle検索することができます。 わざわざブラウザを立ち上げて検索する必要がなくなります。
3.5 外部プラグインの利用について(別記事に回します)
デフォルトで入っていないプラグインでもGitHubから引っ張ってくることを記述できますが、 少し込み入った説明と、プラグインによってはzsh
の外部に記述をする必要が出てくるので、 今回は説明しないことにします。
4 まとめ
Home Managerを用いてzshを使えるようにしました。 外部プラグインの設定方法については、またいつか記事にまとめます。 外部プラグインの設定についても、ほんの少し複雑に感じるところはあるかもしれませんが、 Nixの強味がかなり活かせ、一度設定してしまえば移行が楽になります。
NixもHome Managerも初心者なので、 理解していないことやわからないことが多くあるので、 アドバイスや、説明に誤り等を発見しましたら、ご指摘願います。
Home Manager、いじればいじるほど凄いなぁとなってる今日この頃です。