Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Native fish environment with babelfish #270

Merged
merged 1 commit into from
Jan 28, 2021
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
214 changes: 136 additions & 78 deletions modules/programs/fish.nix
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,29 @@ let
mapAttrsFlatten (k: v: "alias ${k} '${v}'") cfg.shellAliases
);

envShellInit = pkgs.writeText "shellInit" cfge.shellInit;

envLoginShellInit = pkgs.writeText "loginShellInit" cfge.loginShellInit;

envInteractiveShellInit = pkgs.writeText "interactiveShellInit" cfge.interactiveShellInit;

fenv = pkgs.fish-foreign-env or pkgs.fishPlugins.foreign-env;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I ran into the same problem because of the redirect at pkgs.fish-foreign-env, looks like flipping around the packages would indeed fix it.

Suggested change
fenv = pkgs.fish-foreign-env or pkgs.fishPlugins.foreign-env;
fenv = pkgs.fishPlugins.foreign-env or pkgs.fish-foreign-env;


sourceEnv = file:
if cfg.useBabelfish then
"source /etc/fish/${file}.fish"
else
''
set fish_function_path ${fenv}/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 = [ cfg.babelfishPackage ];
} "${cfg.babelfishPackage}/bin/babelfish < ${path} > $out;";

in

{
Expand All @@ -27,7 +50,24 @@ 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.
'';
};

babelfishPackage = mkOption {
type = types.package;
description = ''
The babelfish package to use when useBabelfish is
set to true.
'';
};

vendor.config.enable = mkOption {
type = types.bool;
default = true;
Expand All @@ -43,7 +83,7 @@ in
Whether fish should use completion files provided by other packages.
'';
};

vendor.functions.enable = mkOption {
type = types.bool;
default = true;
Expand Down Expand Up @@ -99,82 +139,100 @@ in

config = mkIf cfg.enable {

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 "$__NIX_DARWIN_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_nix_darwin_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_nix_darwin_general_config_sourced 1
end

# if we haven't sourced the login config, do it
status --is-login; and not set -q __fish_nix_darwin_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_nix_darwin_login_config_sourced 1
end

# if we haven't sourced the interactive config, do it
status --is-interactive; and not set -q __fish_nix_darwin_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]

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You're removing a bunch of the shell inits here, which will break gpg-agent for example.

I think we should translate all of the init files and save them as environment.etc."fish/interactiveShellInit.fish" etc. Then we also don't need system.build.setEnvironmentFish

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@bouk I've tried implementing this approach. If you could have a look and give feedback, I'll port the same change to the nixOS module.

${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_nix_darwin_interactive_config_sourced 1
end
'';

# 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 = 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 "$__NIX_DARWIN_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 ${fenv}/share/fish-foreign-env/functions $__fish_datadir/functions

# source the NixOS environment config
if [ -z "$__NIX_DARWIN_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_nix_darwin_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_nix_darwin_general_config_sourced 1
end

# if we haven't sourced the login config, do it
status --is-login; and not set -q __fish_nix_darwin_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_nix_darwin_login_config_sourced 1
end

# if we haven't sourced the interactive config, do it
status --is-interactive; and not set -q __fish_nix_darwin_interactive_config_sourced
and begin
${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_nix_darwin_interactive_config_sourced 1
end
'';
}

# 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 ]; }
];
};

}