diff options
Diffstat (limited to 'nixos/modules/programs/fish.nix')
-rw-r--r-- | nixos/modules/programs/fish.nix | 319 |
1 files changed, 196 insertions, 123 deletions
diff --git a/nixos/modules/programs/fish.nix b/nixos/modules/programs/fish.nix index 39b92edf2ac..8dd7101947f 100644 --- a/nixos/modules/programs/fish.nix +++ b/nixos/modules/programs/fish.nix @@ -8,11 +8,37 @@ let cfg = config.programs.fish; + fishAbbrs = concatStringsSep "\n" ( + mapAttrsFlatten (k: v: "abbr -ag ${k} ${escapeShellArg v}") + cfg.shellAbbrs + ); + fishAliases = concatStringsSep "\n" ( mapAttrsFlatten (k: v: "alias ${k} ${escapeShellArg v}") (filterAttrs (k: v: v != null) cfg.shellAliases) ); + envShellInit = pkgs.writeText "shellInit" cfge.shellInit; + + envLoginShellInit = pkgs.writeText "loginShellInit" cfge.loginShellInit; + + envInteractiveShellInit = pkgs.writeText "interactiveShellInit" cfge.interactiveShellInit; + + sourceEnv = file: + if cfg.useBabelfish then + "source /etc/fish/${file}.fish" + else + '' + set fish_function_path ${pkgs.fishPlugins.foreign-env}/share/fish/vendor_functions.d $fish_function_path + fenv source /etc/fish/foreign-env/${file} > /dev/null + set -e fish_function_path[1] + ''; + + babelfishTranslate = path: name: + pkgs.runCommand "${name}.fish" { + nativeBuildInputs = [ pkgs.babelfish ]; + } "${pkgs.babelfish}/bin/babelfish < ${path} > $out;"; + in { @@ -29,6 +55,15 @@ in type = types.bool; }; + useBabelfish = mkOption { + type = types.bool; + default = false; + description = '' + If enabled, the configured environment will be translated to native fish using <link xlink:href="https://github.com/bouk/babelfish">babelfish</link>. + Otherwise, <link xlink:href="https://github.com/oh-my-fish/plugin-foreign-env">foreign-env</link> will be used. + ''; + }; + vendor.config.enable = mkOption { type = types.bool; default = true; @@ -53,6 +88,18 @@ in ''; }; + shellAbbrs = mkOption { + default = {}; + example = { + gco = "git checkout"; + npu = "nix-prefetch-url"; + }; + description = '' + Set of fish abbreviations. + ''; + type = with types; attrsOf str; + }; + shellAliases = mkOption { default = {}; description = '' @@ -103,74 +150,155 @@ in programs.fish.shellAliases = mapAttrs (name: mkDefault) cfge.shellAliases; # Required for man completions - documentation.man.generateCaches = true; - - environment.etc."fish/foreign-env/shellInit".text = cfge.shellInit; - environment.etc."fish/foreign-env/loginShellInit".text = cfge.loginShellInit; - environment.etc."fish/foreign-env/interactiveShellInit".text = cfge.interactiveShellInit; - - environment.etc."fish/nixos-env-preinit.fish".text = '' - # This happens before $__fish_datadir/config.fish sets fish_function_path, so it is currently - # unset. We set it and then completely erase it, leaving its configuration to $__fish_datadir/config.fish - set fish_function_path ${pkgs.fish-foreign-env}/share/fish-foreign-env/functions $__fish_datadir/functions - - # source the NixOS environment config - if [ -z "$__NIXOS_SET_ENVIRONMENT_DONE" ] - fenv source ${config.system.build.setEnvironment} - end - - # clear fish_function_path so that it will be correctly set when we return to $__fish_datadir/config.fish - set -e fish_function_path - ''; - - environment.etc."fish/config.fish".text = '' - # /etc/fish/config.fish: DO NOT EDIT -- this file has been generated automatically. - - # if we haven't sourced the general config, do it - if not set -q __fish_nixos_general_config_sourced - set fish_function_path ${pkgs.fish-foreign-env}/share/fish-foreign-env/functions $fish_function_path - fenv source /etc/fish/foreign-env/shellInit > /dev/null - set -e fish_function_path[1] - - ${cfg.shellInit} - - # and leave a note so we don't source this config section again from - # this very shell (children will source the general config anew) - set -g __fish_nixos_general_config_sourced 1 - end - - # if we haven't sourced the login config, do it - status --is-login; and not set -q __fish_nixos_login_config_sourced - and begin - set fish_function_path ${pkgs.fish-foreign-env}/share/fish-foreign-env/functions $fish_function_path - fenv source /etc/fish/foreign-env/loginShellInit > /dev/null - set -e fish_function_path[1] - - ${cfg.loginShellInit} - - # and leave a note so we don't source this config section again from - # this very shell (children will source the general config anew) - set -g __fish_nixos_login_config_sourced 1 - end - - # if we haven't sourced the interactive config, do it - status --is-interactive; and not set -q __fish_nixos_interactive_config_sourced - and begin - ${fishAliases} - - set fish_function_path ${pkgs.fish-foreign-env}/share/fish-foreign-env/functions $fish_function_path - fenv source /etc/fish/foreign-env/interactiveShellInit > /dev/null - set -e fish_function_path[1] - - ${cfg.promptInit} - ${cfg.interactiveShellInit} - - # and leave a note so we don't source this config section again from - # this very shell (children will source the general config anew, - # allowing configuration changes in, e.g, aliases, to propagate) - set -g __fish_nixos_interactive_config_sourced 1 - end - ''; + documentation.man.generateCaches = lib.mkDefault true; + + environment = mkMerge [ + (mkIf cfg.useBabelfish + { + etc."fish/setEnvironment.fish".source = babelfishTranslate config.system.build.setEnvironment "setEnvironment"; + etc."fish/shellInit.fish".source = babelfishTranslate envShellInit "shellInit"; + etc."fish/loginShellInit.fish".source = babelfishTranslate envLoginShellInit "loginShellInit"; + etc."fish/interactiveShellInit.fish".source = babelfishTranslate envInteractiveShellInit "interactiveShellInit"; + }) + + (mkIf (!cfg.useBabelfish) + { + etc."fish/foreign-env/shellInit".source = envShellInit; + etc."fish/foreign-env/loginShellInit".source = envLoginShellInit; + etc."fish/foreign-env/interactiveShellInit".source = envInteractiveShellInit; + }) + + { + etc."fish/nixos-env-preinit.fish".text = + if cfg.useBabelfish + then '' + # source the NixOS environment config + if [ -z "$__NIXOS_SET_ENVIRONMENT_DONE" ] + source /etc/fish/setEnvironment.fish + end + '' + else '' + # This happens before $__fish_datadir/config.fish sets fish_function_path, so it is currently + # unset. We set it and then completely erase it, leaving its configuration to $__fish_datadir/config.fish + set fish_function_path ${pkgs.fishPlugins.foreign-env}/share/fish/vendor_functions.d $__fish_datadir/functions + + # source the NixOS environment config + if [ -z "$__NIXOS_SET_ENVIRONMENT_DONE" ] + fenv source ${config.system.build.setEnvironment} + end + + # clear fish_function_path so that it will be correctly set when we return to $__fish_datadir/config.fish + set -e fish_function_path + ''; + } + + { + etc."fish/config.fish".text = '' + # /etc/fish/config.fish: DO NOT EDIT -- this file has been generated automatically. + + # if we haven't sourced the general config, do it + if not set -q __fish_nixos_general_config_sourced + ${sourceEnv "shellInit"} + + ${cfg.shellInit} + + # and leave a note so we don't source this config section again from + # this very shell (children will source the general config anew) + set -g __fish_nixos_general_config_sourced 1 + end + + # if we haven't sourced the login config, do it + status --is-login; and not set -q __fish_nixos_login_config_sourced + and begin + ${sourceEnv "loginShellInit"} + + ${cfg.loginShellInit} + + # and leave a note so we don't source this config section again from + # this very shell (children will source the general config anew) + set -g __fish_nixos_login_config_sourced 1 + end + + # if we haven't sourced the interactive config, do it + status --is-interactive; and not set -q __fish_nixos_interactive_config_sourced + and begin + ${fishAbbrs} + ${fishAliases} + + ${sourceEnv "interactiveShellInit"} + + ${cfg.promptInit} + ${cfg.interactiveShellInit} + + # and leave a note so we don't source this config section again from + # this very shell (children will source the general config anew, + # allowing configuration changes in, e.g, aliases, to propagate) + set -g __fish_nixos_interactive_config_sourced 1 + end + ''; + } + + { + 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 + { + pathsToLink = [] + ++ optional cfg.vendor.config.enable "/share/fish/vendor_conf.d" + ++ optional cfg.vendor.completions.enable "/share/fish/vendor_completions.d" + ++ optional cfg.vendor.functions.enable "/share/fish/vendor_functions.d"; + } + + { systemPackages = [ pkgs.fish ]; } + + { + shells = [ + "/run/current-system/sw/bin/fish" + "${pkgs.fish}/bin/fish" + ]; + } + ]; programs.fish.interactiveShellInit = '' # add completions generated by NixOS to $fish_complete_path @@ -187,61 +315,6 @@ in 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" - ++ optional cfg.vendor.completions.enable "/share/fish/vendor_completions.d" - ++ optional cfg.vendor.functions.enable "/share/fish/vendor_functions.d"; - - environment.systemPackages = [ pkgs.fish ]; - - environment.shells = [ - "/run/current-system/sw/bin/fish" - "${pkgs.fish}/bin/fish" - ]; - }; } |