feat: add conditional spellchecking feature

This commit is contained in:
2024-10-08 04:24:53 -04:00
parent a3f83ecb1f
commit 8e12606aed
+245
View File
@@ -1258,5 +1258,250 @@ function M.mc_statusline()
return status
end
--- Configure conditional spellchecking
---@function This function conditionally enables spellcheck based on the provided parameters.
---@param spellcheck? boolean Whether to enable spellcheck (default: true)
---@param filetypes? table|boolean A list of filetypes to enable/disable spellcheck in
--- (default: nil)
--- - If true, toggle spellcheck for all filetypes
--- - If false, enable spellcheck for the current buffer
--- - If a table, enable spellcheck for the specified filetypes
--- - If nil, enable spellcheck for the current buffer
---@return nil
function M.spellcheck(spellcheck, filetypes)
-- Default to true if spellcheck is not provided
spellcheck = spellcheck == nil and true or spellcheck
-- Set up local toggler
local function toggle()
-- Handle local spellchecking
if spellcheck then -- Enable spellcheck for the current buffer
vim.opt_local.spell = true
else -- Disable spellcheck for the current buffer
vim.opt_local.spell = false
end
end
-- Handle filetype-specific spellchecking
if filetypes then
-- Set up description text
local desc = "Enable"
if not spellcheck then
desc = "Disable"
end
-- Make a comma-separated list of filetypes
local typedesc
if type(filetypes) == "table" then
typedesc = table.concat(filetypes, ",")
else -- Fallback to a string
typedesc = tostring(filetypes)
end
-- If filetypes is a boolean
if filetypes == true then
filetypes = { "*" } -- Apply to all filetypes
elseif filetypes == false then
toggle()
end
-- Create an autocommand for the specified filetypes to manage spellcheck
vim.api.nvim_create_autocmd("FileType", {
group = "Spellcheck",
pattern = filetypes,
callback = function()
vim.opt_local.spell = spellcheck
end,
desc = desc .. " spellcheck for " .. typedesc,
})
else
-- Handle local spellchecking
toggle()
end
end
---@function This function swaps the behavior of `p` and `P`
---@param default? boolean Whether to use the default behavior (default: true)
--- - true: swap the behavior of `p` and `P`
--- - false: revert the behavior of `p` and `P`
---@return nil
function M.swap_paste(default)
if default == nil then
default = true
end
if default then
-- Mapping to swap the behavior of `p` and `P`
-- `p` will now paste before the cursor (originally `P`)
-- `P` will now paste after the cursor (originally `p`)
-- Preserve the original actions of `p` and `P` using Vim commands to avoid interference
-- Set `p` to the original paste after cursor
vim.api.nvim_set_keymap("n", "p", '"_dP', { noremap = true, silent = true })
-- Set `P` to the original paste before cursor
vim.api.nvim_set_keymap(
"n",
"P",
'"_d"0p',
{ noremap = true, silent = true }
)
else
-- Mapping to revert the behavior of `p` and `P` to their original functions
-- `p` will now revert to pasting after the cursor (original behavior)
-- `P` will now revert to pasting before the cursor (original behavior)
-- Remap `p` to its original behavior
vim.api.nvim_set_keymap("n", "p", "p", { noremap = true, silent = true })
-- Remap `P` to its original behavior
vim.api.nvim_set_keymap("n", "P", "P", { noremap = true, silent = true })
end
end
---@function This function extracts text between two marked positions in a buffer,
--- removes empty lines, and trims indentation from the left.
---@return string? text The extracted and trimmed text
--- - nil if there is no text in the specified range
--- - string if the text is in the specified range
function M.trim_yank()
-- Execute the last command in normal mode
vim.cmd.normal("!<Esc>")
-- Get the start and finish positions of the selected text
local start = vim.fn.getpos("'<")
local finish = vim.fn.getpos("'>")
-- Get the lines in the specified range
local lines = vim.fn.getline(start[2], finish[2])
-- Ensure lines is a table even if only one line is selected
if type(lines) == "string" then
lines = { lines }
end
-- Drop empty lines from the selection
for i = #lines, 1, -1 do
if lines[i] == "" then
table.remove(lines, i)
end
end
-- Return early if there are no lines to process
if #lines == 0 then
return
end
-- Find the minimum whitespace (indentation) in the selected lines
local ws = 9999
for _, line in ipairs(lines) do
local lws = line:match("^%s*") -- Extract leading whitespace
if lws and #lws < ws then
ws = #lws
end
end
-- Trim the leading whitespace from each line according to the minimal whitespace found
for i, line in ipairs(lines) do
lines[i] = line:sub(ws + 1)
end
-- Return the resulting lines as a single concatenated string
return table.concat(lines, "\n")
end
---@function Function to open the lazygit popup in a floaterm
---@return nil
function M.open_lazygit_popup()
-- Set floaterm border characters
vim.g.floaterm_borderchars = "─│─│╭╮╯╰"
-- Floaterm configuration properties
local floaterm_props = {
width = "0.98", -- Width of the floaterm
height = "0.95", -- Height of the floaterm
autoclose = "1", -- Auto close the floaterm when finished
command = "lazygit", -- Command to run in the floaterm
name = "LazyGit", -- Name of the floaterm
title = "LazyGit", -- Title of the floaterm
titlepos = "center", -- Title position of the floaterm
}
-- Construct the command string for opening the floaterm with the specified settings
local cmd = string.format(
"FloatermNew --height=%s --width=%s --name=%s --title=%s --titleposition=%s --autoclose=%s %s",
floaterm_props.height,
floaterm_props.width,
floaterm_props.name,
floaterm_props.title,
floaterm_props.titlepos,
floaterm_props.autoclose,
floaterm_props.command
)
-- Execute the command
vim.cmd(cmd) -- Using vim.cmd to run the constructed command
-- Enter insert mode in the floaterm
vim.cmd("startinsert")
end
---@function Function to replace '...' with '…' (ellipsis)
---@return boolean condition true if the replacement was successful, false otherwise
function M.replace_ellipsis()
-- Get the current line and the cursor position
local current_line = vim.api.nvim_get_current_line()
local cursor_pos = vim.api.nvim_win_get_cursor(0) -- Get the current cursor position
-- Check if the current line ends with '...'
if current_line:sub(cursor_pos[2] - 2, cursor_pos[2]) == "..." then
-- Replace '...' with '…' using string manipulation
local new_line = current_line:sub(1, cursor_pos[2] - 3) .. ""
-- Set the new line content
vim.api.nvim_set_current_line(new_line)
-- Move cursor to the new position after replacing
vim.api.nvim_win_set_cursor(0, { cursor_pos[1], cursor_pos[2] - 2 }) -- Adjust cursor position
return true
end
return false
end
---@function Function to automate replacing '...' with '…' (ellipsis)
---@param enable? boolean whether to enable the replacement on InsertLeave
---@return boolean result true if the replacement was enabled, false otherwise
function M.setup_replace_ellipsis(enable)
if enable == nil then
enable = true
end
-- Create an autogroup to handle the autocmds
vim.api.nvim_create_augroup("EllipsisReplace", { clear = true })
if enable then
vim.api.nvim_create_autocmd("InsertLeave", {
group = "EllipsisReplace",
callback = M.replace_ellipsis,
})
-- Optionally, you could call the function on text change as well
vim.api.nvim_create_autocmd("TextChangedI", {
group = "EllipsisReplace",
callback = M.replace_ellipsis,
})
return true
else
-- Remove the autocmds
vim.api.nvim_del_augroup_by_id(
vim.api.nvim_create_augroup("EllipsisReplace", { clear = true })
)
end
return false
end
-- Export the module
return M