Files
nixfiles/home/apps/nvim/lua/multiline/init.lua
2025-12-17 21:43:32 +05:00

211 lines
5.4 KiB
Lua

local M = {}
M.setup = function(opts)
M.max_new_lines = opts.max_new_lines or 1000
M.keep_existing = opts.keep_existing or true
M.void_bounds = opts.void_bounds or true
end
M.nlines = function(count)
-- Please, tell me there is a better way
local output = {}
for _ = 1, count do
table.insert(output, "")
end
return output
end
M.remove_surround = function()
local line = vim.api.nvim_win_get_cursor(0)[1]
local lines = vim.api.nvim_buf_line_count(0)
local count = math.max(1, vim.v.count)
-- Bottom pad
local delete_bottom = 0
for _ = 1, count do
local delete_line = line + delete_bottom
if delete_line == lines then
break
end
local next_line = vim.api.nvim_buf_get_lines(0, delete_line, delete_line + 1, false)[1]
if vim.trim(next_line) ~= "" then
break
end
delete_bottom = delete_bottom + 1
end
vim.api.nvim_buf_set_lines(0, line, line + delete_bottom, false, {})
-- Top pad
local delete_top = 0
for _ = 1, count do
local delete_line = line - delete_top
if delete_line == 1 then
break
end
local prev_line = vim.api.nvim_buf_get_lines(0, delete_line - 2, delete_line - 1, false)[1]
if vim.trim(prev_line) ~= "" then
break
end
delete_top = delete_top + 1
end
vim.api.nvim_buf_set_lines(0, line - delete_top - 1, line - 1, false, {})
end
M.remove_all_surround = function()
local line = vim.api.nvim_win_get_cursor(0)[1]
local lines = vim.api.nvim_buf_line_count(0)
-- Bottom pad
local delete_bottom = 0
while true do
local delete_line = line + delete_bottom
if delete_line == lines then
break
end
local next_line = vim.api.nvim_buf_get_lines(0, delete_line, delete_line + 1, false)[1]
if vim.trim(next_line) ~= "" then
break
end
delete_bottom = delete_bottom + 1
end
vim.api.nvim_buf_set_lines(0, line, line + delete_bottom, false, {})
-- Top pad
local delete_top = 0
while true do
local delete_line = line - delete_top
if delete_line == 1 then
break
end
local prev_line = vim.api.nvim_buf_get_lines(0, delete_line - 2, delete_line - 1, false)[1]
if vim.trim(prev_line) ~= "" then
break
end
delete_top = delete_top + 1
end
vim.api.nvim_buf_set_lines(0, line - delete_top - 1, line - 1, false, {})
end
M.surround_newlines = function(input)
return function()
local line = vim.api.nvim_win_get_cursor(0)[1]
local lines = vim.api.nvim_buf_line_count(0)
local count = math.min(math.max(1, vim.v.count), M.max_new_lines)
-- Bottom pad
local add_bottom = count
if M.keep_existing then
for i = 1, count do
if line + i - 1 == lines then
if M.void_bounds then
add_bottom = 0
end
break
end
local next_line = vim.api.nvim_buf_get_lines(0, line + i - 1, line + i, false)[1]
if vim.trim(next_line) == "" then
add_bottom = add_bottom - 1
else
break
end
end
end
vim.api.nvim_buf_set_lines(0, line, line, false, M.nlines(add_bottom))
-- Top pad
local add_top = count
if M.keep_existing then
for i = 1, count do
if line - i + 1 == 1 then
if M.void_bounds then
add_top = 0
end
break
end
local prev_line = vim.api.nvim_buf_get_lines(0, line - i - 1, line - i, false)[1]
if vim.trim(prev_line) == "" then
add_top = add_top - 1
else
break
end
end
end
vim.api.nvim_buf_set_lines(0, line - 1, line - 1, false, M.nlines(add_top))
if input ~= "" then
vim.api.nvim_input(input)
end
end
end
M.next_surround = function(input)
return function()
local line = vim.api.nvim_win_get_cursor(0)[1]
local count = math.min(math.max(1, vim.v.count), M.max_new_lines)
vim.api.nvim_buf_set_lines(0, line, line, false, M.nlines(count))
vim.api.nvim_win_set_cursor(0, { line + count, 0 })
if input ~= "" then
vim.api.nvim_input(input)
end
end
end
M.prev_surround = function(input)
return function()
local line = vim.api.nvim_win_get_cursor(0)[1]
local count = math.min(math.max(1, vim.v.count), M.max_new_lines)
vim.api.nvim_buf_set_lines(0, line - 1, line - 1, false, M.nlines(count))
vim.api.nvim_win_set_cursor(0, { line, 0 })
if input ~= "" then
vim.api.nvim_input(input)
end
end
end
M.set_surround = function()
M.remove_all_surround()
M.surround_newlines("")()
end
-- Breaking lines with whitespace is a bit wonky but I don't care
M.break_into_lines = function()
local v_start = vim.fn.getpos("v")
local v_end = vim.fn.getpos(".")
if (v_end[2] < v_start[2]) or (v_end[2] == v_start[2] and v_end[3] < v_start[3]) then
v_start, v_end = v_end, v_start
end
-- End split
local end_line = vim.api.nvim_buf_get_lines(0, v_end[2] - 1, v_end[2], false)[1]
if v_end[3] < #end_line then
local line_start = end_line:sub(1, v_end[3]):gsub("%s+$", "")
local line_end = end_line:sub(v_end[3] + 1):gsub("^%s+", "")
local pad = line_start:match("^%s+") or ""
vim.api.nvim_buf_set_lines(0, v_end[2] - 1, v_end[2], false, {
line_start,
pad .. line_end
})
end
-- Start split
local start_line = vim.api.nvim_buf_get_lines(0, v_start[2] - 1, v_start[2], false)[1]
if v_start[3] > 1 then
local line_start = start_line:sub(1, v_start[3] - 1):gsub("%s+$", "")
local line_end = start_line:sub(v_start[3]):gsub("^%s+", "")
local pad = line_start:match("^%s+") or ""
vim.api.nvim_buf_set_lines(0, v_end[2] - 1, v_end[2], false, {
line_start,
pad .. line_end
})
vim.api.nvim_win_set_cursor(0, { v_start[2] + 1, vim.v.maxcol })
else
vim.api.nvim_win_set_cursor(0, { v_start[2], vim.v.maxcol })
end
vim.api.nvim_input("<Esc>>>")
end
return M