add lua-language-server types; fix comment logic

This commit is contained in:
raf 2025-03-05 04:12:40 +03:00
commit b4cd8ff197
Signed by: NotAShelf
GPG key ID: 29D95B64378DB4BF

View file

@ -1,20 +1,25 @@
---@class GaslightingConfig
---@field gaslighting_chance number -- Percentage chance that a line will receive a gaslighting message
---@field min_line_length number -- Minimum length of a trimmed line for gaslighting to apply
---@field highlight string -- Highlight group name used for virtual text messages
---@field debounce_delay number -- Delay in milliseconds before updating decorations
---@field auto_update boolean -- Automatically update decorations on buffer changes
---@field merge_messages boolean -- Merge user-defined messages with default ones
---@field filetypes_to_ignore string[] -- List of filetypes to ignore from gaslighting
---@field messages string[] -- Array of gaslighting messages
local M = {} local M = {}
-- Default configuration options --- Default configuration options
---@type GaslightingConfig
local default_config = { local default_config = {
gaslighting_chance = 5, -- 5% chance per line gaslighting_chance = 5,
min_line_length = 10, -- Minimum trimmed line length to apply gaslighting min_line_length = 10,
highlight = "GaslightingUnderline", -- Highlight group name (linked to Comment by default) highlight = "GaslightingUnderline",
debounce_delay = 500, -- Debounce delay in ms debounce_delay = 500,
auto_update = true, -- Whether to auto-update on buffer events auto_update = true,
merge_messages = false, -- If true, merge user messages with default ones merge_messages = false,
filetypes_to_ignore = { -- List of filetypes to ignore (default: "netrw") filetypes_to_ignore = { "netrw", "NvimTree", "neo-tree", "Telescope", "qf" },
"netrw",
"NvimTree",
"neo-tree",
"Telescope",
"qf"
},
messages = { messages = {
"Are you sure this will pass the code quality checks? 🤔", "Are you sure this will pass the code quality checks? 🤔",
"Is this line really covered by unit tests? 🧐", "Is this line really covered by unit tests? 🧐",
@ -31,14 +36,22 @@ local default_config = {
}, },
} }
local config = {} ---@type GaslightingConfig
local config = vim.deepcopy(default_config)
local api = vim.api local api = vim.api
local timer = nil local timer = nil
local ns = api.nvim_create_namespace("syntax_gaslighting") local ns = api.nvim_create_namespace("syntax_gaslighting")
M.is_enabled = true M.is_enabled = true
-- If user_config.merge_messages is true and user_config.messages is provided, --- Convert filetype list to a set for fast lookup
-- the plugin will merge default messages with user messages. local ignored_filetypes_set = {}
for _, ft in ipairs(default_config.filetypes_to_ignore) do
ignored_filetypes_set[ft] = true
end
--- Merge user configuration with defaults
---@param user_config table
function M.setup(user_config) function M.setup(user_config)
user_config = user_config or {} user_config = user_config or {}
config = vim.tbl_deep_extend("force", {}, default_config, user_config) config = vim.tbl_deep_extend("force", {}, default_config, user_config)
@ -61,7 +74,7 @@ function M.setup(user_config)
}) })
end end
-- Command to toggle the gaslighting functionality. -- Toggle the gaslighting functionality.
api.nvim_create_user_command("SyntaxGaslightingToggle", function() api.nvim_create_user_command("SyntaxGaslightingToggle", function()
M.is_enabled = not M.is_enabled M.is_enabled = not M.is_enabled
if M.is_enabled then if M.is_enabled then
@ -74,7 +87,7 @@ function M.setup(user_config)
end end
end, {}) end, {})
-- Command to change the gaslighting chance percentage. -- Change the gaslighting chance percentage.
api.nvim_create_user_command("SyntaxGaslightingEditChance", function() api.nvim_create_user_command("SyntaxGaslightingEditChance", function()
local input = vim.fn.input("Enter the percentage chance of gaslighting (1-100): ", config.gaslighting_chance) local input = vim.fn.input("Enter the percentage chance of gaslighting (1-100): ", config.gaslighting_chance)
local num = tonumber(input) local num = tonumber(input)
@ -86,31 +99,31 @@ function M.setup(user_config)
print("Invalid input. Please enter a number between 1 and 100.") print("Invalid input. Please enter a number between 1 and 100.")
end end
end, {}) end, {})
api.nvim_create_user_command("SyntaxGaslightingMessages", function()
print("Current gaslighting messages:")
for _, msg in ipairs(config.messages) do
print("- " .. msg)
end
end, {})
end end
-- A simple deterministic hash function (not cryptographically secure) -- A simple, deterministic hash function using sha256
---@param str string
---@return string
local function createHash(str) local function createHash(str)
local hash1, hash2 = 0, 0 return vim.fn.sha256(str)
for i = 1, #str do
local byte = str:byte(i)
hash1 = (hash1 * 31 + byte) % 0xFFFFFFFF
hash2 = (hash2 * 37 + byte) % 0xFFFFFFFF
end
return string.format("%08x%08x", hash1, hash2)
end end
-- Check if the current buffer's filetype is in the ignore list --- Check if the current filetype should be ignored
---@return boolean
local function shouldIgnoreFileType() local function shouldIgnoreFileType()
local filetype = vim.bo.filetype return ignored_filetypes_set[vim.bo.filetype] or false
for _, ft in ipairs(config.filetypes_to_ignore) do
if filetype == ft then
return true
end
end
return false
end end
-- Determine if a gaslighting message should be applied to a line and return it if so. --- Determine if a gaslighting message should be applied to a line
---@param line string
---@return string|nil
local function getGaslightingMessageForLineContent(line) local function getGaslightingMessageForLineContent(line)
local hash = createHash(line) local hash = createHash(line)
local selectionNum = tonumber(hash:sub(1, 8), 16) local selectionNum = tonumber(hash:sub(1, 8), 16)
@ -122,22 +135,45 @@ local function getGaslightingMessageForLineContent(line)
return nil return nil
end end
-- Update the gaslighting decorations in the current buffer. -- Check if the line is a comment based on the filetype
function M.update_decorations() -- TODO: this should be replaced with Treesitter native method of checking for comments
if not M.is_enabled or shouldIgnoreFileType() then -- in the future. I don't care to set up Treesitter for testing, so this is what we have.
return local function isComment(line)
local filetype = vim.bo.filetype
local trimmed_line = vim.trim(line)
-- Lua: '--' for comments
if filetype == "lua" then
return vim.fn.match(trimmed_line, "^--") ~= -1
end end
-- Python: '#' for comments
if filetype == "python" then
return vim.fn.match(trimmed_line, "^#") ~= -1
end
-- C/C++/JavaScript: '//' for comments
if filetype == "c" or filetype == "cpp" or filetype == "javascript" or filetype == "java" then
return vim.fn.match(trimmed_line, "^//") ~= -1
end
-- If no specific filetype matches, return false (i.e., not a comment)
return false
end
--- Update the gaslighting decorations in the current buffer
function M.update_decorations()
if not M.is_enabled or shouldIgnoreFileType() then return end
local bufnr = api.nvim_get_current_buf() local bufnr = api.nvim_get_current_buf()
-- Clear previous extmarks in our namespace. api.nvim_buf_clear_namespace(bufnr, ns, 0, -1) -- Clear previous decorations
api.nvim_buf_clear_namespace(bufnr, ns, 0, -1)
local lines = api.nvim_buf_get_lines(bufnr, 0, -1, false) local lines = api.nvim_buf_get_lines(bufnr, 0, -1, false)
for i, line in ipairs(lines) do for i, line in ipairs(lines) do
local trimmed = vim.trim(line) local trimmed = vim.trim(line)
if #trimmed >= config.min_line_length then
-- Skip dummy comment lines (detection based on starting patterns) -- Skip comment lines entirely
-- TODO: use Treesitter for this if #trimmed >= config.min_line_length and not isComment(trimmed) then
if not (trimmed:find("^//") or trimmed:find("^#") or trimmed:find("^/%*") or trimmed:find("^%*") or trimmed:find("^<!--")) then
local message = getGaslightingMessageForLineContent(trimmed) local message = getGaslightingMessageForLineContent(trimmed)
if message then if message then
local first_non_whitespace = line:find("%S") local first_non_whitespace = line:find("%S")
@ -151,19 +187,16 @@ function M.update_decorations()
end end
end end
end end
end
end end
-- Debounce update: schedules an update after a delay. --- Debounced update function
function M.schedule_update() function M.schedule_update()
if timer then if timer then
timer:stop() timer:stop()
timer:close() timer:close()
end end
timer = vim.loop.new_timer() timer = vim.loop.new_timer()
timer:start(config.debounce_delay, 0, vim.schedule_wrap(function() timer:start(config.debounce_delay, 0, vim.schedule_wrap(M.update_decorations))
M.update_decorations()
end))
end end
return M return M