local M = {} --- -- Validate that `search_lines` matches exactly once in `buffer_lines`. -- Returns the start index (1-based) and end index (inclusive) of the match, -- or errors if there is not exactly one match. local function find_exact_match(buffer_lines, search_lines) local search_text = table.concat(search_lines, "\n") local matches = {} local search_len = #search_lines for i = 1, #buffer_lines - search_len + 1 do local candidate = table.concat(vim.list_slice(buffer_lines, i, i + search_len - 1), "\n") if candidate == search_text then table.insert(matches, { start = i, end_ = i + search_len - 1 }) end end if #matches == 0 then error("search text not found in buffer") elseif #matches > 1 then error("search text matches multiple times") end return matches[1].start, matches[1].end_ end --- -- Insert `lines` before the lines matched by `search_lines`. -- Returns a new table of lines with the insertion applied. -- Errors if `search_lines` does not match exactly once. function M.insert_before(buffer_lines, search_lines, insert_lines) local start, end_ = find_exact_match(buffer_lines, search_lines) local result = {} for i = 1, start - 1 do table.insert(result, buffer_lines[i]) end for _, line in ipairs(insert_lines) do table.insert(result, line) end for i = start, #buffer_lines do table.insert(result, buffer_lines[i]) end return result end --- -- Append `lines` after the lines matched by `search_lines`. -- Returns a new table of lines with the append applied. -- Errors if `search_lines` does not match exactly once. function M.append_after(buffer_lines, search_lines, append_lines) local start, end_ = find_exact_match(buffer_lines, search_lines) local result = {} for i = 1, end_ do table.insert(result, buffer_lines[i]) end for _, line in ipairs(append_lines) do table.insert(result, line) end for i = end_ + 1, #buffer_lines do table.insert(result, buffer_lines[i]) end return result end --- -- Replace the lines matched by `search_lines` with `replace_lines`. -- Returns a new table of lines with the replacement applied. -- Errors if `search_lines` does not match exactly once. function M.replace(buffer_lines, search_lines, replace_lines) local start, end_ = find_exact_match(buffer_lines, search_lines) local result = {} for i = 1, start - 1 do table.insert(result, buffer_lines[i]) end for _, line in ipairs(replace_lines) do table.insert(result, line) end for i = end_ + 1, #buffer_lines do table.insert(result, buffer_lines[i]) end return result end return M