init
This commit is contained in:
commit
daa0c24415
23 changed files with 5336 additions and 0 deletions
201
doc/nixos.md
Normal file
201
doc/nixos.md
Normal file
|
|
@ -0,0 +1,201 @@
|
|||
# nixos integration
|
||||
|
||||
inshellah provides a nixos module that automatically indexes 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 index "$out" --dir $out/share/inshellah
|
||||
```
|
||||
|
||||
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.)
|
||||
- mdoc (bsd) format
|
||||
- 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.
|
||||
|
||||
when `--help` produces rendered manpage output instead of plain help
|
||||
text (e.g. `git stash --help` delegates to `man`), the raw manpage
|
||||
source is located and parsed with the groff parser for richer results.
|
||||
|
||||
### output
|
||||
|
||||
each command gets its own file in `/share/inshellah` under the system
|
||||
profile. native generators produce `.nu` files; parsed results produce
|
||||
`.json` files. the `complete` command reads both formats.
|
||||
|
||||
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 indexed completion files under the system profile
|
||||
# default: "/share/inshellah"
|
||||
completionsPath = "/share/inshellah";
|
||||
|
||||
# additional read-only completion directories to search
|
||||
# these are appended to the --dir path alongside the system completions
|
||||
extraDirs = [ "/etc/profiles/per-user/alice/share/inshellah" ];
|
||||
|
||||
# commands to skip entirely during indexing
|
||||
ignoreCommands = [ "problematic-tool" ];
|
||||
|
||||
# commands to skip manpage parsing for (uses --help instead)
|
||||
helpOnlyCommands = [ "nix" ];
|
||||
};
|
||||
```
|
||||
|
||||
## using the completer
|
||||
|
||||
the flake module sets a read-only `snippet` option containing the nushell
|
||||
config needed to wire up the completer. you can access it via
|
||||
`config.programs.inshellah.snippet` and paste it into your nushell config,
|
||||
or source it from a file generated by your nixos config.
|
||||
|
||||
the snippet sets up the external completer. the wrapper installed by
|
||||
the module has the system completion paths hardcoded, so no flags are
|
||||
needed:
|
||||
|
||||
```nu
|
||||
let inshellah_complete = {|spans|
|
||||
inshellah complete ...$spans | from json
|
||||
}
|
||||
$env.config.completions.external = {
|
||||
enable: true
|
||||
max_results: 100
|
||||
completer: $inshellah_complete
|
||||
}
|
||||
```
|
||||
|
||||
## home manager and other user-level package managers
|
||||
|
||||
the nixos module only indexes packages installed at the system level
|
||||
(those that end up in `/run/current-system/sw`). if you use home-manager,
|
||||
nix-env, or another user-level package manager, those binaries and
|
||||
manpages live elsewhere — typically under `/etc/profiles/per-user/<name>`
|
||||
or `~/.nix-profile`.
|
||||
|
||||
to get completions for user-installed packages, run `inshellah index`
|
||||
against those prefixes separately:
|
||||
|
||||
```sh
|
||||
# home-manager / per-user profile
|
||||
inshellah index /etc/profiles/per-user/$USER
|
||||
|
||||
# classic nix-env profile
|
||||
inshellah index ~/.nix-profile
|
||||
```
|
||||
|
||||
this indexes into the default user cache (`$XDG_CACHE_HOME/inshellah`),
|
||||
which the completer searches automatically. you can re-run this after
|
||||
installing new packages, or add it to a home-manager activation script.
|
||||
|
||||
if you want to automate this in home-manager:
|
||||
|
||||
```nix
|
||||
# home.nix
|
||||
home.activation.inshellah-index = lib.hm.dag.entryAfter [ "writeBoundary" ] ''
|
||||
${pkgs.inshellah}/bin/inshellah index /etc/profiles/per-user/$USER 2>/dev/null || true
|
||||
'';
|
||||
```
|
||||
|
||||
the completer will then search both the system index and the user
|
||||
cache, so completions from both sources are available.
|
||||
|
||||
## troubleshooting
|
||||
|
||||
**completions not appearing**: ensure the completer is configured in
|
||||
your nushell config (see above). check that the system index exists:
|
||||
`ls /run/current-system/sw/share/inshellah/`.
|
||||
|
||||
**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**: indexing failures are non-fatal (`|| true`).
|
||||
check `journalctl` for the build log if completions are missing.
|
||||
Loading…
Add table
Add a link
Reference in a new issue