From d1333dd7e51729a581fed3e429fa035bff77a3db Mon Sep 17 00:00:00 2001 From: George Harker Date: Sun, 19 Mar 2023 18:09:18 -0700 Subject: refactor(indent)!: Rework indent, aligned indent MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit indents now use @indent.X style captures, and indent.PROP for properties to set on those captures, as documented in the help. Captures are: indent.auto indent.begin indent.end indent.dedent indent.branch indent.ignore indent.align indent.zero Properties are: indent.immediate indent.start_at_same_line indent.open_delimiter indent.close_delimiter indent.increment indent.avoid_last_matching_next Multiple opening delims on one line and multiple closing on a line are collapsed so as not to over indent, The final line of @indent.align blocks which must in some cases be treated specially to avoid clashing with the next line is treated the same regardless of whether the @indent.align capture actually uses aligned indentation or just normal indentation. The indent.avoid_last_matching_next property controls this. Adjust python to use these. List, set, dict and tuple all use @indent.align which permits both hanging and aligned styles. Finally, try: on it’s own will indent when typing live but make no guaranteeds about whole-file formatting. Includes lucario387:fix-align-indent --- lua/nvim-treesitter/indent.lua | 101 +++++++++++++++++++++++++++++------------ 1 file changed, 73 insertions(+), 28 deletions(-) (limited to 'lua') diff --git a/lua/nvim-treesitter/indent.lua b/lua/nvim-treesitter/indent.lua index cf819d05b..8035a73d8 100644 --- a/lua/nvim-treesitter/indent.lua +++ b/lua/nvim-treesitter/indent.lua @@ -42,7 +42,10 @@ local function find_delimiter(bufnr, node, delimiter) local linenr = child:start() local line = vim.api.nvim_buf_get_lines(bufnr, linenr, linenr + 1, false)[1] local end_char = { child:end_() } - return child, #line == end_char[2] + local trimmed_after_delim + local escaped_delimiter = delimiter:gsub("[%-%.%+%[%]%(%)%$%^%%%?%*]", "%%%1") + trimmed_after_delim, _ = line:sub(end_char[2] + 1):gsub("[%s" .. escaped_delimiter .. "]*", "") + return child, #trimmed_after_delim == 0 end end end @@ -185,51 +188,93 @@ function M.get_indent(lnum) is_processed = true end + if is_in_err and not q.aligned_indent[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")) + -- matching for all X, instead set do + -- (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()] + break + end + end + end -- do not indent for nodes that starts-and-ends on same line and starts on target line (lnum) - if q.aligned_indent[node:id()] and srow ~= erow and (srow ~= lnum - 1) then + 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()] - local o_delim_node, is_last_in_line ---@type TSNode|nil, boolean|nil - local c_delim_node ---@type TSNode|nil + 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.delimiter then ---@type string local opening_delimiter = metadata.delimiter and metadata.delimiter:sub(1, 1) - o_delim_node, is_last_in_line = find_delimiter(bufnr, node, opening_delimiter) + o_delim_node, o_is_last_in_line = find_delimiter(bufnr, node, opening_delimiter) + ---@type string local closing_delimiter = metadata.delimiter and meta