indents: refactor hanging indent

This commit is contained in:
Stephan Seitz 2022-01-22 17:07:25 +01:00
parent 059fbc487c
commit b9c38a48ca
3 changed files with 25 additions and 36 deletions

View file

@ -13,17 +13,15 @@ local function get_last_node_at_line(root, lnum)
return root:descendant_for_range(lnum - 1, col, lnum - 1, col) return root:descendant_for_range(lnum - 1, col, lnum - 1, col)
end end
local function get_matching_prev_sibling(anchor, start, matcher) local function find_delimiter(bufnr, node, delimiter)
local start_row, start_col = start[1], start[2] for child, _ in node:iter_children() do
local node = anchor:descendant_for_range(start_row, start_col, start_row, start_col) if child:type() == delimiter then
local pos = 1 local linenr = child:start()
-- TODO: reconsider this 999 limit or do something differently in future. local line = vim.api.nvim_buf_get_lines(bufnr, linenr, linenr + 1, false)[1]
-- if anchor has more than 999 children, this would not work. local end_char = {child:end_()}
while pos < 999 and node and not matcher(node) do return child, #line == end_char[2]
node = node:prev_sibling() end
pos = pos + 1
end end
return node, pos
end end
local M = {} local M = {}
@ -59,6 +57,7 @@ function M.get_indent(lnum)
if not parser or not lnum then if not parser or not lnum then
return -1 return -1
end end
local bufnr = vim.api.nvim_get_current_buf()
-- get_root_for_position is 0-based. -- get_root_for_position is 0-based.
local root, _, lang_tree = tsutils.get_root_for_position(lnum - 1, 0, parser) local root, _, lang_tree = tsutils.get_root_for_position(lnum - 1, 0, parser)
@ -126,23 +125,16 @@ function M.get_indent(lnum)
if q.aligned_indent[node:id()] and srow ~= erow and (srow ~= lnum - 1) then if q.aligned_indent[node:id()] and srow ~= erow and (srow ~= lnum - 1) then
local metadata = q.aligned_indent[node:id()] local metadata = q.aligned_indent[node:id()]
local opening_delimiter = metadata.delimiter:sub(1, 1) local opening_delimiter = metadata.delimiter:sub(1, 1)
local o_delim_node, pos = get_matching_prev_sibling(node, { srow, #vim.fn.getline(srow + 1) - 1 }, function(n) local o_delim_node, is_last_in_line = find_delimiter(bufnr, node, opening_delimiter)
return n:type() == opening_delimiter
end)
if o_delim_node then if o_delim_node then
if pos == 1 then if is_last_in_line then
-- hanging indent (previous line ended with starting delimiter) -- hanging indent (previous line ended with starting delimiter)
indent = indent + indent_size * 1 indent = indent + indent_size * 1
else else
local _, o_scol = o_delim_node:start() local _, o_scol = o_delim_node:end_()
local aligned_indent = math.max(indent, 0) + o_scol o_scol = o_scol + (metadata.increment or 0)
if indent > 0 then return math.max(indent, 0) + o_scol
indent = aligned_indent
else
indent = aligned_indent + 1 -- extra space for starting delimiter
end
is_processed = true
end end
end end
end end

View file

@ -1,3 +0,0 @@
int a[] = {
1, 2, 3,
4};

View file

@ -1,17 +1,17 @@
class Foo { class Foo {
Foo(int a, int b, int c, int d) Foo(int a, int b, int c, int d)
: m_a(a) : m_a(a)
, m_b(b) , m_b(b)
, m_c(c) , m_c(c)
, m_d(d) {} , m_d(d) {}
Foo(int a, int b, int c) : Foo(int a, int b, int c) :
m_a(a), m_a(a),
m_b(b), m_b(b),
m_c(c) m_c(c)
{} {}
int m_a, m_b, m_c, m_d; int m_a, m_b, m_c, m_d;
}; };