-- 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