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";
buildRelease = mkBuildScript "Release";
# Use this to specify commands that should be ran after entering fish shell
initProjectShell = pkgs.writers.writeFish "init-shell.fish" ''
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)
# Add project-local fish abbrs here
abbrs = {
# 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++:
# abbr -a cmake-debug "${cmakeDebug}"
# abbr -a cmake-release "${cmakeRelease}"
# abbr -a build-debug "${buildDebug}"
# abbr -a build-release "${buildRelease}"
# cmake-debug = "${cmakeDebug}";
# cmake-release = "${cmakeRelease}";
# build-debug = "${buildDebug}";
# build-release = "${buildRelease}";
# Clojure:
# abbr -a clojure-deps "deps-lock --lein"
# clojure-deps = "deps-lock --lein";
# Python:
# abbr -a run "python ./app/main.py"
# abbr -a profile "py-spy record -o profile.svg -- python ./app/main.py && firefox profile.svg"
# abbr -a ptop "py-spy top -- python ./app/main.py"
# run = "python ./app/main.py";
# profile = "py-spy record -o profile.svg -- python ./app/main.py && firefox profile.svg";
# 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
builtins.concatStringsSep "\n" [
# 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
# ''
# fishdir=$(mktemp -d)

180
flake.lock generated
View File

@ -1,5 +1,24 @@
{
"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": {
"locked": {
"lastModified": 1754269165,
@ -17,7 +36,7 @@
},
"devshell": {
"inputs": {
"nixpkgs": "nixpkgs"
"nixpkgs": "nixpkgs_2"
},
"locked": {
"lastModified": 1768818222,
@ -33,6 +52,28 @@
"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": {
"inputs": {
"nixpkgs": [
@ -56,7 +97,7 @@
},
"elephant": {
"inputs": {
"nixpkgs": "nixpkgs_2",
"nixpkgs": "nixpkgs_3",
"systems": "systems"
},
"locked": {
@ -165,6 +206,45 @@
}
},
"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": {
"nixpkgs-lib": [
"lanzaboote",
@ -185,7 +265,7 @@
"type": "github"
}
},
"flake-parts_2": {
"flake-parts_4": {
"inputs": {
"nixpkgs-lib": [
"nixvim",
@ -206,7 +286,7 @@
"type": "github"
}
},
"flake-parts_3": {
"flake-parts_5": {
"inputs": {
"nixpkgs-lib": [
"nur",
@ -343,7 +423,7 @@
},
"hytale-launcher": {
"inputs": {
"nixpkgs": "nixpkgs_3"
"nixpkgs": "nixpkgs_4"
},
"locked": {
"lastModified": 1774383212,
@ -362,7 +442,7 @@
"impermanence": {
"inputs": {
"home-manager": "home-manager_2",
"nixpkgs": "nixpkgs_4"
"nixpkgs": "nixpkgs_5"
},
"locked": {
"lastModified": 1769548169,
@ -382,7 +462,7 @@
"inputs": {
"crane": "crane",
"flake-compat": "flake-compat",
"flake-parts": "flake-parts",
"flake-parts": "flake-parts_3",
"nixpkgs": [
"nixpkgs"
],
@ -428,7 +508,7 @@
"naersk": {
"inputs": {
"fenix": "fenix",
"nixpkgs": "nixpkgs_7"
"nixpkgs": "nixpkgs_8"
},
"locked": {
"lastModified": 1763384566,
@ -506,7 +586,7 @@
"inputs": {
"flake-compat": "flake-compat_2",
"nix-index-database": "nix-index-database",
"nixpkgs": "nixpkgs_5"
"nixpkgs": "nixpkgs_6"
},
"locked": {
"lastModified": 1771150922,
@ -582,20 +662,35 @@
},
"nixpkgs": {
"locked": {
"lastModified": 1762156382,
"narHash": "sha256-Yg7Ag7ov5+36jEFC1DaZh/12SEXo6OO3/8rqADRxiqs=",
"lastModified": 1766902085,
"narHash": "sha256-coBu0ONtFzlwwVBzmjacUQwj3G+lybcZ1oeNSQkgC0M=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "7241bcbb4f099a66aafca120d37c65e8dda32717",
"rev": "c0b0e0fddf73fd517c3471e546c0df87a42d53f4",
"type": "github"
},
"original": {
"owner": "NixOS",
"ref": "nixpkgs-unstable",
"ref": "nixos-unstable",
"repo": "nixpkgs",
"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": {
"locked": {
"lastModified": 1774244481,
@ -629,6 +724,22 @@
}
},
"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": {
"lastModified": 1764242076,
"narHash": "sha256-sKoIWfnijJ0+9e4wRvIgm/HgE27bzwQxcEmo2J/gNpI=",
@ -644,7 +755,7 @@
"type": "github"
}
},
"nixpkgs_3": {
"nixpkgs_4": {
"locked": {
"lastModified": 1774106199,
"narHash": "sha256-US5Tda2sKmjrg2lNHQL3jRQ6p96cgfWh3J1QBliQ8Ws=",
@ -660,7 +771,7 @@
"type": "github"
}
},
"nixpkgs_4": {
"nixpkgs_5": {
"locked": {
"lastModified": 1768564909,
"narHash": "sha256-Kell/SpJYVkHWMvnhqJz/8DqQg2b6PguxVWOuadbHCc=",
@ -676,7 +787,7 @@
"type": "github"
}
},
"nixpkgs_5": {
"nixpkgs_6": {
"locked": {
"lastModified": 1771008912,
"narHash": "sha256-gf2AmWVTs8lEq7z/3ZAsgnZDhWIckkb+ZnAo5RzSxJg=",
@ -692,7 +803,7 @@
"type": "github"
}
},
"nixpkgs_6": {
"nixpkgs_7": {
"locked": {
"lastModified": 1774386573,
"narHash": "sha256-4hAV26quOxdC6iyG7kYaZcM3VOskcPUrdCQd/nx8obc=",
@ -708,7 +819,7 @@
"type": "github"
}
},
"nixpkgs_7": {
"nixpkgs_8": {
"locked": {
"lastModified": 1752077645,
"narHash": "sha256-HM791ZQtXV93xtCY+ZxG1REzhQenSQO020cu6rHtAPk=",
@ -724,7 +835,7 @@
"type": "github"
}
},
"nixpkgs_8": {
"nixpkgs_9": {
"locked": {
"lastModified": 1768564909,
"narHash": "sha256-Kell/SpJYVkHWMvnhqJz/8DqQg2b6PguxVWOuadbHCc=",
@ -742,7 +853,7 @@
},
"nixvim": {
"inputs": {
"flake-parts": "flake-parts_2",
"flake-parts": "flake-parts_4",
"nixpkgs": [
"nixpkgs"
],
@ -787,7 +898,7 @@
},
"nur": {
"inputs": {
"flake-parts": "flake-parts_3",
"flake-parts": "flake-parts_5",
"nixpkgs": [
"nixpkgs"
]
@ -834,7 +945,9 @@
},
"root": {
"inputs": {
"comfyui-nix": "comfyui-nix",
"devshell": "devshell",
"direnv-instant": "direnv-instant",
"disko": "disko",
"elephant": "elephant",
"hardware": "hardware",
@ -847,7 +960,7 @@
"nix-alien": "nix-alien",
"nix-darwin": "nix-darwin",
"nix-flatpak": "nix-flatpak",
"nixpkgs": "nixpkgs_6",
"nixpkgs": "nixpkgs_7",
"nixpkgs-stable": "nixpkgs-stable_2",
"nixvim": "nixvim",
"nps": "nps",
@ -1011,12 +1124,33 @@
"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": {
"inputs": {
"elephant": [
"elephant"
],
"nixpkgs": "nixpkgs_8",
"nixpkgs": "nixpkgs_9",
"systems": "systems_5"
},
"locked": {

View File

@ -78,10 +78,17 @@
nix-flatpak.url = "github:gmodena/nix-flatpak/?ref=latest";
# 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
# musnix.url = "github:musnix/musnix";
# musnix.inputs.nixpkgs.follows = "nixpkgs";
# ComfyUI
comfyui-nix.url = "github:utensils/comfyui-nix";
# HyTale
hytale-launcher.url = "github:JPyke3/hytale-launcher-nix";
@ -138,7 +145,7 @@
inputs.nur.overlays.default
inputs.niri.overlays.niri
# inputs.emacs-overlay.overlay
# inputs.comfyui-nix.overlays.default
inputs.comfyui-nix.overlays.default
# All my own overlays (derivations + modifications)
(import ./overlays {inherit inputs nixpkgs pkgs-stable;})
@ -250,7 +257,7 @@
[
inputs.disko.nixosModules.disko
# inputs.nixified-ai.nixosModules.comfyui
# inputs.comfyui-nix.nixosModules.default
inputs.comfyui-nix.nixosModules.default
]
++ commonModules;
};

View File

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

View File

@ -87,6 +87,40 @@ in {
shellInit = ''
set fish_greeting
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 [

View File

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

View File

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