ZshからNushellに平和的に移行した話
はじめに
ZshよりもNushellはモダンで扱いやすいシェルだと聞いたので、元のZshで利用していた設定をなるべく破壊することなく移行することを試みた記録です。
設定ファイルの分割インポートなどは以下の記事を引用しました。
対象読者
- Nushellのことが気になっているけど移行が不安で手を出せない人
- Nushellの設定管理方法を知りたい人
- モダンなシェル環境に興味がある人
Shellとは何か
Shellは、ユーザーとオペレーティングシステム(OS)の間を仲介するプログラムです。コマンドを入力すると、Shellがそれを解釈してOSに伝え、結果を返してくれます。
私たちが普段ターミナルでlsやcdといったコマンドを実行しているとき、実際にはShellがそれらのコマンドを解釈して実行しています。Shellには様々な種類があり、macOSやLinuxでは以下のようなものがよく使われています:
- Bash:多くのLinuxディストリビューションでデフォルト
- Zsh:macOS Catalina以降のデフォルトシェル。Bashの拡張版として人気
- Fish:ユーザーフレンドリーな補完機能が特徴
- Nushell:本記事で紹介する、構造化データを扱える新世代のシェル
従来のShellは主にテキスト処理を前提としていますが、現代のデータは構造化されていることが多く、JSONやCSVなどを扱う際に不便さを感じることがあります。そこで登場したのがNushellです。
NuShellについて
Nushellは2019年に登場した比較的新しいシェルで、Rust言語で書かれています。従来のShellとは異なり、すべてのデータを構造化データとして扱うという革新的なアプローチを取っています。
Nushellの主な特徴
構造化データの第一級サポート
従来のShellではテキストを行単位で処理していましたが、Nushellではテーブル形式のデータとして扱います。例えばlsコマンドの出力は、テキストではなく構造化されたテーブルとして返されます。
nu> ls | where size > 1mb | sort-by modified
このように、SQLライクな操作でデータをフィルタリング・ソートできます。
型システム
Nushellは型を持っており、文字列、数値、日付、バイナリなどを明確に区別します。これにより、予期しないエラーを減らし、より安全なスクリプト記述が可能になります。
豊富な組み込みコマンド
JSON、CSV、YAML、TOMLなどの形式を直接パースして操作できる組み込みコマンドが多数用意されています。jqやawkのような外部ツールに頼る必要が減ります。
優れたエラーメッセージ
Rustの影響を受けた分かりやすいエラーメッセージで、問題の特定が容易です。
段階的移行
インストール
まずはbrew経由でNushellをインストールします。
brew install nushell
念の為、インストール完了後はbrew listできちんとNushellがインストールされていることを確認してください。
インストールが出来ていれば、そのままターミナルで以下のコマンドを実行してください。
nu -l
-lオプションを付けることでNushellをログインシェルとして起動します。この挙動は一時的なもので、デフォルトシェルを変更するものではありません。
次のようなログが確認できれば大丈夫です。
__ ,
.--()°'.' Welcome to Nushell,
'|, . ,' based on the nu language,
!_-(_\ where all data is structured!
Version: 0.107.0 (aarch64-apple-darwin)
Please join our Discord community at https://discord.gg/NtAbbG
Our GitHub repository is at https://github.com/nushell/nushell
Our Documentation is located at https://nushell.sh
And the Latest Nushell News at https://nushell.sh/blog/
Learn how to remove this at: https://nushell.sh/book/configuration.html#remove-welcome-message
It's been this long since Nushell's first commit:
6yrs 4months 24days 11hrs 25mins 32secs 591ms 584µs
Startup Time: 14ms 979µs 917ns
この時、コンフィグファイルが存在しないため新規に作成したことを報告するログも表示されます。
作成先はデフォルトで/users/user/.config/nushellであり、env.nu, config.nuの二つが作成されます。
~/.config/nushell/
├── env.nu
└── config.nu
コンフィグの機能別分割
設定の管理をやりやすくするために、設定フォルダを分割してそれぞれエクスポートし、最終的にconfig.nuでインポートする形式をとります。
コンフィグフォルダにそれぞれプラグイン用、デフォルト設定用、自作関数用のフォルダを作成してください。+マークは新規作成するフォルダです。
~/.config/nushell/
├── + conf.d/
├── + functions/
├── env.nu
└── config.nu
以下で各フォルダの構成について記述します。
conf.d
conf.dフォルダではこのように3つのファイルを作成してください。
~/.config/nushell/
├── conf.d/
│ ├── + alias.nu
│ ├── + index.nu
│ └── + theme.nu
├── functions/
├── env.nu
└── config.nu
index.nuファイルは、他の2ファイルをエクスポートする記述を書きます。
export use theme.nu *
export use alias.nu *
export useという記述は、Nushellのドキュメントexport useに説明があります。
末尾の*は、該当ファイル内の全てのコマンドや関数をエクスポートするための記述です。
alias.nuファイルは、エイリアスを定義する記述を書きます。
export alias g = git
export alias nv = nvim
export aliasと記述することで、エイリアスを定義します。
functions
functionsフォルダでは、自分でカスタムコマンドを作成することができます。
例えば、以下のコマンドはghqとfzfを組み合わせて、設定したルートディレクトリより以下にある.gitを持つディレクトリを検索し、ローカルリポジトリの一覧を提示してくれます。
# ghq-fzf
export def --env "ghq fzf" [] {
let src = (ghq list | fzf --preview $"bat --color=always --style=header,grid --line-range :80 (ghq root)/{}/README.*")
if $src != "" {
cd $"(ghq root)/($src)"
}
}
作成した関数は、mod.nuでエクスポートします。
export use ghq-fzf.nu *
そして、config.nuの適切な場所に以下のようなコードを追加することで、この関数をCtrl+Gのキーバインドで呼び出せるようにします。
$env.config.keybindings ++= [{
name: ghq-fzf
modifier: control
keycode: char_g
mode: emacs
event: { send: executehostcommand, cmd: "ghq fzf" }
}]
ここまでが初期設定および段階的移行時の設定になります。
これらを行った上で、しばらくはzshからnuを起動して使用するということを続けました。
本格移行
ある程度Nushell環境でも問題なく扱えることが分かってきたので、本格的にデフォルトのシェルをNushellに置き換えます。
まず、Zsh上で以下のコマンドを実行し、nuコマンドが何を呼び出しているのか確認します。
which nu
Apple siliconであれば/opt/homebrew/bin/nuとなっていると思います。
これを、/etc/shellsに追加します。
echo "/opt/homebrew/bin/nu" | sudo tee -a /etc/shells
追加されているかどうかは次のコマンドで確認できます。
cat /etc/shells
# List of acceptable shells for chpass(1).
# Ftpd will not allow users to connect who are not using
# one of these shells.
/bin/bash
/bin/csh
/bin/dash
/bin/ksh
/bin/sh
/bin/tcsh
/bin/zsh
/opt/homebrew/bin/nu
最後に、chshコマンドを使ってデフォルトシェルを変更します。
chsh -s /opt/homebrew/bin/nu
おわりに
この記事がデフォルトシェルをモダンなツールに乗り換えたい全ての人の役に立ってくれると幸いです。
何か間違った解説をしている部分、「貸せ、シェル移行はこうする」といった部分があればコメントで教えてくれると嬉しいです。
あとは設定参照先変えられるようになって欲しい。(ハードコーディングしなきゃいけない関係上難しそうだけど...)
Discussion