Skip to content

Commit cc77338

Browse files
committed
Adapt REPL/line rendering for multi-line promptbuf changes
1 parent 1c75a79 commit cc77338

3 files changed

Lines changed: 103 additions & 27 deletions

File tree

lua/dap/repl.lua

Lines changed: 26 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,19 @@ end
2020
local execute -- required for forward reference
2121

2222

23+
---@param buf integer
24+
local function line_count(buf)
25+
assert(vim.bo[buf].buftype == "prompt", "buf must have buftype=prompt")
26+
if vim.fn.has("nvim-0.12") == 1 then
27+
local ok, mark = pcall(api.nvim_buf_get_mark, buf, ":")
28+
if ok then
29+
return mark[1] - 1
30+
end
31+
end
32+
return api.nvim_buf_line_count(buf) - 1
33+
end
34+
35+
2336
local function new_buf()
2437
local prev_buf = api.nvim_get_current_buf()
2538
local buf = api.nvim_create_buf(true, true)
@@ -79,7 +92,7 @@ local function new_buf()
7992
local active_buf = api.nvim_win_get_buf(0)
8093
if active_buf == buf then
8194
local lnum = api.nvim_win_get_cursor(0)[1]
82-
autoscroll = lnum == api.nvim_buf_line_count(buf)
95+
autoscroll = lnum >= line_count(buf)
8396
end
8497
end
8598
})
@@ -189,7 +202,7 @@ end
189202

190203
local function evaluate_handler(err, resp)
191204
if err then
192-
M.append(tostring(err), nil, { newline = false })
205+
M.append(tostring(err), nil, { newline = true })
193206
return
194207
end
195208
local layer = ui.layer(repl.buf)
@@ -201,16 +214,15 @@ local function evaluate_handler(err, resp)
201214
-- Appending twice would result in a intermediate "dap> " prompt
202215
-- To avoid that this eagerly fetches the children; pre-renders the region
203216
-- and lets tree.render override it
204-
local lnum = api.nvim_buf_line_count(repl.buf) - 1
205217
if spec.has_children(resp) then
206218
spec.fetch_children(resp, function()
207-
tree.render(layer, resp, nil, lnum, -1)
219+
tree.render(layer, resp, nil)
208220
end)
209221
else
210-
tree.render(layer, resp, nil, lnum, -1)
222+
tree.render(layer, resp, nil)
211223
end
212224
else
213-
M.append(resp.result, nil, { newline = false })
225+
M.append(resp.result, nil, { newline = true })
214226
end
215227
end
216228

