summaryrefslogtreecommitdiffstats
path: root/lua/dotfiles/selection.lua
blob: 33f45b2ce7798636f9ffc9959431a82779c72e3a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
-- Apply transformations to the visual selection. The mechanics are generic: read the selected
-- text, delete it, and put the transformed result in its place. Features wire specific transforms
-- to keymaps in plugin/50-transform_text.lua.
--
-- API:
--   transform(fn) — replace the selection with fn(selected_text)

local M = {}

-- The visually selected text, joined with newlines. Reads the live selection straight from the
-- 'v'/'.' marks, so it must be called while the selection is still active.
local function get_text()
	return table.concat(
		vim.fn.getregion(vim.fn.getpos("v"), vim.fn.getpos("."), { type = vim.fn.mode() }),
		"\n"
	)
end

-- Delete the visual selection from the current buffer. getregionpos gives 1-based rows and 1-based
-- inclusive columns; in charwise 'v' the region's own end is exact, but in other modes we fall back
-- to the further of the two marks. nvim_buf_set_text wants 0-based rows and an end-exclusive col,
-- hence the -1 / +0 adjustments.
local function delete()
	local mode = vim.fn.mode()
	local eovisual_pos, cur_pos = vim.fn.getpos("v"), vim.fn.getpos(".")
	local region = vim.fn.getregionpos(eovisual_pos, cur_pos, { type = mode })[1]
	local start_row, start_col = unpack(region[1], 2, 3)
	local end_row, end_col =
		mode == "v" and region[2][2] or math.max(eovisual_pos[2], cur_pos[2]), region[2][3]
	vim.api.nvim_buf_set_text(0, start_row - 1, start_col - 1, end_row - 1, end_col, {})
end

-- Replace the visual selection with fn(selected_text): grab the text, delete it, then put the
-- transformed string where it was.
function M.transform(fn)
	local text = get_text()
	delete()
	vim.api.nvim_put({ fn(text) }, "c", true, true)
end

return M