2020-04-24 23:36:52 +00:00
{ config , lib , pkgs , . . . }:
with lib ;
let
cfge = config . environment ;
cfg = config . programs . fish ;
fishAliases = concatStringsSep " \n " (
mapAttrsFlatten ( k : v : " a l i a s ${ k } ${ escapeShellArg v } " )
( filterAttrs ( k : v : v != null ) cfg . shellAliases )
) ;
in
{
options = {
programs . fish = {
enable = mkOption {
default = false ;
description = ''
Whether to configure fish as an interactive shell .
'' ;
type = types . bool ;
} ;
vendor . config . enable = mkOption {
type = types . bool ;
default = true ;
description = ''
Whether fish should source configuration snippets provided by other packages .
'' ;
} ;
vendor . completions . enable = mkOption {
type = types . bool ;
default = true ;
description = ''
Whether fish should use completion files provided by other packages .
'' ;
} ;
vendor . functions . enable = mkOption {
type = types . bool ;
default = true ;
description = ''
Whether fish should autoload fish functions provided by other packages .
'' ;
} ;
shellAliases = mkOption {
default = { } ;
description = ''
Set of aliases for fish shell , which overrides <option> environment . shellAliases < /option > .
See <option> environment . shellAliases < /option > for an option format description .
'' ;
type = with types ; attrsOf ( nullOr ( either str path ) ) ;
} ;
shellInit = mkOption {
default = " " ;
description = ''
Shell script code called during fish shell initialisation .
'' ;
type = types . lines ;
} ;
loginShellInit = mkOption {
default = " " ;
description = ''
Shell script code called during fish login shell initialisation .
'' ;
type = types . lines ;
} ;
interactiveShellInit = mkOption {
default = " " ;
description = ''
Shell script code called during interactive fish shell initialisation .
'' ;
type = types . lines ;
} ;
promptInit = mkOption {
default = " " ;
description = ''
Shell script code used to initialise fish prompt .
'' ;
type = types . lines ;
} ;
} ;
} ;
config = mkIf cfg . enable {
programs . fish . shellAliases = mapAttrs ( name : mkDefault ) cfge . shellAliases ;
2020-07-18 16:06:22 +00:00
# Required for man completions
documentation . man . generateCaches = true ;
2020-04-24 23:36:52 +00:00
environment . etc . " f i s h / f o r e i g n - e n v / s h e l l I n i t " . text = cfge . shellInit ;
environment . etc . " f i s h / f o r e i g n - e n v / l o g i n S h e l l I n i t " . text = cfge . loginShellInit ;
environment . etc . " f i s h / f o r e i g n - e n v / i n t e r a c t i v e S h e l l I n i t " . text = cfge . interactiveShellInit ;
environment . etc . " f i s h / n i x o s - e n v - p r e i n i t . f i s h " . 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 " $ _ _ N I X O S _ S E T _ E N V I R O N M E N T _ D O N E " ]
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 . " f i s h / c o n f i g . f i s h " . 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
'' ;
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 " ^ . * ? ( ? = \x 0 0 [ ^ \x 0 0 ] * g e n e r a t e d _ c o m p l e t i o n s . * ) " | string split0 | string match - er " . " )
set - l post ( string join0 $ fish_complete_path | string match - - regex " [ ^ \x 0 0 ] * g e n e r a t e d _ c o m p l e t i o n s . * " | string split0 | string match - er " . " )
set fish_complete_path $ prev " / e t c / f i s h / g e n e r a t e d _ c o m p l e t i o n s " $ post
end
2020-05-03 17:38:23 +00:00
# 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
2020-04-24 23:36:52 +00:00
'' ;
environment . etc . " f i s h / g e n e r a t e d _ c o m p l e t i o n s " . source =
let
patchedGenerator = pkgs . stdenv . mkDerivation {
name = " f i s h _ p a t c h e d - c o m p l e t i o n - g e n e r a t o r " ;
srcs = [
" ${ pkgs . fish } / s h a r e / f i s h / t o o l s / c r e a t e _ m a n p a g e _ c o m p l e t i o n s . p y "
" ${ pkgs . fish } / s h a r e / f i s h / t o o l s / d e r o f f . p y "
] ;
unpackCmd = " c p $ c u r S r c $ ( b a s e n a m e $ c u r S r c ) " ;
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 } _ f i s h - c o m p l e t i o n s "
(
{
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 = " s y s t e m _ f i s h - c o m p l e t i o n s " ;
ignoreCollisions = true ;
paths = map generateCompletions config . environment . systemPackages ;
} ;
# include programs that bring their own completions
environment . pathsToLink = [ ]
++ optional cfg . vendor . config . enable " / s h a r e / f i s h / v e n d o r _ c o n f . d "
++ optional cfg . vendor . completions . enable " / s h a r e / f i s h / v e n d o r _ c o m p l e t i o n s . d "
++ optional cfg . vendor . functions . enable " / s h a r e / f i s h / v e n d o r _ f u n c t i o n s . d " ;
environment . systemPackages = [ pkgs . fish ] ;
environment . shells = [
" / r u n / c u r r e n t - s y s t e m / s w / b i n / f i s h "
" ${ pkgs . fish } / b i n / f i s h "
] ;
} ;
}