From 86c939ba91e97f0364bf5ba877a0fb4f45309c35 Mon Sep 17 00:00:00 2001 From: ashab-k <145352237+ashab-k@users.noreply.github.com> Date: Thu, 15 Jan 2026 07:50:24 +0530 Subject: [PATCH] fix(treesitter): fix spell navigation on first line (#37361) Problem: Spell navigation skips words on the first line because _on_spell_nav passes an empty range (0,0) to the highlighter. Solution: Use math.max(erow, srow + 1) to ensure a valid search window. Signed-off-by: ashab-k --- runtime/lua/vim/treesitter/highlighter.lua | 3 ++- test/functional/treesitter/highlight_spec.lua | 20 +++++++++++++++++++ 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/runtime/lua/vim/treesitter/highlighter.lua b/runtime/lua/vim/treesitter/highlighter.lua index a5b60acc9b..b71f0db9a7 100644 --- a/runtime/lua/vim/treesitter/highlighter.lua +++ b/runtime/lua/vim/treesitter/highlighter.lua @@ -508,9 +508,10 @@ function TSHighlighter._on_spell_nav(_, _, buf, srow, _, erow, _) -- Do not affect potentially populated highlight state. Here we just want a temporary -- empty state so the C code can detect whether the region should be spell checked. local highlight_states = self._highlight_states + local search_erow = math.max(erow, srow + 1) self:prepare_highlight_states(srow, erow) - on_range_impl(self, buf, srow, 0, erow, 0, true, false) + on_range_impl(self, buf, srow, 0, search_erow, 0, true, false) self._highlight_states = highlight_states end diff --git a/test/functional/treesitter/highlight_spec.lua b/test/functional/treesitter/highlight_spec.lua index 40d528a379..bf085aa42d 100644 --- a/test/functional/treesitter/highlight_spec.lua +++ b/test/functional/treesitter/highlight_spec.lua @@ -1453,3 +1453,23 @@ it('no nil index for missing highlight query', function() vim.treesitter.highlighter.new(parser) ]]) end) + +it('spell navigation correctly wraps back to the first line (Row 0) #36970', function() + clear() + insert([[ +mispelledone +mispelledtwo]]) + + command('set spell') + command('set wrapscan') + exec_lua(function() + vim.treesitter.start(0, 'markdown') + end) + + api.nvim_win_set_cursor(0, { 2, 0 }) + + feed(']s') + + local pos = api.nvim_win_get_cursor(0) + eq(1, pos[1], 'Should have wrapped back to Line 1') +end)