From 04e5203db66417d548ae1ff188a9f591836dfaa7 Mon Sep 17 00:00:00 2001 From: mikaeladev <100416544+mikaeladev@users.noreply.github.com> Date: Fri, 30 Jan 2026 22:48:22 +0000 Subject: [PATCH] prismlauncher: add module --- .../misc/news/2026/01/2026-01-27_20-02-41.nix | 10 ++ modules/programs/prismlauncher.nix | 114 ++++++++++++++++++ .../programs/prismlauncher/default.nix | 3 + .../programs/prismlauncher/settings.nix | 65 ++++++++++ 4 files changed, 192 insertions(+) create mode 100644 modules/misc/news/2026/01/2026-01-27_20-02-41.nix create mode 100644 modules/programs/prismlauncher.nix create mode 100644 tests/modules/programs/prismlauncher/default.nix create mode 100644 tests/modules/programs/prismlauncher/settings.nix diff --git a/modules/misc/news/2026/01/2026-01-27_20-02-41.nix b/modules/misc/news/2026/01/2026-01-27_20-02-41.nix new file mode 100644 index 00000000..be050265 --- /dev/null +++ b/modules/misc/news/2026/01/2026-01-27_20-02-41.nix @@ -0,0 +1,10 @@ +{ + time = "2026-01-27T20:02:41+00:00"; + condition = true; + message = '' + A new module is available: 'programs.prismlauncher'. + + An open-source Minecraft launcher that can manage multiple instances, + accounts, and mods. Focused on user freedom and free redistributability. + ''; +} diff --git a/modules/programs/prismlauncher.nix b/modules/programs/prismlauncher.nix new file mode 100644 index 00000000..fc15c6a3 --- /dev/null +++ b/modules/programs/prismlauncher.nix @@ -0,0 +1,114 @@ +{ + config, + lib, + pkgs, + ... +}: + +let + inherit (pkgs.stdenv.hostPlatform) isDarwin; + + inherit (lib) + escapeShellArg + getExe + listToAttrs + literalExpression + mkEnableOption + mkIf + mkMerge + mkOption + mkPackageOption + types + ; + + cfg = config.programs.prismlauncher; + + dataDir = + if (isDarwin && !config.xdg.enable) then + "Library/Application Support/PrismLauncher" + else + "${config.xdg.dataHome}/PrismLauncher"; + + iniFormat = pkgs.formats.ini { }; + + impureConfigMerger = filePath: staticSettingsFile: emptySettingsFile: '' + mkdir -p $(dirname '${escapeShellArg filePath}') + + if [ ! -e '${escapeShellArg filePath}' ]; then + cat '${escapeShellArg emptySettingsFile}' > '${escapeShellArg filePath}' + fi + + ${getExe pkgs.crudini} --merge --ini-options=nospace \ + '${escapeShellArg filePath}' < '${escapeShellArg staticSettingsFile}' + ''; +in + +{ + meta.maintainers = with lib.hm.maintainers; [ + mikaeladev + ]; + + options.programs.prismlauncher = { + enable = mkEnableOption "Prism Launcher"; + + package = mkPackageOption pkgs "prismlauncher" { nullable = true; }; + + extraPackages = mkOption { + type = types.listOf types.package; + default = [ ]; + description = '' + Additional theme packages to install to the user environment. + + Themes can be sourced from and should + install to `$out/share/PrismLauncher/{themes,iconthemes,catpacks}`. + ''; + }; + + icons = mkOption { + type = types.listOf types.path; + default = [ ]; + example = literalExpression "[ ./java.png ]"; + description = '' + List of paths to instance icons. + + These will be linked in {file}`$XDG_DATA_HOME/PrismLauncher/icons` on Linux and + {file}`~/Library/Application Support/PrismLauncher/icons` on macOS. + ''; + }; + + settings = mkOption { + type = types.attrsOf iniFormat.lib.types.atom; + default = { }; + example = { + ShowConsole = true; + ConsoleMaxLines = 100000; + }; + description = '' + Configuration written to {file}`prismlauncher.cfg`. + ''; + }; + }; + + config = mkIf cfg.enable { + home.packages = mkMerge ([ (mkIf (cfg.package != null) [ cfg.package ]) ] ++ cfg.extraPackages); + + home.activation = { + prismlauncherConfigActivation = ( + lib.hm.dag.entryAfter [ "linkGeneration" ] ( + impureConfigMerger "${dataDir}/prismlauncher.cfg" (iniFormat.generate "prismlauncher-static.cfg" { + General = cfg.settings; + }) (iniFormat.generate "prismlauncher-empty.cfg" { General = { }; }) + ) + ); + }; + + home.file = mkIf (cfg.icons != [ ]) ( + listToAttrs ( + map (source: { + name = "${dataDir}/icons/${baseNameOf source}"; + value = { inherit source; }; + }) cfg.icons + ) + ); + }; +} diff --git a/tests/modules/programs/prismlauncher/default.nix b/tests/modules/programs/prismlauncher/default.nix new file mode 100644 index 00000000..4400999a --- /dev/null +++ b/tests/modules/programs/prismlauncher/default.nix @@ -0,0 +1,3 @@ +{ + prismlauncher-settings = ./settings.nix; +} diff --git a/tests/modules/programs/prismlauncher/settings.nix b/tests/modules/programs/prismlauncher/settings.nix new file mode 100644 index 00000000..ac0843de --- /dev/null +++ b/tests/modules/programs/prismlauncher/settings.nix @@ -0,0 +1,65 @@ +{ + config, + lib, + pkgs, + ... +}: + +let + configPath = ".local/share/PrismLauncher/prismlauncher.cfg"; + + preexistingConfig = pkgs.writeText "preexisting.cfg" '' + [General] + ApplicationTheme=system + MaxMemAlloc=8192 + MinMemAlloc=512 + ''; + + expectedConfig = pkgs.writeText "expected.cfg" '' + [General] + ApplicationTheme=dark + MaxMemAlloc=8192 + MinMemAlloc=512 + ConsoleMaxLines=100000 + ShowConsole=true + ''; + + activationScript = pkgs.writeScript "activation" config.home.activation.prismlauncherConfigActivation.data; +in + +{ + programs.prismlauncher = { + enable = true; + package = config.lib.test.mkStubPackage { }; + + settings = { + ApplicationTheme = "dark"; + ShowConsole = true; + ConsoleMaxLines = 100000; + }; + }; + + home.homeDirectory = lib.mkForce "/@TMPDIR@/hm-user"; + + nmt.script = '' + export HOME=$TMPDIR/hm-user + + # write preexisting config + mkdir -p $HOME/.local/share/PrismLauncher + cat ${preexistingConfig} > $HOME/${configPath} + + # run the activation script + substitute ${activationScript} $TMPDIR/activate --subst-var TMPDIR + chmod +x $TMPDIR/activate + $TMPDIR/activate + + # validate the merged config + assertFileExists "$HOME/${configPath}" + assertFileContent "$HOME/${configPath}" "${expectedConfig}" + + # test idempotence + $TMPDIR/activate + assertFileExists "$HOME/${configPath}" + assertFileContent "$HOME/${configPath}" "${expectedConfig}" + ''; +}