# NixOS module: automatic nushell completion generation from manpages # # Modeled on nixpkgs' programs/fish.nix completion generator. # For each package in environment.systemPackages, a small derivation runs # `inshellah manpage-dir` against its share/man directory. Results are merged # into a single directory and placed in nushell's vendor autoload path. # # Usage in your NixOS configuration: # # { pkgs, ... }: { # imports = [ ./path/to/inshellah/nix/module.nix ]; # programs.inshellah.enable = true; # # Optionally add packages not in systemPackages: # # programs.inshellah.extraPackages = [ pkgs.kubectl ]; # } { config, lib, pkgs, ... }: let cfg = config.programs.inshellah; # The inshellah binary — override this if you build from the local flake inshellahPkg = cfg.package; # Per-package derivation: run inshellah manpage-dir against a package's manpages generateCompletions = package: pkgs.runCommandLocal (let inherit (lib.strings) stringLength substring storeDir; storeLength = stringLength storeDir + 34; pathName = substring storeLength (stringLength package - storeLength) package; in (package.name or pathName) + "_nu-completions" ) ({ inherit package; nativeBuildInputs = [ inshellahPkg ]; } // lib.optionalAttrs (package ? meta.priority) { meta.priority = package.meta.priority; }) '' mkdir -p $out if [ -d "$package/share/man" ]; then inshellah manpage-dir "$package/share/man" > "$out/completions.nu" 2>/dev/null || true # Remove empty files find $out -empty -delete fi ''; in { options.programs.inshellah = { enable = lib.mkEnableOption "nushell completion generation from manpages via inshellah"; package = lib.mkOption { type = lib.types.package; description = "The inshellah package to use for generating completions."; }; extraPackages = lib.mkOption { type = lib.types.listOf lib.types.package; default = []; description = '' Additional packages to generate nushell completions from, beyond those in {option}`environment.systemPackages`. ''; }; generatedCompletionsPath = lib.mkOption { type = lib.types.str; default = "/share/nushell/vendor/autoload"; description = '' Subdirectory within the merged environment where completion files are placed. The default matches nushell's vendor autoload convention (discovered via XDG_DATA_DIRS). ''; }; }; config = lib.mkIf cfg.enable { # Merge all per-package completions into a single directory. # This path ends up in the system profile, and nushell discovers it # via XDG_DATA_DIRS -> $prefix/share/nushell/vendor/autoload/ environment.pathsToLink = [ cfg.generatedCompletionsPath ]; environment.systemPackages = [ (pkgs.buildEnv { name = "nushell-generated-completions"; ignoreCollisions = true; paths = map generateCompletions ( config.environment.systemPackages ++ cfg.extraPackages ); pathsToLink = [ "/" ]; # Nest everything under the vendor autoload path postBuild = '' if [ -d "$out" ]; then tmp=$(mktemp -d) cp -r "$out/"* "$tmp/" 2>/dev/null || true rm -rf "$out/"* mkdir -p "$out${cfg.generatedCompletionsPath}" for f in "$tmp"/*.nu; do [ -f "$f" ] && cp "$f" "$out${cfg.generatedCompletionsPath}/" done rm -rf "$tmp" fi ''; }) ]; }; }