This commit is contained in:
atagen 2026-03-18 15:40:47 +11:00
commit 71de2e7b4b
22 changed files with 3717 additions and 0 deletions

140
doc/nixos.md Normal file
View file

@ -0,0 +1,140 @@
# NixOS integration
inshellah provides a NixOS module that automatically generates nushell
completions for all installed packages at system build time.
## Enabling
```nix
# In your flake.nix outputs:
{
nixosConfigurations.myhost = nixpkgs.lib.nixosSystem {
modules = [
inshellah.nixosModules.default
{
programs.inshellah.enable = true;
}
];
};
}
```
Or if importing the module directly:
```nix
# configuration.nix
{ pkgs, ... }: {
imports = [ ./path/to/inshellah/nix/module.nix ];
programs.inshellah = {
enable = true;
package = pkgs.inshellah; # or your local build
};
}
```
## What happens at build time
The module hooks into `environment.extraSetup`, which runs during the
system profile build (the `buildEnv` that creates `/run/current-system/sw`).
At that point, all system packages are merged, so `$out/bin` contains every
executable and `$out/share/man` contains every manpage.
inshellah runs a single command:
```
inshellah generate $out/bin $out/share/man -o $out/share/nushell/vendor/autoload
```
This executes a three-phase pipeline:
### Phase 1: Native completion detection (parallel)
For each executable, inshellah scans the ELF binary for the string
`completion`. If found, it probes common patterns like
`CMD completions nushell` to see if the program can generate its own
nushell completions. Native output is used verbatim — these are always
higher quality than parsed completions.
Programs like `niri`, and any Clap/Cobra tool with nushell support,
are handled this way.
### Phase 2: Manpage parsing (sequential)
For commands not covered by Phase 1, inshellah parses manpages from
man1 (user commands) and man8 (sysadmin commands). It handles:
- GNU `.TP` style (coreutils, help2man)
- `.IP` style (curl, hand-written)
- `.PP`+`.RS`/`.RE` style (git, DocBook)
- Nix3 bullet+hyperlink style (`nix run`, `nix build`, etc.)
- Deroff fallback for unusual formats
SYNOPSIS sections are parsed to detect subcommands: `git-commit.1`
generates `export extern "git commit"`, not `export extern "git-commit"`.
### Phase 3: --help fallback (parallel)
Remaining executables without manpages get `--help` (or `-h`) called
with a 200ms timeout. ELF binaries are pre-scanned for the `-h` string
to skip those that don't support help flags. Shell scripts are run
directly (they're fast). Execution is parallelized to available cores.
### Output
Each command gets its own `.nu` file in the vendor autoload directory,
module-wrapped:
```nu
module git-completions {
export extern "git commit" [
--all(-a) # Automatically stage modified and deleted files
--message(-m): string # Use the given msg as the commit message
...
]
}
use git-completions *
```
Nushell built-in commands (ls, cd, cp, mv, etc.) are excluded since
nushell provides its own completions.
### Performance
On a typical NixOS system (~950 executables, ~1600 manpages):
- Total time: ~4-10 seconds
- Native gzip decompression (camlzip, no process spawning)
- Parallel --help with core-scaled forking
- ELF string scanning to skip ~15% of binaries
## Module options
```nix
programs.inshellah = {
enable = true;
# The inshellah package (set automatically by the flake module)
package = pkgs.inshellah;
# Where to place generated .nu files
# Default matches nushell's vendor autoload convention
generatedCompletionsPath = "/share/nushell/vendor/autoload";
};
```
## Troubleshooting
**Completions not appearing**: Ensure nushell discovers the vendor
autoload path. Check `$env.NU_VENDOR_AUTOLOAD_DIRS` or verify that
`/run/current-system/sw/share` is in `$XDG_DATA_DIRS`.
**Missing completions for a specific command**: Check if it's a nushell
built-in (`help commands | where name == "thecommand"`). Built-ins are
excluded because nushell serves its own completions for them.
**Stale completions after update**: Completions regenerate on every
`nixos-rebuild`. If a command changed its flags, rebuild to pick up
the changes.
**Build-time errors**: Generation failures are non-fatal (`|| true`).
Check `journalctl` for the build log if completions are missing.