+function M.get_visual_selection()
+ local _, start_row, start_col, _ = unpack(vim.fn.getpos("'<"))
+ local _, end_row, end_col, _ = unpack(vim.fn.getpos("'>"))
+
+ -- Ensure proper order
+ if start_row > end_row or (start_row == end_row and start_col > end_col) then
+ start_row, end_row = end_row, start_row
+ start_col, end_col = end_col, start_col
+ end
+
+ local lines = vim.api.nvim_buf_get_lines(0, start_row - 1, end_row, false)
+
+ if #lines == 0 then return "", {}, {} end
+
+ lines[1] = string.sub(lines[1], start_col)
+ if #lines > 1 then
+ lines[#lines] = string.sub(lines[#lines], 1, end_col)
+ else
+ lines[1] = string.sub(lines[1], 1, end_col - start_col + 1)
+ end
+
+ local selection = table.concat(lines, "\n")
+
+ local collections = {}
+ local delimiters = {}
+ local allHex = {}
+
+ for hex, delim in selection:gmatch("([0-9A-Fa-f]+)([^0-9A-Fa-f]*)") do
+ table.insert(collections, hex)
+ table.insert(allHex, hex)
+ if delim ~= "" and not selection:match(delim .. "$") then
+ table.insert(delimiters, delim)
+ end
+ end
+
+ if #collections > 1 then
+ table.insert(collections, table.concat(allHex))
+ end
+ return selection, collections, delimiters
+end
+