From 1f34c2c855751c74b01df5068cf4dd64ea2c7d95 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pierre-Yves=20Landur=C3=A9?= Date: Fri, 31 Oct 2025 12:01:41 +0100 Subject: [PATCH] zed-editor: options to generate debug.json Add `mutableUserDebug` and `userDebug` options to generate `debug.json` file. The options are heavily inspired by `mutableUserTasks` and `userTasks` options implementation. Closes #8091 --- modules/programs/zed-editor.nix | 41 +++++++ .../programs/zed-editor/debug-empty.nix | 83 +++++++++++++++ .../programs/zed-editor/debug-immutable.nix | 58 ++++++++++ tests/modules/programs/zed-editor/debug.nix | 100 ++++++++++++++++++ tests/modules/programs/zed-editor/default.nix | 3 + 5 files changed, 285 insertions(+) create mode 100644 tests/modules/programs/zed-editor/debug-empty.nix create mode 100644 tests/modules/programs/zed-editor/debug-immutable.nix create mode 100644 tests/modules/programs/zed-editor/debug.nix diff --git a/modules/programs/zed-editor.nix b/modules/programs/zed-editor.nix index 5b6fc4ff3..d95f59e88 100644 --- a/modules/programs/zed-editor.nix +++ b/modules/programs/zed-editor.nix @@ -81,6 +81,15 @@ in ''; }; + mutableUserDebug = mkOption { + type = types.bool; + default = true; + example = false; + description = '' + Whether user debug configurations (debug.json) can be updated by zed. + ''; + }; + userSettings = mkOption { type = jsonFormat.type; default = { }; @@ -140,6 +149,27 @@ in ''; }; + userDebug = mkOption { + type = jsonFormat.type; + default = [ ]; + example = literalExpression '' + [ + { + label = "Go (Delve)"; + adapter = "Delve"; + program = "$ZED_FILE"; + request = "launch"; + mode = "debug"; + } + ] + ''; + description = '' + Configuration written to Zed's {file}`debug.json`. + + Global debug configurations for Zed's [Debugger](https://zed.dev/docs/debugger). + ''; + }; + extensions = mkOption { type = types.listOf types.str; default = [ ]; @@ -241,6 +271,14 @@ in (jsonFormat.generate "zed-user-tasks" cfg.userTasks) ); }) + (mkIf (cfg.mutableUserDebug && cfg.userDebug != [ ]) { + zedDebugActivation = lib.hm.dag.entryAfter [ "linkGeneration" ] ( + impureConfigMerger "[]" + "$dynamic + $static | group_by(.label) | map(reduce .[] as $item ({}; . * $item))" + "${config.xdg.configHome}/zed/debug.json" + (jsonFormat.generate "zed-user-debug" cfg.userDebug) + ); + }) ]; xdg.configFile = mkMerge [ @@ -265,6 +303,9 @@ in (mkIf (!cfg.mutableUserTasks && cfg.userTasks != [ ]) { "zed/tasks.json".source = jsonFormat.generate "zed-user-tasks" cfg.userTasks; }) + (mkIf (!cfg.mutableUserDebug && cfg.userDebug != [ ]) { + "zed/debug.json".source = jsonFormat.generate "zed-user-debug" cfg.userDebug; + }) ]; assertions = [ diff --git a/tests/modules/programs/zed-editor/debug-empty.nix b/tests/modules/programs/zed-editor/debug-empty.nix new file mode 100644 index 000000000..eed8e7354 --- /dev/null +++ b/tests/modules/programs/zed-editor/debug-empty.nix @@ -0,0 +1,83 @@ +{ + config, + lib, + pkgs, + ... +}: + +{ + programs.zed-editor = { + enable = true; + package = config.lib.test.mkStubPackage { }; + userDebug = [ + { + label = "PHP: Listen to Xdebug"; + adapter = "Xdebug"; + request = "launch"; + port = 9003; + } + { + label = "PHP: Debug this test"; + adapter = "Xdebug"; + request = "launch"; + program = "vendor/bin/phpunit"; + args = [ + "--filter" + "$ZED_SYMBOL" + ]; + } + ]; + }; + + home.homeDirectory = lib.mkForce "/@TMPDIR@/hm-user"; + + nmt.script = + let + preexistingDebug = builtins.toFile "preexisting.json" ""; + + expectedContent = builtins.toFile "expected.json" '' + [ + { + "adapter": "Xdebug", + "args": [ + "--filter", + "$ZED_SYMBOL" + ], + "label": "PHP: Debug this test", + "program": "vendor/bin/phpunit", + "request": "launch" + }, + { + "adapter": "Xdebug", + "label": "PHP: Listen to Xdebug", + "port": 9003, + "request": "launch" + } + ] + ''; + + debugPath = ".config/zed/debug.json"; + activationScript = pkgs.writeScript "activation" config.home.activation.zedDebugActivation.data; + in + '' + export HOME=$TMPDIR/hm-user + + # Simulate preexisting debug + mkdir -p $HOME/.config/zed + cat ${preexistingDebug} > $HOME/${debugPath} + + # Run the activation script + substitute ${activationScript} $TMPDIR/activate --subst-var TMPDIR + chmod +x $TMPDIR/activate + $TMPDIR/activate + + # Validate the merged debug + assertFileExists "$HOME/${debugPath}" + assertFileContent "$HOME/${debugPath}" "${expectedContent}" + + # Test idempotency + $TMPDIR/activate + assertFileExists "$HOME/${debugPath}" + assertFileContent "$HOME/${debugPath}" "${expectedContent}" + ''; +} diff --git a/tests/modules/programs/zed-editor/debug-immutable.nix b/tests/modules/programs/zed-editor/debug-immutable.nix new file mode 100644 index 000000000..f433d9128 --- /dev/null +++ b/tests/modules/programs/zed-editor/debug-immutable.nix @@ -0,0 +1,58 @@ +# Test custom keymap functionality +{ config, ... }: + +{ + programs.zed-editor = { + enable = true; + package = config.lib.test.mkStubPackage { }; + mutableUserDebug = false; + userDebug = [ + { + label = "PHP: Listen to Xdebug"; + adapter = "Xdebug"; + request = "launch"; + port = 9003; + } + { + label = "PHP: Debug this test"; + adapter = "Xdebug"; + request = "launch"; + program = "vendor/bin/phpunit"; + args = [ + "--filter" + "$ZED_SYMBOL" + ]; + } + ]; + }; + + nmt.script = + let + expectedContent = builtins.toFile "expected.json" '' + [ + { + "adapter": "Xdebug", + "label": "PHP: Listen to Xdebug", + "port": 9003, + "request": "launch" + }, + { + "adapter": "Xdebug", + "args": [ + "--filter", + "$ZED_SYMBOL" + ], + "label": "PHP: Debug this test", + "program": "vendor/bin/phpunit", + "request": "launch" + } + ] + ''; + + settingsPath = ".config/zed/debug.json"; + in + '' + assertFileExists "home-files/${settingsPath}" + assertFileContent "home-files/${settingsPath}" "${expectedContent}" + ''; +} diff --git a/tests/modules/programs/zed-editor/debug.nix b/tests/modules/programs/zed-editor/debug.nix new file mode 100644 index 000000000..b49fb85d3 --- /dev/null +++ b/tests/modules/programs/zed-editor/debug.nix @@ -0,0 +1,100 @@ +{ + config, + lib, + pkgs, + ... +}: + +{ + programs.zed-editor = { + enable = true; + package = config.lib.test.mkStubPackage { }; + userDebug = [ + { + label = "PHP: Listen to Xdebug"; + adapter = "Xdebug"; + request = "launch"; + port = 9003; + } + { + label = "PHP: Debug this test"; + adapter = "Xdebug"; + request = "launch"; + program = "vendor/bin/phpunit"; + args = [ + "--filter" + "$ZED_SYMBOL" + ]; + } + ]; + }; + + home.homeDirectory = lib.mkForce "/@TMPDIR@/hm-user"; + + nmt.script = + let + preexistingDebug = builtins.toFile "preexisting.json" '' + [ + { + "label": "Debug active Python file", + "adapter": "Debugpy", + "program": "$ZED_FILE", + "request": "launch", + "cwd": "$ZED_WORKTREE_ROOT" + } + ] + ''; + + expectedContent = builtins.toFile "expected.json" '' + [ + { + "label": "Debug active Python file", + "adapter": "Debugpy", + "program": "$ZED_FILE", + "request": "launch", + "cwd": "$ZED_WORKTREE_ROOT" + }, + { + "adapter": "Xdebug", + "args": [ + "--filter", + "$ZED_SYMBOL" + ], + "label": "PHP: Debug this test", + "program": "vendor/bin/phpunit", + "request": "launch" + }, + { + "adapter": "Xdebug", + "label": "PHP: Listen to Xdebug", + "port": 9003, + "request": "launch" + } + ] + ''; + + debugPath = ".config/zed/debug.json"; + activationScript = pkgs.writeScript "activation" config.home.activation.zedDebugActivation.data; + in + '' + export HOME=$TMPDIR/hm-user + + # Simulate preexisting debug + mkdir -p $HOME/.config/zed + cat ${preexistingDebug} > $HOME/${debugPath} + + # Run the activation script + substitute ${activationScript} $TMPDIR/activate --subst-var TMPDIR + chmod +x $TMPDIR/activate + $TMPDIR/activate + + # Validate the merged debug + assertFileExists "$HOME/${debugPath}" + assertFileContent "$HOME/${debugPath}" "${expectedContent}" + + # Test idempotency + $TMPDIR/activate + assertFileExists "$HOME/${debugPath}" + assertFileContent "$HOME/${debugPath}" "${expectedContent}" + ''; +} diff --git a/tests/modules/programs/zed-editor/default.nix b/tests/modules/programs/zed-editor/default.nix index 1029dba99..b7717320c 100644 --- a/tests/modules/programs/zed-editor/default.nix +++ b/tests/modules/programs/zed-editor/default.nix @@ -11,5 +11,8 @@ zed-tasks = ./tasks.nix; zed-tasks-immutable = ./tasks-immutable.nix; zed-tasks-empty = ./tasks-empty.nix; + zed-debug = ./debug.nix; + zed-debug-immutable = ./debug-immutable.nix; + zed-debug-empty = ./debug-empty.nix; zed-themes = ./themes; }