diff --git a/lua/hacker-helper.lua b/lua/hacker-helper.lua index 7e3d3d9..a5a2308 100644 --- a/lua/hacker-helper.lua +++ b/lua/hacker-helper.lua @@ -9,9 +9,9 @@ local function check_luasocket_installed() vim.log.levels.ERROR ) vim.notify("Hacker Helper Error: sudo apt install luarocks", vim.log.levels.ERROR) - return false + return nil end - return true + return mime end ---@class Config @@ -41,9 +41,10 @@ M.config = config ---@param user_config Config? User-provided configuration M.setup = function(user_config) -- Check if luasocket is installed - if not check_luasocket_installed() then + local mime = check_luasocket_installed() + if not mime then return - end + end -- Ensure LuaSocket is installed -- Merge user configuration with defaults M.config = vim.tbl_deep_extend("force", M.config, user_config or {}) @@ -59,131 +60,109 @@ M.setup = function(user_config) end, { noremap = true, silent = true, desc = "Execute Command" }) -- Register the group names for both encoding and decoding vim.keymap.set( - "n", + "v", M.config.prefix .. M.config.keys.encode_prefix, function() end, { noremap = true, silent = true, desc = "Encode" } ) vim.keymap.set( - "n", + "v", M.config.prefix .. M.config.keys.decode_prefix, function() end, { noremap = true, silent = true, desc = "Decoder" } ) - -- Encoding key mappings + -- Key mappings for encoding and decoding vim.keymap.set("v", M.config.prefix .. M.config.keys.encode_prefix .. M.config.keys.encode_url, function() - M.transform_selected_text("url", "encode") + M.transform_selection("url", "encode") end, { noremap = true, silent = true, desc = "URL Encode" }) vim.keymap.set("v", M.config.prefix .. M.config.keys.encode_prefix .. M.config.keys.encode_base64, function() - M.transform_selected_text("base64", "encode") + M.transform_selection("base64", "encode") end, { noremap = true, silent = true, desc = "Base64 Encode" }) - -- Decoding key mappings vim.keymap.set("v", M.config.prefix .. M.config.keys.decode_prefix .. M.config.keys.decode_url, function() - M.transform_selected_text("url", "decode") + M.transform_selection("url", "decode") end, { noremap = true, silent = true, desc = "URL Decode" }) vim.keymap.set("v", M.config.prefix .. M.config.keys.decode_prefix .. M.config.keys.decode_base64, function() - M.transform_selected_text("base64", "decode") + M.transform_selection("base64", "decode") end, { noremap = true, silent = true, desc = "Base64 Decode" }) end -- Function to handle encoding/decoding based on selection -M.transform_selected_text = function(type, mode) +M.transform_selection = function(type, mode) + local mime = check_luasocket_installed() + if not mime then + return + end -- Ensure LuaSocket is installed + + -- Capture the selection local start_pos = vim.fn.getpos("'<") local end_pos = vim.fn.getpos("'>") - local start_line, start_col = start_pos[2], start_pos[3] - 1 -- Convert to 0-based index - local end_line, end_col = end_pos[2], end_pos[3] - 1 -- Convert to 0-based index + + local start_line = start_pos[2] + local start_col = start_pos[3] - 1 -- 0-based index + + local end_line = end_pos[2] + local end_col = end_pos[3] -- inclusive -- Get selected lines local lines = vim.fn.getline(start_line, end_line) - -- If no lines were selected, return early - if not lines or #lines == 0 then - vim.notify("No lines selected for transformation.", vim.log.levels.ERROR) - return - end - - -- Handle full line selection - if start_col == 0 and end_col == -1 then - -- Full-line transformation - if type == "url" then - lines = M.transform_lines(lines, mode, "url") - elseif type == "base64" then - lines = M.transform_lines(lines, mode, "base64") + -- Handle full-line selection (V mode) and partial selection + if vim.fn.mode() == "V" then + -- Full line selection, transform entire lines + for i, line in ipairs(lines) do + lines[i] = M.transform_text(line, type, mode, mime) end - -- Replace all selected lines with the transformed lines + -- Replace the entire range with transformed lines vim.fn.setline(start_line, lines) else - -- Handle partial selection within a single line - if lines and lines[1] then + -- Partial selection within a single line + if start_line == end_line then + -- Handle partial selection on a single line local line = lines[1] - - -- Ensure end_col doesn't exceed line length - local line_len = #line - end_col = math.min(end_col, line_len) - - -- Get the selected portion local selection = string.sub(line, start_col + 1, end_col) - - -- If selection is nil or empty, return early - if not selection or selection == "" then - vim.notify("Invalid selection for transformation.", vim.log.levels.ERROR) - return - end - - local transformed = "" - - if type == "url" then - transformed = M.transform_text(selection, mode, "url") - elseif type == "base64" then - transformed = M.transform_text(selection, mode, "base64") - end - - -- Use `vim.api.nvim_buf_set_text` to replace the selected part - local bufnr = vim.api.nvim_get_current_buf() - vim.api.nvim_buf_set_text(bufnr, start_line - 1, start_col, start_line - 1, end_col, { transformed }) - - -- Optionally move cursor if you want it to behave similarly to the `c` command - vim.api.nvim_win_set_cursor(0, { start_line, start_col + #transformed }) + local transformed = M.transform_text(selection, type, mode, mime) + local new_line = string.sub(line, 1, start_col) .. transformed .. string.sub(line, end_col + 1) + vim.fn.setline(start_line, new_line) else - vim.notify("No valid line found for transformation.", vim.log.levels.ERROR) + -- Handle multi-line selection, applying the transformation to partial lines + lines[1] = string.sub(lines[1], 1, start_col) + .. M.transform_text(string.sub(lines[1], start_col + 1), type, mode, mime) + lines[#lines] = M.transform_text(string.sub(lines[#lines], 1, end_col), type, mode, mime) + .. string.sub(lines[#lines], end_col + 1) + for i = 2, #lines - 1 do + lines[i] = M.transform_text(lines[i], type, mode, mime) + end + -- Replace the entire range with transformed lines + vim.fn.setline(start_line, lines) end end end --- Function to transform lines for full-line selection -M.transform_lines = function(lines, mode, type) - local transformed_lines = {} - for _, line in ipairs(lines) do - if type == "url" then - table.insert(transformed_lines, M.transform_text(line, mode, "url")) - elseif type == "base64" then - table.insert(transformed_lines, M.transform_text(line, mode, "base64")) - end - end - return transformed_lines -end +M.transform_text = function(text, mode, type, mime) + mime = mime or require("mime") -- Ensure LuaSocket's mime module is loaded --- Function to transform individual text based on type and mode -M.transform_text = function(text, mode, type) - local mime = require("mime") if type == "url" then if mode == "encode" then return text:gsub("([^%w%.%-_])", function(c) return string.format("%%%02X", string.byte(c)) end) - else -- decode + elseif mode == "decode" then return text:gsub("%%(%x%x)", function(hex) return string.char(tonumber(hex, 16)) end) end elseif type == "base64" then if mode == "encode" then - return mime.b64(text) - else -- decode - return mime.unb64(text) + local encoded = mime.b64(text) -- Use only the first return value + return encoded + elseif mode == "decode" then + local decoded = mime.unb64(text) -- Use only the first return value + return decoded end end + + return text -- return the original text if no valid type or mode is provided end M.hello = function()