💓

Nix Home-ManagerでNeovimの環境構築

2024/11/15に公開

筆者について

2024年9月初めからHome-Managerを使いはじめ、9月半ばくらいからNixOSを使いはじめました。

vim-jp slackでは#tech-nixチャンネルがあり、日本語情報が多く交換されています。

私もvim-jp slackのほうで情報収集、質問をしました。

Nixの日本語情報が多いのでぜひ参加をすすめます。

NixでNeovimの環境構築をするメリット

  • ビルド済みバイナリが手に入る。

Nixを使うと、ビルド済みのバイナリパッケージを直接取得できるため、手動でのビルド作業を省略できます。

例えば、telescope-fzf-native.nvimを導入する際、通常はビルド手順を実行しないと libfzf.so は生成されませんが、Nix経由ではあらかじめビルドされたパッケージが提供されているため、この手順をスキップすることができます。

  • プラグインマネージャーによる初回のgit cloneの実行を避けて、即完成されたNeovimを使うことができる。

環境

  • NVIM v0.10.2
  • lazy.nvim

解説

オプションについてはHome Manager OPTION SEARCHを駆使することで楽に調べることができます。

https://github.com/s0racat/dotfiles-nix/blob/57606ef37b97a4827015562b06515c9a8d4ad615/home-manager/console/neovim/base.nix

programs.neovim.plugins

programs.neovim.pluginsに指定するとruntimepathに追加されてneovim起動時に自動的にロードしてくれるようになります。

例えば/nix/store/r9apcpdgh4zaa32iqjd3xgc5acwr0491-vim-pack-dir/pack/myNeovimPackages/start/lazy.nvimになります。

config.lib.file.mkOutOfStoreSymlinkを使用すると、dotfilesリポジトリにsymlinkを貼ることでNixの特性である書き込み禁止の制約を逃れることができます。

ただし、config.lib.file.mkOutOfStoreSymlinkには制約があり引数にフルパスを記述しないといけません。例: /home/alice/dotfiles-nix/home-manager/console/neovim

また、/home/alice/dotfiles-nix/home-manager/console/neovimのような表記はconfigを使い${config.home.homeDirectory}/dotfiles-nix/home-manager/console/neovimのように置き換えることができます。

let in間にinherit (config.lib.file) mkOutOfStoreSymlinkと記述するとmkOutOfStoreSymlinkと省略できるようになり、何度も使用する場合は便利です。

関数の定義元はこのようになっています。

https://github.com/nix-community/home-manager/blob/2f23fa308a7c067e52dfcc30a0758f47043ec176/modules/files.nix#L64-L69

plugin管理

https://github.com/s0racat/dotfiles-nix/blob/1ee8fd1a9eae6bb93591c1dcc643c03328c724e8/home-manager/console/neovim/plugins.nix

programs.neovim.extraLuaConfigの中でpluginのパッケージを宣言しています

110行目ではskkeletonの設定にNixの置換を使いたくないので、xdg.dataFile.<name>.sourceを使いファイルリンクを貼ります。

https://github.com/s0racat/dotfiles-nix/blob/3f551936a13eea9ebd9550ccd075a84f8d38e636/home-manager/console/neovim/plugins/skkeleton.lua#L4-L11

mkEntryFromDrv

drvを引数に、もしdrvがderivationの場合は

{
    name = "${lib.getName drv}"; # ハッシュとversion無しのパッケージ名
    path = drv;
}

pluginsに{name = "hello"; path = pkgs.hello; }を指定されている場合はlib.isDerivationがfalseなためdrvをそのまま返します。

pkgs.linkFarm

次にpkgs.linkFarmを使います。

pkg.linkFarmは引数を元に複数のpluginを1つのディレクトリにまとめる役割をします。

nameに指定した値でファイルリンクが作成され、パッケージ名とpluginのリポジトリ名が異なる場合を解決することができます。

最後にlazy.nvimにnixにて作成したpluginのディレクトリを指定するために@LazyPath@を置換します。

https://github.com/s0racat/dotfiles-nix/blob/1ee8fd1a9eae6bb93591c1dcc643c03328c724e8/home-manager/console/neovim/init.lua#L9-L15

> eza --tree /nix/store/8mvymm4m716ny8xngavdlxrcl2ghjcxm-lazy-plugins
/nix/store/8mvymm4m716ny8xngavdlxrcl2ghjcxm-lazy-plugins
├── bufferline.nvim -> /nix/store/lrz3k70kz5l755pjiyywh566aas3h9nw-vimplugin-bufferline.nvim-2024-10-24
├── cmp-buffer -> /nix/store/p9zxhc3rdsrzr3a04ppzfc579khgzsnr-vimplugin-cmp-buffer-2022-08-10
├── cmp-cmdline -> /nix/store/l7yv0drp0pf7pk2ag0fyj3lsskpa2sib-vimplugin-cmp-cmdline-2024-03-22
...
# パッケージ名とリポジトリ名が異なる場合
├── LuaSnip -> /nix/store/ra8zr3flv77rw0skhll9wpkarl1v2bid-vimplugin-lua5.1-luasnip-2.3.0-1-unstable-2024-11-03
...

後は通常通りで、luaにてpluginの設定や、neovimのオプションの設定を書くことができます。

例: ~/.config/nvim/lua/plugins, ~/.config/nvim/lua/conf

参考

おまけ

nix repl

nix repl -f '<nixpkgs>'をshellで実行することでnix言語を実行することができます。

nix-repl> lib.isDerivation pkgs.hello
true

また、lfを使うことでflake導入後のオプション探しに役にたてることができます。

nix-repl> :lf .
nix-repl> outputs.homeConfigurations."takumi@debian-wsl".config.xdg.dataHome
"/home/takumi/.local/share"

nvfetcher

https://github.com/berberman/nvfetcher

を使うことでnixpkgsに存在しないプラグインを導入することが格段に楽になります。

ここでは説明しませんが、いくつか役にたちそうなファイルを示します。

Home-Managerによるパッケージのインストールを回避する

副作用が発生する場合があるので、Home-Managerのモジュールを読むことをおすすめします。

Discussion