8000 mini.nvim/lua/mini/comment.lua at main · yilisharcs/mini.nvim · GitHub
[go: up one dir, main page]

Skip to content

Latest commit

 

History

History
577 lines (494 loc) · 23.5 KB

comment.lua

File metadata and controls

577 lines (494 loc) · 23.5 KB
H.check_type('hooks', config.hooks, 'table')
H.check_type('hooks.pre', config.hooks.pre, 'function')
H.check_type('hooks.post', config.hooks.post, 'function')
return config
end
H.apply_config = function(config)
MiniComment.config = config
-- Make mappings
local operator_rhs = function() return MiniComment.operator() end
H.map('n', config.mappings.comment, operator_rhs, { expr = true, desc = 'Comment' })
H.map('x', config.mappings.comment_visual, operator_rhs, { expr = true, desc = 'Comment selection' })
H.map(
'n',
config.mappings.comment_line,
function() return MiniComment.operator() .. '_' end,
{ expr = true, desc = 'Comment line' }
)
-- Use `<Cmd>...<CR>` to have proper dot-repeat
-- See https://github.com/neovim/neovim/issues/23406
local modes = config.mappings.textobject == config.mappings.comment_visual and { 'o' } or { 'x', 'o' }
H.map(modes, config.mappings.textobject, '<Cmd>lua MiniComment.textobject()<CR>', { desc = 'Comment textobject' })
end
H.is_disabled = function() return vim.g.minicomment_disable == true or vim.b.minicomment_disable == true end
H.get_config = function(config)
return vim.tbl_deep_extend('force', MiniComment.config, vim.b.minicomment_config or {}, config or {})
end
-- Core implementations -------------------------------------------------------
H.get_comment_parts = function(ref_position, options)
local cs
if vim.is_callable(options.custom_commentstring) then cs = options.custom_commentstring(ref_position) end
cs = cs or MiniComment.get_commentstring(ref_position)
if cs == nil or cs == '' then
vim.api.nvim_echo({ { '(mini.comment) ', 'WarningMsg' }, { [[Option 'commentstring' is empty.]] } }, true, {})
return { left = '', right = '' }
end
if not (type(cs) == 'string' and string.find(cs, '%%s') ~= nil) then
H.error(vim.inspect(cs) .. " is not a valid 'commentstring'.")
end
-- Structure of 'commentstring': <left part> <%s> <right part>
local left, right = string.match(cs, '^(.-)%%s(.-)$')
-- Force single space padding if requested
if options.pad_comment_parts then
left, right = vim.trim(left), vim.trim(right)
left, right = left == '' and '' or (left .. ' '), right == '' and '' or (' ' .. right)
end
return { left = left, right = right }
end
H.make_comment_check = function(parts, options)
local l_esc, r_esc = vim.pesc(parts.left), vim.pesc(parts.right)
local prefix = options.start_of_line and '' or '%s-'
-- Commented line has the following structure:
-- <whitespace> <trimmed left> <anything> <trimmed right> <whitespace>
local regex = '^' .. prefix .. vim.trim(l_esc) .. '.*' .. vim.trim(r_esc) .. '%s-$'
return function(line) return string.find(line, regex) ~= nil end
end
H.get_lines_info = function(lines, parts, options)
local comment_check = H.make_comment_check(parts, options)
local is_commented = true
local indent, indent_width = nil, math.huge
for _, l in ipairs(lines) do
-- Update lines indent: minimum of all indents except blank lines
local _, indent_width_cur, indent_cur = string.find(l, '^(%s*)')
-- Ignore blank lines completely when making a decision
if indent_width_cur < l:len() then
-- NOTE: Copying actual indent instead of recreating it with `indent_width`
-- allows to handle both tabs and spaces
if indent_width_cur < indent_width then
indent_width, indent = indent_width_cur, indent_cur
end
-- Update comment info: commented if every non-blank line is commented
if is_commented then is_commented = comment_check(l) end
end
end
-- `indent` can still be `nil` in case all `lines` are empty
return indent or '', is_commented
end
H.make_comment_function = function(parts, indent, options)
local prefix = options.start_of_line and (parts.left .. indent) or (indent .. parts.left)
local nonindent_start = string.len(indent) + 1
local suffix = parts.right
local blank_comment = indent .. vim.trim(parts.left) .. vim.trim(parts.right)
local ignore_blank_line = options.ignore_blank_line
return function(line)
if H.is_blank(line) then return ignore_blank_line and line or blank_comment end
return prefix .. string.sub(line, nonindent_start) .. suffix
end
end
H.make_uncomment_function = function(parts)
local l_esc, r_esc = vim.pesc(parts.left), vim.pesc(parts.right)
local regex = '^(%s*)' .. l_esc .. '(.*)' .. r_esc .. '(%s-)$'
local regex_trimmed = '^(%s*)' .. vim.trim(l_esc) .. '(.*)' .. vim.trim(r_esc) .. '(%s-)$'
return function(line)
-- Try regex with exact comment parts first, fall back to trimmed parts
local indent, new_line, trail = line:match(regex)
if new_line == nil then
indent, new_line, trail = line:match(regex_trimmed)
end
-- Return original if line is not commented
if new_line == nil then return line end
-- Prevent trailing whitespace
if H.is_blank(new_line) then
indent, trail = '', ''
end
return indent .. new_line .. trail
end
end
-- Utilities ------------------------------------------------------------------
H.error = function(msg) error('(mini.comment) ' .. msg, 0) end
H.check_type = function(name, val, ref, allow_nil)
if type(val) == ref or (ref == 'callable' and vim.is_callable(val)) or (allow_nil and val == nil) then return end
H.error(string.format('`%s` should be %s, not %s', name, ref, type(val)))
end
H.map = function(mode, lhs, rhs, opts)
if lhs == '' then return end
opts = vim.tbl_deep_extend('force', { silent = true }, opts or {})
vim.keymap.set(mode, lhs, rhs, opts)
end
H.is_blank = function(x) return string.find(x, '^%s*$') ~= nil end
return MiniComment
0