diff --git a/modules/programs/zed-editor.nix b/modules/programs/zed-editor.nix index 472fc1698..a9bd28e5e 100644 --- a/modules/programs/zed-editor.nix +++ b/modules/programs/zed-editor.nix @@ -14,6 +14,16 @@ let cfg = config.programs.zed-editor; jsonFormat = pkgs.formats.json { }; + impureConfigMerger = empty: jqOperation: path: staticSettings: '' + mkdir -p $(dirname ${lib.escapeShellArg path}) + if [ ! -e ${lib.escapeShellArg path} ]; then + # No file? Create it + echo ${lib.escapeShellArg empty} > ${lib.escapeShellArg path} + fi + config="$(${pkgs.jq}/bin/jq -s ${lib.escapeShellArg jqOperation} ${lib.escapeShellArg path} ${lib.escapeShellArg staticSettings})" + printf '%s\n' "$config" > ${lib.escapeShellArg path} + unset config + ''; mergedSettings = cfg.userSettings @@ -155,34 +165,31 @@ in } ); - xdg.configFile = - lib.attrsets.unionOfDisjoint - { - "zed/settings.json" = ( - mkIf (mergedSettings != { }) { - source = jsonFormat.generate "zed-user-settings" mergedSettings; - } - ); + home.activation = { + zedSettingsActivation = lib.hm.dag.entryAfter [ "linkGeneration" ] ( + impureConfigMerger "{}" ".[0] * .[1]" "${config.xdg.configHome}/zed/settings.json" ( + jsonFormat.generate "zed-user-settings" mergedSettings + ) + ); + zedKeymapActivation = lib.hm.dag.entryAfter [ "linkGeneration" ] ( + impureConfigMerger "[]" + ".[0] + .[1] | group_by(.context) | map(reduce .[] as $item ({}; . * $item))" + "${config.xdg.configHome}/zed/keymap.json" + (jsonFormat.generate "zed-user-keymaps" cfg.userKeymaps) + ); + }; - "zed/keymap.json" = ( - mkIf (cfg.userKeymaps != { }) { - source = jsonFormat.generate "zed-user-keymaps" cfg.userKeymaps; - } - ); - } - ( - lib.mapAttrs' ( - n: v: - lib.nameValuePair "zed/themes/${n}.json" { - source = - if lib.isString v then - pkgs.writeText "zed-theme-${n}" v - else if builtins.isPath v || lib.isStorePath v then - v - else - jsonFormat.generate "zed-theme-${n}" v; - } - ) cfg.themes - ); + xdg.configFile = lib.mapAttrs' ( + n: v: + lib.nameValuePair "zed/themes/${n}.json" { + source = + if lib.isString v then + pkgs.writeText "zed-theme-${n}" v + else if builtins.isPath v || lib.isStorePath v then + v + else + jsonFormat.generate "zed-theme-${n}" v; + } + ) cfg.themes; }; } diff --git a/tests/modules/programs/zed-editor/extensions.nix b/tests/modules/programs/zed-editor/extensions.nix index e3d868725..0cb20a9a0 100644 --- a/tests/modules/programs/zed-editor/extensions.nix +++ b/tests/modules/programs/zed-editor/extensions.nix @@ -1,4 +1,9 @@ -{ config, ... }: +{ + config, + lib, + pkgs, + ... +}: { programs.zed-editor = { @@ -11,20 +16,54 @@ ]; }; + home.homeDirectory = lib.mkForce "/@TMPDIR@/hm-user"; + nmt.script = let + preexistingSettings = builtins.toFile "preexisting.json" '' + { + "auto_install_extensions": { + "python": true, + "javascript": true + } + } + ''; + expectedContent = builtins.toFile "expected.json" '' { "auto_install_extensions": { + "python": true, + "javascript": true, "html": true, "swift": true, "xy-zed": true } } ''; + + settingsPath = ".config/zed/settings.json"; + + activationScript = pkgs.writeScript "activation" config.home.activation.zedSettingsActivation.data; in '' - assertFileExists "home-files/.config/zed/settings.json" - assertFileContent "home-files/.config/zed/settings.json" "${expectedContent}" + export HOME=$TMPDIR/hm-user + + # Simulate preexisting settings + mkdir -p $HOME/.config/zed + cat ${preexistingSettings} > $HOME/${settingsPath} + + # Run the activation script + substitute ${activationScript} $TMPDIR/activate --subst-var TMPDIR + chmod +x $TMPDIR/activate + $TMPDIR/activate + + # Validate the merged settings + assertFileExists "$HOME/${settingsPath}" + assertFileContent "$HOME/${settingsPath}" "${expectedContent}" + + # Test idempotency + $TMPDIR/activate + assertFileExists "$HOME/${settingsPath}" + assertFileContent "$HOME/${settingsPath}" "${expectedContent}" ''; } diff --git a/tests/modules/programs/zed-editor/keymap.nix b/tests/modules/programs/zed-editor/keymap.nix index ca70647a1..03a3a3fcd 100644 --- a/tests/modules/programs/zed-editor/keymap.nix +++ b/tests/modules/programs/zed-editor/keymap.nix @@ -1,5 +1,9 @@ -# Test custom keymap functionality -{ config, ... }: +{ + config, + lib, + pkgs, + ... +}: { programs.zed-editor = { @@ -20,28 +24,78 @@ ]; }; + home.homeDirectory = lib.mkForce "/@TMPDIR@/hm-user"; + nmt.script = let - expectedContent = builtins.toFile "expected.json" '' + preexistingKeymaps = builtins.toFile "preexisting.json" '' [ { "bindings": { - "up": "menu::SelectPrev" + "down": "menu::SelectNext" } }, { "bindings": { - "escape": "editor::Cancel" + "down": "select" + }, + "context": "Terminal" + }, + { + "bindings": { + "enter": "newline" }, "context": "Editor" } ] ''; + expectedContent = builtins.toFile "expected.json" '' + [ + { + "bindings": { + "down": "menu::SelectNext", + "up": "menu::SelectPrev" + } + }, + { + "bindings": { + "enter": "newline", + "escape": "editor::Cancel" + }, + "context": "Editor" + }, + { + "bindings": { + "down": "select" + }, + "context": "Terminal" + } + ] + ''; + keymapPath = ".config/zed/keymap.json"; + activationScript = pkgs.writeScript "activation" config.home.activation.zedKeymapActivation.data; in '' - assertFileExists "home-files/${keymapPath}" - assertFileContent "home-files/${keymapPath}" "${expectedContent}" + export HOME=$TMPDIR/hm-user + + # Simulate preexisting keymaps + mkdir -p $HOME/.config/zed + cat ${preexistingKeymaps} > $HOME/${keymapPath} + + # Run the activation script + substitute ${activationScript} $TMPDIR/activate --subst-var TMPDIR + chmod +x $TMPDIR/activate + $TMPDIR/activate + + # Validate the merged keymaps + assertFileExists "$HOME/${keymapPath}" + assertFileContent "$HOME/${keymapPath}" "${expectedContent}" + + # Test idempotency + $TMPDIR/activate + assertFileExists "$HOME/${keymapPath}" + assertFileContent "$HOME/${keymapPath}" "${expectedContent}" ''; } diff --git a/tests/modules/programs/zed-editor/settings.nix b/tests/modules/programs/zed-editor/settings.nix index 258d4ceac..2e95507ee 100644 --- a/tests/modules/programs/zed-editor/settings.nix +++ b/tests/modules/programs/zed-editor/settings.nix @@ -1,5 +1,10 @@ # Test custom keymap functionality -{ config, ... }: +{ + config, + lib, + pkgs, + ... +}: { programs.zed-editor = { @@ -16,24 +21,56 @@ }; }; + home.homeDirectory = lib.mkForce "/@TMPDIR@/hm-user"; + nmt.script = let + preexistingSettings = builtins.toFile "preexisting.json" '' + { + "theme": "Default", + "features": { + "copilot": true, + "ai_assist": true + }, + "vim_mode": true + } + ''; + expectedContent = builtins.toFile "expected.json" '' { - "buffer_font_size": 16, - "features": { - "copilot": false - }, "theme": "XY-Zed", - "ui_font_size": 16, - "vim_mode": false + "features": { + "copilot": false, + "ai_assist": true + }, + "vim_mode": false, + "buffer_font_size": 16, + "ui_font_size": 16 } ''; settingsPath = ".config/zed/settings.json"; + activationScript = pkgs.writeScript "activation" config.home.activation.zedSettingsActivation.data; in '' - assertFileExists "home-files/${settingsPath}" - assertFileContent "home-files/${settingsPath}" "${expectedContent}" + export HOME=$TMPDIR/hm-user + + # Simulate preexisting settings + mkdir -p $HOME/.config/zed + cat ${preexistingSettings} > $HOME/${settingsPath} + + # Run the activation script + substitute ${activationScript} $TMPDIR/activate --subst-var TMPDIR + chmod +x $TMPDIR/activate + $TMPDIR/activate + + # Validate the merged settings + assertFileExists "$HOME/${settingsPath}" + assertFileContent "$HOME/${settingsPath}" "${expectedContent}" + + # Test idempotency + $TMPDIR/activate + assertFileExists "$HOME/${settingsPath}" + assertFileContent "$HOME/${settingsPath}" "${expectedContent}" ''; }