mirror of
https://github.com/nvim-treesitter/nvim-treesitter.git
synced 2026-07-18 11:20:07 -04:00
Textobjects: set jump before going to adjacent_textobject
This commit is contained in:
parent
f3ed370643
commit
32271b26ef
4 changed files with 88 additions and 88 deletions
|
|
@ -1,6 +1,7 @@
|
||||||
-- Definition based navigation module
|
-- Definition based navigation module
|
||||||
|
|
||||||
local ts_utils = require'nvim-treesitter.ts_utils'
|
local ts_utils = require'nvim-treesitter.ts_utils'
|
||||||
|
local utils = require'nvim-treesitter.utils'
|
||||||
local locals = require'nvim-treesitter.locals'
|
local locals = require'nvim-treesitter.locals'
|
||||||
local configs = require'nvim-treesitter.configs'
|
local configs = require'nvim-treesitter.configs'
|
||||||
local api = vim.api
|
local api = vim.api
|
||||||
|
|
@ -11,8 +12,7 @@ function M.goto_definition(bufnr)
|
||||||
local bufnr = bufnr or api.nvim_get_current_buf()
|
local bufnr = bufnr or api.nvim_get_current_buf()
|
||||||
local node_at_point = ts_utils.get_node_at_cursor()
|
local node_at_point = ts_utils.get_node_at_cursor()
|
||||||
|
|
||||||
-- Set the item in jump list
|
utils.set_jump()
|
||||||
vim.cmd "normal! m'"
|
|
||||||
|
|
||||||
if not node_at_point then return end
|
if not node_at_point then return end
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@ local configs = require "nvim-treesitter.configs"
|
||||||
local parsers = require "nvim-treesitter.parsers"
|
local parsers = require "nvim-treesitter.parsers"
|
||||||
local queries = require'nvim-treesitter.query'
|
local queries = require'nvim-treesitter.query'
|
||||||
local ts_utils = require'nvim-treesitter.ts_utils'
|
local ts_utils = require'nvim-treesitter.ts_utils'
|
||||||
|
local utils = require'nvim-treesitter.utils'
|
||||||
|
|
||||||
local M = {}
|
local M = {}
|
||||||
|
|
||||||
|
|
@ -80,63 +81,11 @@ function M.select_textobject(query_string)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
local function swap_textobject(query_string, direction)
|
local function get_adjacent(forward, node, query_string, same_parent, overlapping_range_ok, bufnr)
|
||||||
local bufnr, textobject_range, node = textobject_at_point(query_string)
|
local fn = forward and M.next_textobject or M.previous_textobject
|
||||||
local step = direction > 0 and 1 or -1
|
return fn(node, query_string, same_parent, overlapping_range_ok, bufnr)
|
||||||
if not node then return end
|
|
||||||
local overlapping_range_ok = false
|
|
||||||
local same_parent = true
|
|
||||||
for _ = 1, math.abs(direction), step do
|
|
||||||
if direction > 0 then
|
|
||||||
ts_utils.swap_nodes(textobject_range,
|
|
||||||
M.next_textobject(node, query_string, same_parent, overlapping_range_ok, bufnr),
|
|
||||||
bufnr,
|
|
||||||
"yes, set cursor!")
|
|
||||||
else
|
|
||||||
ts_utils.swap_nodes(textobject_range,
|
|
||||||
M.previous_textobject(node, query_string, same_parent, overlapping_range_ok, bufnr),
|
|
||||||
bufnr,
|
|
||||||
"yes, set cursor!")
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
function M.swap_next(query_string)
|
|
||||||
swap_textobject(query_string, 1)
|
|
||||||
end
|
|
||||||
|
|
||||||
function M.swap_previous(query_string)
|
|
||||||
swap_textobject(query_string, -1)
|
|
||||||
end
|
|
||||||
|
|
||||||
function M.goto_adjacent(query_string, forward, start, same_parent, overlapping_range_ok)
|
|
||||||
local bufnr, _, node = textobject_at_point(query_string)
|
|
||||||
local adjacent_textobject
|
|
||||||
if forward then
|
|
||||||
adjacent_textobject = M.next_textobject(node, query_string, same_parent, overlapping_range_ok, bufnr)
|
|
||||||
else
|
|
||||||
adjacent_textobject = M.previous_textobject(node, query_string, same_parent, overlapping_range_ok, bufnr)
|
|
||||||
end
|
|
||||||
|
|
||||||
if adjacent_textobject then
|
|
||||||
local adjacent_textobject_range = {adjacent_textobject:range()}
|
|
||||||
if start then
|
|
||||||
api.nvim_win_set_cursor(api.nvim_get_current_win(),
|
|
||||||
{ adjacent_textobject_range[1] + 1, adjacent_textobject_range[2] })
|
|
||||||
else
|
|
||||||
api.nvim_win_set_cursor(api.nvim_get_current_win(),
|
|
||||||
{ adjacent_textobject_range[3] + 1, adjacent_textobject_range[4] })
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
-- luacheck: push ignore 631
|
|
||||||
M.goto_next_start = function(query_string) M.goto_adjacent(query_string, 'forward', 'start', not 'same_parent', 'overlap ok') end
|
|
||||||
M.goto_next_end = function(query_string) M.goto_adjacent(query_string, 'forward', not 'start', not 'same_parent', 'overlap ok') end
|
|
||||||
M.goto_previous_start = function(query_string) M.goto_adjacent(query_string, not 'forward', 'start', not 'same_parent', 'overlap ok') end
|
|
||||||
M.goto_previous_end = function(query_string) M.goto_adjacent(query_string, not 'forward', not 'start', not 'same_parent', 'overlap ok') end
|
|
||||||
-- luacheck: pop
|
|
||||||
|
|
||||||
function M.next_textobject(node, query_string, same_parent, overlapping_range_ok, bufnr)
|
function M.next_textobject(node, query_string, same_parent, overlapping_range_ok, bufnr)
|
||||||
local node = node or ts_utils.get_node_at_cursor()
|
local node = node or ts_utils.get_node_at_cursor()
|
||||||
local bufnr = bufnr or api.nvim_get_current_buf()
|
local bufnr = bufnr or api.nvim_get_current_buf()
|
||||||
|
|
@ -149,22 +98,20 @@ function M.next_textobject(node, query_string, same_parent, overlapping_range_ok
|
||||||
else
|
else
|
||||||
_, _, search_start = node:end_()
|
_, _, search_start = node:end_()
|
||||||
end
|
end
|
||||||
|
local function scoring_function(match)
|
||||||
|
if match.node == node then return end
|
||||||
|
if not same_parent or node:parent() == match.node:parent() then
|
||||||
|
local _, _, start = match.node:start()
|
||||||
|
local _, _, end_ = match.node:end_()
|
||||||
|
return start > search_start and end_ >= node_end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
local function filter_function(match)
|
||||||
|
local _, _, node_start = match.node:start()
|
||||||
|
return -node_start
|
||||||
|
end
|
||||||
|
|
||||||
local next_node = queries.find_best_match(bufnr,
|
local next_node = queries.find_best_match(bufnr, query_string, 'textobjects', scoring_function, filter_function)
|
||||||
query_string,
|
|
||||||
'textobjects',
|
|
||||||
function(match)
|
|
||||||
if match.node == node then return end
|
|
||||||
if not same_parent or node:parent() == match.node:parent() then
|
|
||||||
local _, _, start = match.node:start()
|
|
||||||
local _, _, end_ = match.node:end_()
|
|
||||||
return start > search_start and end_ >= node_end
|
|
||||||
end
|
|
||||||
end,
|
|
||||||
function(match)
|
|
||||||
local _, _, node_start = match.node:start()
|
|
||||||
return -node_start
|
|
||||||
end)
|
|
||||||
|
|
||||||
return next_node and next_node.node
|
return next_node and next_node.node
|
||||||
end
|
end
|
||||||
|
|
@ -182,24 +129,73 @@ function M.previous_textobject(node, query_string, same_parent, overlapping_rang
|
||||||
else
|
else
|
||||||
_, _, search_end = node:start()
|
_, _, search_end = node:start()
|
||||||
end
|
end
|
||||||
local previous_node = queries.find_best_match(bufnr,
|
|
||||||
query_string,
|
local function scoring_function(match)
|
||||||
'textobjects',
|
if not same_parent or node:parent() == match.node:parent() then
|
||||||
function(match)
|
local _, _, end_ = match.node:end_()
|
||||||
if not same_parent or node:parent() == match.node:parent() then
|
local _, _, start = match.node:start()
|
||||||
local _, _, end_ = match.node:end_()
|
return end_ < search_end and start < node_start
|
||||||
local _, _, start = match.node:start()
|
end
|
||||||
return end_ < search_end and start < node_start
|
end
|
||||||
end
|
|
||||||
end,
|
local function filter_function(match)
|
||||||
function(match)
|
local _, _, node_end = match.node:end_()
|
||||||
local _, _, node_end = match.node:end_()
|
return node_end
|
||||||
return node_end
|
end
|
||||||
end)
|
|
||||||
|
local previous_node = queries.find_best_match(bufnr, query_string, 'textobjects', scoring_function, filter_function)
|
||||||
|
|
||||||
return previous_node and previous_node.node
|
return previous_node and previous_node.node
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function M.goto_adjacent(query_string, forward, start, same_parent, overlapping_range_ok)
|
||||||
|
local bufnr, _, node = textobject_at_point(query_string)
|
||||||
|
local adjacent_textobject = get_adjacent(forward, node, query_string, same_parent, overlapping_range_ok, bufnr)
|
||||||
|
|
||||||
|
if adjacent_textobject then
|
||||||
|
utils.set_jump()
|
||||||
|
|
||||||
|
local adjacent_textobject_range = {adjacent_textobject:range()}
|
||||||
|
local position
|
||||||
|
if start then
|
||||||
|
position = { adjacent_textobject_range[1] + 1, adjacent_textobject_range[2] }
|
||||||
|
else
|
||||||
|
position = { adjacent_textobject_range[3] + 1, adjacent_textobject_range[4] }
|
||||||
|
end
|
||||||
|
api.nvim_win_set_cursor(api.nvim_get_current_win(), position)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local function swap_textobject(query_string, direction)
|
||||||
|
local bufnr, textobject_range, node = textobject_at_point(query_string)
|
||||||
|
if not node then return end
|
||||||
|
|
||||||
|
local step = direction > 0 and 1 or -1
|
||||||
|
local overlapping_range_ok = false
|
||||||
|
local same_parent = true
|
||||||
|
for _ = 1, math.abs(direction), step do
|
||||||
|
local forward = direction > 0
|
||||||
|
local adjacent_textobject = get_adjacent(forward, node, query_string, same_parent, overlapping_range_ok, bufnr)
|
||||||
|
ts_utils.swap_nodes(textobject_range, adjacent_textobject, bufnr, "yes, set cursor!")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function M.swap_next(query_string)
|
||||||
|
swap_textobject(query_string, 1)
|
||||||
|
end
|
||||||
|
|
||||||
|
function M.swap_previous(query_string)
|
||||||
|
swap_textobject(query_string, -1)
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
-- luacheck: push ignore 631
|
||||||
|
M.goto_next_start = function(query_string) M.goto_adjacent(query_string, 'forward', 'start', not 'same_parent', 'overlap ok') end
|
||||||
|
M.goto_next_end = function(query_string) M.goto_adjacent(query_string, 'forward', not 'start', not 'same_parent', 'overlap ok') end
|
||||||
|
M.goto_previous_start = function(query_string) M.goto_adjacent(query_string, not 'forward', 'start', not 'same_parent', 'overlap ok') end
|
||||||
|
M.goto_previous_end = function(query_string) M.goto_adjacent(query_string, not 'forward', not 'start', not 'same_parent', 'overlap ok') end
|
||||||
|
-- luacheck: pop
|
||||||
|
|
||||||
local normal_mode_functions = { "swap_next",
|
local normal_mode_functions = { "swap_next",
|
||||||
"swap_previous",
|
"swap_previous",
|
||||||
"goto_next_start",
|
"goto_next_start",
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
local api = vim.api
|
local api = vim.api
|
||||||
|
|
||||||
local parsers = require'nvim-treesitter.parsers'
|
local parsers = require'nvim-treesitter.parsers'
|
||||||
|
local utils = require'nvim-treesitter.utils'
|
||||||
|
|
||||||
local M = {}
|
local M = {}
|
||||||
|
|
||||||
|
|
@ -241,8 +242,7 @@ function M.swap_nodes(node_or_range1, node_or_range2, bufnr, cursor_to_second)
|
||||||
vim.lsp.util.apply_text_edits({edit1, edit2}, bufnr)
|
vim.lsp.util.apply_text_edits({edit1, edit2}, bufnr)
|
||||||
|
|
||||||
if cursor_to_second then
|
if cursor_to_second then
|
||||||
-- Set the item in jump list
|
utils.set_jump()
|
||||||
vim.cmd "normal! m'"
|
|
||||||
|
|
||||||
local char_delta = 0
|
local char_delta = 0
|
||||||
local line_delta = 0
|
local line_delta = 0
|
||||||
|
|
|
||||||
|
|
@ -67,4 +67,8 @@ function M.print_warning(text)
|
||||||
api.nvim_command(string.format([[echohl WarningMsg | echo "%s" | echohl None]], text))
|
api.nvim_command(string.format([[echohl WarningMsg | echo "%s" | echohl None]], text))
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function M.set_jump()
|
||||||
|
vim.cmd "normal! m'"
|
||||||
|
end
|
||||||
|
|
||||||
return M
|
return M
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue