Local Rust docs with Nixpkgs and Fenix

The Rust ecosystem has a nifty trick for opening documentation locally, but when managing Rust with Nix, we're missing one important piece in the toolchain.

rustup doc is an praise-worthy little feature of the Rust ecosystem, but we don’t have rustup when managing our Rust tooling with Nix.

Fortunately, there’s a trick one can use when Fenix is in play.

open "$(nix build fenix#latest.rust-docs --json --no-link | jq -r '.[0].outputs.out')/share/doc/rust/html/index.html

Note that on Linux, one will likely want to use xdg-open in place of macOS’ open to browse the generated docs.

A full Home-Manager module for macOS might look like this:

{
  config,
  lib,
  pkgs,
  ...
}: let
  inherit (lib) mkEnableOption mkIf;
  cfg = config.my.home.rust;

  rust-docs = pkgs.writeShellScriptBin "rust-docs" ''
    open "$(nix build fenix#latest.rust-docs --json --no-link | jq -r '.[0].outputs.out')/share/doc/rust/html/index.html"
  '';
in {
  options.my.home.rust = {
    enable = mkEnableOption "rust";
  };

  config = mkIf cfg.enable {
    home = {
      sessionVariables = {
        RUSTUP_HOME = "${config.xdg.dataHome}/rustup";
      };

      packages = with pkgs; [
        (fenix.stable.withComponents [
          "cargo"
          "clippy"
          "rust-analyzer"
          "rust-src"
          "rustc"
          "rustfmt"
        ])
        rust-docs
      ];
    };
  };
}