mirror of
https://github.com/nvim-treesitter/nvim-treesitter.git
synced 2026-07-01 19:17:02 -04:00
use indent.X syntax for captures and properties of set directives
update CONTRIBUTING.md adjust indents for bass fix doc capture comment
This commit is contained in:
parent
b4fcc61175
commit
cb568af539
80 changed files with 592 additions and 575 deletions
|
|
@ -52,18 +52,31 @@ end
|
|||
|
||||
local get_indents = tsutils.memoize_by_buf_tick(function(bufnr, root, lang)
|
||||
local map = {
|
||||
auto = {},
|
||||
indent = {},
|
||||
indent_end = {},
|
||||
dedent = {},
|
||||
branch = {},
|
||||
ignore = {},
|
||||
aligned_indent = {},
|
||||
zero_indent = {},
|
||||
indent = {
|
||||
auto = {},
|
||||
begin = {},
|
||||
["end"] = {},
|
||||
dedent = {},
|
||||
branch = {},
|
||||
ignore = {},
|
||||
align = {},
|
||||
zero = {},
|
||||
},
|
||||
}
|
||||
|
||||
local function split(to_split)
|
||||
local t = {}
|
||||
for str in string.gmatch(to_split, "([^.]+)") do
|
||||
table.insert(t, str)
|
||||
end
|
||||
return t
|
||||
end
|
||||
|
||||
for name, node, metadata in queries.iter_captures(bufnr, "indents", root, lang) do
|
||||
map[name][node:id()] = metadata or {}
|
||||
local path = split(name)
|
||||
-- node may contain a period so append directly.
|
||||
table.insert(path, node:id())
|
||||
queries.insert_to_path(map, path, metadata or {})
|
||||
end
|
||||
|
||||
return map
|
||||
|
|
@ -116,7 +129,7 @@ function M.get_indent(lnum)
|
|||
if is_empty_line then
|
||||
local prevlnum = vim.fn.prevnonblank(lnum)
|
||||
node = get_last_node_at_line(root, prevlnum)
|
||||
if q.indent_end[node:id()] then
|
||||
if q.indent["end"][node:id()] then
|
||||
node = get_first_node_at_line(root, lnum)
|
||||
end
|
||||
else
|
||||
|
|
@ -134,16 +147,16 @@ function M.get_indent(lnum)
|
|||
-- tracks to ensure multiple indent levels are not applied for same line
|
||||
local is_processed_by_row = {}
|
||||
|
||||
if q.zero_indent[node:id()] then
|
||||
if q.indent.zero[node:id()] then
|
||||
return 0
|
||||
end
|
||||
|
||||
while node do
|
||||
-- do 'autoindent' if not marked as @indent
|
||||
if
|
||||
not q.indent[node:id()]
|
||||
and not q.aligned_indent[node:id()]
|
||||
and q.auto[node:id()]
|
||||
not q.indent.begin[node:id()]
|
||||
and not q.indent.align[node:id()]
|
||||
and q.indent.auto[node:id()]
|
||||
and node:start() < lnum - 1
|
||||
and lnum - 1 <= node:end_()
|
||||
then
|
||||
|
|
@ -153,7 +166,12 @@ function M.get_indent(lnum)
|
|||
-- Do not indent if we are inside an @ignore block.
|
||||
-- If a node spans from L1,C1 to L2,C2, we know that lines where L1 < line <= L2 would
|
||||
-- have their indentations contained by the node.
|
||||
if not q.indent[node:id()] and q.ignore[node:id()] and node:start() < lnum - 1 and lnum - 1 <= node:end_() then
|
||||
if
|
||||
not q.indent.begin[node:id()]
|
||||
and q.indent.ignore[node:id()]
|
||||
and node:start() < lnum - 1
|
||||
and lnum - 1 <= node:end_()
|
||||
then
|
||||
return 0
|
||||
end
|
||||
|
||||
|
|
@ -163,7 +181,7 @@ function M.get_indent(lnum)
|
|||
|
||||
if
|
||||
not is_processed_by_row[srow]
|
||||
and ((q.branch[node:id()] and srow == lnum - 1) or (q.dedent[node:id()] and srow ~= lnum - 1))
|
||||
and ((q.indent.branch[node:id()] and srow == lnum - 1) or (q.indent.dedent[node:id()] and srow ~= lnum - 1))
|
||||
then
|
||||
indent = indent - indent_size
|
||||
is_processed = true
|
||||
|
|
@ -179,16 +197,16 @@ function M.get_indent(lnum)
|
|||
if
|
||||
should_process
|
||||
and (
|
||||
q.indent[node:id()]
|
||||
and (srow ~= erow or is_in_err or q.indent[node:id()].immediate_indent)
|
||||
and (srow ~= lnum - 1 or q.indent[node:id()].start_at_same_line)
|
||||
q.indent.begin[node:id()]
|
||||
and (srow ~= erow or is_in_err or q.indent.begin[node:id()]["indent.immediate"])
|
||||
and (srow ~= lnum - 1 or q.indent.begin[node:id()]["indent.start_at_same_line"])
|
||||
)
|
||||
then
|
||||
indent = indent + indent_size
|
||||
is_processed = true
|
||||
end
|
||||
|
||||
if is_in_err and not q.aligned_indent[node:id()] then
|
||||
if is_in_err and not q.indent.align[node:id()] then
|
||||
-- only when the node is in error, promote the
|
||||
-- first child's aligned indent to the error node
|
||||
-- to work around ((ERROR "X" . (_)) @aligned_indent (#set! "delimeter" "AB"))
|
||||
|
|
@ -196,25 +214,25 @@ function M.get_indent(lnum)
|
|||
-- (ERROR "X" @aligned_indent (#set! "delimeter" "AB") . (_))
|
||||
-- and we will fish it out here.
|
||||
for c in node:iter_children() do
|
||||
if q.aligned_indent[c:id()] then
|
||||
q.aligned_indent[node:id()] = q.aligned_indent[c:id()]
|
||||
if q.indent.align[c:id()] then
|
||||
q.indent.align[node:id()] = q.indent.align[c:id()]
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
-- do not indent for nodes that starts-and-ends on same line and starts on target line (lnum)
|
||||
if should_process and q.aligned_indent[node:id()] and (srow ~= erow or is_in_err) and (srow ~= lnum - 1) then
|
||||
local metadata = q.aligned_indent[node:id()]
|
||||
if should_process and q.indent.align[node:id()] and (srow ~= erow or is_in_err) and (srow ~= lnum - 1) then
|
||||
local metadata = q.indent.align[node:id()]
|
||||
local o_delim_node, o_is_last_in_line ---@type TSNode|nil, boolean|nil
|
||||
local c_delim_node, c_is_last_in_line ---@type TSNode|nil, boolean|nil, boolean|nil
|
||||
local indent_is_absolute = false
|
||||
if metadata.open_delimiter then
|
||||
o_delim_node, o_is_last_in_line = find_delimiter(bufnr, node, metadata.open_delimiter)
|
||||
if metadata["indent.open_delimiter"] then
|
||||
o_delim_node, o_is_last_in_line = find_delimiter(bufnr, node, metadata["indent.open_delimiter"])
|
||||
else
|
||||
o_delim_node = node
|
||||
end
|
||||
if metadata.close_delimiter then
|
||||
c_delim_node, c_is_last_in_line = find_delimiter(bufnr, node, metadata.close_delimiter)
|
||||
if metadata["indent.close_delimiter"] then
|
||||
c_delim_node, c_is_last_in_line = find_delimiter(bufnr, node, metadata["indent.close_delimiter"])
|
||||
else
|
||||
c_delim_node = node
|
||||
end
|
||||
|
|
@ -245,7 +263,7 @@ function M.get_indent(lnum)
|
|||
-- Then its indent level shouldn't be affected by `@aligned_indent` node
|
||||
indent = math.max(indent - indent_size, 0)
|
||||
else
|
||||
indent = o_scol + (metadata.increment or 1)
|
||||
indent = o_scol + (metadata["indent.increment"] or 1)
|
||||
indent_is_absolute = true
|
||||
end
|
||||
end
|
||||
|
|
@ -254,9 +272,9 @@ function M.get_indent(lnum)
|
|||
if c_srow and c_srow ~= o_srow and c_srow == lnum - 1 then
|
||||
-- delims end on current line, and are not open and closed same line.
|
||||
-- then this last line may need additional indent to avoid clashes
|
||||
-- with the next. `avoid_last_matching_next` controls this behavior,
|
||||
-- with the next. `indent.avoid_last_matching_next` controls this behavior,
|
||||
-- for example this is needed for function parameters.
|
||||
avoid_last_matching_next = metadata.avoid_last_matching_next or false
|
||||
avoid_last_matching_next = metadata["indent.avoid_last_matching_next"] or false
|
||||
end
|
||||
if avoid_last_matching_next then
|
||||
-- last line must be indented more in cases where
|
||||
|
|
|
|||
|
|
@ -213,6 +213,24 @@ local function prepare_query(bufnr, query_name, root, root_lang)
|
|||
}
|
||||
end
|
||||
|
||||
-- Given a path (i.e. a List(String)) this functions inserts value at path
|
||||
---@param object any
|
||||
---@param path string[]
|
||||
---@param value any
|
||||
function M.insert_to_path(object, path, value)
|
||||
local curr_obj = object
|
||||
|
||||
for index = 1, (#path - 1) do
|
||||
if curr_obj[path[index]] == nil then
|
||||
curr_obj[path[index]] = {}
|
||||
end
|
||||
|
||||
curr_obj = curr_obj[path[index]]
|
||||
end
|
||||
|
||||
curr_obj[path[#path]] = value
|
||||
end
|
||||
|
||||
---@param query Query
|
||||
---@param bufnr integer
|
||||
---@param start_row integer
|
||||
|
|
@ -230,24 +248,6 @@ function M.iter_prepared_matches(query, qnode, bufnr, start_row, end_row)
|
|||
return t
|
||||
end
|
||||
|
||||
-- Given a path (i.e. a List(String)) this functions inserts value at path
|
||||
---@param object any
|
||||
---@param path string[]
|
||||
---@param value any
|
||||
local function insert_to_path(object, path, value)
|
||||
local curr_obj = object
|
||||
|
||||
for index = 1, (#path - 1) do
|
||||
if curr_obj[path[index]] == nil then
|
||||
curr_obj[path[index]] = {}
|
||||
end
|
||||
|
||||
curr_obj = curr_obj[path[index]]
|
||||
end
|
||||
|
||||
curr_obj[path[#path]] = value
|
||||
end
|
||||
|
||||
local matches = query:iter_matches(qnode, bufnr, start_row, end_row)
|
||||
|
||||
local function iterator()
|
||||
|
|
@ -260,9 +260,9 @@ function M.iter_prepared_matches(query, qnode, bufnr, start_row, end_row)
|
|||
local name = query.captures[id] -- name of the capture in the query
|
||||
if name ~= nil then
|
||||
local path = split(name .. ".node")
|
||||
insert_to_path(prepared_match, path, node)
|
||||
M.insert_to_path(prepared_match, path, node)
|
||||
local metadata_path = split(name .. ".metadata")
|
||||
insert_to_path(prepared_match, metadata_path, metadata[id])
|
||||
M.insert_to_path(prepared_match, metadata_path, metadata[id])
|
||||
end
|
||||
end
|
||||
|
||||
|
|
@ -273,10 +273,10 @@ function M.iter_prepared_matches(query, qnode, bufnr, start_row, end_row)
|
|||
for _, pred in pairs(preds) do
|
||||
-- functions
|
||||
if pred[1] == "set!" and type(pred[2]) == "string" then
|
||||
insert_to_path(prepared_match, split(pred[2]), pred[3])
|
||||
M.insert_to_path(prepared_match, split(pred[2]), pred[3])
|
||||
end
|
||||
if pred[1] == "make-range!" and type(pred[2]) == "string" and #pred == 4 then
|
||||
insert_to_path(
|
||||
M.insert_to_path(
|
||||
prepared_match,
|
||||
split(pred[2] .. ".node"),
|
||||
tsrange.TSRange.from_nodes(bufnr, match[pred[3]], match[pred[4]])
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue