fish: add babelfish translation option

Configuration may be ran through fenv at shell start time
(as previously) or translated to fish at build time with
the babelfish package.
This commit is contained in:
Kevin Griffin 2021-01-11 16:11:29 +09:00 committed by Cole Helbling
parent 4aaa445477
commit 515d801aee

View File

@ -13,6 +13,27 @@ let
(filterAttrs (k: v: v != null) cfg.shellAliases) (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-foreign-env/functions $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 in
{ {
@ -29,6 +50,15 @@ in
type = types.bool; 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 { vendor.config.enable = mkOption {
type = types.bool; type = types.bool;
default = true; default = true;
@ -105,11 +135,32 @@ in
# Required for man completions # Required for man completions
documentation.man.generateCaches = lib.mkDefault true; documentation.man.generateCaches = lib.mkDefault true;
environment.etc."fish/foreign-env/shellInit".text = cfge.shellInit; environment = mkMerge [
environment.etc."fish/foreign-env/loginShellInit".text = cfge.loginShellInit; (mkIf cfg.useBabelfish
environment.etc."fish/foreign-env/interactiveShellInit".text = cfge.interactiveShellInit; {
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";
})
environment.etc."fish/nixos-env-preinit.fish".text = '' (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 # 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 # 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 set fish_function_path ${pkgs.fishPlugins.foreign-env}/share/fish/vendor_functions.d $__fish_datadir/functions
@ -122,15 +173,15 @@ in
# clear fish_function_path so that it will be correctly set when we return to $__fish_datadir/config.fish # clear fish_function_path so that it will be correctly set when we return to $__fish_datadir/config.fish
set -e fish_function_path set -e fish_function_path
''; '';
}
environment.etc."fish/config.fish".text = '' {
etc."fish/config.fish".text = ''
# /etc/fish/config.fish: DO NOT EDIT -- this file has been generated automatically. # /etc/fish/config.fish: DO NOT EDIT -- this file has been generated automatically.
# if we haven't sourced the general config, do it # if we haven't sourced the general config, do it
if not set -q __fish_nixos_general_config_sourced if not set -q __fish_nixos_general_config_sourced
set --prepend fish_function_path ${pkgs.fishPlugins.foreign-env}/share/fish/vendor_functions.d ${sourceEnv "shellInit"}
fenv source /etc/fish/foreign-env/shellInit > /dev/null
set -e fish_function_path[1]
${cfg.shellInit} ${cfg.shellInit}
@ -142,9 +193,7 @@ in
# if we haven't sourced the login config, do it # if we haven't sourced the login config, do it
status --is-login; and not set -q __fish_nixos_login_config_sourced status --is-login; and not set -q __fish_nixos_login_config_sourced
and begin and begin
set --prepend fish_function_path ${pkgs.fishPlugins.foreign-env}/share/fish/vendor_functions.d ${sourceEnv "loginShellInit"}
fenv source /etc/fish/foreign-env/loginShellInit > /dev/null
set -e fish_function_path[1]
${cfg.loginShellInit} ${cfg.loginShellInit}
@ -158,9 +207,7 @@ in
and begin and begin
${fishAliases} ${fishAliases}
set --prepend fish_function_path ${pkgs.fishPlugins.foreign-env}/share/fish/vendor_functions.d ${sourceEnv "interactiveShellInit"}
fenv source /etc/fish/foreign-env/interactiveShellInit > /dev/null
set -e fish_function_path[1]
${cfg.promptInit} ${cfg.promptInit}
${cfg.interactiveShellInit} ${cfg.interactiveShellInit}
@ -171,23 +218,10 @@ in
set -g __fish_nixos_interactive_config_sourced 1 set -g __fish_nixos_interactive_config_sourced 1
end end
''; '';
}
programs.fish.interactiveShellInit = '' {
# add completions generated by NixOS to $fish_complete_path etc."fish/generated_completions".source =
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
# prevent fish from generating completions on first run
if not test -d $__fish_user_data_dir/generated_completions
${pkgs.coreutils}/bin/mkdir $__fish_user_data_dir/generated_completions
end
'';
environment.etc."fish/generated_completions".source =
let let
patchedGenerator = pkgs.stdenv.mkDerivation { patchedGenerator = pkgs.stdenv.mkDerivation {
name = "fish_patched-completion-generator"; name = "fish_patched-completion-generator";
@ -228,19 +262,40 @@ in
ignoreCollisions = true; ignoreCollisions = true;
paths = map generateCompletions config.environment.systemPackages; paths = map generateCompletions config.environment.systemPackages;
}; };
}
# include programs that bring their own completions # include programs that bring their own completions
environment.pathsToLink = [] {
pathsToLink = []
++ optional cfg.vendor.config.enable "/share/fish/vendor_conf.d" ++ optional cfg.vendor.config.enable "/share/fish/vendor_conf.d"
++ optional cfg.vendor.completions.enable "/share/fish/vendor_completions.d" ++ optional cfg.vendor.completions.enable "/share/fish/vendor_completions.d"
++ optional cfg.vendor.functions.enable "/share/fish/vendor_functions.d"; ++ optional cfg.vendor.functions.enable "/share/fish/vendor_functions.d";
}
environment.systemPackages = [ pkgs.fish ]; { systemPackages = [ pkgs.fish ]; }
environment.shells = [ {
shells = [
"/run/current-system/sw/bin/fish" "/run/current-system/sw/bin/fish"
"${pkgs.fish}/bin/fish" "${pkgs.fish}/bin/fish"
]; ];
}
];
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
# prevent fish from generating completions on first run
if not test -d $__fish_user_data_dir/generated_completions
${pkgs.coreutils}/bin/mkdir $__fish_user_data_dir/generated_completions
end
'';
}; };