Skip to content

Commit 438ea47

Browse files
authored
fix(footnotes): add nil check in goto_definition navigation (#208)
1 parent 9a75a71 commit 438ea47

2 files changed

Lines changed: 60 additions & 0 deletions

File tree

lua/markdown-plus/footnotes/navigation.lua

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,14 @@ function M.goto_definition()
2929

3030
-- Jump to definition, position cursor after ": "
3131
local line = vim.api.nvim_buf_get_lines(bufnr, def.line_num - 1, def.line_num, false)[1]
32+
if not line then
33+
local line_count = vim.api.nvim_buf_line_count(bufnr)
34+
local target_line = math.min(def.line_num, line_count)
35+
vim.cmd("normal! m'")
36+
vim.api.nvim_win_set_cursor(0, { target_line, 0 })
37+
utils.notify("Footnote definition moved; jumped to nearest available line", vim.log.levels.INFO)
38+
return
39+
end
3240
local content_start = line:find(":%s*")
3341
if content_start then
3442
content_start = content_start + 1

spec/markdown-plus/footnotes_spec.lua

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -428,4 +428,56 @@ describe("markdown-plus footnotes", function()
428428
assert.equals(true, config.confirm_delete)
429429
end)
430430
end)
431+
432+
describe("navigation", function()
433+
local navigation = require("markdown-plus.footnotes.navigation")
434+
435+
describe("goto_definition", function()
436+
it("jumps to footnote definition from reference", function()
437+
vim.api.nvim_buf_set_lines(0, 0, -1, false, {
438+
"Text with[^1] footnote.",
439+
"",
440+
"[^1]: The definition.",
441+
})
442+
vim.api.nvim_win_set_cursor(0, { 1, 11 }) -- on [^1]
443+
444+
navigation.goto_definition()
445+
446+
local cursor = vim.api.nvim_win_get_cursor(0)
447+
assert.equals(3, cursor[1])
448+
end)
449+
450+
it("does not error when definition line is out of range", function()
451+
vim.api.nvim_buf_set_lines(0, 0, -1, false, {
452+
"Text with[^1] footnote.",
453+
"",
454+
"[^1]: The definition.",
455+
})
456+
vim.api.nvim_win_set_cursor(0, { 1, 11 }) -- on [^1]
457+
458+
-- Stub nvim_buf_get_lines to return empty (simulating buffer shrink)
459+
local orig_get_lines = vim.api.nvim_buf_get_lines
460+
vim.api.nvim_buf_get_lines = function(buf, start, stop, strict)
461+
-- Only intercept the single-line read for the definition
462+
if start == 2 and stop == 3 then
463+
return {}
464+
end
465+
return orig_get_lines(buf, start, stop, strict)
466+
end
467+
468+
local success = pcall(function()
469+
navigation.goto_definition()
470+
end)
471+
472+
vim.api.nvim_buf_get_lines = orig_get_lines
473+
assert.is_true(success, "goto_definition should not error when line is nil")
474+
475+
-- Verify cursor jumped to a safe position (clamped to buffer line count)
476+
local cursor = vim.api.nvim_win_get_cursor(0)
477+
local line_count = vim.api.nvim_buf_line_count(0)
478+
assert.is_true(cursor[1] >= 1 and cursor[1] <= line_count, "cursor should be within buffer bounds")
479+
assert.equals(0, cursor[2], "cursor column should be 0 on fallback")
480+
end)
481+
end)
482+
end)
431483
end)

0 commit comments

Comments
 (0)