From f3466fe6295d719300502086454297b506f3c91f Mon Sep 17 00:00:00 2001 From: Ching Pei Yang Date: Sat, 13 Jun 2026 00:07:24 +0200 Subject: [PATCH 1/6] nvim-dap: add adapters option --- .../plugins/debugger/nvim-dap/nvim-dap.nix | 234 +++++++++++++++++- 1 file changed, 231 insertions(+), 3 deletions(-) diff --git a/modules/plugins/debugger/nvim-dap/nvim-dap.nix b/modules/plugins/debugger/nvim-dap/nvim-dap.nix index 521823df..82ed0b32 100644 --- a/modules/plugins/debugger/nvim-dap/nvim-dap.nix +++ b/modules/plugins/debugger/nvim-dap/nvim-dap.nix @@ -4,9 +4,213 @@ ... }: let inherit (lib.options) mkEnableOption mkOption; - inherit (lib.types) bool attrsOf str; - inherit (lib.nvim.types) mkPluginSetupOption; + inherit (lib.types) bool attrsOf str submodule anything either enum oneOf listOf nullOr int; + inherit (lib.nvim.types) mkPluginSetupOption luaInline; inherit (config.vim.lib) mkMappingOption; + + commonOptions = { + initialize_timeout_sec = mkOption { + type = nullOr int; + default = null; + defaultText = "4"; # plugin default + description = '' + How many seconds to wait for a response on an initialize request before + emitting a warning + ''; + }; + + disconnect_timeout_sec = mkOption { + type = nullOr int; + default = null; + defaultText = "3"; # plugin default + description = '' + How many seconds to wait for a disconnect response before + emitting a warning and closing the connection + ''; + }; + + source_filetype = mkOption { + type = nullOr str; + default = null; + description = '' + The filetype to use for content retrieved via a source request + ''; + }; + }; + + execAdapterType = submodule { + options = { + type = mkOption { + type = enum ["executable"]; + }; + + command = mkOption { + type = str; + description = "Command to invoke"; + }; + + args = mkOption { + type = listOf str; + }; + + options = + commonOptions + // { + env = mkOption { + type = nullOr (attrsOf str); + default = null; + description = "Environment variables passed to the command"; + }; + + cwd = mkOption { + type = nullOr str; + default = null; + description = "Set the working directory for the command"; + }; + + detached = mkOption { + type = nullOr bool; + default = null; + defaultText = "true"; # plugin default + description = '' + Whether to spawn the debug adapter process in a detached state + ''; + }; + }; + + id = mkOption { + type = nullOr str; + default = null; + description = '' + Identifier of the adapter. This is used for the `adapterId` property + of the initialize request. + ''; + }; + }; + }; + + serverPipeExecutable = submodule { + options = { + command = mkOption { + type = nullOr str; + description = "Command that spawns the debug adapter"; + }; + + args = mkOption { + type = nullOr (listOf str); + default = null; + }; + + detached = mkOption { + type = nullOr bool; + default = null; + defaultText = "true"; # plugin default + description = '' + Whether to spawn the debug adapter process in a detached state + ''; + }; + + cwd = mkOption { + type = nullOr str; + default = null; + description = "Working directory"; + }; + }; + }; + + serverAdapterType = submodule { + options = { + type = mkOption { + type = enum ["server"]; + }; + + host = mkOption { + type = nullOr str; + default = null; + defaultText = "127.0.0.1"; # plugin default + description = "Host to connect to"; + }; + + port = mkOption { + type = either int (enum ["\${port}"]); + description = '' + Port to connect to. Use "''${port}" for a dynamically resolved free + port. This is intended to be used with executable.args. + ''; + }; + + id = mkOption { + type = nullOr str; + default = null; + description = '' + Identifier of the adapter. This is used for the `adapterId` property + of the initialize request. + ''; + }; + + executable = mkOption { + type = nullOr serverPipeExecutable; + default = null; + description = '' + Optional executable configuration to launch the debug adapter before + connecting via TCP + ''; + }; + + options = + commonOptions + // { + max_retries = mkOption { + type = nullOr int; + default = null; + defaultText = "14"; # plugin default + description = '' + Amount of times the client should attempt to connect before + erroring out (250ms delay between retries) + ''; + }; + }; + }; + }; + + pipeAdapterType = submodule { + options = { + type = mkOption { + type = enum ["pipe"]; + }; + + pipe = mkOption { + type = str; + description = '' + Absolute path to the pipe file. Use \"''${pipe}\" for a dynamically + generated temporary filename + ''; + }; + + executable = mkOption { + type = nullOr serverPipeExecutable; + default = null; + description = '' + Optional executable configuration to launch the debug adapter before + connecting via pipe + ''; + }; + + options = + commonOptions + // { + timeout = mkOption { + type = nullOr int; + default = null; + defaultText = "5000"; # plugin default + description = '' + Max amount of time in ms to wait between spawning the + executable and connecting to the pipe + ''; + }; + }; + }; + }; in { options.vim.debugger.nvim-dap = { enable = mkEnableOption "debugging via nvim-dap"; @@ -19,7 +223,10 @@ in { autoStart = mkOption { type = bool; default = true; - description = "Automatically Opens and Closes DAP-UI upon starting/closing a debugging session"; + description = '' + Automatically Opens and Closes DAP-UI upon starting/closing a + debugging session + ''; }; }; @@ -29,6 +236,27 @@ in { type = attrsOf str; }; + adapters = mkOption { + type = attrsOf (oneOf [ + execAdapterType + serverAdapterType + pipeAdapterType + luaInline + ]); + default = {}; + description = "Adapter configurations. See `:help dap-adapter`"; + }; + + configurations = mkOption { + type = attrsOf (listOf anything); + default = {}; + description = '' + Mapping of filetype to list of possible `Configuration`. + + See `:help dap-configuration`. + ''; + }; + mappings = { continue = mkMappingOption "Continue" "dc"; restart = mkMappingOption "Restart" "dR"; From 1c98cf407944151f052832d8bd2b8ce16fda0b7e Mon Sep 17 00:00:00 2001 From: Ching Pei Yang Date: Sat, 13 Jun 2026 00:07:24 +0200 Subject: [PATCH 2/6] nvim-dap: add type for configurations --- .../plugins/debugger/nvim-dap/nvim-dap.nix | 25 ++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/modules/plugins/debugger/nvim-dap/nvim-dap.nix b/modules/plugins/debugger/nvim-dap/nvim-dap.nix index 82ed0b32..65985e9b 100644 --- a/modules/plugins/debugger/nvim-dap/nvim-dap.nix +++ b/modules/plugins/debugger/nvim-dap/nvim-dap.nix @@ -211,6 +211,29 @@ }; }; }; + + configurationType = submodule { + freeformType = attrsOf anything; + options = { + type = mkOption { + type = str; + description = "Which debug adapter to use"; + }; + + request = mkOption { + type = str; + description = '' + Either `attach` or `launch`. Indicates whether the debug adapter + should launch a debugee or attach to one that is already running. + ''; + }; + + name = mkOption { + type = str; + description = "A user-readable name for the configuration"; + }; + }; + }; in { options.vim.debugger.nvim-dap = { enable = mkEnableOption "debugging via nvim-dap"; @@ -248,7 +271,7 @@ in { }; configurations = mkOption { - type = attrsOf (listOf anything); + type = attrsOf (listOf configurationType); default = {}; description = '' Mapping of filetype to list of possible `Configuration`. From 45f463574ee0de0f1f7d88ae3d851fffdf20f284 Mon Sep 17 00:00:00 2001 From: Ching Pei Yang Date: Sat, 13 Jun 2026 00:07:24 +0200 Subject: [PATCH 3/6] nvim-dap: impl adapters and configurations --- modules/plugins/debugger/nvim-dap/config.nix | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/modules/plugins/debugger/nvim-dap/config.nix b/modules/plugins/debugger/nvim-dap/config.nix index 70bd9891..a495bda7 100644 --- a/modules/plugins/debugger/nvim-dap/config.nix +++ b/modules/plugins/debugger/nvim-dap/config.nix @@ -4,11 +4,13 @@ lib, ... }: let + inherit (builtins) concatStringsSep; inherit (lib.strings) optionalString; inherit (lib.modules) mkIf mkMerge; - inherit (lib.attrsets) mapAttrs; + inherit (lib.attrsets) mapAttrs mapAttrsToList; inherit (lib.nvim.binds) mkKeymap; inherit (lib.nvim.dag) entryAnywhere entryAfter; + inherit (lib.nvim.lua) toLuaObject; cfg = config.vim.debugger.nvim-dap; opt = { @@ -28,6 +30,22 @@ in { nvim-dap = entryAnywhere '' local dap = require("dap") vim.fn.sign_define("DapBreakpoint", { text = "🛑", texthl = "ErrorMsg", linehl = "", numhl = "" }) + + ${ + concatStringsSep "\n" + (mapAttrsToList (name: opts: '' + dap.adapters[${toLuaObject name}] = ${toLuaObject opts} + '') + cfg.adapters) + } + + ${ + concatStringsSep "\n" + (mapAttrsToList (ft: opts: '' + dap.configurations[${toLuaObject ft}] = ${toLuaObject opts} + '') + cfg.configurations) + } ''; } // mapAttrs (_: v: (entryAfter ["nvim-dap"] v)) cfg.sources; From b4e32220dce8cef861dae4399193a97dab4ff5cb Mon Sep 17 00:00:00 2001 From: Ching Pei Yang Date: Sat, 13 Jun 2026 00:07:24 +0200 Subject: [PATCH 4/6] lib: update doc comment --- lib/types/custom.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/types/custom.nix b/lib/types/custom.nix index 9974070e..3dfa8f92 100644 --- a/lib/types/custom.nix +++ b/lib/types/custom.nix @@ -46,7 +46,7 @@ in { # Example: # # vim.languages.typescript.lsp.servers = mkOption { - # type = renamedEnum + # type = enumWithRename # "vim.languages.typescript.lsp.servers" # ["typescript-language-server" "some-other-server"] # { ts_ls = "typescript-language-server"; }; From 987867905e03b34319d29ea178aa550221a11544 Mon Sep 17 00:00:00 2001 From: Ching Pei Yang Date: Sat, 13 Jun 2026 00:07:24 +0200 Subject: [PATCH 5/6] language/clang: use new dap config format --- modules/extra/deprecations.nix | 7 ++ modules/plugins/debugger/nvim-dap/default.nix | 1 + .../debugger/nvim-dap/presets/default.nix | 5 ++ .../debugger/nvim-dap/presets/lldb.nix | 22 +++++++ modules/plugins/languages/clang.nix | 64 +++++++++---------- 5 files changed, 65 insertions(+), 34 deletions(-) create mode 100644 modules/plugins/debugger/nvim-dap/presets/default.nix create mode 100644 modules/plugins/debugger/nvim-dap/presets/lldb.nix diff --git a/modules/extra/deprecations.nix b/modules/extra/deprecations.nix index 4ef31779..82a0541c 100644 --- a/modules/extra/deprecations.nix +++ b/modules/extra/deprecations.nix @@ -396,5 +396,12 @@ in { Linters can still be customized via `vim.diagnostics.nvim-lint..args` '') ] + + # 2026-06-13 + [ + (mkRemovedOptionModule ["vim" "languages" "clang" "dap" "package"] '' + Please use `vim.debugger.nvim-dap.adapters..command` instead. + '') + ] ]; } diff --git a/modules/plugins/debugger/nvim-dap/default.nix b/modules/plugins/debugger/nvim-dap/default.nix index a921e26b..787d86f5 100644 --- a/modules/plugins/debugger/nvim-dap/default.nix +++ b/modules/plugins/debugger/nvim-dap/default.nix @@ -1,5 +1,6 @@ { imports = [ + ./presets ./config.nix ./nvim-dap.nix ]; diff --git a/modules/plugins/debugger/nvim-dap/presets/default.nix b/modules/plugins/debugger/nvim-dap/presets/default.nix new file mode 100644 index 00000000..1c08aff6 --- /dev/null +++ b/modules/plugins/debugger/nvim-dap/presets/default.nix @@ -0,0 +1,5 @@ +{ + imports = [ + ./lldb.nix + ]; +} diff --git a/modules/plugins/debugger/nvim-dap/presets/lldb.nix b/modules/plugins/debugger/nvim-dap/presets/lldb.nix new file mode 100644 index 00000000..7442a548 --- /dev/null +++ b/modules/plugins/debugger/nvim-dap/presets/lldb.nix @@ -0,0 +1,22 @@ +{ + lib, + pkgs, + config, + ... +}: let + inherit (lib.modules) mkIf; + inherit (lib.options) mkEnableOption; + + cfg = config.vim.debugger.nvim-dap.presets.lldb; +in { + options.vim.debugger.nvim-dap.presets.lldb = { + enable = mkEnableOption "LLDB debugger using lldb-dap"; + }; + + config.vim.debugger.nvim-dap.adapters = mkIf cfg.enable { + lldb = { + type = "executable"; + command = "${pkgs.lldb}/bin/lldb-dap"; + }; + }; +} diff --git a/modules/plugins/languages/clang.nix b/modules/plugins/languages/clang.nix index 7698e424..f07466aa 100644 --- a/modules/plugins/languages/clang.nix +++ b/modules/plugins/languages/clang.nix @@ -6,7 +6,7 @@ }: let inherit (builtins) attrNames; inherit (lib.options) mkEnableOption mkOption literalExpression; - inherit (lib.types) bool enum package listOf; + inherit (lib.types) bool enum listOf; inherit (lib) genAttrs; inherit (lib.meta) getExe getExe'; inherit (lib.modules) mkIf mkMerge; @@ -14,38 +14,32 @@ inherit (lib.generators) mkLuaInline; inherit (lib.nvim.dag) entryAfter; inherit (lib.nvim.attrsets) mapListToAttrs; + inherit (lib.nvim.types) deprecatedSingleOrListOf enumWithRename; cfg = config.vim.languages.clang; defaultServers = ["clangd"]; servers = ["ccls" "clangd"]; - defaultDebugger = "lldb-vscode"; + defaultDebugger = ["lldb"]; debuggers = { - lldb-vscode = { - package = pkgs.lldb; - dapConfig = '' - dap.adapters.lldb = { - type = 'executable', - command = '${cfg.dap.package}/bin/lldb-dap', - name = 'lldb' - } - dap.configurations.cpp = { - { - name = 'Launch', - type = 'lldb', - request = 'launch', - program = function() - return vim.fn.input('Path to executable: ', vim.fn.getcwd() .. '/', 'file') - end, - cwd = "''${workspaceFolder}", - stopOnEntry = false, - args = {}, - }, - } - - dap.configurations.c = dap.configurations.cpp - ''; + lldb = let + configuration = { + name = "Launch"; + type = "lldb"; + request = "launch"; + program = mkLuaInline '' + function() + return vim.fn.input("Path to executable: ", vim.fn.getcwd() .. "/", "file") + end + ''; + cwd = "\${workspaceFolder}"; + stopOnEntry = false; + args = {}; + }; + in { + c = [configuration]; + cpp = [configuration]; }; }; @@ -147,14 +141,13 @@ in { }; debugger = mkOption { description = "clang debugger to use"; - type = enum (attrNames debuggers); + type = + deprecatedSingleOrListOf "vim.langauges.clang.dap.debugger" + (enumWithRename "vim.langauges.clang.dap.debugger" (attrNames debuggers) { + lldb-vscode = "lldb"; + }); default = defaultDebugger; }; - package = mkOption { - description = "clang debugger package."; - type = package; - default = debuggers.${cfg.dap.debugger}.package; - }; }; format = { @@ -208,8 +201,11 @@ in { }) (mkIf cfg.dap.enable { - vim.debugger.nvim-dap.enable = true; - vim.debugger.nvim-dap.sources.clang-debugger = debuggers.${cfg.dap.debugger}.dapConfig; + vim.debugger.nvim-dap = { + enable = true; + presets.lldb.enable = true; + configurations = mkMerge (map (name: debuggers.${name}) cfg.dap.debugger); + }; }) (mkIf cfg.format.enable { From 1f457c85e789d8928bd2297d6da957623d6a06ec Mon Sep 17 00:00:00 2001 From: Ching Pei Yang Date: Sat, 13 Jun 2026 00:07:24 +0200 Subject: [PATCH 6/6] languages/zig: use new dap config format --- modules/plugins/languages/zig.nix | 55 +++++++++++++++---------------- 1 file changed, 26 insertions(+), 29 deletions(-) diff --git a/modules/plugins/languages/zig.nix b/modules/plugins/languages/zig.nix index a9589f9c..c14d980d 100644 --- a/modules/plugins/languages/zig.nix +++ b/modules/plugins/languages/zig.nix @@ -7,42 +7,34 @@ inherit (builtins) attrNames; inherit (lib.options) mkEnableOption mkOption literalExpression; inherit (lib.modules) mkIf mkMerge mkDefault; + inherit (lib.generators) mkLuaInline; inherit (lib) genAttrs; inherit (lib.types) bool package enum listOf; - inherit (lib.nvim.types) mkGrammarOption; + inherit (lib.nvim.types) mkGrammarOption deprecatedSingleOrListOf enumWithRename; cfg = config.vim.languages.zig; defaultServers = ["zls"]; servers = ["zls"]; - # TODO: dap.adapter.lldb is duplicated when enabling the - # vim.languages.clang.dap module. This does not cause - # breakage... but could be cleaner. - defaultDebugger = "lldb-vscode"; + defaultDebugger = ["lldb"]; debuggers = { - lldb-vscode = { - package = pkgs.lldb; - dapConfig = '' - dap.adapters.lldb = { - type = 'executable', - command = '${cfg.dap.package}/bin/lldb-dap', - name = 'lldb' - } - dap.configurations.zig = { - { - name = 'Launch', - type = 'lldb', - request = 'launch', - program = function() + lldb = { + zig = [ + { + name = "Launch"; + type = "lldb"; + request = "launch"; + program = mkLuaInline '' + function() return vim.fn.input('Path to executable: ', vim.fn.getcwd() .. '/', 'file') - end, - cwd = "''${workspaceFolder}", - stopOnEntry = false, - args = {}, - }, + end + ''; + cwd = "\${workspaceFolder}"; + stopOnEntry = false; + args = {}; } - ''; + ]; }; }; in { @@ -83,7 +75,11 @@ in { }; debugger = mkOption { - type = enum (attrNames debuggers); + type = + deprecatedSingleOrListOf "vim.langauges.zig.dap.debugger" + (enumWithRename "vim.langauges.zig.dap.debugger" (attrNames debuggers) { + lldb-vscode = "lldb"; + }); default = defaultDebugger; description = "Zig debugger to use"; }; @@ -119,9 +115,10 @@ in { }) (mkIf cfg.dap.enable { - vim = { - debugger.nvim-dap.enable = true; - debugger.nvim-dap.sources.zig-debugger = debuggers.${cfg.dap.debugger}.dapConfig; + vim.debugger.nvim-dap = { + enable = true; + presets.lldb.enable = true; + configurations = mkMerge (map (name: debuggers.${name}) cfg.dap.debugger); }; }) ]);