1

Modules/Fish: Add mechanism to load/unload fish environment shells with direnv

This commit is contained in:
2026-04-20 11:27:18 +02:00
parent f259b7d326
commit 2533183d80
7 changed files with 258 additions and 45 deletions

View File

@ -98,38 +98,65 @@ rec {
buildDebug = mkBuildScript "Debug"; buildDebug = mkBuildScript "Debug";
buildRelease = mkBuildScript "Release"; buildRelease = mkBuildScript "Release";
# Use this to specify commands that should be ran after entering fish shell # Add project-local fish abbrs here
initProjectShell = pkgs.writers.writeFish "init-shell.fish" '' abbrs = {
echo "Entering \"${description}\" environment..."
# Determine the project root, used e.g. in cmake scripts
set -g -x FLAKE_PROJECT_ROOT (git rev-parse --show-toplevel)
# Rust Bevy: # Rust Bevy:
# abbr -a build-release-windows "CARGO_FEATURE_PURE=1 cargo xwin build --release --target x86_64-pc-windows-msvc" # build-release-windows = "CARGO_FEATURE_PURE=1 cargo xwin build --release --target x86_64-pc-windows-msvc";
# C/C++: # C/C++:
# abbr -a cmake-debug "${cmakeDebug}" # cmake-debug = "${cmakeDebug}";
# abbr -a cmake-release "${cmakeRelease}" # cmake-release = "${cmakeRelease}";
# abbr -a build-debug "${buildDebug}" # build-debug = "${buildDebug}";
# abbr -a build-release "${buildRelease}" # build-release = "${buildRelease}";
# Clojure: # Clojure:
# abbr -a clojure-deps "deps-lock --lein" # clojure-deps = "deps-lock --lein";
# Python: # Python:
# abbr -a run "python ./app/main.py" # run = "python ./app/main.py";
# abbr -a profile "py-spy record -o profile.svg -- python ./app/main.py && firefox profile.svg" # profile = "py-spy record -o profile.svg -- python ./app/main.py && firefox profile.svg";
# abbr -a ptop "py-spy top -- python ./app/main.py" # ptop = "py-spy top -- python ./app/main.py";
};
eraseAbbr = name: value: ''abbr --erase ${name} 2>/dev/null'';
createAbbr = name: value: ''abbr -a ${name} "${value}"'';
# This will be sourced by the global fish config if INIT_PROJECT_SHELL gets unset
unloadProjectShell = pkgs.writers.writeFish "unload-shell.fish" ''
echo "Unloading \"${description}\" environment..."
${builtins.concatStringsSep "\n" (lib.mapAttrsToList eraseAbbr abbrs)}
'';
# This will be sourced by the global fish config if INIT_PROJECT_SHELL gets set
initProjectShell = pkgs.writers.writeFish "init-shell.fish" ''
# Unload just in case, to not have redefinition errors
source ${unloadProjectShell}
echo "Sourcing \"${description}\" environment..."
${builtins.concatStringsSep "\n" (lib.mapAttrsToList createAbbr abbrs)}
''; '';
in in
builtins.concatStringsSep "\n" [ builtins.concatStringsSep "\n" [
# Launch into pure fish shell # Launch into pure fish shell
'' ''
exec "$(type -p fish)" -C "source ${initProjectShell} && abbr -a menu '${pkgs.bat}/bin/bat "${initProjectShell}"'" # Determine the project root, used e.g. in cmake scripts
export FLAKE_PROJECT_ROOT="$(git rev-parse --show-toplevel)"
# Can't do the "exec" with nix-direnv
# - The "exec fish" would call direnv again => Infinite loop
# - The shellHook is Bash/POSIX, so fish syntax doesn't work
# Use this for "nix develop" without direnv
# exec "$(type -p fish)" -C "source ${initProjectShell} && abbr -a menu '${pkgs.bat}/bin/bat "${initProjectShell}"'"
# Use this for direnv without "nix develop"
export INIT_PROJECT_SHELL="${initProjectShell}"
export UNLOAD_PROJECT_SHELL="${unloadProjectShell}"
'' ''
# Qt: Launch into wrapped fish shell # Qt: Launch into wrapped fish shell (direnv incompatible)
# https://nixos.org/manual/nixpkgs/stable/#sec-language-qt # https://nixos.org/manual/nixpkgs/stable/#sec-language-qt
# '' # ''
# fishdir=$(mktemp -d) # fishdir=$(mktemp -d)

180
flake.lock generated
View File

@ -1,5 +1,24 @@
{ {
"nodes": { "nodes": {
"comfyui-nix": {
"inputs": {
"flake-parts": "flake-parts",
"nixpkgs": "nixpkgs"
},
"locked": {
"lastModified": 1775530069,
"narHash": "sha256-LuWit2RDTkiwwHwAhqfPcfo6ZUcV931XXijeQqD6FTM=",
"owner": "utensils",
"repo": "comfyui-nix",
"rev": "255224118c3a7d7514c4f0d975120feb3cb16b58",
"type": "github"
},
"original": {
"owner": "utensils",
"repo": "comfyui-nix",
"type": "github"
}
},
"crane": { "crane": {
"locked": { "locked": {
"lastModified": 1754269165, "lastModified": 1754269165,
@ -17,7 +36,7 @@
}, },
"devshell": { "devshell": {
"inputs": { "inputs": {
"nixpkgs": "nixpkgs" "nixpkgs": "nixpkgs_2"
}, },
"locked": { "locked": {
"lastModified": 1768818222, "lastModified": 1768818222,
@ -33,6 +52,28 @@
"type": "github" "type": "github"
} }
}, },
"direnv-instant": {
"inputs": {
"flake-parts": "flake-parts_2",
"nixpkgs": [
"nixpkgs"
],
"treefmt-nix": "treefmt-nix"
},
"locked": {
"lastModified": 1776064408,
"narHash": "sha256-usJh+oOUfRDHvWd1rRjSJX/OyRskHqumg93laPhz88I=",
"owner": "Mic92",
"repo": "direnv-instant",
"rev": "f1a33bf99b030e3289b9eb00fdfea81437eda536",
"type": "github"
},
"original": {
"owner": "Mic92",
"repo": "direnv-instant",
"type": "github"
}
},
"disko": { "disko": {
"inputs": { "inputs": {
"nixpkgs": [ "nixpkgs": [
@ -56,7 +97,7 @@
}, },
"elephant": { "elephant": {
"inputs": { "inputs": {
"nixpkgs": "nixpkgs_2", "nixpkgs": "nixpkgs_3",
"systems": "systems" "systems": "systems"
}, },
"locked": { "locked": {
@ -165,6 +206,45 @@
} }
}, },
"flake-parts": { "flake-parts": {
"inputs": {
"nixpkgs-lib": "nixpkgs-lib"
},
"locked": {
"lastModified": 1767609335,
"narHash": "sha256-feveD98mQpptwrAEggBQKJTYbvwwglSbOv53uCfH9PY=",
"owner": "hercules-ci",
"repo": "flake-parts",
"rev": "250481aafeb741edfe23d29195671c19b36b6dca",
"type": "github"
},
"original": {
"owner": "hercules-ci",
"repo": "flake-parts",
"type": "github"
}
},
"flake-parts_2": {
"inputs": {
"nixpkgs-lib": [
"direnv-instant",
"nixpkgs"
]
},
"locked": {
"lastModified": 1775087534,
"narHash": "sha256-91qqW8lhL7TLwgQWijoGBbiD4t7/q75KTi8NxjVmSmA=",
"owner": "hercules-ci",
"repo": "flake-parts",
"rev": "3107b77cd68437b9a76194f0f7f9c55f2329ca5b",
"type": "github"
},
"original": {
"owner": "hercules-ci",
"repo": "flake-parts",
"type": "github"
}
},
"flake-parts_3": {
"inputs": { "inputs": {
"nixpkgs-lib": [ "nixpkgs-lib": [
"lanzaboote", "lanzaboote",
@ -185,7 +265,7 @@
"type": "github" "type": "github"
} }
}, },
"flake-parts_2": { "flake-parts_4": {
"inputs": { "inputs": {
"nixpkgs-lib": [ "nixpkgs-lib": [
"nixvim", "nixvim",
@ -206,7 +286,7 @@
"type": "github" "type": "github"
} }
}, },
"flake-parts_3": { "flake-parts_5": {
"inputs": { "inputs": {
"nixpkgs-lib": [ "nixpkgs-lib": [
"nur", "nur",
@ -343,7 +423,7 @@
}, },
"hytale-launcher": { "hytale-launcher": {
"inputs": { "inputs": {
"nixpkgs": "nixpkgs_3" "nixpkgs": "nixpkgs_4"
}, },
"locked": { "locked": {
"lastModified": 1774383212, "lastModified": 1774383212,
@ -362,7 +442,7 @@
"impermanence": { "impermanence": {
"inputs": { "inputs": {
"home-manager": "home-manager_2", "home-manager": "home-manager_2",
"nixpkgs": "nixpkgs_4" "nixpkgs": "nixpkgs_5"
}, },
"locked": { "locked": {
"lastModified": 1769548169, "lastModified": 1769548169,
@ -382,7 +462,7 @@
"inputs": { "inputs": {
"crane": "crane", "crane": "crane",
"flake-compat": "flake-compat", "flake-compat": "flake-compat",
"flake-parts": "flake-parts", "flake-parts": "flake-parts_3",
"nixpkgs": [ "nixpkgs": [
"nixpkgs" "nixpkgs"
], ],
@ -428,7 +508,7 @@
"naersk": { "naersk": {
"inputs": { "inputs": {
"fenix": "fenix", "fenix": "fenix",
"nixpkgs": "nixpkgs_7" "nixpkgs": "nixpkgs_8"
}, },
"locked": { "locked": {
"lastModified": 1763384566, "lastModified": 1763384566,
@ -506,7 +586,7 @@
"inputs": { "inputs": {
"flake-compat": "flake-compat_2", "flake-compat": "flake-compat_2",
"nix-index-database": "nix-index-database", "nix-index-database": "nix-index-database",
"nixpkgs": "nixpkgs_5" "nixpkgs": "nixpkgs_6"
}, },
"locked": { "locked": {
"lastModified": 1771150922, "lastModified": 1771150922,
@ -582,20 +662,35 @@
}, },
"nixpkgs": { "nixpkgs": {
"locked": { "locked": {
"lastModified": 1762156382, "lastModified": 1766902085,
"narHash": "sha256-Yg7Ag7ov5+36jEFC1DaZh/12SEXo6OO3/8rqADRxiqs=", "narHash": "sha256-coBu0ONtFzlwwVBzmjacUQwj3G+lybcZ1oeNSQkgC0M=",
"owner": "NixOS", "owner": "NixOS",
"repo": "nixpkgs", "repo": "nixpkgs",
"rev": "7241bcbb4f099a66aafca120d37c65e8dda32717", "rev": "c0b0e0fddf73fd517c3471e546c0df87a42d53f4",
"type": "github" "type": "github"
}, },
"original": { "original": {
"owner": "NixOS", "owner": "NixOS",
"ref": "nixpkgs-unstable", "ref": "nixos-unstable",
"repo": "nixpkgs", "repo": "nixpkgs",
"type": "github" "type": "github"
} }
}, },
"nixpkgs-lib": {
"locked": {
"lastModified": 1765674936,
"narHash": "sha256-k00uTP4JNfmejrCLJOwdObYC9jHRrr/5M/a/8L2EIdo=",
"owner": "nix-community",
"repo": "nixpkgs.lib",
"rev": "2075416fcb47225d9b68ac469a5c4801a9c4dd85",
"type": "github"
},
"original": {
"owner": "nix-community",
"repo": "nixpkgs.lib",
"type": "github"
}
},
"nixpkgs-stable": { "nixpkgs-stable": {
"locked": { "locked": {
"lastModified": 1774244481, "lastModified": 1774244481,
@ -629,6 +724,22 @@
} }
}, },
"nixpkgs_2": { "nixpkgs_2": {
"locked": {
"lastModified": 1762156382,
"narHash": "sha256-Yg7Ag7ov5+36jEFC1DaZh/12SEXo6OO3/8rqADRxiqs=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "7241bcbb4f099a66aafca120d37c65e8dda32717",
"type": "github"
},
"original": {
"owner": "NixOS",
"ref": "nixpkgs-unstable",
"repo": "nixpkgs",
"type": "github"
}
},
"nixpkgs_3": {
"locked": { "locked": {
"lastModified": 1764242076, "lastModified": 1764242076,
"narHash": "sha256-sKoIWfnijJ0+9e4wRvIgm/HgE27bzwQxcEmo2J/gNpI=", "narHash": "sha256-sKoIWfnijJ0+9e4wRvIgm/HgE27bzwQxcEmo2J/gNpI=",
@ -644,7 +755,7 @@
"type": "github" "type": "github"
} }
}, },
"nixpkgs_3": { "nixpkgs_4": {
"locked": { "locked": {
"lastModified": 1774106199, "lastModified": 1774106199,
"narHash": "sha256-US5Tda2sKmjrg2lNHQL3jRQ6p96cgfWh3J1QBliQ8Ws=", "narHash": "sha256-US5Tda2sKmjrg2lNHQL3jRQ6p96cgfWh3J1QBliQ8Ws=",
@ -660,7 +771,7 @@
"type": "github" "type": "github"
} }
}, },
"nixpkgs_4": { "nixpkgs_5": {
"locked": { "locked": {
"lastModified": 1768564909, "lastModified": 1768564909,
"narHash": "sha256-Kell/SpJYVkHWMvnhqJz/8DqQg2b6PguxVWOuadbHCc=", "narHash": "sha256-Kell/SpJYVkHWMvnhqJz/8DqQg2b6PguxVWOuadbHCc=",
@ -676,7 +787,7 @@
"type": "github" "type": "github"
} }
}, },
"nixpkgs_5": { "nixpkgs_6": {
"locked": { "locked": {
"lastModified": 1771008912, "lastModified": 1771008912,
"narHash": "sha256-gf2AmWVTs8lEq7z/3ZAsgnZDhWIckkb+ZnAo5RzSxJg=", "narHash": "sha256-gf2AmWVTs8lEq7z/3ZAsgnZDhWIckkb+ZnAo5RzSxJg=",
@ -692,7 +803,7 @@
"type": "github" "type": "github"
} }
}, },
"nixpkgs_6": { "nixpkgs_7": {
"locked": { "locked": {
"lastModified": 1774386573, "lastModified": 1774386573,
"narHash": "sha256-4hAV26quOxdC6iyG7kYaZcM3VOskcPUrdCQd/nx8obc=", "narHash": "sha256-4hAV26quOxdC6iyG7kYaZcM3VOskcPUrdCQd/nx8obc=",
@ -708,7 +819,7 @@
"type": "github" "type": "github"
} }
}, },
"nixpkgs_7": { "nixpkgs_8": {
"locked": { "locked": {
"lastModified": 1752077645, "lastModified": 1752077645,
"narHash": "sha256-HM791ZQtXV93xtCY+ZxG1REzhQenSQO020cu6rHtAPk=", "narHash": "sha256-HM791ZQtXV93xtCY+ZxG1REzhQenSQO020cu6rHtAPk=",
@ -724,7 +835,7 @@
"type": "github" "type": "github"
} }
}, },
"nixpkgs_8": { "nixpkgs_9": {
"locked": { "locked": {
"lastModified": 1768564909, "lastModified": 1768564909,
"narHash": "sha256-Kell/SpJYVkHWMvnhqJz/8DqQg2b6PguxVWOuadbHCc=", "narHash": "sha256-Kell/SpJYVkHWMvnhqJz/8DqQg2b6PguxVWOuadbHCc=",
@ -742,7 +853,7 @@
}, },
"nixvim": { "nixvim": {
"inputs": { "inputs": {
"flake-parts": "flake-parts_2", "flake-parts": "flake-parts_4",
"nixpkgs": [ "nixpkgs": [
"nixpkgs" "nixpkgs"
], ],
@ -787,7 +898,7 @@
}, },
"nur": { "nur": {
"inputs": { "inputs": {
"flake-parts": "flake-parts_3", "flake-parts": "flake-parts_5",
"nixpkgs": [ "nixpkgs": [
"nixpkgs" "nixpkgs"
] ]
@ -834,7 +945,9 @@
}, },
"root": { "root": {
"inputs": { "inputs": {
"comfyui-nix": "comfyui-nix",
"devshell": "devshell", "devshell": "devshell",
"direnv-instant": "direnv-instant",
"disko": "disko", "disko": "disko",
"elephant": "elephant", "elephant": "elephant",
"hardware": "hardware", "hardware": "hardware",
@ -847,7 +960,7 @@
"nix-alien": "nix-alien", "nix-alien": "nix-alien",
"nix-darwin": "nix-darwin", "nix-darwin": "nix-darwin",
"nix-flatpak": "nix-flatpak", "nix-flatpak": "nix-flatpak",
"nixpkgs": "nixpkgs_6", "nixpkgs": "nixpkgs_7",
"nixpkgs-stable": "nixpkgs-stable_2", "nixpkgs-stable": "nixpkgs-stable_2",
"nixvim": "nixvim", "nixvim": "nixvim",
"nps": "nps", "nps": "nps",
@ -1011,12 +1124,33 @@
"type": "github" "type": "github"
} }
}, },
"treefmt-nix": {
"inputs": {
"nixpkgs": [
"direnv-instant",
"nixpkgs"
]
},
"locked": {
"lastModified": 1775636079,
"narHash": "sha256-pc20NRoMdiar8oPQceQT47UUZMBTiMdUuWrYu2obUP0=",
"owner": "numtide",
"repo": "treefmt-nix",
"rev": "790751ff7fd3801feeaf96d7dc416a8d581265ba",
"type": "github"
},
"original": {
"owner": "numtide",
"repo": "treefmt-nix",
"type": "github"
}
},
"walker": { "walker": {
"inputs": { "inputs": {
"elephant": [ "elephant": [
"elephant" "elephant"
], ],
"nixpkgs": "nixpkgs_8", "nixpkgs": "nixpkgs_9",
"systems": "systems_5" "systems": "systems_5"
}, },
"locked": { "locked": {

View File

@ -78,10 +78,17 @@
nix-flatpak.url = "github:gmodena/nix-flatpak/?ref=latest"; nix-flatpak.url = "github:gmodena/nix-flatpak/?ref=latest";
# nix-flatpak.inputs.nixpkgs.follows = "nixpkgs"; # nix-flatpak doesn't have this # nix-flatpak.inputs.nixpkgs.follows = "nixpkgs"; # nix-flatpak doesn't have this
# Instant Direnv (load environment in background)
direnv-instant.url = "github:Mic92/direnv-instant";
direnv-instant.inputs.nixpkgs.follows = "nixpkgs";
# Realtime audio # Realtime audio
# musnix.url = "github:musnix/musnix"; # musnix.url = "github:musnix/musnix";
# musnix.inputs.nixpkgs.follows = "nixpkgs"; # musnix.inputs.nixpkgs.follows = "nixpkgs";
# ComfyUI
comfyui-nix.url = "github:utensils/comfyui-nix";
# HyTale # HyTale
hytale-launcher.url = "github:JPyke3/hytale-launcher-nix"; hytale-launcher.url = "github:JPyke3/hytale-launcher-nix";
@ -138,7 +145,7 @@
inputs.nur.overlays.default inputs.nur.overlays.default
inputs.niri.overlays.niri inputs.niri.overlays.niri
# inputs.emacs-overlay.overlay # inputs.emacs-overlay.overlay
# inputs.comfyui-nix.overlays.default inputs.comfyui-nix.overlays.default
# All my own overlays (derivations + modifications) # All my own overlays (derivations + modifications)
(import ./overlays {inherit inputs nixpkgs pkgs-stable;}) (import ./overlays {inherit inputs nixpkgs pkgs-stable;})
@ -250,7 +257,7 @@
[ [
inputs.disko.nixosModules.disko inputs.disko.nixosModules.disko
# inputs.nixified-ai.nixosModules.comfyui # inputs.nixified-ai.nixosModules.comfyui
# inputs.comfyui-nix.nixosModules.default inputs.comfyui-nix.nixosModules.default
] ]
++ commonModules; ++ commonModules;
}; };

View File

@ -39,6 +39,7 @@
inputs.nixvim.homeModules.nixvim inputs.nixvim.homeModules.nixvim
inputs.textfox.homeManagerModules.default inputs.textfox.homeManagerModules.default
inputs.walker.homeManagerModules.default inputs.walker.homeManagerModules.default
inputs.direnv-instant.homeModules.direnv-instant
# inputs.niri.homeModules.niri # Imported by system module # inputs.niri.homeModules.niri # Imported by system module
# inputs.noctalia.homeModules.default # inputs.noctalia.homeModules.default
# inputs.caelestia.homeManagerModules.default # inputs.caelestia.homeManagerModules.default

View File

@ -87,6 +87,40 @@ in {
shellInit = '' shellInit = ''
set fish_greeting set fish_greeting
yes | fish_config theme save "system-theme" yes | fish_config theme save "system-theme"
# Because we can't source that in a project flake's shellHook (is POSIX), source it here
function __project_shell_reload --on-variable INIT_PROJECT_SHELL
# Leaving the environment
if not set -q INIT_PROJECT_SHELL; or test -z "$INIT_PROJECT_SHELL"
if test -n "$__last_unload_project_shell"; and test -f "$__last_unload_project_shell"
source "$__last_unload_project_shell"
end
set -e __last_init_project_shell
set -e __last_unload_project_shell
return
end
# Entering or switching environments
if test "$INIT_PROJECT_SHELL" != "$__last_init_project_shell"
# Cleanup the previous environment
if test -n "$__last_unload_project_shell"; and test -f "$__last_unload_project_shell"
source "$__last_unload_project_shell"
end
# Store into variables to persist until next environment switch in the same shell
set -g __last_init_project_shell "$INIT_PROJECT_SHELL"
if set -q UNLOAD_PROJECT_SHELL; and test -f "$UNLOAD_PROJECT_SHELL"
set -g __last_unload_project_shell "$UNLOAD_PROJECT_SHELL"
else
set -e __last_unload_project_shell
end
# Source the new environment
if test -f "$INIT_PROJECT_SHELL"
source "$INIT_PROJECT_SHELL"
end
end
end
''; '';
functions = lib.mergeAttrsList [ functions = lib.mergeAttrsList [

View File

@ -31,8 +31,8 @@ in {
settings = lib.mkMerge [ settings = lib.mkMerge [
# Linux config # Linux config
(lib.mkIf pkgs.stdenv.isLinux { (lib.mkIf pkgs.stdenv.isLinux {
allow_remote_control = "yes"; # For nnn file preview or nvim scrollback allow_remote_control = true; # For nnn file preview or nvim scrollback
listen_on = "unix:@mykitty"; listen_on = lib.mkDefault "unix:@mykitty"; # This conflicts with direnv-instant
}) })
# Common config # Common config

View File

@ -204,9 +204,19 @@ in {
direnv = { direnv = {
enable = true; enable = true;
enableFishIntegration = !config.programs.direnv-instant.enable;
silent = true;
nix-direnv.enable = true; nix-direnv.enable = true;
}; };
# This replaces the normal direnv.enableFishIntegration.
# direnv-instant = {
# enable = true;
# enableFishIntegration = true;
# enableKittyIntegration = true;
# settings.use_cache = true;
# };
eza = { eza = {
enable = true; enable = true;
enableFishIntegration = config.homemodules.fish.enable; enableFishIntegration = config.homemodules.fish.enable;