mirror of
https://github.com/mfussenegger/nvim-dap
synced 2024-09-16 14:24:03 +02:00
Add config providers; always load .vscode/launch.json
- Introduces a dap.providers.configs table which plugins can extend to add additional sources for dynamic configuration generation - Implements the two built-in configuration sources as providers - `.vscode/launch.json` files are now loaded automatically by one of these providers. The entries from the file always display even if the type doesn't match the current filetype. This gets rid of the `type_to_filetypes` mapping requirements.
This commit is contained in:
parent
5e2895a8d2
commit
54f891ae4c
3 changed files with 155 additions and 33 deletions
63
doc/dap.txt
63
doc/dap.txt
|
@ -1178,10 +1178,18 @@ You could also customize the buffer and window creation using a low-level builde
|
|||
.build()
|
||||
<
|
||||
|
||||
|
||||
==============================================================================
|
||||
EXTENSIONS API *dap-extensions*
|
||||
|
||||
nvim-dap provides extension points for plugins:
|
||||
|
||||
- |dap-listeners|
|
||||
- |dap-providers|
|
||||
|
||||
|
||||
==============================================================================
|
||||
LISTENERS EXTENSIONS API *dap-listeners*
|
||||
|
||||
|
||||
nvim-dap supports subscribing and listening to all responses or events that a
|
||||
debug adapter might send to nvim-dap.
|
||||
|
@ -1232,6 +1240,59 @@ For events, the listeners are called with two arguments:
|
|||
1. The session
|
||||
2. The event payload
|
||||
|
||||
|
||||
==============================================================================
|
||||
PROVIDERS EXTENSIONS API *dap-providers*
|
||||
|
||||
==============================================================================
|
||||
CONFIG PROVIDERS EXTENSIONS API *dap-providers-configs*
|
||||
|
||||
If a user starts a debug session via |dap.continue()|, nvim-dap looks for
|
||||
a suitable configuration (|dap-configuration|) to use.
|
||||
|
||||
To do so it uses so called configuration providers registered in a
|
||||
`dap.providers.configs` table.
|
||||
|
||||
Plugins can extend this table with additional config providers.
|
||||
|
||||
There are two providers built-in:
|
||||
|
||||
- `dap.global` - looks for configuration entries in
|
||||
`dap.configurations.<filetype>`
|
||||
|
||||
- `dap.launch.json` - looks for configuration entries in a
|
||||
`.vscode/launch.json` file.
|
||||
|
||||
|
||||
The key for the table is a `plugin-id`. Plugins should use their plugin name.
|
||||
Do _not_ use the `dap.` namespace. It is reserved for nvim-dap itself.
|
||||
|
||||
The value for the table is a function that takes a buffer number as parameter
|
||||
and must return |dap-configuration| entries as list.
|
||||
|
||||
An example:
|
||||
|
||||
>lua
|
||||
local dap = require("dap")
|
||||
dap.providers.configs["mydummy_provider"] = function(bufnr)
|
||||
return {
|
||||
{
|
||||
name = "This config always shows up",
|
||||
type = "gdb",
|
||||
request = "launch",
|
||||
program = "/usr/bin/zig",
|
||||
args = {"run", "${file}"},
|
||||
cwd = "${workspaceFolder}",
|
||||
},
|
||||
}
|
||||
end
|
||||
<
|
||||
|
||||
To support async operations, the config providers functions are called
|
||||
within a coroutine and they can also return a `thread` which must be suspended
|
||||
and which will be resumed at most once and must then yield the configurations
|
||||
as list.
|
||||
|
||||
==============================================================================
|
||||
UTILS API *dap-utils*
|
||||
|
||||
|
|
107
lua/dap.lua
107
lua/dap.lua
|
@ -238,6 +238,7 @@ M.adapters = {}
|
|||
---@field request "launch"|"attach"
|
||||
---@field name string
|
||||
|
||||
|
||||
--- Configurations per adapter. See `:help dap-configuration` for more help.
|
||||
---
|
||||
--- An example:
|
||||
|
@ -255,6 +256,40 @@ M.adapters = {}
|
|||
---@type table<string, Configuration[]>
|
||||
M.configurations = {}
|
||||
|
||||
local providers_mt = {
|
||||
__newindex = function()
|
||||
error("Cannot add item to dap.providers")
|
||||
end,
|
||||
}
|
||||
M.providers = setmetatable({
|
||||
|
||||
---@type table<string, fun(bufnr: integer): thread|Configuration[]>
|
||||
configs = {
|
||||
},
|
||||
}, providers_mt)
|
||||
|
||||
|
||||
M.providers.configs["dap.global"] = function(bufnr)
|
||||
local filetype = vim.bo[bufnr].filetype
|
||||
local configurations = M.configurations[filetype] or {}
|
||||
assert(
|
||||
islist(configurations),
|
||||
string.format(
|
||||
'`dap.configurations.%s` must be a list of configurations, got %s',
|
||||
filetype,
|
||||
vim.inspect(configurations)
|
||||
)
|
||||
)
|
||||
return configurations
|
||||
end
|
||||
|
||||
|
||||
M.providers.configs["dap.launch.json"] = function()
|
||||
local ok, configs = pcall(require("dap.ext.vscode").getconfigs)
|
||||
return ok and configs or {}
|
||||
end
|
||||
|
||||
|
||||
local signs = {
|
||||
DapBreakpoint = { text = "B", texthl = "", linehl = "", numhl = "" },
|
||||
DapBreakpointCondition = { text = "C", texthl = "", linehl = "", numhl = "" },
|
||||
|
@ -421,35 +456,55 @@ end
|
|||
|
||||
|
||||
local function select_config_and_run(opts)
|
||||
local filetype = vim.bo.filetype
|
||||
local configurations = M.configurations[filetype] or {}
|
||||
assert(
|
||||
islist(configurations),
|
||||
string.format(
|
||||
'`dap.configurations.%s` must be a list of configurations, got %s',
|
||||
filetype,
|
||||
vim.inspect(configurations)
|
||||
)
|
||||
)
|
||||
if #configurations == 0 then
|
||||
local msg = 'No configuration found for `%s`. You need to add configs to `dap.configurations.%s` (See `:h dap-configuration`)'
|
||||
notify(string.format(msg, filetype, filetype), vim.log.levels.INFO)
|
||||
return
|
||||
end
|
||||
opts = opts or {}
|
||||
opts.filetype = opts.filetype or filetype
|
||||
lazy.ui.pick_if_many(
|
||||
configurations,
|
||||
"Configuration: ",
|
||||
function(i) return i.name end,
|
||||
function(configuration)
|
||||
if configuration then
|
||||
M.run(configuration, opts)
|
||||
local bufnr = api.nvim_get_current_buf()
|
||||
local filetype = vim.bo[bufnr].filetype
|
||||
lazy.async.run(function()
|
||||
local all_configs = {}
|
||||
local co = coroutine.running()
|
||||
local providers = vim.tbl_keys(M.providers.configs)
|
||||
table.sort(providers)
|
||||
for _, provider in ipairs(providers) do
|
||||
local config_provider = M.providers.configs[provider]
|
||||
local configs = config_provider(bufnr)
|
||||
if type(configs) == "thread" then
|
||||
assert(
|
||||
coroutine.status(configs) == "suspended",
|
||||
"If configs provider returns a thread it must be suspended"
|
||||
)
|
||||
vim.schedule(function()
|
||||
coroutine.resume(configs, co)
|
||||
end)
|
||||
configs = coroutine.yield()
|
||||
end
|
||||
if islist(configs) then
|
||||
vim.list_extend(all_configs, configs)
|
||||
else
|
||||
notify('No configuration selected', vim.log.levels.INFO)
|
||||
local msg = "Configuration provider %s must return a list of configurations. Got: %s"
|
||||
notify(msg:format(provider, vim.inspect(configs)), vim.log.levels.WARN)
|
||||
end
|
||||
end
|
||||
)
|
||||
|
||||
if #all_configs == 0 then
|
||||
local msg = 'No configuration found for `%s`. You need to add configs to `dap.configurations.%s` (See `:h dap-configuration`)'
|
||||
notify(string.format(msg, filetype, filetype), vim.log.levels.INFO)
|
||||
return
|
||||
end
|
||||
|
||||
opts = opts or {}
|
||||
opts.filetype = opts.filetype or filetype
|
||||
lazy.ui.pick_if_many(
|
||||
all_configs,
|
||||
"Configuration: ",
|
||||
function(i) return i.name end,
|
||||
function(configuration)
|
||||
if configuration then
|
||||
M.run(configuration, opts)
|
||||
else
|
||||
notify('No configuration selected', vim.log.levels.INFO)
|
||||
end
|
||||
end
|
||||
)
|
||||
end)
|
||||
end
|
||||
|
||||
|
||||
|
|
|
@ -174,13 +174,12 @@ function M._load_json(jsonstr)
|
|||
return configs
|
||||
end
|
||||
|
||||
|
||||
--- Extends dap.configurations with entries read from .vscode/launch.json
|
||||
function M.load_launchjs(path, type_to_filetypes)
|
||||
type_to_filetypes = vim.tbl_extend('keep', type_to_filetypes or {}, M.type_to_filetypes)
|
||||
---@param path string?
|
||||
---@return Configuration[]
|
||||
function M.getconfigs(path)
|
||||
local resolved_path = path or (vim.fn.getcwd() .. '/.vscode/launch.json')
|
||||
if not vim.loop.fs_stat(resolved_path) then
|
||||
return
|
||||
return {}
|
||||
end
|
||||
local lines = {}
|
||||
for line in io.lines(resolved_path) do
|
||||
|
@ -189,7 +188,14 @@ function M.load_launchjs(path, type_to_filetypes)
|
|||
end
|
||||
end
|
||||
local contents = table.concat(lines, '\n')
|
||||
local configurations = M._load_json(contents)
|
||||
return M._load_json(contents)
|
||||
end
|
||||
|
||||
|
||||
--- Extends dap.configurations with entries read from .vscode/launch.json
|
||||
function M.load_launchjs(path, type_to_filetypes)
|
||||
type_to_filetypes = vim.tbl_extend('keep', type_to_filetypes or {}, M.type_to_filetypes)
|
||||
local configurations = M.getconfigs(path)
|
||||
|
||||
assert(configurations, "launch.json must have a 'configurations' key")
|
||||
for _, config in ipairs(configurations) do
|
||||
|
|
Loading…
Reference in a new issue