2023-02-20 21:01:31 +00:00
|
|
|
local argonaut_configs = {
|
|
|
|
default = {
|
|
|
|
line_prefix = '',
|
|
|
|
padded_braces = {},
|
|
|
|
tail_comma = false,
|
|
|
|
tail_comma_braces = {},
|
|
|
|
tail_indent_braces = {},
|
|
|
|
wrap_closing_brace = true,
|
|
|
|
comma_first = false,
|
|
|
|
comma_first_indent = false,
|
2023-02-20 22:21:29 +00:00
|
|
|
},
|
|
|
|
go = {
|
|
|
|
tail_comma = true,
|
2023-02-20 21:01:31 +00:00
|
|
|
}
|
2023-01-29 03:20:14 +00:00
|
|
|
}
|
2022-12-30 23:10:22 +00:00
|
|
|
|
2023-02-20 21:01:31 +00:00
|
|
|
local function setup(opts, filetypes)
|
2023-01-29 03:20:14 +00:00
|
|
|
if opts then
|
2023-02-20 21:01:31 +00:00
|
|
|
if type(filetypes) == 'string' then
|
|
|
|
filetypes = {filetypes}
|
|
|
|
elseif not filetypes then
|
|
|
|
filetypes = {'default'}
|
|
|
|
end
|
|
|
|
|
|
|
|
for _, filetype in ipairs(filetypes) do
|
|
|
|
local config = argonaut_configs[filetype]
|
|
|
|
if not config then
|
|
|
|
config = {}
|
|
|
|
argonaut_configs[filetype] = config
|
|
|
|
end
|
|
|
|
|
|
|
|
for key, value in pairs(opts) do
|
|
|
|
config[key] = value
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
local function get_config()
|
|
|
|
local file_config = argonaut_configs[vim.bo.filetype]
|
|
|
|
|
|
|
|
local config = {}
|
|
|
|
for key, value in pairs(argonaut_configs.default) do
|
|
|
|
config[key] = value
|
|
|
|
if file_config then
|
|
|
|
local file_value = file_config[key]
|
|
|
|
if file_value ~= nil then
|
|
|
|
config[key] = file_config[key]
|
|
|
|
end
|
2023-01-29 03:20:14 +00:00
|
|
|
end
|
|
|
|
end
|
2023-02-20 21:01:31 +00:00
|
|
|
|
|
|
|
return config
|
2022-12-30 23:10:22 +00:00
|
|
|
end
|
|
|
|
|
2023-01-29 06:43:56 +00:00
|
|
|
local function get_cursor_pos()
|
|
|
|
local _, row, col, _ = unpack(vim.fn.getpos('.'))
|
|
|
|
return {row = row, col = col}
|
|
|
|
end
|
|
|
|
|
2023-02-20 20:35:38 +00:00
|
|
|
local function get_brace_alt(brace)
|
2023-02-08 02:10:12 +00:00
|
|
|
local brace_pairs = {{'(', ')'}, {'[', ']'}, {'{', '}'}, {'<', '>'}}
|
|
|
|
|
|
|
|
for _, brace_pair in ipairs(brace_pairs) do
|
|
|
|
if brace_pair[1] == brace then
|
|
|
|
return brace_pair[2], true
|
|
|
|
elseif brace_pair[2] == brace then
|
|
|
|
return brace_pair[1], false
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2023-02-20 20:35:38 +00:00
|
|
|
local function is_string_literal(pos)
|
|
|
|
if not pos then
|
|
|
|
pos = get_cursor_pos()
|
|
|
|
end
|
|
|
|
|
2023-02-20 22:21:29 +00:00
|
|
|
local syn_id = vim.fn.synID(pos.row, pos.col, false)
|
2023-02-20 20:35:38 +00:00
|
|
|
local syn_attr = vim.fn.synIDattr(syn_id, 'name')
|
|
|
|
|
|
|
|
return syn_attr:find('String$')
|
|
|
|
end
|
|
|
|
|
2023-02-08 02:10:12 +00:00
|
|
|
local function find_brace_range(brace)
|
2023-02-20 20:35:38 +00:00
|
|
|
local brace_alt, _ = get_brace_alt(brace)
|
2023-02-08 02:10:12 +00:00
|
|
|
assert(brace_alt)
|
|
|
|
|
2023-02-20 20:31:38 +00:00
|
|
|
local escape_brace = function(brace_raw)
|
|
|
|
if brace_raw == '[' or brace_raw == ']' then
|
|
|
|
return '\\' .. brace_raw
|
|
|
|
else
|
|
|
|
return brace_raw
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2023-02-20 01:53:06 +00:00
|
|
|
---@diagnostic disable-next-line: param-type-mismatch
|
2023-02-20 05:11:47 +00:00
|
|
|
local row1, col1 = unpack(vim.fn.searchpairpos(escape_brace(brace), '', escape_brace(brace_alt), 'Wnb', is_string_literal))
|
2023-01-29 03:20:14 +00:00
|
|
|
if row1 > 0 and col1 > 0 then
|
2023-02-20 01:53:06 +00:00
|
|
|
---@diagnostic disable-next-line: param-type-mismatch
|
2023-02-08 02:10:12 +00:00
|
|
|
local row2, col2 = unpack(vim.fn.searchpairpos(escape_brace(brace), '', escape_brace(brace_alt), 'Wcn', is_string_literal))
|
2023-01-29 03:20:14 +00:00
|
|
|
if row2 > 0 and col2 > 0 then
|
|
|
|
return {
|
2023-02-08 02:10:12 +00:00
|
|
|
brace = brace,
|
2023-01-29 03:20:14 +00:00
|
|
|
row1 = row1,
|
|
|
|
col1 = col1,
|
|
|
|
row2 = row2,
|
|
|
|
col2 = col2
|
|
|
|
}
|
|
|
|
end
|
|
|
|
end
|
2022-12-30 23:10:22 +00:00
|
|
|
end
|
|
|
|
|
2023-02-08 02:10:12 +00:00
|
|
|
local function find_all_brace_ranges(braces)
|
|
|
|
local brace_ranges = {}
|
|
|
|
for _, brace in ipairs(braces) do
|
|
|
|
local brace_range = find_brace_range(brace)
|
|
|
|
if brace_range then
|
|
|
|
table.insert(brace_ranges, brace_range)
|
2023-01-29 03:20:14 +00:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2023-02-08 02:10:12 +00:00
|
|
|
if #brace_ranges > 0 then
|
|
|
|
return brace_ranges
|
2023-01-29 03:20:14 +00:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2023-02-08 02:10:12 +00:00
|
|
|
local function find_closest_brace_range(braces)
|
|
|
|
local cursor_pos = get_cursor_pos()
|
|
|
|
local compare_brace_ranges = function(brace_range_1, brace_range_2)
|
|
|
|
local row_diff1 = cursor_pos.row - brace_range_1.row1
|
|
|
|
local row_diff2 = cursor_pos.row - brace_range_2.row1
|
2023-02-07 06:36:11 +00:00
|
|
|
if row_diff1 < row_diff2 then
|
|
|
|
return -1
|
|
|
|
elseif row_diff1 > row_diff2 then
|
|
|
|
return 1
|
|
|
|
end
|
2023-01-29 03:20:14 +00:00
|
|
|
|
2023-02-08 02:10:12 +00:00
|
|
|
local col_diff1 = cursor_pos.col - brace_range_1.col1
|
|
|
|
local col_diff2 = cursor_pos.col - brace_range_2.col1
|
2023-02-07 06:36:11 +00:00
|
|
|
if col_diff1 < col_diff2 then
|
|
|
|
return -1
|
|
|
|
elseif col_diff1 > col_diff2 then
|
|
|
|
return 1
|
|
|
|
end
|
2023-01-29 03:20:14 +00:00
|
|
|
|
2023-02-07 06:36:11 +00:00
|
|
|
return 0
|
|
|
|
end
|
2022-12-30 23:10:22 +00:00
|
|
|
|
2023-02-08 02:10:12 +00:00
|
|
|
local brace_ranges = find_all_brace_ranges(braces)
|
|
|
|
if brace_ranges then
|
|
|
|
return vim.fn.sort(brace_ranges, compare_brace_ranges)[1]
|
2023-01-29 03:20:14 +00:00
|
|
|
end
|
2022-12-30 23:10:22 +00:00
|
|
|
end
|
|
|
|
|
2023-02-08 02:10:12 +00:00
|
|
|
local function parse_brace_range(brace_range)
|
2023-02-20 01:53:06 +00:00
|
|
|
brace_range.params = {}
|
2023-02-20 02:40:34 +00:00
|
|
|
|
|
|
|
local first_line = vim.fn.getline(brace_range.row1)
|
2023-02-20 05:11:47 +00:00
|
|
|
brace_range.indent = first_line:match('^(%s*)') ---@diagnostic disable-line: undefined-field
|
|
|
|
brace_range.prefix = first_line:sub(#brace_range.indent + 1, brace_range.col1) ---@diagnostic disable-line: undefined-field
|
2023-02-20 02:40:34 +00:00
|
|
|
|
|
|
|
local last_line = vim.fn.getline(brace_range.row2)
|
|
|
|
brace_range.suffix = last_line:sub(brace_range.col2) ---@diagnostic disable-line: undefined-field
|
2023-02-20 01:53:06 +00:00
|
|
|
|
2023-02-08 02:10:12 +00:00
|
|
|
local brace_range_param = ''
|
|
|
|
local flush_brace_range_param = function()
|
|
|
|
if #brace_range_param > 0 then
|
2023-02-20 01:53:06 +00:00
|
|
|
table.insert(brace_range.params, brace_range_param)
|
2023-02-08 02:10:12 +00:00
|
|
|
brace_range_param = ''
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
local brace_stack = {}
|
|
|
|
local update_brace_stack = function(c)
|
|
|
|
local brace_stack_size = #brace_stack
|
2023-02-20 20:35:38 +00:00
|
|
|
local brace_alt, brace_open = get_brace_alt(c)
|
2023-02-08 02:10:12 +00:00
|
|
|
if brace_stack_size > 0 and brace_alt == brace_stack[brace_stack_size] and not brace_open then
|
|
|
|
table.remove(brace_stack, brace_stack_size)
|
|
|
|
elseif brace_alt then
|
|
|
|
table.insert(brace_stack, c)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
local brace_range_elements = {}
|
2023-02-20 20:23:29 +00:00
|
|
|
local pad_newline = false
|
|
|
|
|
2023-02-08 02:10:12 +00:00
|
|
|
for row = brace_range.row1, brace_range.row2 do
|
2023-02-20 20:23:29 +00:00
|
|
|
local lead_padding = true
|
2023-02-07 06:36:11 +00:00
|
|
|
local line = vim.fn.getline(row)
|
|
|
|
|
2023-02-20 20:23:29 +00:00
|
|
|
local col1 = 1
|
2023-02-08 02:10:12 +00:00
|
|
|
if row == brace_range.row1 then
|
|
|
|
col1 = brace_range.col1 + 1
|
2023-02-07 06:36:11 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
local col2 = #line
|
2023-02-08 02:10:12 +00:00
|
|
|
if row == brace_range.row2 then
|
|
|
|
col2 = brace_range.col2 - 1
|
2023-02-07 06:36:11 +00:00
|
|
|
end
|
|
|
|
|
2023-02-20 20:23:29 +00:00
|
|
|
for col = col1, col2 do
|
|
|
|
local c = line:sub(col, col) ---@diagnostic disable-line: undefined-field
|
|
|
|
assert(#c > 0)
|
|
|
|
|
|
|
|
if lead_padding then
|
|
|
|
if c:match('%s') then
|
|
|
|
if pad_newline and col == col1 then
|
|
|
|
c = ' '
|
|
|
|
else
|
|
|
|
c = nil
|
|
|
|
end
|
|
|
|
else
|
|
|
|
lead_padding = false
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
if c then
|
|
|
|
table.insert(brace_range_elements, {
|
|
|
|
char = c,
|
|
|
|
literal = is_string_literal({row = row, col = col}),
|
|
|
|
})
|
|
|
|
|
|
|
|
if c == ',' then
|
|
|
|
pad_newline = true
|
|
|
|
else
|
|
|
|
pad_newline = false
|
|
|
|
end
|
|
|
|
end
|
2023-02-07 06:36:11 +00:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2023-02-08 02:10:12 +00:00
|
|
|
if #brace_range_elements > 0 then
|
|
|
|
for _, brace_range_element in ipairs(brace_range_elements) do
|
|
|
|
local append = true
|
|
|
|
if not brace_range_element.literal then
|
|
|
|
update_brace_stack(brace_range_element.char)
|
|
|
|
if #brace_stack == 0 and brace_range_element.char == ',' then
|
|
|
|
flush_brace_range_param()
|
|
|
|
append = false
|
2023-02-07 06:36:11 +00:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2023-02-08 02:10:12 +00:00
|
|
|
if append then
|
|
|
|
brace_range_param = brace_range_param .. brace_range_element.char
|
2023-02-07 06:36:11 +00:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2023-02-08 02:10:12 +00:00
|
|
|
flush_brace_range_param()
|
2023-02-07 06:36:11 +00:00
|
|
|
end
|
2023-02-20 01:53:06 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
local function wrap_brace_range(brace_range)
|
2023-02-20 22:21:29 +00:00
|
|
|
local config = get_config()
|
|
|
|
|
2023-02-20 05:11:47 +00:00
|
|
|
vim.fn.setline(brace_range.row1, brace_range.indent .. brace_range.prefix)
|
2023-02-20 04:45:40 +00:00
|
|
|
|
|
|
|
local row = brace_range.row1
|
|
|
|
for i, param in ipairs(brace_range.params) do
|
2023-02-20 22:21:29 +00:00
|
|
|
local on_last_row = i == #brace_range.params
|
2023-02-20 04:45:40 +00:00
|
|
|
|
2023-02-20 05:11:47 +00:00
|
|
|
local line = brace_range.indent .. param
|
2023-02-20 22:21:29 +00:00
|
|
|
if config.tail_comma or not on_last_row then
|
2023-02-20 04:45:40 +00:00
|
|
|
line = line .. ','
|
|
|
|
end
|
|
|
|
|
2023-02-20 22:21:29 +00:00
|
|
|
if on_last_row and not config.wrap_closing_brace then
|
|
|
|
line = line .. brace_range.suffix
|
|
|
|
end
|
|
|
|
|
2023-02-20 04:45:40 +00:00
|
|
|
vim.fn.append(row, line)
|
|
|
|
vim.fn.execute(string.format('%d>', row + 1))
|
|
|
|
|
|
|
|
row = row + 1
|
|
|
|
end
|
|
|
|
|
2023-02-20 22:21:29 +00:00
|
|
|
if config.wrap_closing_brace then
|
|
|
|
vim.fn.append(row, brace_range.indent .. brace_range.suffix)
|
|
|
|
end
|
2023-02-20 01:53:06 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
local function unwrap_brace_range(brace_range)
|
2023-02-20 05:11:47 +00:00
|
|
|
local line = brace_range.indent .. brace_range.prefix
|
2023-02-20 02:40:34 +00:00
|
|
|
for i, param in ipairs(brace_range.params) do
|
|
|
|
line = line .. param
|
|
|
|
if i < #brace_range.params then
|
|
|
|
line = line .. ', '
|
|
|
|
end
|
|
|
|
end
|
|
|
|
line = line .. brace_range.suffix
|
2023-02-07 06:36:11 +00:00
|
|
|
|
2023-02-20 02:40:34 +00:00
|
|
|
vim.fn.setline(brace_range.row1, line)
|
2023-02-20 22:21:29 +00:00
|
|
|
vim.fn.execute(string.format('%d,%dd_', brace_range.row1 + 1, brace_range.row2), true)
|
2023-02-07 06:36:11 +00:00
|
|
|
end
|
|
|
|
|
2023-01-29 03:20:14 +00:00
|
|
|
local function reflow()
|
2023-02-20 22:21:29 +00:00
|
|
|
local brace_range = find_closest_brace_range({'(', '[', '{', '<'})
|
2023-02-08 02:10:12 +00:00
|
|
|
if brace_range then
|
|
|
|
parse_brace_range(brace_range)
|
2023-02-20 01:53:06 +00:00
|
|
|
if brace_range.row1 == brace_range.row2 then
|
|
|
|
wrap_brace_range(brace_range)
|
|
|
|
else
|
2023-02-20 02:40:34 +00:00
|
|
|
unwrap_brace_range(brace_range)
|
2023-02-20 01:53:06 +00:00
|
|
|
end
|
2023-01-29 03:20:14 +00:00
|
|
|
end
|
2022-12-30 18:40:23 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
return {
|
2023-01-29 03:20:14 +00:00
|
|
|
reflow = reflow,
|
2023-02-20 21:01:31 +00:00
|
|
|
setup = setup,
|
2022-12-30 18:40:23 +00:00
|
|
|
}
|