@@ -383,8 +395,8 @@ end
383395
---@param text string
384396
---@param opts? dap.repl.execute.Opts
385397
function M.execute(text, opts)
386-
M.append(prompt .. text .. "\n", "$", { newline = true })
387-
local numlines = api.nvim_buf_line_count(repl.buf)
398+
M.append(prompt .. text, "$", { newline = true })
399+
local numlines = line_count(repl.buf)
388400
if repl.win and api.nvim_win_is_valid(repl.win) then
389401
pcall(api.nvim_win_set_cursor, repl.win, { numlines, 0 })
390402
api.nvim_win_call(repl.win, function()
@@ -449,6 +461,7 @@ function M.on_down()
449461
end
450462

451463

464+
452465
---@param line string
453466
---@param lnum (integer|string)?
454467
---@param opts? {newline: boolean}
@@ -460,22 +473,22 @@ function M.append(line, lnum, opts)
460473
end
461474
local lines = vim.split(line, '\n')
462475
if lnum == '$' or not lnum then
463-
lnum = api.nvim_buf_line_count(buf) - 1
476+
lnum = line_count(buf)
464477
if opts.newline == false then
465-
local last_line = api.nvim_buf_get_lines(buf, -2, -1, true)[1]
466-
local insert_pos = #last_line
478+
local last_line = api.nvim_buf_get_lines(buf, lnum, lnum + 1, true)[1]
479+
local insert_pos = last_line ~= nil and #last_line or 0
467480
if last_line == prompt then
468481
-- insert right in front of the empty prompt
469482
insert_pos = 0
470483
if lines[#lines] ~= '' then
471484
table.insert(lines, #lines + 1, '')
472485
end
473-
elseif vim.startswith(last_line, prompt) then
486+
elseif vim.startswith(last_line or "", prompt) then
474487
table.insert(lines, 1, '')
475488
end
476489
api.nvim_buf_set_text(buf, lnum, insert_pos, lnum, insert_pos, lines)
477490
else
478-
api.nvim_buf_set_lines(buf, -1, -1, true, lines)
491+
api.nvim_buf_set_lines(buf, lnum, lnum, true, lines)
479492
end
480493
elseif type(lnum) == "number" then
481494
api.nvim_buf_set_lines(buf, lnum, lnum, true, lines)

lua/dap/ui.lua

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -216,7 +216,7 @@ function M.new_tree(opts)
216216
}
217217
context = vim.tbl_deep_extend('keep', context, extra_context)
218218
for _, child in pairs(opts.get_children(value)) do
219-
layer.render({child}, with_indent(indent, opts.render_child), context, -1)
219+
layer.render({child}, with_indent(indent, opts.render_child), context)
220220
if is_expanded(child) then
221221
render_all_expanded(layer, child, indent + 2)
222222
end
@@ -426,6 +426,21 @@ end
426426
---@field item any
427427
---@field context table|nil
428428

429+
430+
---@param buf integer
431+
local function line_count(buf)
432+
if vim.bo[buf].buftype ~= "prompt" then
433+
return api.nvim_buf_line_count(buf)
434+
end
435+
if vim.fn.has("nvim-0.12") == 1 then
436+
local ok, mark = pcall(api.nvim_buf_get_mark, buf, ":")
437+
if ok then
438+
return mark[1] - 1
439+
end
440+
end
441+
return api.nvim_buf_line_count(buf) - 1
442+
end
443+
429444
--- Returns a layer, creating it if it's missing.
430445
---@param buf integer
431446
---@return dap.ui.Layer
@@ -473,7 +488,7 @@ function M.layer(buf)
473488
local modifiable = vim.bo[buf].modifiable
474489
vim.bo[buf].modifiable = true
475490
if not start and not end_ then
476-
start = api.nvim_buf_line_count(buf)
491+
start = line_count(buf)
477492
-- Avoid inserting a new line at the end of the buffer
478493
-- The case of no lines and one empty line are ambiguous;
479494
-- set_lines(buf, 0, 0) would "preserve" the "empty buffer line" while set_lines(buf, 0, -1) replaces it
@@ -485,7 +500,7 @@ function M.layer(buf)
485500
end_ = start
486501
end
487502
else
488-
start = start or (api.nvim_buf_line_count(buf) - 1)
503+
start = start or (line_count(buf) - 1)
489504
end_ = end_ or start
490505
end
491506
render_fn = render_fn or tostring
@@ -499,7 +514,7 @@ function M.layer(buf)
499514
local lines = vim.tbl_map(function() return '' end, xs)
500515
api.nvim_buf_set_lines(buf, start, end_, true, lines)
501516
if start == -1 then
502-
start = api.nvim_buf_line_count(buf) - #lines
517+
start = line_count(buf) - #lines
503518
end
504519

505520
for i = start, start + #lines - 1 do

spec/repl_spec.lua

Lines changed: 58 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,16 @@ local function getcompletion_results(server)
5050
end
5151

5252

53+
---@param buf integer
54+
---@param lnum integer
55+
local function assert_prompt_mark(buf, lnum)
56+
if vim.fn.has("nvim-0.12") == 1 then
57+
local prompt_mark = api.nvim_buf_get_mark(buf, ":")
58+
assert.are.same(lnum, prompt_mark[1], "prompt mark expected to be in line " .. tostring(lnum))
59+
end
60+
end
61+
62+
5363
describe('dap.repl', function()
5464
local server
5565
before_each(function()
@@ -68,20 +78,26 @@ describe('dap.repl', function()
6878
local buf = repl.open()
6979
repl.append('foo', nil, { newline = false })
7080
repl.append('bar', nil, { newline = false })
81+
assert_prompt_mark(buf, 1)
7182
repl.append('\nbaz\n', nil, { newline = false })
7283

7384
local lines = api.nvim_buf_get_lines(buf, 0, -1, true)
7485
assert.are.same({'foobar', 'baz', ''}, lines)
86+
assert_prompt_mark(buf, 3)
7587
end)
7688

7789
it("adds newline with newline = true", function()
7890
local buf = repl.open()
91+
assert_prompt_mark(buf, 1)
7992
repl.append("foo", nil, { newline = true })
93+
assert_prompt_mark(buf, 2)
8094
repl.append("bar", nil, { newline = true })
95+
assert_prompt_mark(buf, 3)
8196
repl.append("\nbaz\n", nil, { newline = true })
97+
assert_prompt_mark(buf, 6)
8298

8399
local lines = api.nvim_buf_get_lines(buf, 0, -1, true)
84-
assert.are.same({"", "foo", "bar", "", "baz", ""}, lines)
100+
assert.are.same({"foo", "bar", "", "baz", "", ""}, lines)
85101
end)
86102

87103
it("repl.execute inserts text and executes it, shows result", function()
@@ -98,12 +114,18 @@ describe('dap.repl', function()
98114
repl.execute("1 + 1")
99115
local commands = helpers.wait_for_response(server, "evaluate")
100116
assert.are.same({"initialize", "launch", "evaluate"}, commands)
101-
helpers.wait(function()
102-
local lines = api.nvim_buf_get_lines(buf, 0, -1, true)
103-
return lines[3] == "2"
104-
end)
117+
helpers.wait(
118+
function()
119+
local lines = api.nvim_buf_get_lines(buf, 0, -1, true)
120+
return lines[2] == "2"
121+
end,
122+
function()
123+
return api.nvim_buf_get_lines(buf, 0, -1, true)
124+
end
125+
)
105126
local lines = api.nvim_buf_get_lines(buf, 0, -1, true)
106-
assert.are.same({"", "dap> 1 + 1", "2"}, lines)
127+
assert.are.same({"dap> 1 + 1", "2", ""}, lines)
128+
assert_prompt_mark(buf, 3)
107129
end)
108130
it("repl.execute shows structured results", function()
109131
server = require("spec.server").spawn()
@@ -138,21 +160,47 @@ describe('dap.repl', function()
138160
helpers.wait(
139161
function()
140162
local lines = api.nvim_buf_get_lines(buf, 0, -1, true)
141-
return lines[3] == "table xy"
163+
return lines[2] == "table xy"
142164
end,
143165
function()
144166
return api.nvim_buf_get_lines(buf, 0, -1, true)
145167
end
146168
)
147-
local lines = api.nvim_buf_get_lines(buf, 0, -1, true)
148169
local expected = {
170+
"dap> tbl",
171+
"table xy",
172+
" x: 1",
173+
" y: 2",
149174
"",
175+
}
176+
assert.are.same(expected, api.nvim_buf_get_lines(buf, 0, -1, true))
177+
assert_prompt_mark(buf, 5)
178+
179+
server.spy.clear()
180+
repl.execute("tbl")
181+
commands = helpers.wait_for_response(server, "evaluate")
182+
assert.are.same({"evaluate"}, commands)
183+
helpers.wait(
184+
function()
185+
local lines = api.nvim_buf_get_lines(buf, 0, -1, true)
186+
return lines[6] == "table xy"
187+
end,
188+
function()
189+
return api.nvim_buf_get_lines(buf, 0, -1, true)
190+
end
191+
)
192+
expected = {
150193
"dap> tbl",
151194
"table xy",
152195
" x: 1",
153-
" y: 2"
196+
" y: 2",
197+
"dap> tbl",
198+
"table xy",
199+
" x: 1",
200+
" y: 2",
201+
"",
154202
}
155-
assert.are.same(expected, lines)
203+
assert.are.same(expected, api.nvim_buf_get_lines(buf, 0, -1, true))
156204
end)
157205
end)
158206

0 commit comments

Comments
 (0)