diff --git a/default.nix b/default.nix index 20fd31f..cd3b98a 100644 --- a/default.nix +++ b/default.nix @@ -51,6 +51,7 @@ in # keep-sorted end # keep-sorted start + ghosttyShaders = recurseCallPackage ./pkgs/ghostty-shaders; gotifyPlugins = recurseIntoAttrs (callPackage ./pkgs/gotify-server/plugins {inherit (allPackages) gotify-server;}); hyprlandPlugins = recurseCallPackage ./pkgs/hyprland/plugins; spicetifyExtensions = recurseCallPackage ./pkgs/spicetify/extensions; diff --git a/pkgs/ghostty-shaders/default.nix b/pkgs/ghostty-shaders/default.nix new file mode 100644 index 0000000..8d2f917 --- /dev/null +++ b/pkgs/ghostty-shaders/default.nix @@ -0,0 +1,73 @@ +{ + # keep-sorted start + callPackage, + lib, + stdenvNoCC, + # keep-sorted end +}: let + inherit (lib) mapAttrs recurseIntoAttrs; + + mkShaderArgs = { + # keep-sorted start + homepage, + name, + shaderFile, + src, + version, + # keep-sorted end + }: { + pname = "ghostty-shader-${name}"; + inherit version; + + inherit src; + + installPhase = '' + runHook preInstall + + mkdir -p "$out" + cp ${shaderFile} "$out/${shaderFile}" + + runHook postInstall + ''; + + dontBuild = true; + + passthru = {inherit shaderFile;}; + + meta = { + # keep-sorted start + description = "${name} cursor shader for Ghostty"; + inherit homepage; + license = lib.licenses.mit; + platforms = lib.platforms.all; + # keep-sorted end + }; + }; + + mkShaders = { + # keep-sorted start + homepage, + shaders, + src, + version, + # keep-sorted end + }: + recurseIntoAttrs (mapAttrs (name: shaderFile: + stdenvNoCC.mkDerivation (mkShaderArgs { + inherit + # keep-sorted start + homepage + name + shaderFile + src + version + # keep-sorted end + ; + })) + shaders); +in { + # keep-sorted start + hced = callPackage ./hced.nix {inherit mkShaders;}; + sahaj = callPackage ./sahaj.nix {inherit mkShaders;}; + # keep-sorted end +} diff --git a/pkgs/ghostty-shaders/hced.nix b/pkgs/ghostty-shaders/hced.nix new file mode 100644 index 0000000..f69609c --- /dev/null +++ b/pkgs/ghostty-shaders/hced.nix @@ -0,0 +1,34 @@ +{ + # keep-sorted start + fetchFromGitHub, + mkShaders, + # keep-sorted end +}: let + version = "unstable-2026-04-14"; + + owner = "hced"; + repo = "ghostty-cursor-trails"; + + src = fetchFromGitHub { + inherit owner repo; + rev = "78f597cf66427bc382077e5e33f26981a86bb207"; + hash = "sha256-NHeCd/avyJ8SaYW8pYWcetwVroFQNokN7saiWCMu3TM="; + }; +in + mkShaders { + inherit + # keep-sorted start + src + version + # keep-sorted end + ; + homepage = "https://github.com/${owner}/${repo}"; + + shaders = { + # keep-sorted start + boo = "boo-cursor.glsl"; + tinkle = "tinkle-cursor.glsl"; + wisp = "wisp-cursor.glsl"; + # keep-sorted end + }; + } diff --git a/pkgs/ghostty-shaders/sahaj.nix b/pkgs/ghostty-shaders/sahaj.nix new file mode 100644 index 0000000..ce09ee2 --- /dev/null +++ b/pkgs/ghostty-shaders/sahaj.nix @@ -0,0 +1,38 @@ +{ + # keep-sorted start + fetchFromGitHub, + mkShaders, + # keep-sorted end +}: let + version = "unstable-2026-06-16"; + + owner = "sahaj-b"; + repo = "ghostty-cursor-shaders"; + + src = fetchFromGitHub { + inherit owner repo; + rev = "0a274beac8b93ee6ce6b94402b7313a0417b8e38"; + hash = "sha256-B7B6K7Ee4uJlW8zzLP3ILgddnbcIQyNimY+rVllzbR0="; + }; +in + mkShaders { + inherit + # keep-sorted start + src + version + # keep-sorted end + ; + homepage = "https://github.com/${owner}/${repo}"; + + shaders = { + # keep-sorted start + cursor-sweep = "cursor_sweep.glsl"; + cursor-tail = "cursor_tail.glsl"; + cursor-warp = "cursor_warp.glsl"; + rectangle-boom-cursor = "rectangle_boom_cursor.glsl"; + ripple-cursor = "ripple_cursor.glsl"; + ripple-rectangle-cursor = "ripple_rectangle_cursor.glsl"; + sonic-boom-cursor = "sonic_boom_cursor.glsl"; + # keep-sorted end + }; + } diff --git a/updater/nix.py b/updater/nix.py index c5c17c0..85d5ddc 100644 --- a/updater/nix.py +++ b/updater/nix.py @@ -59,13 +59,21 @@ let isDerivation = v: builtins.isAttrs v && v ? type && v.type == "derivation"; hasDerivationMembers = set: builtins.any (name: isDerivation (builtins.getAttr name set)) (builtins.attrNames set); + visit = prefix: set: + builtins.concatLists + (map + (name: + let + value = builtins.getAttr name set; + path = if prefix == "" then name else "${prefix}.${name}"; + nested = builtins.isAttrs value && !isDerivation value; + recursive = nested && (value.recurseForDerivations or false); + in + (if recursive && hasDerivationMembers value then [path] else []) + ++ (if recursive then visit path value else [])) + (builtins.attrNames set)); in - builtins.concatStringsSep "\n" - (builtins.filter - (name: - let v = builtins.getAttr name attrs; - in builtins.isAttrs v && !isDerivation v && hasDerivationMembers v) - (builtins.attrNames attrs)) + builtins.concatStringsSep "\n" (visit "" attrs) """, ] ).stdout @@ -134,7 +142,12 @@ pkgs: return None root_dir = file_path.parent - for candidate in (root_dir / attr / "default.nix", root_dir / f"{attr}.nix"): + attrset_file = root_dir / f"{attrset.rsplit('.', 1)[-1]}.nix" + for candidate in ( + root_dir / attr / "default.nix", + root_dir / f"{attr}.nix", + attrset_file, + ): if candidate.is_file(): return candidate return file_path