mirror of
https://github.com/SpaceVim/SpaceVim.git
synced 2025-02-03 01:00:05 +08:00
91 lines
3.7 KiB
Lua
91 lines
3.7 KiB
Lua
local buffer = require("nvim-surround.buffer")
|
|
local config = require("nvim-surround.config")
|
|
local functional = require("nvim-surround.functional")
|
|
|
|
local M = {}
|
|
|
|
-- Do nothing.
|
|
M.NOOP = function() end
|
|
|
|
-- Gets the nearest two selections for the left and right surrounding pair.
|
|
---@param char string|nil A character representing what kind of surrounding pair is to be selected.
|
|
---@param action "delete"|"change" A string representing what action is being performed.
|
|
---@return selections|nil @A table containing the start and end positions of the delimiters.
|
|
---@nodiscard
|
|
M.get_nearest_selections = function(char, action)
|
|
char = config.get_alias(char)
|
|
local chars = functional.to_list(config.get_opts().aliases[char] or char)
|
|
if not chars then
|
|
return nil
|
|
end
|
|
|
|
local curpos = buffer.get_curpos()
|
|
local winview = vim.fn.winsaveview()
|
|
local selections_list = {}
|
|
-- Iterate through all possible selections for each aliased character, and find the closest pair
|
|
for _, c in ipairs(chars) do
|
|
local cur_selections = (function()
|
|
if action == "change" then
|
|
return config.get_change(c).target(c)
|
|
else
|
|
return config.get_delete(c)(c)
|
|
end
|
|
end)()
|
|
-- If found, add the current selections to the list of all possible selections
|
|
if cur_selections then
|
|
selections_list[#selections_list + 1] = cur_selections
|
|
end
|
|
-- Reset the cursor position
|
|
buffer.set_curpos(curpos)
|
|
end
|
|
-- Reset the window view (in case some delimiters were off screen)
|
|
vim.fn.winrestview(winview)
|
|
|
|
local nearest_selections = M.filter_selections_list(selections_list)
|
|
return nearest_selections
|
|
end
|
|
|
|
-- Filters down a list of selections to the best one, based on the jumping heuristic.
|
|
---@param selections_list selections[] The given list of selections.
|
|
---@return selections|nil @The best selections from the list.
|
|
---@nodiscard
|
|
M.filter_selections_list = function(selections_list)
|
|
local curpos = buffer.get_curpos()
|
|
local best_selections
|
|
for _, cur_selections in ipairs(selections_list) do
|
|
if cur_selections then
|
|
best_selections = best_selections or cur_selections
|
|
if buffer.is_inside(curpos, best_selections) then
|
|
-- Handle case where the cursor is inside the nearest selections
|
|
if
|
|
buffer.is_inside(curpos, cur_selections)
|
|
and buffer.comes_before(best_selections.left.first_pos, cur_selections.left.first_pos)
|
|
and buffer.comes_before(cur_selections.right.last_pos, best_selections.right.last_pos)
|
|
then
|
|
best_selections = cur_selections
|
|
end
|
|
elseif buffer.comes_before(curpos, best_selections.left.first_pos) then
|
|
-- Handle case where the cursor comes before the nearest selections
|
|
if
|
|
buffer.is_inside(curpos, cur_selections)
|
|
or buffer.comes_before(curpos, cur_selections.left.first_pos)
|
|
and buffer.comes_before(cur_selections.left.first_pos, best_selections.left.first_pos)
|
|
then
|
|
best_selections = cur_selections
|
|
end
|
|
else
|
|
-- Handle case where the cursor comes after the nearest selections
|
|
if
|
|
buffer.is_inside(curpos, cur_selections)
|
|
or buffer.comes_before(best_selections.right.last_pos, cur_selections.right.last_pos)
|
|
then
|
|
best_selections = cur_selections
|
|
end
|
|
end
|
|
end
|
|
end
|
|
return best_selections
|
|
end
|
|
|
|
return M
|