From ba15db2a1565e1779de23bdbacbc420412648289 Mon Sep 17 00:00:00 2001 From: Raul Rodrigues de Oliveira Date: Thu, 6 Nov 2025 13:27:58 -0300 Subject: [PATCH] fish: added completions option (#8127) --- modules/programs/fish.nix | 47 +++++++++++++++++++++ tests/modules/programs/fish/completions.nix | 45 ++++++++++++++++++++ tests/modules/programs/fish/default.nix | 1 + 3 files changed, 93 insertions(+) create mode 100644 tests/modules/programs/fish/completions.nix diff --git a/modules/programs/fish.nix b/modules/programs/fish.nix index 49922ef50..1bc5b54c5 100644 --- a/modules/programs/fish.nix +++ b/modules/programs/fish.nix @@ -153,6 +153,17 @@ let }; }; + completionModule = types.submodule { + options = { + body = mkOption { + type = types.lines; + description = '' + The completion file's body. + ''; + }; + }; + }; + abbrModule = types.submodule { options = { expansion = mkOption { @@ -556,6 +567,28 @@ in . ''; }; + + programs.fish.completions = mkOption { + type = with types; attrsOf (either lines completionModule); + default = { }; + example = literalExpression '' + { + my-prog = ''' + complete -c myprog -s o -l output + '''; + + my-app = { + body = ''' + complete -c myapp -s -v + '''; + }; + } + ''; + description = '' + Custom fish completions. For more information see + . + ''; + }; }; config = mkIf cfg.enable ( @@ -734,6 +767,20 @@ in }; }) cfg.functions; } + { + xdg.configFile = lib.mapAttrs' (name: def: { + name = "fish/completions/${name}.fish"; + value = { + source = + let + body = if isAttrs def then def.body else def; + in + fishIndent "${name}.fish" '' + ${lib.strings.removeSuffix "\n" body} + ''; + }; + }) cfg.completions; + } # Each plugin gets a corresponding conf.d/plugin-NAME.fish file to load # in the paths and any initialization scripts. diff --git a/tests/modules/programs/fish/completions.nix b/tests/modules/programs/fish/completions.nix new file mode 100644 index 000000000..069255d27 --- /dev/null +++ b/tests/modules/programs/fish/completions.nix @@ -0,0 +1,45 @@ +{ lib, pkgs, ... }: +let + myProg = pkgs.writeText "my-prog.fish" '' + complete -c myprog -s o -l output + ''; + + myApp = pkgs.writeText "my-app.fish" '' + complete -c myapp -s -v + ''; +in +{ + config = { + programs.fish = { + enable = true; + + completions = { + my-prog = '' + complete -c myprog -s o -l output + ''; + my-app = { + body = '' + complete -c myapp -s -v + ''; + }; + }; + }; + + xdg.dataFile."fish/home-manager_generated_completions".source = lib.mkForce ( + builtins.toFile "empty" "" + ); + + nmt = { + description = "if fish.completions is set, check file exists and contents match"; + script = '' + assertFileExists home-files/.config/fish/completions/my-prog.fish + echo ${myProg} + assertFileContent home-files/.config/fish/completions/my-prog.fish ${myProg} + + assertFileExists home-files/.config/fish/completions/my-app.fish + echo ${myApp} + assertFileContent home-files/.config/fish/completions/my-app.fish ${myApp} + ''; + }; + }; +} diff --git a/tests/modules/programs/fish/default.nix b/tests/modules/programs/fish/default.nix index ff1bc7582..6ee6aa2a7 100644 --- a/tests/modules/programs/fish/default.nix +++ b/tests/modules/programs/fish/default.nix @@ -2,6 +2,7 @@ fish-abbrs = ./abbrs.nix; fish-format-scripts = ./format-scripts.nix; fish-functions = ./functions.nix; + fish-completions = ./completions.nix; fish-no-functions = ./no-functions.nix; fish-plugins = ./plugins.nix; fish-manpage = ./manpage.nix;