Skip to content

Instantly share code, notes, and snippets.

@radgeRayden
Created May 31, 2025 20:04
Show Gist options
  • Save radgeRayden/ceda2167bb208d8f7aa6af4c208ffe50 to your computer and use it in GitHub Desktop.
Save radgeRayden/ceda2167bb208d8f7aa6af4c208ffe50 to your computer and use it in GitHub Desktop.
local function search_previous_lines(pattern)
return vim.fn.search(pattern, 'znbW')
end
local block_starting_keywords = {
'if',
'else',
'elseif',
'then',
'case',
'pass',
'default',
'except',
'fn',
'fn\\.\\.\\.',
'inline\\.\\.\\.',
'sugar',
'spice',
'inline',
'label',
'do',
'embed',
'try',
'loop',
'for',
'fold',
'while',
'spice-quote',
'enum',
'struct',
'::',
'static-if',
'sugar-if',
}
local block_ending_keywords = {
'return',
'break',
'repeat',
'continue',
'merge',
}
local function re_or(items)
return ('\\(%s\\)'):format(table.concat(items, '\\|'))
end
local block_start_pattern = re_or { '^ *' .. re_or(block_starting_keywords) .. re_or { ' ', '$' }, re_or { '=', ':=' } .. ' *$' }
local block_start_regexp = vim.regex(block_start_pattern)
local block_end_pattern = '^ *' .. re_or(block_ending_keywords) .. re_or { ';', '\\s\\+\\S\\+.*' } .. '$'
local block_end_regexp = vim.regex(block_end_pattern)
local blank_line_regexp = vim.regex '^ *$'
local indent = vim.fn.indent
local getline = vim.fn.getline
local function scopes_indent_algorithm()
local line_number = vim.v.lnum
local prev_line_number = search_previous_lines '[^ \\n]'
-- if at the start of the file (no prior non-blank lines), indent to the beginning of the line
if prev_line_number == 0 then
return 0
end
local cur_line = getline(line_number)
local prev_line = getline(prev_line_number)
local prev_indent = indent(prev_line_number)
local cur_indent = indent(line_number)
local is_blank_line = not not blank_line_regexp:match_str(cur_line)
local max_indent = prev_indent + 4
local next_alignment = cur_indent + (4 - (cur_indent % 4))
local is_aligned = cur_indent + 4 == next_alignment
-- are we reindenting a line?
if not is_blank_line then
if cur_indent >= max_indent then
return max_indent
elseif is_aligned then
return cur_indent + 4
else
return next_alignment
end
-- entirely new line
elseif cur_indent == 0 then
if block_start_regexp:match_str(prev_line) then
return max_indent
elseif block_end_regexp:match_str(prev_line) then
return math.max(0, prev_indent - 4)
else
return is_aligned and math.min(prev_indent, cur_indent + 4) or next_alignment
end
-- adjusting new line
else
return is_aligned and math.min(max_indent, cur_indent + 4) or next_alignment
end
end
return {
scopes_indent_algorithm = scopes_indent_algorithm,
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment