### Install TreeSJ with packer.nvim Source: https://github.com/wansmer/treesj/blob/main/README.md Instructions for installing the TreeSJ Neovim plugin using the packer.nvim package manager. This setup includes declaring a dependency on nvim-treesitter for parser management and demonstrates how to call the setup function for initial configuration within the 'use' block. ```Lua use({ 'Wansmer/treesj', requires = { 'nvim-treesitter/nvim-treesitter' }, -- if you install parsers with `nvim-treesitter` config = function() require('treesj').setup({--[[ your config ]]) end, }) ``` -------------------------------- ### Install TreeSJ with packer.nvim Source: https://github.com/wansmer/treesj/blob/main/doc/treesj.txt This snippet demonstrates how to install the TreeSJ Neovim plugin using the packer.nvim plugin manager. It specifies the plugin's repository and its dependency on `nvim-treesitter`. The `config` function shows the basic setup call for the plugin. ```Lua use({ 'Wansmer/treesj', requires = { 'nvim-treesitter/nvim-treesitter' }, -- if you install parsers with `nvim-treesitter` config = function() require('treesj').setup({--[[ your config ]]) end, }) ``` -------------------------------- ### Install TreeSJ with lazy.nvim Source: https://github.com/wansmer/treesj/blob/main/README.md Instructions for installing the TreeSJ Neovim plugin using the lazy.nvim package manager. This configuration includes specifying keys for toggle, join, and split actions, and declares a dependency on nvim-treesitter for parser management. It also shows how to call the setup function for initial configuration. ```Lua return { 'Wansmer/treesj', keys = { 'm', 'j', 's' }, dependencies = { 'nvim-treesitter/nvim-treesitter' }, -- if you install parsers with `nvim-treesitter` config = function() require('treesj').setup({--[[ your config ]]) end, } ``` -------------------------------- ### Install TreeSJ with lazy.nvim Source: https://github.com/wansmer/treesj/blob/main/doc/treesj.txt This snippet shows how to install the TreeSJ Neovim plugin using the lazy.nvim plugin manager. It includes the plugin's repository, key mappings, and a dependency on `nvim-treesitter` for parser installation. The `config` function demonstrates how to call `require('treesj').setup()`. ```Lua return { 'Wansmer/treesj', keys = { 'm', 'j', 's' }, dependencies = { 'nvim-treesitter/nvim-treesitter' }, -- if you install parsers with `nvim-treesitter` config = function() require('treesj').setup({--[[ your config ]]) end, } ``` -------------------------------- ### treesj Node Detection and Formatting Example Source: https://github.com/wansmer/treesj/blob/main/doc/treesj.txt Illustrates how treesj detects the relevant code node under the cursor, traverses the Abstract Syntax Tree (AST), and applies formatting based on configured presets. It shows examples for both 'self' and 'reference' based node configurations. ```txt // with preset for self const arr = [ 1, |2, 3 ]; | first node is 'number' - not configured, parent node is 'array' - configured and will be split // with referens cons|t arr = [ 1, 2, 3 ]; | first node is 'variable_declarator' - not configured, parent node is 'lexical_declaration' - configured and has reference { target_nodes = { 'array', 'object' } }, first configured nested node is 'array' and array will be splitted ``` -------------------------------- ### TreeSJ Node Detection and Splitting Example Source: https://github.com/wansmer/treesj/blob/main/README.md Illustrates how TreeSJ identifies nodes under the cursor, checks for configured presets (self or reference), and applies formatting based on the detected node hierarchy. Shows examples for both 'preset for self' and 'reference for nested nodes' scenarios. ```text // with preset for self const arr = [ 1, |2, 3 ]; | first node is 'number' - not configured, parent node is 'array' - configured and will be split // with referens cons|t arr = [ 1, 2, 3 ]; | first node is 'variable_declarator' - not configured, parent node is 'lexical_declaration' - configured and has reference { target_nodes = { 'array', 'object' } }, first configured nested node is 'array' and array will be splitted ``` -------------------------------- ### Example Content for treesj Test Sample File (JavaScript) Source: https://github.com/wansmer/treesj/blob/main/tests/README.md This JavaScript snippet demonstrates the expected content for `index.${type_of_file}` in the `/tests/sample/` directory. It shows examples of both joined and split code structures, used as reference for testing `treesj`'s split and join functionalities on an object node. ```JavaScript // RESULT OF JOIN (node "object", preset default) const obj = { one: "one", two: [1, 2], three: { one: "one", two: [1, 2] } }; // RESULT OF SPLIT (node "object", preset default) const obj = { one: "one", two: [1, 2], three: { one: "one", two: [1, 2] } }; ``` -------------------------------- ### TreeSJ Language Configuration Example (Lua) Source: https://github.com/wansmer/treesj/blob/main/README.md Demonstrates how to configure language-specific presets within TreeSJ's `langs` section in Lua. It shows how to define presets for array and object nodes, and how to use `target_nodes` for function references. ```lua local langs = { javascript = { array = {--[[ preset ]]}, object = {--[[ preset ]]}, ['function'] = { target_nodes = {--[[ targets ]]}} } } ``` -------------------------------- ### Specific Test Data Examples for treesj Split and Join Operations (Lua) Source: https://github.com/wansmer/treesj/blob/main/tests/README.md These Lua snippets provide concrete examples of `data_for_split` and `data_for_join` configurations. They illustrate how to define test cases with specific `path`, `mode`, `lang`, `desc`, `cursor`, `expected`, and `result` ranges for testing the `split` and `join` operations on an 'object' node. ```Lua local data_for_split = { { path = PATH, mode = 'split', lang = LANG, desc = 'lang "%s", node "object", preset default', cursor = { 2, 16 }, expected = { 3, 8 }, result = { 1, 6 }, }, } local data_for_join = { { path = PATH, mode = 'join', lang = LANG, desc = 'lang "%s", node "object", preset default', cursor = { 5, 9 }, expected = { 1, 2 }, result = { 4, 5 }, }, } ``` -------------------------------- ### Configure Language Presets with TreeSJ Utilities Source: https://github.com/wansmer/treesj/blob/main/doc/treesj.txt Demonstrates how to configure language-specific node presets using `treesj.langs.utils` functions. This example shows setting up presets for JavaScript and Lua, including custom `join` rules for JavaScript's `statement_block`. ```Lua local lang_utils = require('treesj.langs.utils') local langs = { javascript = { object = lang_utils.set_preset_for_dict(), array = lang_utils.set_preset_for_list(), formal_parameters = lang_utils.set_preset_for_args(), arguments = lang_utils.set_preset_for_args(), statement_block = lang_utils.set_preset_for_statement({ join = { no_insert_if = { 'function_declaration', 'try_statement', 'if_statement', }, }, }), }, lua = { table_constructor = lang_utils.set_preset_for_dict(), arguments = lang_utils.set_preset_for_args(), parameters = lang_utils.set_preset_for_args(), }, } ``` -------------------------------- ### Configuring treesj Keymaps with Presets in Lua Source: https://github.com/wansmer/treesj/blob/main/doc/treesj.txt Examples demonstrating how to set up Neovim keybindings for treesj, including passing a custom preset to the `toggle` function to override default behavior, such as enabling recursive splitting for specific node types. ```Lua vim.keymap.set('n', 'm', require('treesj').toggle) vim.keymap.set('n', 'M', function() require('treesj').toggle({ split = { recursive = true } }) end) ``` -------------------------------- ### Ruby Class and Module Join/Split Example Source: https://github.com/wansmer/treesj/blob/main/doc/treesj.txt This Ruby code illustrates the desired transformation for `class` and `module` definitions, showing how nested modules and classes can be joined into a single block or split into separate, nested blocks. This scenario is challenging for `treesj` to handle directly, necessitating a fallback mechanism. ```Ruby # RESULT OF JOIN class Foo::Bar::Baz < Quux def initialize # foo end end # RESULT OF SPLIT module Foo module Bar class Baz < Quux def initialize # foo end end end end ``` -------------------------------- ### TreeSJ:preset Method Source: https://github.com/wansmer/treesj/blob/main/README.md Retrieves the preset configuration for the current TreeSJ node. An optional `mode` parameter ('split' or 'join') can be provided to get a mode-specific preset. ```APIDOC TreeSJ:preset(mode?) - mode?: 'split'|'join' - Optional. The current mode for which to retrieve the preset. - Returns: table|nil - The preset table for the current TreeSJ, or nil if no preset is found. ``` -------------------------------- ### TreeSJ Default Configuration Options Source: https://github.com/wansmer/treesj/blob/main/README.md This snippet outlines the default configuration options available for the TreeSJ plugin. It includes settings for enabling default keymaps, checking syntax errors, defining maximum join length, controlling cursor behavior ('hold', 'start', 'end'), enabling notifications, supporting dot-repeat, and setting a custom error handler. ```Lua local tsj = require('treesj') local langs = {--[[ configuration for languages ]]} tsj.setup({ ---@type boolean Use default keymaps (m - toggle, j - join, s - split) use_default_keymaps = true, ---@type boolean Node with syntax error will not be formatted check_syntax_error = true, ---If line after join will be longer than max value, ---@type number If line after join will be longer than max value, node will not be formatted max_join_length = 120, ---Cursor behavior: ---hold - cursor follows the node/place on which it was called ---start - cursor jumps to the first symbol of the node being formatted ---end - cursor jumps to the last symbol of the node being formatted ---@type 'hold'|'start'|'end' cursor_behavior = 'hold', ---@type boolean Notify about possible problems or not notify = true, ---@type boolean Use `dot` for repeat action dot_repeat = true, ---@type nil|function Callback for treesj error handler. func (err_text, level, ...other_text) on_error = nil, ---@type table Presets for languages -- langs = {}, -- See the default presets in lua/treesj/langs }) ``` -------------------------------- ### Illustrate `format_tree` Problem with Python Import Statement Source: https://github.com/wansmer/treesj/blob/main/README.md This Python example demonstrates the desired formatting for `import_from_statement`, where modules are wrapped in parentheses for multi-line imports. The challenge is to add these parentheses during splitting and remove them during joining, which `format_tree` can address. ```python # from from re import search, match,sub # to this and back from re import ( search, match, sub, ) ``` -------------------------------- ### TreeSJ `format_resulted_lines` Function Example Source: https://github.com/wansmer/treesj/blob/main/doc/treesj.txt Illustrates the usage of the `format_resulted_lines` function, which takes an array of strings (representing the content of a base node) and an optional processed node. This function allows modification of the lines before they are concatenated, useful for adjusting indentation or other line-based formatting. The example shows how a simple Lua table can be formatted into multi-line output. ```lua -- base node local dict = { one = 'one', two = 'two' } -- array of string for replacement is { "{", " one = 'one',", " two = 'two',", "}" } -- base node after format local dict = { one = 'one', two = 'two', } ``` -------------------------------- ### Example: Updating Text in a TreeSJ Node Source: https://github.com/wansmer/treesj/blob/main/doc/treesj.txt This Lua code snippet demonstrates how to use `TreeSJ` methods like `type()`, `child()`, `will_be_formatted()`, `has_preset()`, `text()`, and `update_text()` within a `format_tree` function. It shows conditional logic for updating text based on node type, formatting status, and preset configurations, specifically for adding a 'return' keyword. ```lua { format_tree = function(tsj) if tsj:type() ~= 'statement_block' then -- ... local body = tsj:child(2) if body:will_be_formatted() then local set_return if body:has_preset('split') then set_return = body:child(1) else set_return = body:child(1):child(1) end set_return:update_text('return ' .. set_return:text()) else body:update_text('return ' .. body:text()) end -- ... end end, } ``` -------------------------------- ### Lua Code Formatting Problem: Non-Bracket Node Handling Source: https://github.com/wansmer/treesj/blob/main/README.md Illustrates a formatting challenge in Lua where `block` nodes lack explicit brackets but need to be treated as if they have framing elements for proper joining and splitting. This example shows how a multi-line function block transforms into a single line. ```Lua -- `block` in Lua does not have parentheses, but when it joins, -- it must jump up a line and pull an `end` node that is not part of it. -- To do this, you need to create imitators of framing nodes one line above -- and one line below | -- imitator left-side bracket function test()| | -- real start of `block` |print(123) return 123| -- real end of `block` | -- imitator right-side bracket |end -- from function test() print(123) return 123 end -- to and back function test() print(123) return 123 end ``` -------------------------------- ### Merge Existing Language Presets in Treesj Source: https://github.com/wansmer/treesj/blob/main/README.md This example illustrates how to merge an existing language preset (e.g., CSS) into a new language configuration (e.g., SCSS) using `tsj_utils.merge_preset`. This allows for reusing common formatting rules while providing an option to override or add language-specific nodes. ```lua local tsj_utils = require('treesj.langs.utils') local css = require('treesj.langs.css') local langs = { scss = tsj_utils.merge_preset(css, { --[[ Here you can override existing nodes or add language-specific nodes ]]}) } ``` -------------------------------- ### TreeSJ:parent_preset Method Source: https://github.com/wansmer/treesj/blob/main/README.md Retrieves the preset configuration for the parent of the current TreeSJ node. An optional `mode` parameter ('split' or 'join') can be provided to get a mode-specific preset for the parent. ```APIDOC TreeSJ:parent_preset(mode?) - mode?: 'split'|'join' - Optional. The current mode for which to retrieve the parent's preset. - Returns: table|nil - The preset table for the TreeSJ parent, or nil if no parent or preset is found. ``` -------------------------------- ### Python `import_from_statement` Formatting Problem and Solution Source: https://github.com/wansmer/treesj/blob/main/doc/treesj.txt Illustrates a common formatting challenge in Python where `import_from_statement` lacks a direct container for a list of imported modules, leading to a desire for multi-line, parenthesized imports. The Python example shows the 'before' and 'after' states. The Lua snippet provides a `treesj` configuration to automatically add parentheses during a 'split' operation (if they don't exist) and remove them during a 'join' operation, ensuring consistent formatting. ```python # from from re import search, match,sub # to this and back from re import ( search, match, sub, ) ``` ```lua local python = { import_from_statement = lang_utils.set_preset_for_args({ both = { -- There is no need to wrap the second element, the 'import' node, -- and the first parenthesis, which does not already exist. omit = { lang_utils.omit.if_second, 'import', ' (' }, }, split = { last_separator = true, format_tree = function(tsj) -- If there are no brackets, then create them if not tsj:has_children({ '(', ')' }) then tsj:create_child({ text = ' (' }, 4) tsj:create_child({ text = ')' }, #tsj:children() + 1) -- Since the elements have moved, you need to add the penultimate -- separator manually local penult = tsj:child(-2) penult:update_text(penult:text() .. ',') end end, }, join = { format_tree = function(tsj) -- Remove brackets tsj:remove_child({ '(', ')' }) end, }, }), } ``` -------------------------------- ### Ruby Conditional Statement Formatting Problem and Solution Source: https://github.com/wansmer/treesj/blob/main/doc/treesj.txt Demonstrates a Ruby formatting problem involving the transformation between a multi-line `if/else` block and a single-line ternary operator. The Ruby example shows the 'from' and 'to' states. The Lua snippet provides a `treesj` configuration using `format_tree` to restructure the AST (e.g., changing '?' to 'if', ':' to 'else', reordering children) and `format_resulted_lines` to adjust indentation for the 'else' keyword during the 'split' operation. ```ruby # from if cond do_that('cond') else do_this('not nond') end # to this and back cond ? do_that('cond') : do_this('not nond') ``` ```lua local ruby = { conditional = lang_utils.set_default_preset({ join = { enable = false }, split = { omit = { lang_utils.omit.if_second }, format_tree = function(tsj) local children = tsj:children() table.insert(children, tsj:create_child({ text = 'end', type = 'end' })) tsj:child('?'):update_text('if ') tsj:child(':'):update_text('else') local first, second = tsj:child(1), tsj:child(2) children[1] = second children[2] = first tsj:update_children(children) end, format_resulted_lines = function(lines) return vim.tbl_map(function(line) -- Need to remove one indent on `else` element if line:match('%s.else$') then local rgx = '^' .. (' '):rep(vim.fn.shiftwidth()) return line:gsub(rgx, '') else return line end end, lines) end, }, }), } ``` -------------------------------- ### Commands for Running treesj Tests Source: https://github.com/wansmer/treesj/blob/main/tests/README.md These Bash commands are used to manage and execute tests for the treesj project. They include commands for pre-installing Tree-sitter parsers, running all tests, running tests for all languages, and running tests for a specific language. ```Bash make preinstall-ts-parsers ``` ```Bash make test ``` ```Bash make test-langs ``` ```Bash make test-langs LP=lang_name ``` -------------------------------- ### Basic treesj Lua Commands Source: https://github.com/wansmer/treesj/blob/main/doc/treesj.txt These are the fundamental Lua commands to toggle, split, and join code nodes using the treesj plugin directly from the Neovim command line. ```Lua :lua require('treesj').toggle() :lua require('treesj').split() :lua require('treesj').join() ``` -------------------------------- ### TreeSJ Neovim User Commands Source: https://github.com/wansmer/treesj/blob/main/doc/treesj.txt This section documents the user commands provided by the TreeSJ Neovim plugin. It includes commands for toggling, splitting, and joining code nodes under the cursor. These commands offer direct control over the plugin's core functionality within Neovim. ```APIDOC :TSJToggle - Toggles node under cursor (splits if one-line, joins if multiline). :TSJSplit - Splits node under cursor. :TSJJoin - Joins node under cursor. ``` -------------------------------- ### TreeSJ Neovim User Commands and Lua API Source: https://github.com/wansmer/treesj/blob/main/README.md This section details the user commands and their corresponding Lua API functions provided by the TreeSJ plugin for manipulating code blocks. It covers toggling, splitting, and joining operations, and explains how to customize behavior using optional presets in Lua. ```APIDOC TreeSJ User Commands: :TSJToggle - Toggles the node under the cursor (splits if one-line, joins if multi-line). :TSJSplit - Splits the node under the cursor. :TSJJoin - Joins the node under the cursor. TreeSJ Lua API: require('treesj').toggle(preset?: table) - Toggles the node under the cursor. - Parameters: - preset: (Optional) A table to override default preset values. Should contain 'split' or 'join' keys. require('treesj').split(preset?: table) - Splits the node under the cursor. - Parameters: - preset: (Optional) A table to override default preset values. Should contain 'split' or 'join' keys. require('treesj').join(preset?: table) - Joins the node under the cursor. - Parameters: - preset: (Optional) A table to override default preset values. Should contain 'split' or 'join' keys. Usage Examples: -- For default preset vim.keymap.set('n', 'm', require('treesj').toggle) -- For extending default preset with `recursive = true` vim.keymap.set('n', 'M', function() require('treesj').toggle({ split = { recursive = true } }) end) ``` -------------------------------- ### Illustrative Go Import Formatting Problem Source: https://github.com/wansmer/treesj/blob/main/README.md This Go code snippet illustrates a common formatting problem related to import statements, specifically how to handle single-line imports versus multi-line import blocks and the conditions under which `import_spec` or `import_spec_list` should be enabled or disabled for formatting. ```go // from 'import_spec_list' import ( "123" ) // to 'import_spec' and back import "123" // but disable 'import_spec_list' when two or more 'import_spec' inside and // disable 'import_spec' when it already inside 'import_spec_list' import ( "123" "321" ) ``` -------------------------------- ### TreeSJ Class Methods API Reference Source: https://github.com/wansmer/treesj/blob/main/README.md This section provides a comprehensive API reference for the `TreeSJ` class, which is central to manipulating and formatting syntax tree nodes. It details methods for querying children, iterating through the tree, navigating parent-child relationships, and creating new `TreeSJ` instances. ```APIDOC TreeSJ:has_children(types? string[]): boolean - Description: Checks if the specified types of children exist among the list of children. If types are omitted, checks that there is at least one child. TreeSJ:iter_children(): function, table - Description: Iterate all TreeSJ children. Use: `... for child, index in tsj:iter_children() do ...` TreeSJ:children(types? string[]): TreeSJ[] - Description: Get the children list of the current TreeSJ. Returns all children if `types` are omitted, otherwise returns all children of the listed types. - Parameters: - types: List-like table with child's types for filtering (optional). TreeSJ:root(): TreeSJ - Description: Get root TreeSJ node of current TreeSJ. TreeSJ:parent(): TreeSJ|nil - Description: Get parent TreeSJ. TreeSJ:child(type_or_index: number|string): TreeSJ|nil - Description: Get the child of the current node, using its `type` (`tsj:type()`) or `index`. The `index` can be a negative value, which means to search from the end of the list. If a `type` is passed, the first element found will be returned. To get an array of similar elements, use `TreeSJ:children(types)`. - Parameters: - type_or_index: Type of TreeSJ child (string) or its index in children list (number). TreeSJ:create_child(data: table, index?: integer): TreeSJ|nil - Description: Creates a new TreeSJ instance as a child of the current TreeSJ. The 'copy_from' field in `data` is used if a node needs to be duplicated and expects TreeSJ. If a TreeSJ instance is passed to it, then the 'text' and 'type' fields will be ignored. If `index` is present, it puts the new child in the children list and returns it; otherwise, it returns the child but does not add it to the list. Index can be a negative value, meaning insert from the end. If an index is specified that is outside the list of children, then `nil` will be returned. - Parameters: - data: A table containing child data. Must include `text` (string) and optionally `type` (string). If `type` is not present, the value of `text` is used. Can also include `copy_from` (TreeSJ instance) to duplicate an existing node. - index: Optional integer specifying where the child should be inserted in the children list. ``` -------------------------------- ### TreeSJ Instance Methods (Lua API) Source: https://github.com/wansmer/treesj/blob/main/doc/treesj.txt This section details the core methods available on a TreeSJ instance for interacting with and manipulating the tree structure. It includes functions for checking children, iterating, retrieving, creating, updating, removing, wrapping, and swapping child nodes, as well as accessing parent and root nodes. ```APIDOC HAS_CHILDREN ---@param types? string[] ---@return boolean function TreeSJ:has_children(types) - Checks if the specified types of children exist among the list of children. If types are omitted, checks that there is at least one child. ITER_CHILDREN ---@return function, table function TreeSJ:iter_children() - Iterate all TreeSJ children. - Usage: `... for child, index in tsj:iter_children() do ...` CHILDREN ---@param types? string[] List-like table with child's types for filtering ---@return TreeSJ[] function TreeSJ:children(types) - Get the children list of the current TreeSJ. Returns all children if `types` are omitted, otherwise returns all children of the listed types. ROOT ---@return TreeSJ TreeSJ instance function TreeSJ:root() - Get root TreeSJ node of current TreeSJ. PARENT ---@return TreeSJ|nil function TreeSJ:parent() - Get parent TreeSJ. CHILD ---@param type_or_index number|string Type of TreeSJ child or it index in children list ---@return TreeSJ|nil function TreeSJ:child(type_or_index) - Get the child of the current node, using its `type` (`tsj:type()`) or `index`. - The `index` can be a negative value, which means to search from the end of the list. - If a `type` is passed, the first element found will be returned. To get an array of similar elements, use `TreeSJ:children(types)`. CREATE_CHILD ---@param data table { text = string, type? = string }. If `type` not present, uses value of `text` ---@param index? integer Index where the child should be inserted. ---@return TreeSJ|nil function TreeSJ:create_child(data, index) - Creating a new TreeSJ instance as a child of current TreeSJ. - `data`: {text=string, type=string|nil, copy_from=TreeSJ|nil}. The "copy_from" field is used if a node needs to be duplicated and expects TreeSJ. If a TreeSJ instance is passed to it, then the "text" and "type" fields will be ignored. - `index`: If index present, puts it in children list and returned this child, if not – returned child, but not puts it in children list. Index can be a negative value, meaning insert from the end. If an index is specified that is outside the list of children, then `nil` will be returned. UPDATE_CHILDREN ---@param children TreeSJ[] function TreeSJ:update_children(children) - Updating children list of current TreeSJ. This function must be called every time you update the list of children from outside. - Example usage: local children = tsj:children() local child = tsj:create_child({ text = 'end' }) table.insert(children, child) tsj:update_children(children) -- important REMOVE_CHILD ---@param types_or_index string|string[]|integer Type, types, or index of child to remove function TreeSJ:remove_child(types_or_index) - Removes children by the passed types or index. WRAP ---@param data table { left = string, right = string } ---@param mode? 'wrap'|'inline' 'wrap' by default function TreeSJ:wrap(data, mode) - Creates the first and last elements in the list of children of the current TreeSJ. - If the `wrap` mode is passed (the default), then a new list of children is created with one element as itself, and the wrapping elements are added to it. - If the `inline` mode is passed, then the real list of children of the current TreeSJ is used to add framing elements. SWAP_CHILDREN ---@param index1 integer ---@param index2 integer function TreeSJ:swap_children(index1, index2) - Helps to swap elements by their indexes. TSNODE - Get |TSNode| or TSNode imitator of current TreeSJ. If you plan to use tsnode. ``` -------------------------------- ### TreeSJ Node Configuration Options Source: https://github.com/wansmer/treesj/blob/main/doc/treesj.txt Defines the comprehensive set of configuration parameters for `treesj` nodes, covering general behavior, join-specific settings, and split-specific settings. These options control how nodes are formatted, merged, or separated. ```APIDOC Node Configuration Options: fallback: function|nil function(node: TSNode): void - Passes control to an external script and terminates treesj execution. omit: table - List-like table with types 'string' (type of node) or 'function' (function(child: TreeSJ): boolean). - The text of the node will be merged with the previous one, without wrapping to a new line. non_bracket_node: boolean|table - Non-bracket nodes (e.g., with 'then|()' ... 'end' instead of { ... }|< ... >|[ ... ]). - If value is table, should contain keys: { left = 'text', right = 'text' }. Empty string used by default. shrink_node: table|nil - If you need to process only nodes in the range from / to. - If `shrink_node` is present, `non_bracket_node` will be ignored. - Format: { from = string, to = string }. disable: boolean - If 'true', node will be completely removed from langs preset. target_nodes: string[]|table - TreeSJ will search child from list into this node and redirect to found child. - If list not empty, another fields (split, join) will be ignored. join (Use only for join. If contains field from 'both', field here has higher priority): space_in_brackets: boolean - Adding space in framing brackets or last/end element. space_separator: boolean - Insert space between nodes or not. force_insert: string - Adds instruction separator like ';' in statement block. - Not the same as `separator`: `separator` is a separate node, `force_insert` is a last symbol of code instruction. no_insert_if: table - List-like table with types 'string' (type of node) or 'function' (function(child: TreeSJ): boolean). - The `force_insert` symbol will be omitted if the type of node contains in this list (e.g. function_declaration inside statement_block in JS no require instruction separator (';')). split (Use only for split. If contains field from 'both', field here has higher priority): recursive: boolean - All nested configured nodes will process according to their presets. last_indent: 'normal'|'inner' - Which indent must be on the last line of the formatted node. - 'normal' – indent equals of the indent from first line; - 'inner' – indent, like all inner nodes (indent of start line of node + vim.fn.shiftwidth()). inner_indent: 'normal'|'inner' - Which indent must be on the last line of the formatted node. - 'normal' – indent equals of the indent from first line; - 'inner' – indent, like all inner nodes (indent of start line of node + vim.fn.shiftwidth()). ``` -------------------------------- ### TreeSJ Preset Utility Functions Source: https://github.com/wansmer/treesj/blob/main/doc/treesj.txt Describes the utility functions provided by `treesj` for setting default presets for common node types. These functions simplify the configuration process by applying predefined formatting rules. ```APIDOC Preset Utility Functions: set_default_preset(override: table) - Applies default node formatting presets. - Parameters: - override: A table with settings to be overwritten. set_preset_for_list(override: table) - Applies presets suitable for list-like nodes. - Parameters: - override: A table with settings to be overwritten. set_preset_for_dict(override: table) - Applies presets suitable for dictionary-like nodes. - Parameters: - override: A table with settings to be overwritten. set_preset_for_statement(override: table) - Applies presets suitable for statement-like nodes. - Parameters: - override: A table with settings to be overwritten. set_preset_for_args(override: table) - Applies presets suitable for argument-like nodes. - Parameters: - override: A table with settings to be overwritten. set_preset_for_non_bracket(override: table) - Applies presets suitable for non-bracket nodes. - Parameters: - override: A table with settings to be overwritten. ``` -------------------------------- ### TreeSJ Object API Reference Source: https://github.com/wansmer/treesj/blob/main/doc/treesj.txt Comprehensive API documentation for the `TreeSJ` object in Lua, detailing its methods for navigating tree nodes, accessing node properties like type and text, checking various states (e.g., if a node will be formatted, if it's an imitator, its position relative to siblings), and updating node content or presets. Each method includes its signature, parameters, and return types. ```APIDOC TreeSJ:tsnode() - Description: Returns the underlying TSNode or a TSNode imitator. It's important to check if the returned value is an imitator before proceeding with future methods. - Returns: `TSNode|table` (TSNode or TSNode imitator) TreeSJ:prev() - Description: Gets the TreeSJ node immediately to the left (previous sibling). - Returns: `TreeSJ|nil` TreeSJ:next() - Description: Gets the TreeSJ node immediately to the right (next sibling). - Returns: `TreeSJ|nil` TreeSJ:type() - Description: Gets the node type of the current TreeSJ. - Returns: `string` TreeSJ:text() - Description: Gets the text content of the current TreeSJ. When `format_tree` is executed, this will always return a string, not a table. - Returns: `string|table` TreeSJ:update_text(new_text) - Description: Updates the text content of the current TreeSJ. If 'split' and 'recursively' modes are active, `new_text` can be an array, requiring updates to children directly. - Parameters: - `new_text`: `string|string[]` - The new text or array of texts to set. TreeSJ:will_be_formatted() - Description: Checks if the current TreeSJ node will be formatted. This is true if recursion is active, the element has a preset, or its descendants include nodes to be processed. - Returns: `boolean` TreeSJ:is_ignore() - Description: Checks if the current TreeSJ child should be ignored during recursive formatting. - Returns: `boolean` TreeSJ:has_to_format() - Description: Checks if the TreeSJ node contains children that require formatting. - Returns: `boolean` TreeSJ:is_first() - Description: Checks if the current node is the first among its siblings. - Returns: `boolean` TreeSJ:is_last() - Description: Checks if the current node is the last among its siblings. - Returns: `boolean` TreeSJ:is_framing() - Description: Checks if the current node is either the first or the last among its siblings. - Returns: `boolean` TreeSJ:is_omit() - Description: Checks if the text of the current TreeSJ's type is present in `preset[mode].omit`. - Returns: `boolean` TreeSJ:is_imitator() - Description: Checks if the current TreeSJ is a node-imitator. - Returns: `boolean` TreeSJ:preset(mode?) - Description: Retrieves the preset configuration for the current TreeSJ node. - Parameters: - `mode`: `'split'|'join'` (optional) - The current processing mode. - Returns: `table|nil` TreeSJ:parent_preset(mode?) - Description: Retrieves the preset configuration of the TreeSJ parent node. - Parameters: - `mode`: `'split'|'join'` (optional) - The current processing mode. - Returns: `table|nil` TreeSJ:update_preset(new_preset, mode?) - Description: Updates the preset configuration for the current TreeSJ node. - Parameters: - `new_preset`: `table` - The new preset table to apply. - `mode`: `'split'|'join'` (optional) - The current processing mode. ``` -------------------------------- ### Illustrative Ruby Class/Module Formatting Problem Source: https://github.com/wansmer/treesj/blob/main/README.md This Ruby code snippet demonstrates a complex formatting scenario for classes and modules, showing how nested modules can be joined into a single class definition or split back into individual module and class blocks. This highlights a case where `treesj` might need to defer to external tools for complex transformations. ```ruby # RESULT OF JOIN class Foo::Bar::Baz < Quux def initialize # foo end end # RESULT OF SPLIT module Foo module Bar class Baz < Quux def initialize # foo end end end end ``` -------------------------------- ### Merge Existing Language Presets in TreeSJ Source: https://github.com/wansmer/treesj/blob/main/doc/treesj.txt Illustrates how to reuse and merge an existing language preset (e.g., `css`) for a new language (`scss`) that shares a similar structure. This avoids duplicating configuration for common node types. ```Lua local tsj_utils = require('treesj.langs.utils') local css = require('treesj.langs.css') local langs = { scss = tsj_utils.merge_preset(css, {--[[ ``` -------------------------------- ### Configure TreeSJ Plugin Settings Source: https://github.com/wansmer/treesj/blob/main/doc/treesj.txt This Lua snippet provides the default configuration options for the TreeSJ Neovim plugin. It showcases various settings such as `use_default_keymaps`, `check_syntax_error`, `max_join_length`, `cursor_behavior`, `notify`, `dot_repeat`, and `on_error`. These settings allow users to customize the plugin's behavior for splitting and joining code blocks. ```Lua local tsj = require('treesj') local langs = {--[[ configuration for languages ]]} tsj.setup({ ---@type boolean Use default keymaps (m - toggle, j - join, s - split) use_default_keymaps = true, ---@type boolean Node with syntax error will not be formatted check_syntax_error = true, ---If line after join will be longer than max value, ---@type number If line after join will be longer than max value, node will not be formatted max_join_length = 120, ---Cursor behavior: ---hold - cursor follows the node/place on which it was called ---start - cursor jumps to the first symbol of the node being formatted ---end - cursor jumps to the last symbol of the node being formatted ---@type 'hold'|'start'|'end' cursor_behavior = 'hold', ---@type boolean Notify about possible problems or not notify = true, ---@type boolean Use `dot` for repeat action dot_repeat = true, ---@type nil|function Callback for treesj error handler. func (err_text, level, ...other_text) on_error = nil, ---@type table Presets for languages -- langs = {}, -- See the default presets in lua/treesj/langs }) ``` -------------------------------- ### TreeSJ Node Preset Configuration Functions Source: https://github.com/wansmer/treesj/blob/main/README.md Provides functions to apply default presets for various types of TreeSJ nodes, allowing users to override default settings. These functions simplify the configuration of common node patterns like lists, dictionaries, statements, and arguments. ```APIDOC TreeSJ Node Preset Functions: set_default_preset(override: table) - Applies the default node preset. set_preset_for_list(override: table) - Applies a preset for list-like nodes. set_preset_for_dict(override: table) - Applies a preset for dictionary-like nodes. set_preset_for_statement(override: table) - Applies a preset for statement-like nodes. set_preset_for_args(override: table) - Applies a preset for argument-like nodes. set_preset_for_non_bracket(override: table) - Applies a preset for non-bracket nodes. Parameters: override: table - A table containing settings to override the default preset values. ``` -------------------------------- ### Configuring Custom Language Presets in treesj Lua Source: https://github.com/wansmer/treesj/blob/main/doc/treesj.txt Demonstrates how to define custom presets for specific languages and node types within the treesj configuration. This allows fine-grained control over formatting behavior for different syntax elements, such as JavaScript arrays or objects. ```Lua local langs = { javascript = { array = {--[[ preset ]]}, object = {--[[ preset ]]}, ['function'] = { target_nodes = {--[[ targets ]]}} } } ``` -------------------------------- ### Configure Treesj Presets for JavaScript and Lua Source: https://github.com/wansmer/treesj/blob/main/README.md This snippet demonstrates how to configure `treesj` presets for JavaScript and Lua using `lang_utils.set_preset_for_dict`, `set_preset_for_list`, and `set_preset_for_args`. It shows how to define specific formatting rules for nodes like objects, arrays, parameters, and statement blocks, including conditional joining rules for JavaScript. ```lua local lang_utils = require('treesj.langs.utils') local langs = { javascript = { object = lang_utils.set_preset_for_dict(), array = lang_utils.set_preset_for_list(), formal_parameters = lang_utils.set_preset_for_args(), arguments = lang_utils.set_preset_for_args(), statement_block = lang_utils.set_preset_for_statement({ join = { no_insert_if = { 'function_declaration', 'try_statement', 'if_statement', }, }, }), }, lua = { table_constructor = lang_utils.set_preset_for_dict(), arguments = lang_utils.set_preset_for_args(), parameters = lang_utils.set_preset_for_args(), }, } ``` -------------------------------- ### treesj Node Configuration Preset Structure Source: https://github.com/wansmer/treesj/blob/main/doc/treesj.txt Defines the default structure and available options for configuring a node's behavior within treesj. This includes properties for preventing formatting, defining separators, handling empty nodes, enabling recursion, and advanced formatting functions. ```APIDOC local node_type = { -- `both` will be merged with both presets from `split` and `join` modes tables. -- If you need different values for different modes, they can be overridden -- in mode tables unless otherwise noted. both = { ---If a node contains descendants with a type from the list, it will not be formatted ---@type string[] no_format_with = { 'comment' }, ---Separator for arrays, objects, hash e.c.t. (usually ',') ---@type string separator = '', ---Set last separator or not ---@type boolean last_separator = false, ---If true, empty brackets, empty tags, or node which only contains nodes from 'omit' no will handling ---@type boolean format_empty_node = true, ---All nested configured nodes will process according to their presets ---@type boolean recursive = true, ---Type of configured node that must be ignored ---@type string[] recursive_ignore = {}, --[[ Working with the options below is explained in detail in `advanced node configuration` section. ]] ---Set `false` if node should't be splitted or joined. ---@type boolean|function For function: function(tsnode: TSNode): boolean enable = true, ---@type function|nil function(tsj: TreeSJ): void format_tree = nil, ---@type function|nil function(lines: string[], tsn?: TSNode): string[] format_resulted_lines = nil } ``` -------------------------------- ### Redirect Node Processing with `target_nodes` for Custom Presets Source: https://github.com/wansmer/treesj/blob/main/doc/treesj.txt Demonstrates how `target_nodes` can redirect the processing of specific fields or nodes to custom presets. This allows applying different configuration logic to nodes based on their context, such as processing a `block` inside a `function_declaration` with a specialized preset. ```Lua { block = lang_utils.set_preset_for_statement(), my_custom_preset_for_block_inside_fun_dec = {--[[ another preset ]]}, function_declaration = { target_nodes = { ['block'] = 'my_custom_preset_for_block_inside_fun_dec' } } } ```