Compare commits
15 Commits
09db9fb7aa
...
2b2d831837
Author | SHA1 | Date | |
---|---|---|---|
2b2d831837 | |||
5de6deae99 | |||
50216e52a9 | |||
9d241775a9 | |||
c068ad5b84 | |||
66400690bf | |||
0deb8db17e | |||
75cc3a3cb5 | |||
ca45fc2fdb | |||
a9b2f24d46 | |||
170dccdaa9 | |||
d06d6865df | |||
e8dcbc6da4 | |||
0778dbca64 | |||
193d7fbd57 |
@ -1,4 +1,4 @@
|
|||||||
local configs = {
|
local opt_curr = {
|
||||||
default = {
|
default = {
|
||||||
brace_last_indent = false,
|
brace_last_indent = false,
|
||||||
brace_last_wrap = true,
|
brace_last_wrap = true,
|
||||||
@ -6,57 +6,50 @@ local configs = {
|
|||||||
comma_last = false,
|
comma_last = false,
|
||||||
comma_prefix = false,
|
comma_prefix = false,
|
||||||
comma_prefix_indent = false,
|
comma_prefix_indent = false,
|
||||||
|
line_max = 32,
|
||||||
line_prefix = '',
|
line_prefix = '',
|
||||||
|
trim_inner_spaces = true,
|
||||||
},
|
},
|
||||||
go = {
|
go = {
|
||||||
comma_last = true,
|
comma_last = true,
|
||||||
},
|
},
|
||||||
vim = {
|
vim = {
|
||||||
brace_last_wrap = false,
|
line_prefix = '\\',
|
||||||
line_prefix = '\\ ',
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
local function set(opts, filetypes)
|
local function setup(opt)
|
||||||
if opts then
|
for file_type, file_opt in pairs(opt) do
|
||||||
if type(filetypes) == 'string' then
|
local file_opt_curr = opt_curr[file_type]
|
||||||
filetypes = {filetypes}
|
if not file_opt_curr then
|
||||||
elseif not filetypes then
|
file_opt_curr = {}
|
||||||
filetypes = {'default'}
|
opt_curr[file_type] = file_opt_curr
|
||||||
end
|
end
|
||||||
|
|
||||||
for _, filetype in ipairs(filetypes) do
|
for param_name, param_value in pairs(file_opt) do
|
||||||
local config = configs[filetype]
|
file_opt_curr[param_name] = param_value
|
||||||
if not config then
|
|
||||||
config = {}
|
|
||||||
configs[filetype] = config
|
|
||||||
end
|
|
||||||
|
|
||||||
for key, value in pairs(opts) do
|
|
||||||
config[key] = value
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
local function get()
|
local function get()
|
||||||
local file_config = configs[vim.bo.filetype]
|
local file_opt_curr = opt_curr[vim.bo.filetype]
|
||||||
|
|
||||||
local config = {}
|
local file_opt = {}
|
||||||
for key, value in pairs(configs.default) do
|
for param_name, param_value in pairs(opt_curr.default) do
|
||||||
config[key] = value
|
file_opt[param_name] = param_value
|
||||||
if file_config then
|
if file_opt_curr then
|
||||||
local file_value = file_config[key]
|
param_value = file_opt_curr[param_name]
|
||||||
if file_value ~= nil then
|
if param_value ~= nil then
|
||||||
config[key] = file_config[key]
|
file_opt[param_name] = param_value
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
return config
|
return file_opt
|
||||||
end
|
end
|
||||||
|
|
||||||
return {
|
return {
|
||||||
set = set,
|
setup = setup,
|
||||||
get = get,
|
get = get,
|
||||||
}
|
}
|
||||||
|
@ -10,5 +10,5 @@ end
|
|||||||
|
|
||||||
return {
|
return {
|
||||||
reflow = reflow,
|
reflow = reflow,
|
||||||
setup = config.set,
|
setup = config.setup,
|
||||||
}
|
}
|
||||||
|
@ -14,11 +14,11 @@ function Cursor:is_valid()
|
|||||||
return self.row > 0 and self.col > 0
|
return self.row > 0 and self.col > 0
|
||||||
end
|
end
|
||||||
|
|
||||||
function Cursor:is_string()
|
function Cursor:is_literal()
|
||||||
assert(self:is_valid())
|
assert(self:is_valid())
|
||||||
local syn_id = vim.fn.synID(self.row, self.col, false)
|
local syn_id = vim.fn.synID(self.row, self.col, false)
|
||||||
local syn_attr = vim.fn.synIDattr(syn_id, 'name')
|
local syn_attr = vim.fn.synIDattr(syn_id, 'name')
|
||||||
return syn_attr:find('String$')
|
return syn_attr:find('String$') ~= nil or syn_attr:find('Comment$') ~= nil
|
||||||
end
|
end
|
||||||
|
|
||||||
function Cursor.get_current()
|
function Cursor.get_current()
|
||||||
@ -86,7 +86,7 @@ function BracePair:find_closest(backward)
|
|||||||
|
|
||||||
local ignore_func = function()
|
local ignore_func = function()
|
||||||
local cursor = Cursor.get_current()
|
local cursor = Cursor.get_current()
|
||||||
return cursor:is_string()
|
return cursor:is_literal()
|
||||||
end
|
end
|
||||||
|
|
||||||
local escaped_pair = self:get_escaped()
|
local escaped_pair = self:get_escaped()
|
||||||
@ -191,6 +191,10 @@ function BraceRange.find_closest_any()
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function BraceRange:get_rows()
|
||||||
|
return self.stop.row - self.start.row
|
||||||
|
end
|
||||||
|
|
||||||
function BraceRange:is_wrapped()
|
function BraceRange:is_wrapped()
|
||||||
return self.start.row < self.stop.row
|
return self.start.row < self.stop.row
|
||||||
end
|
end
|
||||||
@ -223,35 +227,100 @@ end
|
|||||||
local Param = {}
|
local Param = {}
|
||||||
Param.__index = Param
|
Param.__index = Param
|
||||||
|
|
||||||
function Param.new(text, pair)
|
function Param.new(pair, opt)
|
||||||
local param = {
|
local param = {
|
||||||
text = text,
|
|
||||||
pair = pair,
|
pair = pair,
|
||||||
|
opt = opt,
|
||||||
|
text = '',
|
||||||
|
literals = {},
|
||||||
offset = nil,
|
offset = nil,
|
||||||
|
start = nil,
|
||||||
|
stop = nil,
|
||||||
|
terminator = nil,
|
||||||
}
|
}
|
||||||
|
|
||||||
return setmetatable(param, Param)
|
return setmetatable(param, Param)
|
||||||
end
|
end
|
||||||
|
|
||||||
function Param:append(char)
|
function Param:append(char, cursor)
|
||||||
|
assert(cursor:is_valid())
|
||||||
|
|
||||||
self.text = self.text .. char
|
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
|
end
|
||||||
|
|
||||||
function Param:activate()
|
function Param:terminate(cursor)
|
||||||
|
self.terminator = cursor
|
||||||
|
if self.terminator == Cursor.get_current() then
|
||||||
self.offset = #self.text
|
self.offset = #self.text
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function Param:is_active()
|
function Param:is_active()
|
||||||
return self.offset ~= nil
|
return self.offset ~= nil
|
||||||
end
|
end
|
||||||
|
|
||||||
function Param:flush()
|
function Param:slice(start, stop)
|
||||||
if self.offset then
|
assert(#self.text == #self.literals)
|
||||||
self.offset = math.min(self.offset, #self.text:match('(.-)%s*$'))
|
|
||||||
self.offset = math.max(self.offset - #self.text:match('^%s*'), 1)
|
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)
|
||||||
|
|
||||||
|
if self.text:match('^' .. self.opt.line_prefix) then
|
||||||
|
self:slice(1 + #self.opt.line_prefix, #self.text)
|
||||||
|
end
|
||||||
|
|
||||||
|
if self.opt.trim_inner_spaces then
|
||||||
|
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
|
||||||
end
|
end
|
||||||
|
|
||||||
self.text = self.text:match('^%s*(.-)%s*$')
|
|
||||||
return #self.text > 0
|
return #self.text > 0
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -262,9 +331,10 @@ end
|
|||||||
local ParamList = {}
|
local ParamList = {}
|
||||||
ParamList.__index = ParamList
|
ParamList.__index = ParamList
|
||||||
|
|
||||||
function ParamList.new(range)
|
function ParamList.new(range, opt)
|
||||||
local params = {
|
local params = {
|
||||||
range = range,
|
range = range,
|
||||||
|
opt = opt,
|
||||||
current = nil,
|
current = nil,
|
||||||
parsed = {},
|
parsed = {},
|
||||||
}
|
}
|
||||||
@ -272,33 +342,34 @@ function ParamList.new(range)
|
|||||||
return setmetatable(params, ParamList)
|
return setmetatable(params, ParamList)
|
||||||
end
|
end
|
||||||
|
|
||||||
function ParamList:flush()
|
function ParamList:flush(cursor)
|
||||||
if self.current then
|
if self.current then
|
||||||
if self.current:flush() then
|
if cursor then
|
||||||
|
self.current:terminate(cursor)
|
||||||
|
end
|
||||||
|
|
||||||
|
if self.current:trim() then
|
||||||
table.insert(self.parsed, self.current)
|
table.insert(self.parsed, self.current)
|
||||||
end
|
end
|
||||||
|
|
||||||
self.current = nil
|
self.current = nil
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function ParamList:update(char, brace_stack, cursor)
|
function ParamList:update(char, brace_stack, cursor)
|
||||||
if not cursor:is_string() then
|
if not cursor:is_literal() then
|
||||||
brace_stack:update(char)
|
brace_stack:update(char)
|
||||||
if brace_stack:empty() and char == ',' then
|
if brace_stack:empty() and char == ',' then
|
||||||
self:flush()
|
self:flush(cursor)
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
if self.current then
|
if not self.current then
|
||||||
self.current:append(char)
|
self.current = Param.new(self.range, self.opt)
|
||||||
else
|
|
||||||
self.current = Param.new(char, self.range)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
if cursor == Cursor.get_current() then
|
self.current:append(char, cursor)
|
||||||
self.current:activate()
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
function ParamList:parse()
|
function ParamList:parse()
|
||||||
@ -320,9 +391,9 @@ function ParamList:parse()
|
|||||||
for col = start_col, stop_col do
|
for col = start_col, stop_col do
|
||||||
self:update(line:sub(col, col), brace_stack, Cursor.new(row, col))
|
self:update(line:sub(col, col), brace_stack, Cursor.new(row, col))
|
||||||
end
|
end
|
||||||
end
|
|
||||||
|
|
||||||
self:flush()
|
self:flush()
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
--
|
--
|
||||||
@ -376,7 +447,8 @@ WrapContext.__index = WrapContext
|
|||||||
|
|
||||||
function WrapContext.new(opt)
|
function WrapContext.new(opt)
|
||||||
local wrap_context = {
|
local wrap_context = {
|
||||||
opt = opt,
|
opt = nil,
|
||||||
|
base_opt = opt,
|
||||||
indent = '',
|
indent = '',
|
||||||
prefix = '',
|
prefix = '',
|
||||||
suffix = '',
|
suffix = '',
|
||||||
@ -387,50 +459,71 @@ function WrapContext.new(opt)
|
|||||||
return setmetatable(wrap_context, WrapContext)
|
return setmetatable(wrap_context, WrapContext)
|
||||||
end
|
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()
|
function WrapContext:parse()
|
||||||
self.range = BraceRange.find_closest_any()
|
self.range = BraceRange.find_closest_any()
|
||||||
if not self.range then
|
if not self.range then
|
||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
|
|
||||||
local first_line = vim.fn.getline(self.range.start.row)
|
self:config_opt()
|
||||||
local indent = #first_line:match('^(%s*)')
|
|
||||||
self.prefix = first_line:sub(indent + 1, self.range.start.col)
|
if self.range:get_rows() > self.opt.line_max then
|
||||||
if vim.o.expandtab then
|
return false
|
||||||
self.indent_level = indent / vim.o.shiftwidth
|
|
||||||
self.indent_block = string.rep(' ', vim.o.shiftwidth)
|
|
||||||
else
|
|
||||||
self.indent_level = indent
|
|
||||||
self.indent_block = '\t'
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
local first_line = vim.fn.getline(self.range.start.row)
|
||||||
local last_line = vim.fn.getline(self.range.stop.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.suffix = last_line:sub(self.range.stop.col)
|
||||||
|
|
||||||
self.params = ParamList.new(self.range)
|
self.params = ParamList.new(self.range, self.opt)
|
||||||
self.params:parse()
|
self.params:parse()
|
||||||
|
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
function WrapContext:update_builder_param(builder, param, opt)
|
function WrapContext:update_builder_param(builder, param)
|
||||||
local text = param.text
|
|
||||||
if #opt.line_prefix > 0 then
|
|
||||||
text = param.text:match('^%s*[' .. opt.line_prefix .. ']?%s*(.*)')
|
|
||||||
end
|
|
||||||
|
|
||||||
local cursor = nil
|
local cursor = nil
|
||||||
if param:is_active() then
|
if param:is_active() then
|
||||||
cursor = builder:get_offset()
|
cursor = builder:get_offset()
|
||||||
cursor.row = cursor.row + self.range.start.row
|
cursor.row = cursor.row + self.range.start.row
|
||||||
cursor.col = cursor.col + param.offset - (#param.text - #text)
|
cursor.col = cursor.col + param.offset
|
||||||
end
|
end
|
||||||
|
|
||||||
builder:update(text)
|
builder:update(param.text)
|
||||||
return cursor
|
return cursor
|
||||||
end
|
end
|
||||||
|
|
||||||
function WrapContext:wrap(opt)
|
function WrapContext:wrap()
|
||||||
local builder = Builder.new(self.indent_level, self.indent_block)
|
local builder = Builder.new(self.indent_level, self.indent_block)
|
||||||
builder:update(self.prefix)
|
builder:update(self.prefix)
|
||||||
builder:flush()
|
builder:flush()
|
||||||
@ -441,36 +534,35 @@ function WrapContext:wrap(opt)
|
|||||||
local is_first_param = i == 1
|
local is_first_param = i == 1
|
||||||
local is_last_param = i == #self.params.parsed
|
local is_last_param = i == #self.params.parsed
|
||||||
|
|
||||||
if opt.comma_prefix then
|
if self.opt.comma_prefix then
|
||||||
builder:update(opt.line_prefix)
|
builder:update(self.opt.line_prefix)
|
||||||
if not is_first_param then
|
if not is_first_param then
|
||||||
builder:update(', ')
|
builder:update(', ')
|
||||||
elseif opt.comma_prefix_indent and not is_last_param then
|
elseif self.opt.comma_prefix_indent and not is_last_param then
|
||||||
builder:update(' ')
|
builder:update(' ')
|
||||||
end
|
end
|
||||||
|
cursor = self:update_builder_param(builder, param) or cursor
|
||||||
cursor = self:update_builder_param(builder, param, opt) or cursor
|
|
||||||
else
|
else
|
||||||
builder:update(opt.line_prefix)
|
builder:update(self.opt.line_prefix)
|
||||||
cursor = self:update_builder_param(builder, param, opt) or cursor
|
cursor = self:update_builder_param(builder, param) or cursor
|
||||||
|
if not is_last_param or self.opt.comma_last then
|
||||||
if not is_last_param or opt.comma_last then
|
|
||||||
builder:update(',')
|
builder:update(',')
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
if is_last_param and not opt.brace_last_wrap then
|
if is_last_param and not self.opt.brace_last_wrap then
|
||||||
builder:update(self.suffix)
|
builder:update(self.suffix)
|
||||||
end
|
end
|
||||||
|
|
||||||
builder:flush()
|
builder:flush()
|
||||||
end
|
end
|
||||||
|
|
||||||
if not opt.brace_last_indent then
|
if not self.opt.brace_last_indent then
|
||||||
builder:unindent()
|
builder:unindent()
|
||||||
end
|
end
|
||||||
|
|
||||||
if opt.brace_last_wrap then
|
if self.opt.brace_last_wrap then
|
||||||
|
builder:update(self.opt.line_prefix)
|
||||||
builder:update(self.suffix)
|
builder:update(self.suffix)
|
||||||
builder:flush()
|
builder:flush()
|
||||||
end
|
end
|
||||||
@ -485,14 +577,16 @@ function WrapContext:wrap(opt)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
if cursor then
|
if not cursor then
|
||||||
cursor:set_current()
|
cursor = self.range.start
|
||||||
end
|
end
|
||||||
|
|
||||||
|
cursor:set_current()
|
||||||
end
|
end
|
||||||
|
|
||||||
function WrapContext:unwrap(opt)
|
function WrapContext:unwrap()
|
||||||
local padding = ''
|
local padding = ''
|
||||||
if opt.brace_pad then
|
if self.opt.brace_pad then
|
||||||
padding = ' '
|
padding = ' '
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -502,7 +596,7 @@ function WrapContext:unwrap(opt)
|
|||||||
|
|
||||||
local cursor = nil
|
local cursor = nil
|
||||||
for i, param in ipairs(self.params.parsed) do
|
for i, param in ipairs(self.params.parsed) do
|
||||||
cursor = self:update_builder_param(builder, param, opt) or cursor
|
cursor = self:update_builder_param(builder, param) or cursor
|
||||||
if i < #self.params.parsed then
|
if i < #self.params.parsed then
|
||||||
builder:update(', ')
|
builder:update(', ')
|
||||||
end
|
end
|
||||||
@ -513,45 +607,23 @@ function WrapContext:unwrap(opt)
|
|||||||
builder:flush()
|
builder:flush()
|
||||||
|
|
||||||
vim.fn.setline(self.range.start.row, builder.lines[1])
|
vim.fn.setline(self.range.start.row, builder.lines[1])
|
||||||
vim.fn.execute(string.format(
|
vim.fn.execute(string.format('%d,%dd_', self.range.start.row + 1, self.range.stop.row))
|
||||||
'%d,%dd_',
|
|
||||||
self.range.start.row + 1,
|
|
||||||
self.range.stop.row
|
|
||||||
))
|
|
||||||
|
|
||||||
if cursor then
|
if not cursor then
|
||||||
cursor:set_current()
|
cursor = self.range.start
|
||||||
end
|
end
|
||||||
|
|
||||||
|
cursor:set_current()
|
||||||
end
|
end
|
||||||
|
|
||||||
function WrapContext:toggle()
|
function WrapContext:toggle()
|
||||||
local opt = self:specialize_opt()
|
|
||||||
if self.range:is_wrapped() then
|
if self.range:is_wrapped() then
|
||||||
self:unwrap(opt)
|
self:unwrap()
|
||||||
else
|
else
|
||||||
self:wrap(opt)
|
self:wrap()
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function WrapContext:specialize_opt()
|
|
||||||
local opt = {}
|
|
||||||
for key, value in pairs(self.opt) do
|
|
||||||
if type(value) == 'table' then
|
|
||||||
opt[key] = false
|
|
||||||
for _, brace in ipairs(value) do
|
|
||||||
if self.range.pair == BracePair.from_brace(brace) then
|
|
||||||
opt[key] = true
|
|
||||||
break
|
|
||||||
end
|
|
||||||
end
|
|
||||||
else
|
|
||||||
opt[key] = value
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
return opt
|
|
||||||
end
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
WrapContext = WrapContext,
|
WrapContext = WrapContext,
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user