Skip to content

Instantly share code, notes, and snippets.

@atchim
Last active May 11, 2024 06:07
Show Gist options
  • Select an option

  • Save atchim/4502c3ae6db7993772e6dc59efddd6ba to your computer and use it in GitHub Desktop.

Select an option

Save atchim/4502c3ae6db7993772e6dc59efddd6ba to your computer and use it in GitHub Desktop.
Neovim Tree-Sitter node motion
local api = vim.api
local ctrlv = api.nvim_replace_termcodes('<C-V>', true, true, true)
local function exit_vmode()
local mode = vim.fn.mode()
if mode == 'v' or mode == 'V' or mode == ctrlv then
vim.cmd('normal! ' .. mode)
end
end
---Motion over the best-match named node under the cursor/selection.
local function node_motion()
local bufnr = api.nvim_win_get_buf(0)
local ok, lang_tree = pcall(vim.treesitter.get_parser, bufnr)
if not ok then return end
local cpos = api.nvim_win_get_cursor(0)
local vpos = vim.fn.getpos('v')
local node = lang_tree:named_node_for_range(
{ vpos[2] - 1, vpos[3] - 1, cpos[1] - 1, cpos[2] + 1 },
{ ignore_injections = false }
)
if not node then return end
exit_vmode()
local start_row0, start_col0, end_row0, end_col0 = node:range()
api.nvim_win_set_cursor(0, { start_row0 + 1, start_col0 })
vim.cmd('normal! v')
if node:parent() then
api.nvim_win_set_cursor(0, { end_row0 + 1, end_col0 - 1 })
else
-- It is the root node, so avoid setting the cursor position outside of
-- buffer.
vim.cmd('normal! G$h')
end
end
vim.keymap.set({ 'x', 'o' }, 'n', function() node_motion() end)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment