summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--nixos/modules/programs/fish.nix53
-rw-r--r--nixos/modules/programs/fish_completion-generator.patch11
-rw-r--r--nixos/tests/all-tests.nix1
-rw-r--r--nixos/tests/fish.nix21
4 files changed, 86 insertions, 0 deletions
diff --git a/nixos/modules/programs/fish.nix b/nixos/modules/programs/fish.nix
index b38af07b92c..bcb5a3f341b 100644
--- a/nixos/modules/programs/fish.nix
+++ b/nixos/modules/programs/fish.nix
@@ -169,6 +169,59 @@ in
       end
     '';
 
+    programs.fish.interactiveShellInit = ''
+      # add completions generated by NixOS to $fish_complete_path
+      begin
+        # joins with null byte to acommodate all characters in paths, then respectively gets all paths before (exclusive) / after (inclusive) the first one including "generated_completions",
+        # splits by null byte, and then removes all empty lines produced by using 'string'
+        set -l prev (string join0 $fish_complete_path | string match --regex "^.*?(?=\x00[^\x00]*generated_completions.*)" | string split0 | string match -er ".")
+        set -l post (string join0 $fish_complete_path | string match --regex "[^\x00]*generated_completions.*" | string split0 | string match -er ".")
+        set fish_complete_path $prev "/etc/fish/generated_completions" $post
+      end
+    '';
+
+    environment.etc."fish/generated_completions".source =
+      let
+        patchedGenerator = pkgs.stdenv.mkDerivation {
+          name = "fish_patched-completion-generator";
+          srcs = [
+            "${pkgs.fish}/share/fish/tools/create_manpage_completions.py"
+            "${pkgs.fish}/share/fish/tools/deroff.py"
+          ];
+          unpackCmd = "cp $curSrc $(basename $curSrc)";
+          sourceRoot = ".";
+          patches = [ ./fish_completion-generator.patch ]; # to prevent collisions of identical completion files
+          dontBuild = true;
+          installPhase = ''
+            mkdir -p $out
+            cp * $out/
+          '';
+          preferLocalBuild = true;
+          allowSubstitutes = false;
+        };
+        generateCompletions = package: pkgs.runCommand
+          "${package.name}_fish-completions"
+          (
+            {
+              inherit package;
+              preferLocalBuild = true;
+              allowSubstitutes = false;
+            }
+            // optionalAttrs (package ? meta.priority) { meta.priority = package.meta.priority; }
+          )
+          ''
+            mkdir -p $out
+            if [ -d $package/share/man ]; then
+              find $package/share/man -type f | xargs ${pkgs.python3.interpreter} ${patchedGenerator}/create_manpage_completions.py --directory $out >/dev/null
+            fi
+          '';
+      in
+        pkgs.buildEnv {
+          name = "system_fish-completions";
+          ignoreCollisions = true;
+          paths = map generateCompletions config.environment.systemPackages;
+        };
+
     # include programs that bring their own completions
     environment.pathsToLink = []
       ++ optional cfg.vendor.config.enable "/share/fish/vendor_conf.d"
diff --git a/nixos/modules/programs/fish_completion-generator.patch b/nixos/modules/programs/fish_completion-generator.patch
new file mode 100644
index 00000000000..a8c797d185a
--- /dev/null
+++ b/nixos/modules/programs/fish_completion-generator.patch
@@ -0,0 +1,11 @@
+--- a/create_manpage_completions.py
++++ b/create_manpage_completions.py
+@@ -776,8 +776,6 @@ def parse_manpage_at_path(manpage_path, output_directory):
+
+             built_command_output.insert(0, "# " + CMDNAME)
+
+-            # Output the magic word Autogenerated so we can tell if we can overwrite this
+-            built_command_output.insert(1, "# Autogenerated from man page " + manpage_path)
+             # built_command_output.insert(2, "# using " + parser.__class__.__name__) # XXX MISATTRIBUTES THE CULPABILE PARSER! Was really using Type2 but reporting TypeDeroffManParser
+
+             for line in built_command_output:
diff --git a/nixos/tests/all-tests.nix b/nixos/tests/all-tests.nix
index 65227857a38..2ddb54bcc3d 100644
--- a/nixos/tests/all-tests.nix
+++ b/nixos/tests/all-tests.nix
@@ -74,6 +74,7 @@ in
   ferm = handleTest ./ferm.nix {};
   firefox = handleTest ./firefox.nix {};
   firewall = handleTest ./firewall.nix {};
+  fish = handleTest ./fish.nix {};
   flannel = handleTestOn ["x86_64-linux"] ./flannel.nix {};
   flatpak = handleTest ./flatpak.nix {};
   fsck = handleTest ./fsck.nix {};
diff --git a/nixos/tests/fish.nix b/nixos/tests/fish.nix
new file mode 100644
index 00000000000..97c4e8e37ac
--- /dev/null
+++ b/nixos/tests/fish.nix
@@ -0,0 +1,21 @@
+import ./make-test.nix ({ pkgs, ... }: {
+  name = "fish";
+
+  machine =
+    { pkgs, ... }:
+
+    {
+      programs.fish.enable = true;
+      environment.systemPackages = with pkgs; [
+        coreutils
+        procps # kill collides with coreutils' to test https://github.com/NixOS/nixpkgs/issues/56432
+      ];
+    };
+
+  testScript =
+    ''
+      $machine->waitForFile("/etc/fish/generated_completions/coreutils.fish");
+      $machine->waitForFile("/etc/fish/generated_completions/kill.fish");
+      $machine->succeed("fish -ic 'echo \$fish_complete_path' | grep -q '/share/fish/completions /etc/fish/generated_completions /root/.local/share/fish/generated_completions\$'");
+    '';
+})