home-config/fish/conf.d/nix-env.fish
044a02a12449d8dbfd2f5e5e93319865372624a6
· 6.7 KB · 138 lines
raw
| 1 | # Setup Nix |
| 2 | |
| 3 | # We need to distinguish between single-user and multi-user installs. |
| 4 | # This is difficult because there's no official way to do this. |
| 5 | # We could look for the presence of /nix/var/nix/daemon-socket/socket but this will fail if the |
| 6 | # daemon hasn't started yet. /nix/var/nix/daemon-socket will exist if the daemon has ever run, but |
| 7 | # I don't think there's any protection against accidentally running `nix-daemon` as a user. |
| 8 | # We also can't just look for /nix/var/nix/profiles/default/etc/profile.d/nix-daemon.sh because |
| 9 | # older single-user installs used the default profile instead of a per-user profile. |
| 10 | # We can still check for it first, because all multi-user installs should have it, and so if it's |
| 11 | # not present that's a pretty big indicator that this is a single-user install. If it does exist, |
| 12 | # we still need to verify the install type. To that end we'll look for a root owner and sticky bit |
| 13 | # on /nix/store. Multi-user installs set both, single-user installs don't. It's certainly possible |
| 14 | # someone could do a single-user install as root and then manually set the sticky bit but that |
| 15 | # would be extremely unusual. |
| 16 | |
| 17 | set -l nix_profile_path /nix/var/nix/profiles/default/etc/profile.d/nix-daemon.sh |
| 18 | set -l single_user_profile_path ~/.nix-profile/etc/profile.d/nix.sh |
| 19 | if test -e $nix_profile_path |
| 20 | # The path exists. Double-check that this is a multi-user install. |
| 21 | # We can't just check for ~/.nix-profile/… because this may be a single-user install running as |
| 22 | # the wrong user. |
| 23 | |
| 24 | # stat is not portable. Splitting the output of ls -nd is reliable on most platforms. |
| 25 | set -l owner (string split -n ' ' (command ls -nd /nix/store 2>/dev/null))[3] |
| 26 | if not test -k /nix/store -a $owner -eq 0 |
| 27 | # /nix/store is either not owned by root or not sticky. Assume single-user. |
| 28 | set nix_profile_path $single_user_profile_path |
| 29 | end |
| 30 | else |
| 31 | # The path doesn't exist. Assume single-user |
| 32 | set nix_profile_path $single_user_profile_path |
| 33 | end |
| 34 | |
| 35 | if test -e $nix_profile_path |
| 36 | # Source the nix setup script |
| 37 | # We're going to run the regular Nix profile under bash and then print out a few variables |
| 38 | for line in (command env -u BASH_ENV bash -c '. "$0"; for name in PATH "${!NIX_@}"; do printf "%s=%s\0" "$name" "${!name}"; done' $nix_profile_path | string split0) |
| 39 | set -xg (string split -m 1 = $line) |
| 40 | end |
| 41 | |
| 42 | # Insert Nix's fish share directories into fish's special variables. |
| 43 | # nixpkgs-installed fish tries to set these up already if NIX_PROFILES is defined, which won't |
| 44 | # be the case when sourcing $__fish_data_dir/share/config.fish normally, but might be for a |
| 45 | # recursive invocation. To guard against that, we'll only insert paths that don't already exit. |
| 46 | # Furthermore, for the vendor_conf.d sourcing, we'll use the pre-existing presence of a path in |
| 47 | # $fish_function_path to determine whether we want to source the relevant vendor_conf.d folder. |
| 48 | |
| 49 | # To start, let's locally define NIX_PROFILES if it doesn't already exist. |
| 50 | set -al NIX_PROFILES |
| 51 | if test (count $NIX_PROFILES) -eq 0 |
| 52 | set -a NIX_PROFILES $HOME/.nix-profile |
| 53 | end |
| 54 | # Replicate the logic from nixpkgs version of $__fish_data_dir/__fish_build_paths.fish. |
| 55 | set -l __nix_profile_paths (string split ' ' -- $NIX_PROFILES)[-1..1] |
| 56 | set -l __extra_completionsdir \ |
| 57 | $__nix_profile_paths/etc/fish/completions \ |
| 58 | $__nix_profile_paths/share/fish/vendor_completions.d |
| 59 | set -l __extra_functionsdir \ |
| 60 | $__nix_profile_paths/etc/fish/functions \ |
| 61 | $__nix_profile_paths/share/fish/vendor_functions.d |
| 62 | set -l __extra_confdir \ |
| 63 | $__nix_profile_paths/etc/fish/conf.d \ |
| 64 | $__nix_profile_paths/share/fish/vendor_conf.d \ |
| 65 | |
| 66 | ### Configure fish_function_path ### |
| 67 | # Remove any of our extra paths that may already exist. |
| 68 | # Record the equivalent __extra_confdir path for any function path that exists. |
| 69 | set -l existing_conf_paths |
| 70 | for path in $__extra_functionsdir |
| 71 | if set -l idx (contains --index -- $path $fish_function_path) |
| 72 | set -e fish_function_path[$idx] |
| 73 | set -a existing_conf_paths $__extra_confdir[(contains --index -- $path $__extra_functionsdir)] |
| 74 | end |
| 75 | end |
| 76 | # Insert the paths before $__fish_data_dir. |
| 77 | if set -l idx (contains --index -- $__fish_data_dir/functions $fish_function_path) |
| 78 | # Fish has no way to simply insert into the middle of an array. |
| 79 | set -l new_path $fish_function_path[1..$idx] |
| 80 | set -e new_path[$idx] |
| 81 | set -a new_path $__extra_functionsdir |
| 82 | set fish_function_path $new_path $fish_function_path[$idx..-1] |
| 83 | else |
| 84 | set -a fish_function_path $__extra_functionsdir |
| 85 | end |
| 86 | |
| 87 | ### Configure fish_complete_path ### |
| 88 | # Remove any of our extra paths that may already exist. |
| 89 | for path in $__extra_completionsdir |
| 90 | if set -l idx (contains --index -- $path $fish_complete_path) |
| 91 | set -e fish_complete_path[$idx] |
| 92 | end |
| 93 | end |
| 94 | # Insert the paths before $__fish_data_dir. |
| 95 | if set -l idx (contains --index -- $__fish_data_dir/completions $fish_complete_path) |
| 96 | set -l new_path $fish_complete_path[1..$idx] |
| 97 | set -e new_path[$idx] |
| 98 | set -a new_path $__extra_completionsdir |
| 99 | set fish_complete_path $new_path $fish_complete_path[$idx..-1] |
| 100 | else |
| 101 | set -a fish_complete_path $__extra_completionsdir |
| 102 | end |
| 103 | |
| 104 | ### Source conf directories ### |
| 105 | # The built-in directories were already sourced during shell initialization. |
| 106 | # Any __extra_confdir that came from $__fish_data_dir/__fish_build_paths.fish was also sourced. |
| 107 | # As explained above, we're using the presence of pre-existing paths in $fish_function_path as a |
| 108 | # signal that the corresponding conf dir has also already been sourced. |
| 109 | # In order to simulate this, we'll run through the same algorithm as found in |
| 110 | # $__fish_data_dir/config.fish except we'll avoid sourcing the file if it comes from an |
| 111 | # already-sourced location. |
| 112 | # Caveats: |
| 113 | # * Files will be sourced in a different order than we'd ideally do (because we're coming in |
| 114 | # after the fact to source them). |
| 115 | # * If there are existing extra conf paths, files in them may have been sourced that should have |
| 116 | # been suppressed by paths we're inserting in front. |
| 117 | # * Similarly any files in $__fish_data_dir/vendor_conf.d that should have been suppressed won't |
| 118 | # have been. |
| 119 | set -l sourcelist |
| 120 | for file in $__fish_config_dir/conf.d/*.fish $__fish_sysconf_dir/conf.d/*.fish |
| 121 | # We know these paths were sourced already. Just record them. |
| 122 | set -l basename (string replace -r '^.*/' '' -- $file) |
| 123 | contains -- $basename $sourcelist |
| 124 | or set -a sourcelist $basename |
| 125 | end |
| 126 | for root in $__extra_confdir |
| 127 | for file in $root/*.fish |
| 128 | set -l basename (string replace -r '^.*/' '' -- $file) |
| 129 | contains -- $basename $sourcelist |
| 130 | and continue |
| 131 | set -a sourcelist $basename |
| 132 | contains -- $root $existing_conf_paths |
| 133 | and continue # this is a pre-existing path, it will have been sourced already |
| 134 | [ -f $file -a -r $file ] |
| 135 | and source $file |
| 136 | end |
| 137 | end |
| 138 | end |