Initial commit
This commit is contained in:
commit
056d3e901e
2 changed files with 143 additions and 0 deletions
129
lua/jquote/init.lua
Normal file
129
lua/jquote/init.lua
Normal file
|
@ -0,0 +1,129 @@
|
||||||
|
local M = {}
|
||||||
|
|
||||||
|
M.options = {
|
||||||
|
hotkey = "<leader>tq",
|
||||||
|
quote_chars = { "'", '"', "`" },
|
||||||
|
}
|
||||||
|
|
||||||
|
---Merges user-provided options with default options.
|
||||||
|
---@param user_options table|nil User-provided options
|
||||||
|
function M.setup(user_options)
|
||||||
|
if user_options and type(user_options) == "table" then
|
||||||
|
for k, v in pairs(user_options) do
|
||||||
|
M.options[k] = v
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Checks if a given character is one of the predefined quote characters.
|
||||||
|
--- @param char string The character to check.
|
||||||
|
--- @return boolean true if the character is a quote character, false otherwise.
|
||||||
|
local function is_defined_quote_char(char)
|
||||||
|
for _, qc in ipairs(M.quote_chars) do
|
||||||
|
if char == qc then
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Finds the starting and ending indices of a quoted string on the current line
|
||||||
|
--- that contains the cursor, using a predefined set of quote characters.
|
||||||
|
--- @param line string The current line of text.
|
||||||
|
--- @param cursor_col number The column index of the cursor (0-based).
|
||||||
|
--- @return number start_index The 0-based starting index of the quote, or -1 if not found.
|
||||||
|
--- @return number end_index The 0-based ending index of the quote, or -1 if not found.
|
||||||
|
--- @return string current_quote_char The character of the identified quote, or nil.
|
||||||
|
local function find_quoted_string_at_cursor(line, cursor_col)
|
||||||
|
local start_quote_index = -1
|
||||||
|
local end_quote_index = -1
|
||||||
|
local current_quote_char = nil
|
||||||
|
|
||||||
|
-- Iterate through the line to find a matching pair of quotes that contain the cursor.
|
||||||
|
for i = 0, #line - 1 do
|
||||||
|
local char = line:sub(i + 1, i + 1)
|
||||||
|
|
||||||
|
if not is_defined_quote_char(char) then
|
||||||
|
goto continue_loop -- Not a quote character, skip.
|
||||||
|
end
|
||||||
|
|
||||||
|
-- If we haven't found an opening quote yet, this is a potential candidate.
|
||||||
|
if start_quote_index == -1 then
|
||||||
|
start_quote_index = i
|
||||||
|
current_quote_char = char
|
||||||
|
elseif char == current_quote_char then
|
||||||
|
-- Found a closing quote that matches the current opening quote.
|
||||||
|
end_quote_index = i
|
||||||
|
|
||||||
|
-- Check if the cursor is within this identified quoted string (inclusive of quotes).
|
||||||
|
if (cursor_col >= start_quote_index and cursor_col <= end_quote_index) or (cursor_col <= start_quote_index and cursor_col <= end_quote_index) then
|
||||||
|
return start_quote_index, end_quote_index, current_quote_char
|
||||||
|
else
|
||||||
|
-- Cursor is not in this string, reset to look for the next potential string.
|
||||||
|
start_quote_index = -1
|
||||||
|
end_quote_index = -1
|
||||||
|
current_quote_char = nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
::continue_loop::
|
||||||
|
end
|
||||||
|
|
||||||
|
-- No relevant quoted string found that contains the cursor.
|
||||||
|
return -1, -1, nil
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Cycles to the next quote character in the predefined list.
|
||||||
|
--- @param current_char string The current quote character.
|
||||||
|
--- @return string The next quote character, or nil if current_char is not found.
|
||||||
|
local function get_next_quote_char(current_char)
|
||||||
|
local current_char_list_index = -1
|
||||||
|
for i, qc in ipairs(M.quote_chars) do
|
||||||
|
if qc == current_char then
|
||||||
|
current_char_list_index = i
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if current_char_list_index == -1 then
|
||||||
|
return nil -- Current character not in our defined list.
|
||||||
|
end
|
||||||
|
|
||||||
|
local next_char_list_index = (current_char_list_index % #M.quote_chars) + 1
|
||||||
|
return M.quote_chars[next_char_list_index]
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Toggles the quotes around the string at the cursor position
|
||||||
|
--- by cycling through a predefined list of quote characters.
|
||||||
|
function M.toggle_quotes()
|
||||||
|
local current_line = vim.api.nvim_get_current_line()
|
||||||
|
local cursor_row, cursor_col = unpack(vim.api.nvim_win_get_cursor(0))
|
||||||
|
|
||||||
|
local start_idx, end_idx, current_char =
|
||||||
|
find_quoted_string_at_cursor(current_line, cursor_col)
|
||||||
|
|
||||||
|
-- If no quoted string containing the cursor was found, do nothing.
|
||||||
|
if start_idx == -1 or end_idx == -1 or not current_char then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
local next_char = get_next_quote_char(current_char)
|
||||||
|
if not next_char then
|
||||||
|
-- This should ideally not happen if current_char came from find_quoted_string_at_cursor
|
||||||
|
-- and QUOTE_CHARS is consistent, but acts as a safeguard.
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Reconstruct the line with the new quote characters.
|
||||||
|
local new_line =
|
||||||
|
current_line:sub(1, start_idx) ..
|
||||||
|
next_char ..
|
||||||
|
current_line:sub(start_idx + 2, end_idx) ..
|
||||||
|
next_char ..
|
||||||
|
current_line:sub(end_idx + 2)
|
||||||
|
|
||||||
|
-- Update Neovim's buffer and cursor position.
|
||||||
|
vim.api.nvim_set_current_line(new_line)
|
||||||
|
vim.api.nvim_win_set_cursor(0, { cursor_row, cursor_col })
|
||||||
|
end
|
||||||
|
|
||||||
|
return M
|
14
plugin/jquote.lua
Normal file
14
plugin/jquote.lua
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
if vim.g.jquote_loaded then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
vim.g.jquote_loaded = true
|
||||||
|
|
||||||
|
local jquote = require("jquote")
|
||||||
|
|
||||||
|
local map_opts = {
|
||||||
|
desc = "Swaps the quotes around",
|
||||||
|
silent = true,
|
||||||
|
noremap = true,
|
||||||
|
}
|
||||||
|
|
||||||
|
vim.keymap.set("n", jquote.options.hotkey, jquote.toggle_quotes, map_opts)
|
Loading…
Add table
Add a link
Reference in a new issue