1# This module provides suggestions of packages to install if the user
2# tries to run a missing command in Bash. This is implemented using a
3# SQLite database that maps program names to Nix package names (e.g.,
4# "pdflatex" is mapped to "tetex").
5
6{
7 config,
8 lib,
9 pkgs,
10 ...
11}:
12
13let
14 cfg = config.programs.command-not-found;
15 commandNotFound = pkgs.replaceVarsWith {
16 name = "command-not-found";
17 dir = "bin";
18 src = ./command-not-found.pl;
19 isExecutable = true;
20 replacements = {
21 inherit (cfg) dbPath;
22 perl = pkgs.perl.withPackages (p: [
23 p.DBDSQLite
24 p.StringShellQuote
25 ]);
26 };
27 };
28
29in
30
31{
32 options.programs.command-not-found = {
33
34 enable = lib.mkOption {
35 type = lib.types.bool;
36 default = false;
37 description = ''
38 Whether interactive shells should show which Nix package (if
39 any) provides a missing command.
40
41 Requires nix-channels to be set and downloaded (sudo nix-channels --update.)
42
43 See also nix-index and nix-index-database as an alternative for flakes-based systems.
44
45 Additionally, having the env var NIX_AUTO_RUN set will automatically run the matching package, and with NIX_AUTO_RUN_INTERACTIVE it will confirm the package before running.
46 '';
47 };
48
49 dbPath = lib.mkOption {
50 default = "/nix/var/nix/profiles/per-user/root/channels/nixos/programs.sqlite";
51 description = ''
52 Absolute path to programs.sqlite.
53
54 By default this file will be provided by your channel
55 (nixexprs.tar.xz).
56 '';
57 type = lib.types.path;
58 };
59 };
60
61 config = lib.mkIf cfg.enable {
62 programs.bash.interactiveShellInit = ''
63 command_not_found_handle() {
64 '${commandNotFound}/bin/command-not-found' "$@"
65 }
66 '';
67
68 programs.zsh.interactiveShellInit = ''
69 command_not_found_handler() {
70 '${commandNotFound}/bin/command-not-found' "$@"
71 }
72 '';
73
74 # NOTE: Fish by itself checks for nixos command-not-found, let's instead makes it explicit.
75 programs.fish.interactiveShellInit = ''
76 function fish_command_not_found
77 "${commandNotFound}/bin/command-not-found" $argv
78 end
79 '';
80
81 environment.systemPackages = [ commandNotFound ];
82 };
83
84}