Rework for deep parsing
This commit is contained in:
parent
1d46f84163
commit
5fa76a6522
56
lua/argonaut/builder.lua
Normal file
56
lua/argonaut/builder.lua
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
local Builder = {}
|
||||||
|
Builder.__index = Builder
|
||||||
|
|
||||||
|
function Builder.new(indent_level, indent_block)
|
||||||
|
local builder = {
|
||||||
|
line = '',
|
||||||
|
buffer = {},
|
||||||
|
indent_level = indent_level,
|
||||||
|
indent_block = indent_block,
|
||||||
|
}
|
||||||
|
|
||||||
|
return setmetatable(builder, Builder)
|
||||||
|
end
|
||||||
|
|
||||||
|
function Builder:indent()
|
||||||
|
self:write(self.indent_block)
|
||||||
|
end
|
||||||
|
|
||||||
|
function Builder:push_indent()
|
||||||
|
self.indent_level = self.indent_level + 1
|
||||||
|
end
|
||||||
|
|
||||||
|
function Builder:pop_indent()
|
||||||
|
assert(self.indent_level > 0)
|
||||||
|
self.indent_level = self.indent_level - 1
|
||||||
|
end
|
||||||
|
|
||||||
|
function Builder:write(text)
|
||||||
|
self.line = self.line .. text
|
||||||
|
end
|
||||||
|
|
||||||
|
function Builder:endline()
|
||||||
|
local indent = string.rep(self.indent_block, self.indent_level)
|
||||||
|
table.insert(self.buffer, indent .. self.line)
|
||||||
|
self.line = ''
|
||||||
|
end
|
||||||
|
|
||||||
|
function Builder:output(row_begin, row_end)
|
||||||
|
local row = row_begin
|
||||||
|
local row_count = row_end - row_begin + 1
|
||||||
|
|
||||||
|
for i, line in ipairs(self.buffer) do
|
||||||
|
if i <= row_count then
|
||||||
|
vim.fn.setline(row, line)
|
||||||
|
else
|
||||||
|
vim.fn.append(row - 1, line)
|
||||||
|
end
|
||||||
|
row = row + 1
|
||||||
|
end
|
||||||
|
|
||||||
|
if row <= row_end then
|
||||||
|
vim.fn.execute(string.format('%d,%dd_', row, row_end))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return Builder
|
@ -1,53 +0,0 @@
|
|||||||
local opt_curr = {
|
|
||||||
default = {
|
|
||||||
brace_last_indent = false,
|
|
||||||
brace_last_wrap = true,
|
|
||||||
brace_pad = false,
|
|
||||||
comma_last = false,
|
|
||||||
comma_prefix = false,
|
|
||||||
comma_prefix_indent = false,
|
|
||||||
line_max = 32,
|
|
||||||
},
|
|
||||||
go = {
|
|
||||||
comma_last = true,
|
|
||||||
},
|
|
||||||
vim = {
|
|
||||||
line_prefix = '\\',
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
local function setup(opt)
|
|
||||||
for file_type, file_opt in pairs(opt) do
|
|
||||||
local file_opt_curr = opt_curr[file_type]
|
|
||||||
if not file_opt_curr then
|
|
||||||
file_opt_curr = {}
|
|
||||||
opt_curr[file_type] = file_opt_curr
|
|
||||||
end
|
|
||||||
|
|
||||||
for param_name, param_value in pairs(file_opt) do
|
|
||||||
file_opt_curr[param_name] = param_value
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
local function get()
|
|
||||||
local file_opt_curr = opt_curr[vim.bo.filetype]
|
|
||||||
|
|
||||||
local file_opt = {}
|
|
||||||
for param_name, param_value in pairs(opt_curr.default) do
|
|
||||||
file_opt[param_name] = param_value
|
|
||||||
if file_opt_curr then
|
|
||||||
local param_value_curr = file_opt_curr[param_name]
|
|
||||||
if param_value_curr ~= nil then
|
|
||||||
file_opt[param_name] = param_value_curr
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
return file_opt
|
|
||||||
end
|
|
||||||
|
|
||||||
return {
|
|
||||||
setup = setup,
|
|
||||||
get = get,
|
|
||||||
}
|
|
94
lua/argonaut/cursor.lua
Normal file
94
lua/argonaut/cursor.lua
Normal file
@ -0,0 +1,94 @@
|
|||||||
|
local Cursor = {}
|
||||||
|
Cursor.__index = Cursor
|
||||||
|
|
||||||
|
function Cursor.new(row, col)
|
||||||
|
local cursor = {
|
||||||
|
row = row,
|
||||||
|
col = col,
|
||||||
|
}
|
||||||
|
|
||||||
|
return setmetatable(cursor, Cursor)
|
||||||
|
end
|
||||||
|
|
||||||
|
function Cursor.get_current()
|
||||||
|
local _, row, col, _ = unpack(vim.fn.getpos('.'))
|
||||||
|
return Cursor.new(row, col)
|
||||||
|
end
|
||||||
|
|
||||||
|
function Cursor:set_current()
|
||||||
|
assert(self:is_valid())
|
||||||
|
|
||||||
|
vim.fn.setcursorcharpos({self.row, self.col})
|
||||||
|
end
|
||||||
|
|
||||||
|
function Cursor:get_value()
|
||||||
|
assert(self:is_valid())
|
||||||
|
|
||||||
|
local line = vim.fn.getline(self.row)
|
||||||
|
return line:sub(self.col, self.col)
|
||||||
|
end
|
||||||
|
|
||||||
|
function Cursor:is_valid()
|
||||||
|
return self.row > 0 and self.col > 0
|
||||||
|
end
|
||||||
|
|
||||||
|
function Cursor:is_literal()
|
||||||
|
assert(self:is_valid())
|
||||||
|
|
||||||
|
local syn_id = vim.fn.synID(self.row, self.col, false)
|
||||||
|
local syn_attr = vim.fn.synIDattr(syn_id, 'name')
|
||||||
|
return syn_attr:find('String$') ~= nil or syn_attr:find('Comment$') ~= nil
|
||||||
|
end
|
||||||
|
|
||||||
|
function Cursor:next()
|
||||||
|
assert(self:is_valid())
|
||||||
|
|
||||||
|
local current_line = vim.fn.getline(self.row)
|
||||||
|
local next_col = self.col + 1
|
||||||
|
local next_row = self.row
|
||||||
|
|
||||||
|
if next_col > #current_line then
|
||||||
|
next_row = next_row + 1
|
||||||
|
next_col = 1
|
||||||
|
end
|
||||||
|
|
||||||
|
return Cursor.new(next_row, next_col)
|
||||||
|
end
|
||||||
|
|
||||||
|
function Cursor.__lt(cursor_1, cursor_2)
|
||||||
|
if cursor_1 == cursor_2 then
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
|
if cursor_1.row > cursor_2.row then
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
|
if cursor_1.row == cursor_2.row and cursor_1.col > cursor_2.col then
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
|
function Cursor.__gt(cursor_1, cursor_2)
|
||||||
|
if cursor_1 == cursor_2 then
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
|
if cursor_1.row < cursor_2.row then
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
|
if cursor_1.row == cursor_2.row and cursor_1.col < cursor_2.col then
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
|
function Cursor.__eq(cursor_1, cursor_2)
|
||||||
|
return cursor_1.row == cursor_2.row and cursor_1.col == cursor_2.col
|
||||||
|
end
|
||||||
|
|
||||||
|
return Cursor
|
@ -1,14 +1,44 @@
|
|||||||
local config = require('argonaut.config')
|
local Builder = require('argonaut.builder')
|
||||||
local types = require('argonaut.types')
|
local Cursor = require('argonaut.cursor')
|
||||||
|
local Options = require('argonaut.options')
|
||||||
|
local Range = require('argonaut.range')
|
||||||
|
|
||||||
local function reflow()
|
local function reflow()
|
||||||
local wrap_context = types.WrapContext.new(config.get())
|
local range = Range.find_closest()
|
||||||
if wrap_context:parse() then
|
if not range then
|
||||||
wrap_context:toggle()
|
return false
|
||||||
end
|
end
|
||||||
|
|
||||||
|
local trace = range:hit_test(Cursor.get_current())
|
||||||
|
assert(trace)
|
||||||
|
|
||||||
|
local line_first = vim.fn.getline(range.start_cursor.row)
|
||||||
|
local line_last = vim.fn.getline(range.stop_cursor.row)
|
||||||
|
|
||||||
|
local indent_level = #line_first:match('^(%s*)')
|
||||||
|
local indent_block = '\t'
|
||||||
|
if vim.o.expandtab then
|
||||||
|
indent_level = math.floor(indent_level / vim.o.shiftwidth)
|
||||||
|
indent_block = string.rep(' ', vim.o.shiftwidth)
|
||||||
|
end
|
||||||
|
|
||||||
|
local range_prefix = line_first:sub(indent_level * #indent_block + 1, range.start_cursor.col - 1)
|
||||||
|
local range_suffix = line_last:sub(range.stop_cursor.col + 1)
|
||||||
|
|
||||||
|
local builder = Builder.new(indent_level, indent_block)
|
||||||
|
builder:write(range_prefix)
|
||||||
|
range:write(builder, not range:is_wrapped())
|
||||||
|
builder:write(range_suffix)
|
||||||
|
builder:endline()
|
||||||
|
builder:output(range.start_cursor.row, range.stop_cursor.row)
|
||||||
|
|
||||||
|
local new_range = Range.find_at_cursor(range.start_cursor)
|
||||||
|
new_range:hit_search(trace, 1):set_current()
|
||||||
|
|
||||||
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
return {
|
return {
|
||||||
reflow = reflow,
|
reflow = reflow,
|
||||||
setup = config.setup,
|
setup = Options.setup,
|
||||||
}
|
}
|
||||||
|
61
lua/argonaut/options.lua
Normal file
61
lua/argonaut/options.lua
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
local options_current = {
|
||||||
|
default = {
|
||||||
|
brace_last_indent = false,
|
||||||
|
brace_last_wrap = true,
|
||||||
|
brace_pad = false,
|
||||||
|
comma_last = false,
|
||||||
|
comma_prefix = false,
|
||||||
|
comma_prefix_indent = false,
|
||||||
|
line_max = 32,
|
||||||
|
},
|
||||||
|
go = {
|
||||||
|
comma_last = true,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
local function setup(opt)
|
||||||
|
for file_type, file_options in pairs(opt) do
|
||||||
|
local file_options_current = options_current[file_type]
|
||||||
|
if not file_options_current then
|
||||||
|
file_options_current = {}
|
||||||
|
options_current[file_type] = file_options_current
|
||||||
|
end
|
||||||
|
|
||||||
|
for param_name, param_value in pairs(file_options) do
|
||||||
|
file_options_current[param_name] = param_value
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local function query(param_name, pairing)
|
||||||
|
assert(pairing)
|
||||||
|
|
||||||
|
local default_param_value = options_current.default[param_name]
|
||||||
|
local param_value = default_param_value
|
||||||
|
|
||||||
|
local file_options_current = options_current[vim.bo.filetype]
|
||||||
|
if file_options_current then
|
||||||
|
param_value = file_options_current[param_name]
|
||||||
|
if param_value == nil then
|
||||||
|
param_value = default_param_value
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if type(param_value) == 'table' then
|
||||||
|
param_value = param_value[pairing.open]
|
||||||
|
if param_value == nil then
|
||||||
|
param_value = default_param_value
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if type(param_value) == 'table' then
|
||||||
|
param_value = param_value[pairing.open]
|
||||||
|
end
|
||||||
|
|
||||||
|
return param_value
|
||||||
|
end
|
||||||
|
|
||||||
|
return {
|
||||||
|
setup = setup,
|
||||||
|
query = query,
|
||||||
|
}
|
71
lua/argonaut/pairing.lua
Normal file
71
lua/argonaut/pairing.lua
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
local Cursor = require('argonaut.cursor')
|
||||||
|
|
||||||
|
local Pairing = {}
|
||||||
|
Pairing.__index = Pairing
|
||||||
|
|
||||||
|
function Pairing.new(open, close)
|
||||||
|
local pair = {
|
||||||
|
open = open,
|
||||||
|
close = close
|
||||||
|
}
|
||||||
|
|
||||||
|
return setmetatable(pair, Pairing)
|
||||||
|
end
|
||||||
|
|
||||||
|
function Pairing.from_brace(brace)
|
||||||
|
local all_pairs = {
|
||||||
|
{'(', ')'},
|
||||||
|
{'[', ']'},
|
||||||
|
{'{', '}'},
|
||||||
|
{'<', '>'},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, pair in ipairs(all_pairs) do
|
||||||
|
if pair[1] == brace or pair[2] == brace then
|
||||||
|
return Pairing.new(pair[1], pair[2])
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function Pairing:get_escaped()
|
||||||
|
local escape_func = function(brace_raw)
|
||||||
|
if brace_raw == '[' or brace_raw == ']' then
|
||||||
|
return '\\' .. brace_raw
|
||||||
|
else
|
||||||
|
return brace_raw
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return Pairing.new(
|
||||||
|
escape_func(self.open),
|
||||||
|
escape_func(self.close)
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
function Pairing:find_closest(forward)
|
||||||
|
-- See flags: https://neovim.io/doc/user/builtin.html#search()
|
||||||
|
local flags = 'Wnbc'
|
||||||
|
if forward then
|
||||||
|
flags = 'Wn'
|
||||||
|
end
|
||||||
|
|
||||||
|
local ignore_func = function()
|
||||||
|
local cursor = Cursor.get_current()
|
||||||
|
return cursor:is_literal()
|
||||||
|
end
|
||||||
|
|
||||||
|
local escaped_pair = self:get_escaped()
|
||||||
|
local cursor = Cursor.new(unpack(vim.fn.searchpairpos(
|
||||||
|
escaped_pair.open,
|
||||||
|
'',
|
||||||
|
escaped_pair.close,
|
||||||
|
flags,
|
||||||
|
ignore_func
|
||||||
|
)))
|
||||||
|
|
||||||
|
if cursor:is_valid() then
|
||||||
|
return cursor
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return Pairing
|
95
lua/argonaut/param.lua
Normal file
95
lua/argonaut/param.lua
Normal file
@ -0,0 +1,95 @@
|
|||||||
|
local Param = {}
|
||||||
|
Param.__index = Param
|
||||||
|
|
||||||
|
local function is_empty_cell(cell)
|
||||||
|
return cell.type == 'cursor' and not cell.value:get_value():match('%S')
|
||||||
|
end
|
||||||
|
|
||||||
|
function Param.new(range, index, cells)
|
||||||
|
local param = {
|
||||||
|
range = range,
|
||||||
|
index = index,
|
||||||
|
cells = cells or {},
|
||||||
|
}
|
||||||
|
|
||||||
|
return setmetatable(param, Param)
|
||||||
|
end
|
||||||
|
|
||||||
|
function Param:append(value, type)
|
||||||
|
table.insert(self.cells, {
|
||||||
|
value = value,
|
||||||
|
type = type,
|
||||||
|
})
|
||||||
|
end
|
||||||
|
|
||||||
|
function Param:stripped()
|
||||||
|
local cells = {}
|
||||||
|
for i = self:find_index_begin(), self:find_index_end() do
|
||||||
|
table.insert(cells, self.cells[i])
|
||||||
|
end
|
||||||
|
return Param.new(self.range, self.index, cells)
|
||||||
|
end
|
||||||
|
|
||||||
|
function Param:hit_test(cursor)
|
||||||
|
for i, cell in ipairs(self.cells) do
|
||||||
|
local trace = nil
|
||||||
|
if cell.type == 'range' then
|
||||||
|
local trace_param = cell.value:hit_test(cursor)
|
||||||
|
if trace_param then
|
||||||
|
trace = {i}
|
||||||
|
for _, trace_param_frame in ipairs(trace_param) do
|
||||||
|
table.insert(trace, trace_param_frame)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
elseif cell.type == 'cursor' and cell.value == cursor then
|
||||||
|
trace = {i}
|
||||||
|
end
|
||||||
|
|
||||||
|
if trace then
|
||||||
|
return trace
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function Param:hit_search(trace, depth)
|
||||||
|
local index = trace[depth]
|
||||||
|
local cell = self.cells[index]
|
||||||
|
if cell.type == 'range' then
|
||||||
|
return cell.value:hit_search(trace, depth + 1)
|
||||||
|
elseif cell.type == 'cursor' then
|
||||||
|
return cell.value
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function Param:write(builder, wrapped)
|
||||||
|
for i = self:find_index_begin(), self:find_index_end() do
|
||||||
|
local cell = self.cells[i]
|
||||||
|
if cell.type == 'range' then
|
||||||
|
cell.value:write(builder, wrapped)
|
||||||
|
elseif cell.type == 'cursor' then
|
||||||
|
builder:write(cell.value:get_value())
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function Param:find_index_begin()
|
||||||
|
for i = 1, #self.cells do
|
||||||
|
if not is_empty_cell(self.cells[i]) then
|
||||||
|
return i
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function Param:find_index_end()
|
||||||
|
for i = #self.cells, 1, -1 do
|
||||||
|
if not is_empty_cell(self.cells[i]) then
|
||||||
|
return i
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function Param:is_empty()
|
||||||
|
return self:find_index_begin() == nil
|
||||||
|
end
|
||||||
|
|
||||||
|
return Param
|
236
lua/argonaut/range.lua
Normal file
236
lua/argonaut/range.lua
Normal file
@ -0,0 +1,236 @@
|
|||||||
|
local Cursor = require('argonaut.cursor')
|
||||||
|
local Options = require('argonaut.options')
|
||||||
|
local Pairing = require('argonaut.pairing')
|
||||||
|
local Param = require('argonaut.param')
|
||||||
|
|
||||||
|
local Range = {}
|
||||||
|
Range.__index = Range
|
||||||
|
|
||||||
|
local function find_closest_pair(pairing)
|
||||||
|
local stop_cursor = pairing:find_closest(true)
|
||||||
|
if stop_cursor then
|
||||||
|
local start_cursor = pairing:find_closest(false)
|
||||||
|
if start_cursor then
|
||||||
|
return Range.new(start_cursor, stop_cursor, pairing)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local function find_closest()
|
||||||
|
local ranges = {}
|
||||||
|
for _, brace in pairs({'(', '[', '{', '<'}) do
|
||||||
|
local pairing = Pairing.from_brace(brace)
|
||||||
|
local range = find_closest_pair(pairing)
|
||||||
|
if range then
|
||||||
|
table.insert(ranges, range)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if #ranges > 0 then
|
||||||
|
table.sort(ranges)
|
||||||
|
local range = ranges[1]
|
||||||
|
range:parse()
|
||||||
|
return range
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local function find_at_cursor(start_cursor)
|
||||||
|
local pairing = Pairing.from_brace(start_cursor:get_value())
|
||||||
|
if pairing then
|
||||||
|
local cursor_current = Cursor:get_current()
|
||||||
|
start_cursor:set_current()
|
||||||
|
local stop_cursor = pairing:find_closest(true)
|
||||||
|
cursor_current:set_current()
|
||||||
|
if stop_cursor then
|
||||||
|
local range = Range.new(start_cursor, stop_cursor, pairing)
|
||||||
|
range:parse()
|
||||||
|
return range
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function Range.new(start_cursor, stop_cursor, pairing)
|
||||||
|
local range = {
|
||||||
|
start_cursor = start_cursor,
|
||||||
|
stop_cursor = stop_cursor,
|
||||||
|
pairing = pairing,
|
||||||
|
params = {},
|
||||||
|
}
|
||||||
|
|
||||||
|
return setmetatable(range, Range)
|
||||||
|
end
|
||||||
|
|
||||||
|
function Range:parse()
|
||||||
|
local param = nil
|
||||||
|
local param_index = 1
|
||||||
|
|
||||||
|
local append_param_value = function(value, type)
|
||||||
|
if not param then
|
||||||
|
param = Param.new(self, param_index)
|
||||||
|
param_index = param_index + 1
|
||||||
|
end
|
||||||
|
param:append(value, type)
|
||||||
|
end
|
||||||
|
|
||||||
|
local append_param = function()
|
||||||
|
if param and not param:is_empty() then
|
||||||
|
table.insert(self.params, param:stripped())
|
||||||
|
end
|
||||||
|
param = nil
|
||||||
|
end
|
||||||
|
|
||||||
|
local cursor = self.start_cursor:next()
|
||||||
|
while cursor ~= self.stop_cursor do
|
||||||
|
local value = cursor:get_value()
|
||||||
|
|
||||||
|
if cursor:is_literal() then
|
||||||
|
append_param_value(cursor, 'cursor')
|
||||||
|
else
|
||||||
|
local range = find_at_cursor(cursor)
|
||||||
|
if range then
|
||||||
|
append_param_value(range, 'range')
|
||||||
|
cursor = range.stop_cursor
|
||||||
|
elseif value == ',' then
|
||||||
|
append_param()
|
||||||
|
else
|
||||||
|
append_param_value(cursor, 'cursor')
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
cursor = cursor:next()
|
||||||
|
end
|
||||||
|
|
||||||
|
append_param()
|
||||||
|
end
|
||||||
|
|
||||||
|
function Range:hit_test(cursor)
|
||||||
|
if self:contains(cursor) then
|
||||||
|
local trace = nil
|
||||||
|
for i, param in pairs(self.params) do
|
||||||
|
local trace_param = param:hit_test(cursor)
|
||||||
|
if trace_param then
|
||||||
|
trace = {i}
|
||||||
|
for _, trace_param_frame in ipairs(trace_param) do
|
||||||
|
table.insert(trace, trace_param_frame)
|
||||||
|
end
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if not trace then
|
||||||
|
trace = {0}
|
||||||
|
end
|
||||||
|
|
||||||
|
return trace
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function Range:hit_search(trace, depth)
|
||||||
|
local index = trace[depth]
|
||||||
|
if index == 0 then
|
||||||
|
return self.start_cursor
|
||||||
|
else
|
||||||
|
return self.params[index]:hit_search(trace, depth + 1)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function Range:write(builder, wrapped)
|
||||||
|
if wrapped == nil then
|
||||||
|
wrapped = self:is_wrapped()
|
||||||
|
end
|
||||||
|
|
||||||
|
if wrapped then
|
||||||
|
builder:write(self.pairing.open)
|
||||||
|
|
||||||
|
if #self.params > 0 then
|
||||||
|
builder:endline()
|
||||||
|
builder:push_indent()
|
||||||
|
|
||||||
|
for i, param in ipairs(self.params) do
|
||||||
|
param:write(builder)
|
||||||
|
|
||||||
|
local is_last_param = i == #self.params
|
||||||
|
if not is_last_param or self:query_option('comma_last') then
|
||||||
|
builder:write(',')
|
||||||
|
end
|
||||||
|
if not is_last_param then
|
||||||
|
builder:endline()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if self:query_option('brace_last_wrap') then
|
||||||
|
builder:endline()
|
||||||
|
builder:pop_indent()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if not self:query_option('brace_last_wrap') then
|
||||||
|
if self:query_option('brace_last_indent') then
|
||||||
|
builder:indent()
|
||||||
|
end
|
||||||
|
|
||||||
|
if self:query_option('brace_pad') then
|
||||||
|
builder:write(' ')
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
builder:write(self.pairing.close)
|
||||||
|
else
|
||||||
|
builder:write(self.pairing.open)
|
||||||
|
if self:query_option('brace_pad') then
|
||||||
|
builder:write(' ')
|
||||||
|
end
|
||||||
|
|
||||||
|
for i, param in ipairs( self.params ) do
|
||||||
|
param:write(builder)
|
||||||
|
|
||||||
|
local is_last_param = i == #self.params
|
||||||
|
if not is_last_param then
|
||||||
|
builder:write(', ')
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if self:query_option('brace_pad') then
|
||||||
|
builder:write(' ')
|
||||||
|
end
|
||||||
|
builder:write(self.pairing.close)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function Range:contains(cursor)
|
||||||
|
return cursor >= self.start_cursor and cursor <= self.stop_cursor
|
||||||
|
end
|
||||||
|
|
||||||
|
function Range:query_option(name)
|
||||||
|
return Options.query(name, self.pairing)
|
||||||
|
end
|
||||||
|
|
||||||
|
function Range:is_wrapped()
|
||||||
|
return self.start_cursor.row ~= self.stop_cursor.row
|
||||||
|
end
|
||||||
|
|
||||||
|
function Range.__lt(range_1, range_2)
|
||||||
|
local cursor = Cursor:get_current()
|
||||||
|
|
||||||
|
local row_diff1 = range_1.start_cursor.row - cursor.row
|
||||||
|
local col_diff1 = range_1.start_cursor.col - cursor.col
|
||||||
|
local row_diff2 = range_2.start_cursor.row - cursor.row
|
||||||
|
local col_diff2 = range_2.start_cursor.col - cursor.col
|
||||||
|
|
||||||
|
if row_diff1 < row_diff2 then
|
||||||
|
return false
|
||||||
|
elseif row_diff1 > row_diff2 then
|
||||||
|
return true
|
||||||
|
elseif col_diff1 < col_diff2 then
|
||||||
|
return false
|
||||||
|
elseif col_diff1 > col_diff2 then
|
||||||
|
return true
|
||||||
|
else
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return {
|
||||||
|
find_closest = find_closest,
|
||||||
|
find_at_cursor = find_at_cursor,
|
||||||
|
}
|
@ -1,620 +0,0 @@
|
|||||||
--
|
|
||||||
-- Cursor
|
|
||||||
--
|
|
||||||
|
|
||||||
local Cursor = {}
|
|
||||||
Cursor.__index = Cursor
|
|
||||||
|
|
||||||
function Cursor.new(row, col)
|
|
||||||
local cursor = {row = row, col = col}
|
|
||||||
return setmetatable(cursor, Cursor)
|
|
||||||
end
|
|
||||||
|
|
||||||
function Cursor:is_valid()
|
|
||||||
return self.row > 0 and self.col > 0
|
|
||||||
end
|
|
||||||
|
|
||||||
function Cursor:is_literal()
|
|
||||||
assert(self:is_valid())
|
|
||||||
local syn_id = vim.fn.synID(self.row, self.col, false)
|
|
||||||
local syn_attr = vim.fn.synIDattr(syn_id, 'name')
|
|
||||||
return syn_attr:find('String$') ~= nil or syn_attr:find('Comment$') ~= nil
|
|
||||||
end
|
|
||||||
|
|
||||||
function Cursor.get_current()
|
|
||||||
local _, row, col, _ = unpack(vim.fn.getpos('.'))
|
|
||||||
return Cursor.new(row, col)
|
|
||||||
end
|
|
||||||
|
|
||||||
function Cursor:set_current()
|
|
||||||
assert(self:is_valid())
|
|
||||||
vim.fn.setcursorcharpos({self.row, self.col})
|
|
||||||
end
|
|
||||||
|
|
||||||
function Cursor.__eq(self, other)
|
|
||||||
return self.row == other.row and self.col == other.col
|
|
||||||
end
|
|
||||||
|
|
||||||
--
|
|
||||||
-- BracePair
|
|
||||||
--
|
|
||||||
|
|
||||||
local BracePair = {}
|
|
||||||
BracePair.__index = BracePair
|
|
||||||
|
|
||||||
function BracePair.new(open, close)
|
|
||||||
local pair = {open = open, close = close}
|
|
||||||
return setmetatable(pair, BracePair)
|
|
||||||
end
|
|
||||||
|
|
||||||
function BracePair.from_brace(brace)
|
|
||||||
local all_pairs = {
|
|
||||||
{'(', ')'},
|
|
||||||
{'[', ']'},
|
|
||||||
{'{', '}'},
|
|
||||||
{'<', '>'},
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, pair in ipairs(all_pairs) do
|
|
||||||
if pair[1] == brace or pair[2] == brace then
|
|
||||||
return BracePair.new(pair[1], pair[2])
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function BracePair:get_escaped()
|
|
||||||
local escape_func = function(brace_raw)
|
|
||||||
if brace_raw == '[' or brace_raw == ']' then
|
|
||||||
return '\\' .. brace_raw
|
|
||||||
else
|
|
||||||
return brace_raw
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
return BracePair.new(
|
|
||||||
escape_func(self.open),
|
|
||||||
escape_func(self.close)
|
|
||||||
)
|
|
||||||
end
|
|
||||||
|
|
||||||
function BracePair:find_closest(backward)
|
|
||||||
-- See flags: https://neovim.io/doc/user/builtin.html#search()
|
|
||||||
local flags = 'Wcn'
|
|
||||||
if backward then
|
|
||||||
flags = 'Wcnb'
|
|
||||||
end
|
|
||||||
|
|
||||||
local ignore_func = function()
|
|
||||||
local cursor = Cursor.get_current()
|
|
||||||
return cursor:is_literal()
|
|
||||||
end
|
|
||||||
|
|
||||||
local escaped_pair = self:get_escaped()
|
|
||||||
local position = vim.fn.searchpairpos(
|
|
||||||
escaped_pair.open,
|
|
||||||
'',
|
|
||||||
escaped_pair.close,
|
|
||||||
flags,
|
|
||||||
ignore_func
|
|
||||||
)
|
|
||||||
|
|
||||||
local brace_cursor = Cursor.new(unpack(position))
|
|
||||||
if brace_cursor:is_valid() then
|
|
||||||
return brace_cursor
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function BracePair.__eq(self, other)
|
|
||||||
return self.open == other.open and self.close == other.close
|
|
||||||
end
|
|
||||||
|
|
||||||
--
|
|
||||||
-- BraceStack
|
|
||||||
--
|
|
||||||
|
|
||||||
local BraceStack = {}
|
|
||||||
BraceStack.__index = BraceStack
|
|
||||||
|
|
||||||
function BraceStack.new()
|
|
||||||
local stack = {stack = {}}
|
|
||||||
return setmetatable(stack, BraceStack)
|
|
||||||
end
|
|
||||||
|
|
||||||
function BraceStack:update(brace)
|
|
||||||
local pair = BracePair.from_brace(brace)
|
|
||||||
if pair then
|
|
||||||
if brace == pair.close and self:top() == pair.open then
|
|
||||||
self:pop()
|
|
||||||
else
|
|
||||||
self:push(brace)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function BraceStack:push(brace)
|
|
||||||
table.insert(self.stack, brace)
|
|
||||||
end
|
|
||||||
|
|
||||||
function BraceStack:pop()
|
|
||||||
assert(not self:empty())
|
|
||||||
return table.remove(self.stack, #self.stack)
|
|
||||||
end
|
|
||||||
|
|
||||||
function BraceStack:empty()
|
|
||||||
return #self.stack == 0
|
|
||||||
end
|
|
||||||
|
|
||||||
function BraceStack:top()
|
|
||||||
return self.stack[#self.stack]
|
|
||||||
end
|
|
||||||
|
|
||||||
--
|
|
||||||
-- BraceRange
|
|
||||||
--
|
|
||||||
|
|
||||||
local BraceRange = {}
|
|
||||||
BraceRange.__index = BraceRange
|
|
||||||
|
|
||||||
function BraceRange.new(start, stop, pair)
|
|
||||||
local range = {
|
|
||||||
start = start,
|
|
||||||
stop = stop,
|
|
||||||
pair = pair,
|
|
||||||
}
|
|
||||||
|
|
||||||
return setmetatable(range, BraceRange)
|
|
||||||
end
|
|
||||||
|
|
||||||
function BraceRange.find_closest(pair)
|
|
||||||
local stop = pair:find_closest(false)
|
|
||||||
if stop then
|
|
||||||
local start = pair:find_closest(true)
|
|
||||||
if start then
|
|
||||||
return BraceRange.new(start, stop, pair)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function BraceRange.find_closest_any()
|
|
||||||
local ranges = {}
|
|
||||||
for _, brace in ipairs({'(', '[', '{', '<'}) do
|
|
||||||
local pair = BracePair.from_brace(brace)
|
|
||||||
local range = BraceRange.find_closest(pair)
|
|
||||||
if range then
|
|
||||||
table.insert(ranges, range)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
if #ranges > 0 then
|
|
||||||
table.sort(ranges)
|
|
||||||
return ranges[1]
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function BraceRange:get_rows()
|
|
||||||
return self.stop.row - self.start.row
|
|
||||||
end
|
|
||||||
|
|
||||||
function BraceRange:is_wrapped()
|
|
||||||
return self.start.row < self.stop.row
|
|
||||||
end
|
|
||||||
|
|
||||||
function BraceRange.__lt(range_1, range_2)
|
|
||||||
local cursor = Cursor:get_current()
|
|
||||||
|
|
||||||
local row_diff1 = range_1.start.row - cursor.row
|
|
||||||
local col_diff1 = range_1.start.col - cursor.col
|
|
||||||
local row_diff2 = range_2.start.row - cursor.row
|
|
||||||
local col_diff2 = range_2.start.col - cursor.col
|
|
||||||
|
|
||||||
if row_diff1 < row_diff2 then
|
|
||||||
return false
|
|
||||||
elseif row_diff1 > row_diff2 then
|
|
||||||
return true
|
|
||||||
elseif col_diff1 < col_diff2 then
|
|
||||||
return false
|
|
||||||
elseif col_diff1 > col_diff2 then
|
|
||||||
return true
|
|
||||||
else
|
|
||||||
return true
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
--
|
|
||||||
-- Param
|
|
||||||
--
|
|
||||||
|
|
||||||
local Param = {}
|
|
||||||
Param.__index = Param
|
|
||||||
|
|
||||||
function Param.new(pair, opt)
|
|
||||||
local param = {
|
|
||||||
pair = pair,
|
|
||||||
opt = opt,
|
|
||||||
text = '',
|
|
||||||
literals = {},
|
|
||||||
offset = nil,
|
|
||||||
start = nil,
|
|
||||||
stop = nil,
|
|
||||||
terminator = nil,
|
|
||||||
}
|
|
||||||
|
|
||||||
return setmetatable(param, Param)
|
|
||||||
end
|
|
||||||
|
|
||||||
function Param:append(char, cursor)
|
|
||||||
assert(cursor:is_valid())
|
|
||||||
|
|
||||||
self.text = self.text .. char
|
|
||||||
table.insert(self.literals, cursor:is_literal())
|
|
||||||
|
|
||||||
if cursor == Cursor.get_current() then
|
|
||||||
self.offset = #self.text
|
|
||||||
end
|
|
||||||
|
|
||||||
if not self.start then
|
|
||||||
self.start = cursor
|
|
||||||
end
|
|
||||||
|
|
||||||
self.stop = cursor
|
|
||||||
end
|
|
||||||
|
|
||||||
function Param:terminate(cursor)
|
|
||||||
self.terminator = cursor
|
|
||||||
if self.terminator == Cursor.get_current() then
|
|
||||||
self.offset = #self.text
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function Param:is_active()
|
|
||||||
return self.offset ~= nil
|
|
||||||
end
|
|
||||||
|
|
||||||
function Param:slice(start, stop)
|
|
||||||
assert(#self.text == #self.literals)
|
|
||||||
|
|
||||||
local text = ''
|
|
||||||
local literals = {}
|
|
||||||
|
|
||||||
for i = start, stop do
|
|
||||||
text = text .. self.text:sub(i, i)
|
|
||||||
table.insert(literals, self.literals[i])
|
|
||||||
end
|
|
||||||
|
|
||||||
self.text = text
|
|
||||||
self.literals = literals
|
|
||||||
|
|
||||||
if self.offset then
|
|
||||||
self.offset = math.min(self.offset, stop)
|
|
||||||
self.offset = math.max(self.offset - start + 1, 1)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function Param:trim()
|
|
||||||
assert(#self.text == #self.literals)
|
|
||||||
|
|
||||||
self:slice(1, #self.text - #self.text:match('%s*$'))
|
|
||||||
self:slice(1 + #self.text:match('^%s*'), #self.text)
|
|
||||||
|
|
||||||
local text = ''
|
|
||||||
local literals = {}
|
|
||||||
local offset = self.offset
|
|
||||||
|
|
||||||
for i = 1, #self.text do
|
|
||||||
local char = self.text:sub(i, i)
|
|
||||||
local literal = self.literals[i]
|
|
||||||
|
|
||||||
if literal or not char:match('%s') or not text:match('%s$') then
|
|
||||||
text = text .. char
|
|
||||||
table.insert(literals, literal)
|
|
||||||
elseif offset and offset >= i then
|
|
||||||
self.offset = math.max(1, self.offset - 1)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
self.text = text
|
|
||||||
self.literals = literals
|
|
||||||
|
|
||||||
return #self.text > 0
|
|
||||||
end
|
|
||||||
|
|
||||||
--
|
|
||||||
-- ParamList
|
|
||||||
--
|
|
||||||
|
|
||||||
local ParamList = {}
|
|
||||||
ParamList.__index = ParamList
|
|
||||||
|
|
||||||
function ParamList.new(range, opt)
|
|
||||||
local params = {
|
|
||||||
range = range,
|
|
||||||
opt = opt,
|
|
||||||
current = nil,
|
|
||||||
parsed = {},
|
|
||||||
}
|
|
||||||
|
|
||||||
return setmetatable(params, ParamList)
|
|
||||||
end
|
|
||||||
|
|
||||||
function ParamList:flush(cursor)
|
|
||||||
if self.current then
|
|
||||||
if cursor then
|
|
||||||
self.current:terminate(cursor)
|
|
||||||
end
|
|
||||||
|
|
||||||
if self.current:trim() then
|
|
||||||
table.insert(self.parsed, self.current)
|
|
||||||
end
|
|
||||||
|
|
||||||
self.current = nil
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function ParamList:update(char, brace_stack, cursor)
|
|
||||||
if not cursor:is_literal() then
|
|
||||||
brace_stack:update(char)
|
|
||||||
if brace_stack:empty() and char == ',' then
|
|
||||||
self:flush(cursor)
|
|
||||||
return
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
if not self.current then
|
|
||||||
self.current = Param.new(self.range, self.opt)
|
|
||||||
end
|
|
||||||
|
|
||||||
self.current:append(char, cursor)
|
|
||||||
end
|
|
||||||
|
|
||||||
function ParamList:parse()
|
|
||||||
local brace_stack = BraceStack:new()
|
|
||||||
|
|
||||||
for row = self.range.start.row, self.range.stop.row do
|
|
||||||
local line = vim.fn.getline(row)
|
|
||||||
|
|
||||||
local start_col = 1
|
|
||||||
if row == self.range.start.row then
|
|
||||||
start_col = self.range.start.col + 1
|
|
||||||
end
|
|
||||||
|
|
||||||
local stop_col = #line
|
|
||||||
if row == self.range.stop.row then
|
|
||||||
stop_col = self.range.stop.col - 1
|
|
||||||
end
|
|
||||||
|
|
||||||
for col = start_col, stop_col do
|
|
||||||
self:update(line:sub(col, col), brace_stack, Cursor.new(row, col))
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
self:flush()
|
|
||||||
end
|
|
||||||
|
|
||||||
--
|
|
||||||
-- Builder
|
|
||||||
--
|
|
||||||
|
|
||||||
local Builder = {}
|
|
||||||
Builder.__index = Builder
|
|
||||||
|
|
||||||
function Builder.new(indent_level, indent_block)
|
|
||||||
local builder = {
|
|
||||||
lines = {},
|
|
||||||
line = '',
|
|
||||||
indent_level = indent_level,
|
|
||||||
indent_block = indent_block,
|
|
||||||
}
|
|
||||||
|
|
||||||
return setmetatable(builder, Builder)
|
|
||||||
end
|
|
||||||
|
|
||||||
function Builder:indent()
|
|
||||||
self.indent_level = self.indent_level + 1
|
|
||||||
end
|
|
||||||
|
|
||||||
function Builder:unindent()
|
|
||||||
assert(self.indent_level > 0)
|
|
||||||
self.indent_level = self.indent_level - 1
|
|
||||||
end
|
|
||||||
|
|
||||||
function Builder:update(text)
|
|
||||||
self.line = self.line .. text
|
|
||||||
end
|
|
||||||
|
|
||||||
function Builder:flush()
|
|
||||||
local indent = string.rep(self.indent_block, self.indent_level)
|
|
||||||
table.insert(self.lines, indent .. self.line)
|
|
||||||
self.line = ''
|
|
||||||
end
|
|
||||||
|
|
||||||
function Builder:get_offset()
|
|
||||||
local indent = string.rep(self.indent_block, self.indent_level)
|
|
||||||
return Cursor.new(#self.lines, #self.line + #indent)
|
|
||||||
end
|
|
||||||
|
|
||||||
--
|
|
||||||
-- WrapContext
|
|
||||||
--
|
|
||||||
|
|
||||||
local WrapContext = {}
|
|
||||||
WrapContext.__index = WrapContext
|
|
||||||
|
|
||||||
function WrapContext.new(opt)
|
|
||||||
local wrap_context = {
|
|
||||||
opt = nil,
|
|
||||||
base_opt = opt,
|
|
||||||
indent = '',
|
|
||||||
prefix = '',
|
|
||||||
suffix = '',
|
|
||||||
range = nil,
|
|
||||||
params = nil,
|
|
||||||
}
|
|
||||||
|
|
||||||
return setmetatable(wrap_context, WrapContext)
|
|
||||||
end
|
|
||||||
|
|
||||||
function WrapContext:config_opt()
|
|
||||||
self.opt = {}
|
|
||||||
for key, value in pairs(self.base_opt) do
|
|
||||||
if type(value) == 'table' then
|
|
||||||
self.opt[key] = false
|
|
||||||
for _, brace in ipairs(value) do
|
|
||||||
if self.range.pair == BracePair.from_brace(brace) then
|
|
||||||
self.opt[key] = true
|
|
||||||
break
|
|
||||||
end
|
|
||||||
end
|
|
||||||
else
|
|
||||||
self.opt[key] = value
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function WrapContext:config_indent(line)
|
|
||||||
local padding = #line:match('^(%s*)')
|
|
||||||
if vim.o.expandtab then
|
|
||||||
self.indent_level = math.floor(padding / vim.o.shiftwidth)
|
|
||||||
self.indent_block = string.rep(' ', vim.o.shiftwidth)
|
|
||||||
else
|
|
||||||
self.indent_level = padding
|
|
||||||
self.indent_block = '\t'
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function WrapContext:parse()
|
|
||||||
self.range = BraceRange.find_closest_any()
|
|
||||||
if not self.range then
|
|
||||||
return false
|
|
||||||
end
|
|
||||||
|
|
||||||
self:config_opt()
|
|
||||||
|
|
||||||
if self.range:get_rows() > self.opt.line_max then
|
|
||||||
return false
|
|
||||||
end
|
|
||||||
|
|
||||||
local first_line = vim.fn.getline(self.range.start.row)
|
|
||||||
local last_line = vim.fn.getline(self.range.stop.row)
|
|
||||||
self:config_indent(first_line)
|
|
||||||
self.prefix = first_line:sub(self.indent_level * #self.indent_block + 1, self.range.start.col)
|
|
||||||
self.suffix = last_line:sub(self.range.stop.col)
|
|
||||||
|
|
||||||
self.params = ParamList.new(self.range, self.opt)
|
|
||||||
self.params:parse()
|
|
||||||
|
|
||||||
return true
|
|
||||||
end
|
|
||||||
|
|
||||||
function WrapContext:update_builder_param(builder, param)
|
|
||||||
local cursor = nil
|
|
||||||
if param:is_active() then
|
|
||||||
cursor = builder:get_offset()
|
|
||||||
cursor.row = cursor.row + self.range.start.row
|
|
||||||
cursor.col = cursor.col + param.offset
|
|
||||||
end
|
|
||||||
|
|
||||||
builder:update(param.text)
|
|
||||||
return cursor
|
|
||||||
end
|
|
||||||
|
|
||||||
function WrapContext:wrap()
|
|
||||||
local builder = Builder.new(self.indent_level, self.indent_block)
|
|
||||||
builder:update(self.prefix)
|
|
||||||
builder:flush()
|
|
||||||
builder:indent()
|
|
||||||
|
|
||||||
local cursor = nil
|
|
||||||
for i, param in ipairs(self.params.parsed) do
|
|
||||||
local is_first_param = i == 1
|
|
||||||
local is_last_param = i == #self.params.parsed
|
|
||||||
|
|
||||||
if self.opt.comma_prefix then
|
|
||||||
if not is_first_param then
|
|
||||||
builder:update(', ')
|
|
||||||
elseif self.opt.comma_prefix_indent and not is_last_param then
|
|
||||||
builder:update(' ')
|
|
||||||
end
|
|
||||||
cursor = self:update_builder_param(builder, param) or cursor
|
|
||||||
else
|
|
||||||
cursor = self:update_builder_param(builder, param) or cursor
|
|
||||||
if not is_last_param or self.opt.comma_last then
|
|
||||||
builder:update(',')
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
if is_last_param and not self.opt.brace_last_wrap then
|
|
||||||
builder:update(self.suffix)
|
|
||||||
end
|
|
||||||
|
|
||||||
builder:flush()
|
|
||||||
end
|
|
||||||
|
|
||||||
if not self.opt.brace_last_indent then
|
|
||||||
builder:unindent()
|
|
||||||
end
|
|
||||||
|
|
||||||
if self.opt.brace_last_wrap then
|
|
||||||
builder:update(self.suffix)
|
|
||||||
builder:flush()
|
|
||||||
end
|
|
||||||
|
|
||||||
local row = self.range.start.row
|
|
||||||
for i, line in ipairs(builder.lines) do
|
|
||||||
if i == 1 then
|
|
||||||
vim.fn.setline(row, line)
|
|
||||||
else
|
|
||||||
vim.fn.append(row, line)
|
|
||||||
row = row + 1
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
if not cursor then
|
|
||||||
cursor = self.range.start
|
|
||||||
end
|
|
||||||
|
|
||||||
cursor:set_current()
|
|
||||||
end
|
|
||||||
|
|
||||||
function WrapContext:unwrap()
|
|
||||||
local padding = ''
|
|
||||||
if self.opt.brace_pad then
|
|
||||||
padding = ' '
|
|
||||||
end
|
|
||||||
|
|
||||||
local builder = Builder.new(self.indent_level, self.indent_block)
|
|
||||||
builder:update(self.prefix)
|
|
||||||
builder:update(padding)
|
|
||||||
|
|
||||||
local cursor = nil
|
|
||||||
for i, param in ipairs(self.params.parsed) do
|
|
||||||
cursor = self:update_builder_param(builder, param) or cursor
|
|
||||||
if i < #self.params.parsed then
|
|
||||||
builder:update(', ')
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
builder:update(padding)
|
|
||||||
builder:update(self.suffix)
|
|
||||||
builder:flush()
|
|
||||||
|
|
||||||
vim.fn.setline(self.range.start.row, builder.lines[1])
|
|
||||||
vim.fn.execute(string.format('%d,%dd_', self.range.start.row + 1, self.range.stop.row))
|
|
||||||
|
|
||||||
if not cursor then
|
|
||||||
cursor = self.range.start
|
|
||||||
end
|
|
||||||
|
|
||||||
cursor:set_current()
|
|
||||||
end
|
|
||||||
|
|
||||||
function WrapContext:toggle()
|
|
||||||
if self.range:is_wrapped() then
|
|
||||||
self:unwrap()
|
|
||||||
else
|
|
||||||
self:wrap()
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
return {
|
|
||||||
WrapContext = WrapContext,
|
|
||||||
}
|
|
@ -1,4 +1,4 @@
|
|||||||
if not vim.g.argonaut then
|
if not vim.g.argonaut_loaded then
|
||||||
local function argonaut_reload()
|
local function argonaut_reload()
|
||||||
for name, _ in pairs(package.loaded) do
|
for name, _ in pairs(package.loaded) do
|
||||||
if vim.startswith(name, 'argonaut') then
|
if vim.startswith(name, 'argonaut') then
|
||||||
@ -8,11 +8,12 @@ if not vim.g.argonaut then
|
|||||||
end
|
end
|
||||||
|
|
||||||
local function argonaut_reflow()
|
local function argonaut_reflow()
|
||||||
|
argonaut_reload()
|
||||||
require('argonaut').reflow()
|
require('argonaut').reflow()
|
||||||
end
|
end
|
||||||
|
|
||||||
vim.api.nvim_create_user_command('ArgonautReload', argonaut_reload, {})
|
vim.api.nvim_create_user_command('ArgonautReload', argonaut_reload, {})
|
||||||
vim.api.nvim_create_user_command('ArgonautReflow', argonaut_reflow, {})
|
vim.api.nvim_create_user_command('ArgonautReflow', argonaut_reflow, {})
|
||||||
|
|
||||||
vim.g.argonaut = true
|
vim.g.argonaut_loaded = true
|
||||||
end
|
end
|
||||||
|
Loading…
Reference in New Issue
Block a user