138 lines
4.2 KiB
Nix
138 lines
4.2 KiB
Nix
# NixOS module: automatic nushell completion indexing
|
|
#
|
|
# Indexes completions using three strategies in priority order:
|
|
# 1. Native completion generators (e.g. CMD completions nushell)
|
|
# 2. Manpage parsing
|
|
# 3. --help output parsing
|
|
#
|
|
# Produces a directory of .json/.nu files at build time.
|
|
# The `complete` command reads from this directory as a system overlay.
|
|
#
|
|
# Usage:
|
|
# { pkgs, ... }: {
|
|
# imports = [ ./path/to/inshellah/nix/module.nix ];
|
|
# programs.inshellah.enable = true;
|
|
# }
|
|
|
|
{
|
|
config,
|
|
lib,
|
|
pkgs,
|
|
...
|
|
}:
|
|
|
|
let
|
|
cfg = config.programs.inshellah;
|
|
in
|
|
{
|
|
options.programs.inshellah = {
|
|
enable = lib.mkEnableOption "nushell completion indexing via inshellah";
|
|
|
|
package = lib.mkOption {
|
|
type = lib.types.package;
|
|
description = "package to use for indexing completions";
|
|
};
|
|
|
|
completionsPath = lib.mkOption {
|
|
type = lib.types.str;
|
|
default = "/share/inshellah";
|
|
description = ''
|
|
subdirectory within the system profile where completion files
|
|
are placed. used as --dir for the completer.
|
|
'';
|
|
};
|
|
|
|
extraDirs = lib.mkOption {
|
|
type = lib.types.listOf lib.types.str;
|
|
default = [ ];
|
|
example = [ "/etc/profiles/per-user/alice/share/inshellah" ];
|
|
description = ''
|
|
additional read-only completion directories to search.
|
|
these are appended (colon-separated) to the --dir path
|
|
alongside the system completions path.
|
|
'';
|
|
};
|
|
|
|
ignoreCommands = lib.mkOption {
|
|
type = lib.types.listOf lib.types.str;
|
|
default = [ ];
|
|
example = [ "problematic-tool" ];
|
|
description = ''
|
|
list of command names to skip during completion indexing
|
|
'';
|
|
};
|
|
|
|
helpOnlyCommands = lib.mkOption {
|
|
type = lib.types.listOf lib.types.str;
|
|
default = [ ];
|
|
example = [ "nix" ];
|
|
description = ''
|
|
list of command names to skip manpage parsing for,
|
|
using --help scraping instead
|
|
'';
|
|
};
|
|
|
|
snippet = lib.mkOption {
|
|
type = lib.types.str;
|
|
readOnly = true;
|
|
};
|
|
};
|
|
|
|
config = lib.mkIf cfg.enable {
|
|
environment.systemPackages =
|
|
let
|
|
systemDir = "/run/current-system/sw${cfg.completionsPath}";
|
|
dirPaths = lib.concatStringsSep ":" ([ systemDir ] ++ cfg.extraDirs);
|
|
wrapped = pkgs.writeShellScriptBin "inshellah" ''
|
|
case "''${1:-}" in
|
|
complete|query|dump)
|
|
exec ${cfg.package}/bin/inshellah "$@" --dir "''${XDG_CACHE_HOME:-$HOME/.cache}/inshellah:${dirPaths}"
|
|
;;
|
|
*)
|
|
exec ${cfg.package}/bin/inshellah "$@"
|
|
;;
|
|
esac
|
|
'';
|
|
in
|
|
[
|
|
(lib.hiPrio wrapped)
|
|
cfg.package
|
|
];
|
|
environment.pathsToLink = [ "/share/nushell/autoload" ];
|
|
environment.extraSetup =
|
|
let
|
|
inshellah = "${cfg.package}/bin/inshellah";
|
|
destDir = "$out${cfg.completionsPath}";
|
|
ignoreFile = pkgs.writeText "inshellah-ignore" (lib.concatStringsSep "\n" cfg.ignoreCommands);
|
|
ignoreFlag = lib.optionalString (cfg.ignoreCommands != [ ]) " --ignore ${ignoreFile}";
|
|
helpOnlyFile = pkgs.writeText "inshellah-help-only" (
|
|
lib.concatStringsSep "\n" cfg.helpOnlyCommands
|
|
);
|
|
helpOnlyFlag = lib.optionalString (cfg.helpOnlyCommands != [ ]) " --help-only ${helpOnlyFile}";
|
|
in
|
|
''
|
|
mkdir -p ${destDir}
|
|
|
|
if [ -d "$out/bin" ] && [ -d "$out/share/man" ]; then
|
|
${inshellah} index "$out" --dir ${destDir}${ignoreFlag}${helpOnlyFlag} \
|
|
2>/dev/null || true
|
|
fi
|
|
|
|
find ${destDir} -maxdepth 1 -empty -delete
|
|
|
|
# nushell hardcodes sudo and doas to bypass the external completer,
|
|
# returning command-name completion instead of calling inshellah.
|
|
# these @complete external stubs override that so inshellah handles
|
|
# their flags and elevation stripping. placed in the nushell autoload
|
|
# dir so they are sourced automatically at shell startup.
|
|
mkdir -p $out/share/nushell/vendor/autoload
|
|
cat > $out/share/nushell/vendor/autoload/inshellah-elevation.nu << 'NUSHELL'
|
|
@complete external
|
|
extern "sudo" []
|
|
|
|
@complete external
|
|
extern "doas" []
|
|
NUSHELL
|
|
'';
|
|
};
|
|
}
|