Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
121 changes: 69 additions & 52 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,8 @@
- [Jumping](#jumping)
- [Expanding Variables](#expanding-variables)
- [Highlight Groups](#highlight-groups)
- [Filetypes and autocommands](#filetypes-and-autocommands)
- [Custom buttons](#custom-buttons)
- [Filetypes and Autocommands](#filetypes-and-autocommands)
- [Custom Buttons](#custom-buttons)
- [Roadmap](#roadmap)
- [Known Issues](#known-issues)
- [Acknowledgements](#acknowledgements)
Expand Down Expand Up @@ -78,11 +78,12 @@ return {
The plugin provides 6 "views" that share the same window (so there's clutter)

- Watches view
- Shows a list of (user defined) expressions, that are evaluated by the debug adapter
- Shows a list of user defined expressions, that are evaluated by the debug adapter
- Add, edit and delete expressions from the watch list
- Including adding the variable under the cursor
- Add variable under the cursor using a command
- Copy the value of an expression

![watches view](https://github.com/user-attachments/assets/c6838700-95ed-4b39-9ab5-e0ed0e753995)
![watches view](https://github.com/user-attachments/assets/381a5c9c-7eea-4cdc-8358-a2afe9f247b2)

- Exceptions view
- Control when the debugger should stop, outside of breakpoints (e.g.,
Expand Down Expand Up @@ -126,6 +127,8 @@ The console's default size (height) is resized to match your `nvim-dap-view` con
You can also enable the control bar which exposes some clickable buttons by settings `winbar.controls.enable`.
The control bar is fully customizable, checkout the options on default configuration section.

![controls](https://github.com/user-attachments/assets/3d8d7102-7183-4acf-9759-6a7c7b354e9a)

>[!NOTE]
> Icons are using `Codicons` glyphs so it requires a Nerd Font

Expand Down Expand Up @@ -206,10 +209,11 @@ in the `'winbar'` (e.g., `B` for the breakpoints view).

The breakpoints view, the exceptions view and the scopes view only have 1
mapping: `<CR>`. It jumps to a breakpoint, toggles an exception filter, and
expands a variable, respectively. The watches view comes with 3 mappings:
expands a variable, respectively. The watches view comes with 4 mappings:

- `i` to insert a new expression
- `e` to edit an expression
- `c` to copy an expression (can't copy inner variables for now)
- `d` to delete an expression

Though, the preferred way of adding a new expression is using the
Expand Down Expand Up @@ -322,39 +326,44 @@ return {

### Highlight Groups

`nvim-dap-view` defines 22 highlight groups linked to (somewhat) reasonable defaults, but they may look odd with your colorscheme. If the links aren't defined, no highlighting will be applied. To fix that, you have to manually define the highlight groups (see `:h nvim_set_hl()`). Consider contributing to your colorscheme by sending a PR to add support to `nvim-dap-view`!
`nvim-dap-view` defines 28 highlight groups linked to (somewhat) reasonable defaults, but they may look odd with your colorscheme. If the links aren't defined, no highlighting will be applied. To fix that, you have to manually define the highlight groups (see `:h nvim_set_hl()`). Consider contributing to your colorscheme by sending a PR to add support to `nvim-dap-view`!

<details>
<summary>Highlight groups</summary>

| Highlight Group | Default link |
|--------------------------------------|-----------------------------|
| `NvimDapViewMissingData` | `DapBreakpoint` |
| `NvimDapViewWatchText` | `Comment` |
| `NvimDapViewWatchTextChanged` | `DiagnosticVirtualTextWarn` |
| `NvimDapViewExceptionFilterEnabled` | `DiagnosticOk` |
| `NvimDapViewExceptionFilterDisabled` | `DiagnosticError` |
| `NvimDapViewFileName` | `qfFileName` |
| `NvimDapViewLineNumber` | `qfLineNr` |
| `NvimDapViewSeparator` | `Comment` |
| `NvimDapViewThread` | `@namespace` |
| `NvimDapViewThreadStopped` | `@conditional` |
| `NvimDapViewThread` | `Tag` |
| `NvimDapViewThreadStopped` | `Conditional` |
| `NvimDapViewTab` | `TabLine` |
| `NvimDapViewTabSelected` | `TabLineSel` |
| `NvimDapViewControlNC` | `Comment` |
| `NvimDapViewControlPlay` | `@keyword` |
| `NvimDapViewControlPause` | `@boolean` |
| `NvimDapViewControlStepInto` | `@function` |
| `NvimDapViewControlStepOut` | `@function` |
| `NvimDapViewControlStepOver` | `@function` |
| `NvimDapViewControlStepBack` | `@function` |
| `NvimDapViewControlRunLast` | `@keyword` |
| `NvimDapViewControlPlay` | `Keyword` |
| `NvimDapViewControlPause` | `Boolean` |
| `NvimDapViewControlStepInto` | `Function` |
| `NvimDapViewControlStepOut` | `Function` |
| `NvimDapViewControlStepOver` | `Function` |
| `NvimDapViewControlStepBack` | `Function` |
| `NvimDapViewControlRunLast` | `Keyword` |
| `NvimDapViewControlTerminate` | `DapBreakpoint` |
| `NvimDapViewControlDisconnect` | `DapBreakpoint` |
| `NvimDapViewWatchExpr` | `Identifier` |
| `NvimDapViewWatchError` | `DiagnosticError` |
| `NvimDapViewWatchUpdated` | `DiagnosticVirtualTextWarn` |
| `NvimDapViewBoolean` | `Boolean` |
| `NvimDapViewString` | `String` |
| `NvimDapViewNumber` | `Number` |
| `NvimDapViewFloat` | `Float` |
| `NvimDapViewFunction` | `Function` |

<details>


### Filetypes and Autocommands

`nvim-dap-view` sets the following filetypes:
Expand Down Expand Up @@ -384,9 +393,9 @@ vim.api.nvim_create_autocmd({ "FileType" }, {

</details>

### Custom buttons
### Custom Buttons

`nvim-dap-view` provides some default buttons for the control bar, but you can also add your own. To do that, in the `controls` table you can use the `custom_buttons` table to declare your new button and then add it at the position you want in the `buttons` list.
`nvim-dap-view` provides some default buttons for the control bar, but you can also add your own. To do that, in the `controls` table you can use the `custom_buttons` table to declare your new button and then add it at the position you want in the `buttons` list.

A custom button has 2 methods:

Expand All @@ -402,42 +411,50 @@ See the `@ N` section in `:help statusline` for the complete specifications of a
<summary>Example custom buttons</summary>

An example adding 2 buttons:

- `fun`: the most basic button possible, just prints "🎊" when clicked
- `term_restart`: an hybrid button that acts as a stop/restart button. If the stop button is triggered by anything else than a single left click (middle click, right click, double click or click with a modifier), it will disconnect the session instead.

```lua
winbar = {
controls = {
enabled = true,
buttons = {"play", "step_into", "step_over", "step_out", "term_restart", "fun" },
custom_buttons = {
fun = {
render = function() return "🎉" end,
action = function() vim.print("🎊") end,
},
-- Stop/Restart button
-- Double click, middle click or click with a modifier disconnect instead of stop
term_restart = {
render = function()
local session = require("dap").session()
local group = session and "ControlTerminate" or "ControlRunLast"
local icon = session and "" or ""
return "%#NvimDapView" .. group .. "#" .. icon .. "%*"
end,
action = function(clicks, button, modifiers)
local dap = require("dap")
local alt = clicks > 1 or button ~= "l" or modifiers:gsub(" ", "") ~= ""
if not dap.session() then
dap.run_last()
elseif alt then
dap.disconnect()
else
dap.terminate()
end
end,
},
-- No need to include the "return" statement
return {
winbar = {
controls = {
enabled = true,
buttons = { "play", "step_into", "step_over", "step_out", "term_restart", "fun" },
custom_buttons = {
fun = {
render = function()
return "🎉"
end,
action = function()
vim.print("🎊")
end,
},
-- Stop/Restart button
-- Double click, middle click or click with a modifier disconnect instead of stop
term_restart = {
render = function()
local session = require("dap").session()
local group = session and "ControlTerminate" or "ControlRunLast"
local icon = session and "" or ""
return "%#NvimDapView" .. group .. "#" .. icon .. "%*"
end,
action = function(clicks, button, modifiers)
local dap = require("dap")
local alt = clicks > 1 or button ~= "l" or modifiers:gsub(" ", "") ~= ""
if not dap.session() then
dap.run_last()
elseif alt then
dap.disconnect()
else
dap.terminate()
end
end,
},
},
},
},
},
}
```

Expand Down
17 changes: 3 additions & 14 deletions lua/dap-view/events.lua
Original file line number Diff line number Diff line change
Expand Up @@ -78,17 +78,11 @@ dap.listeners.after.stackTrace[SUBSCRIPTION_ID] = function()
end
end

dap.listeners.after.event_stopped[SUBSCRIPTION_ID] = function(_, body)
state.stopped_thread = body.threadId

dap.listeners.after.event_stopped[SUBSCRIPTION_ID] = function()
require("dap-view.threads").get_threads()

for i, expr in ipairs(state.watched_expressions) do
eval.eval_expr(expr, function(result)
local has_changed = state.expression_results[i] ~= result
state.updated_evaluations[i] = state.expression_results[i] and has_changed
state.expression_results[i] = result
end)
for expr, _ in pairs(state.watched_expressions) do
eval.eval_expr(expr)
end

winbar.redraw_controls()
Expand Down Expand Up @@ -120,11 +114,6 @@ dap.listeners.after.event_terminated[SUBSCRIPTION_ID] = function()
threads.show()
end

-- Clear evaluations so new sessions don't get highlighted as changed
for k in ipairs(state.expression_results) do
state.expression_results[k] = nil
end

winbar.redraw_controls()
end

Expand Down
40 changes: 25 additions & 15 deletions lua/dap-view/highlight.lua
Original file line number Diff line number Diff line change
@@ -1,37 +1,47 @@
local globals = require("dap-view.globals")

local api = vim.api
local prefix = require("dap-view.globals").HL_PREFIX

---@param name string
---@param link string
local hl_create = function(name, link)
api.nvim_set_hl(0, prefix .. name, { link = link })
api.nvim_set_hl(0, globals.HL_PREFIX .. name, { link = link })
end

local define_base_links = function()
hl_create("MissingData", "DapBreakpoint")
hl_create("WatchText", "Comment")
hl_create("WatchTextChanged", "DiagnosticVirtualTextWarn")
hl_create("ExceptionFilterEnabled", "DiagnosticOk")
hl_create("ExceptionFilterDisabled", "DiagnosticError")
hl_create("FileName", "qfFileName")
hl_create("LineNumber", "qfLineNr")
hl_create("Separator", "Comment")
hl_create("Thread", "@namespace")
hl_create("ThreadStopped", "@conditional")
hl_create("Thread", "Tag")
hl_create("ThreadStopped", "Conditional")

hl_create("ExceptionFilterEnabled", "DiagnosticOk")
hl_create("ExceptionFilterDisabled", "DiagnosticError")

hl_create("Tab", "TabLine")
hl_create("TabSelected", "TabLineSel")

hl_create("ControlNC", "Comment")
hl_create("ControlPlay", "@keyword")
hl_create("ControlPause", "@boolean")
hl_create("ControlStepInto", "@function")
hl_create("ControlStepOut", "@function")
hl_create("ControlStepOver", "@function")
hl_create("ControlStepBack", "@function")
hl_create("ControlRunLast", "@keyword")
hl_create("ControlPlay", "Keyword")
hl_create("ControlPause", "Boolean")
hl_create("ControlStepInto", "Function")
hl_create("ControlStepOut", "Function")
hl_create("ControlStepOver", "Function")
hl_create("ControlStepBack", "Function")
hl_create("ControlRunLast", "Keyword")
hl_create("ControlTerminate", "DapBreakpoint")
hl_create("ControlDisconnect", "DapBreakpoint")

hl_create("WatchExpr", "Identifier")
hl_create("WatchError", "DiagnosticError")
hl_create("WatchUpdated", "DiagnosticVirtualTextWarn")

hl_create("Boolean", "Boolean")
hl_create("String", "String")
hl_create("Number", "Number")
hl_create("Float", "Float")
hl_create("Function", "Function")
end

define_base_links()
Expand Down
3 changes: 2 additions & 1 deletion lua/dap-view/options/controls.lua
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
local dap = require("dap")

local statusline = require("dap-view.util.statusline")
local setup = require("dap-view.setup")
local dap = require("dap")
local module = ...

local M = {}
Expand Down
11 changes: 5 additions & 6 deletions lua/dap-view/state.lua
Original file line number Diff line number Diff line change
Expand Up @@ -10,25 +10,24 @@
---@field winnr? integer
---@field term_bufnr? integer
---@field term_winnr? integer
---@field stopped_thread? integer
---@field last_active_adapter? string
---@field current_section? SectionType
---@field exceptions_options ExceptionsOption[]
---@field threads ThreadWithErr[]
---@field threads_err? string
---@field frames_by_line {[number]: dap.StackFrame[]}
---@field expressions_by_line {[integer]: string}
---@field variables_by_reference table<integer, {variable: dap.Variable, updated: boolean}[] | string>
---@field subtle_frames boolean
---@field watched_expressions string[]
---@field expression_results string[]
---@field updated_evaluations boolean[]
---@field watched_expressions table<string,{response?: (dap.EvaluateResponse | string), updated?: boolean}>
local M = {
exceptions_options = {},
threads = {},
frames_by_line = {},
expressions_by_line = {},
variables_by_reference = {},
subtle_frames = false,
watched_expressions = {},
expression_results = {},
updated_evaluations = {},
}

return M
6 changes: 4 additions & 2 deletions lua/dap-view/threads/view.lua
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,9 @@ M.show = function()
-- Clear previous content
api.nvim_buf_set_lines(state.bufnr, 0, -1, true, {})

if views.cleanup_view(not dap.session(), "No active session") then
local session = dap.session()
-- Redundant check to appease the type checker
if views.cleanup_view(session == nil, "No active session") or session == nil then
return
end

Expand All @@ -35,7 +37,7 @@ M.show = function()
local line = 0
for _, thread in pairs(state.threads) do
api.nvim_buf_set_lines(state.bufnr, line, -1, false, { thread.name })
local is_stopped_thread = state.stopped_thread == thread.id
local is_stopped_thread = session.stopped_thread_id == thread.id
hl.hl_range(is_stopped_thread and "ThreadStopped" or "Thread", { line, 0 }, { line, -1 })

local valid_frames = vim.iter(thread.frames or {})
Expand Down
5 changes: 3 additions & 2 deletions lua/dap-view/util/statusline.lua
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
local global = require("dap-view.globals")

local M = {}
local prefix = require("dap-view.globals").HL_PREFIX

---@param text string
---@param group string
M.hl = function(text, group)
return "%#" .. prefix .. group .. "#" .. text .. "%*"
return "%#" .. global.HL_PREFIX .. group .. "#" .. text .. "%*"
end

---@param text string
Expand Down
Loading