diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..c433f47 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,43 @@ +name: CI +on: + push: + pull_request: + +jobs: + tests: + strategy: + matrix: + os: [ubuntu-latest] + runs-on: ${{ matrix.os }} + steps: + - uses: actions/checkout@v3 + - name: Install Neovim + shell: bash + run: | + wget -q https://github.com/neovim/neovim/releases/download/nightly/nvim-linux64.deb -O /tmp/nvim.deb + sudo dpkg -i /tmp/nvim.deb + - name: Run Tests + run: | + nvim --version + [ ! -d tests ] && exit 0 + nvim --headless -u tests/minimal.lua -c "PlenaryBustedDirectory tests/ {minimal_init = 'tests/minimal.lua', sequential = true}" + docs: + runs-on: ubuntu-latest + needs: tests + if: ${{ github.ref == 'refs/heads/main' }} + steps: + - uses: actions/checkout@v3 + - name: panvimdoc + uses: kdheepak/panvimdoc@main + with: + vimdoc: treesj + version: "Neovim >= 0.8.0" + demojify: true + treesitter: true + - name: Push changes + uses: stefanzweifel/git-auto-commit-action@v4 + with: + commit_message: "task: auto-generate vimdoc" + commit_user_name: "github-actions[bot]" + commit_user_email: "github-actions[bot]@users.noreply.github.com" + commit_author: "github-actions[bot] " diff --git a/Makefile b/Makefile index 64b8f67..e64ce66 100644 --- a/Makefile +++ b/Makefile @@ -3,16 +3,36 @@ preinstall-ts-parsers: # LP string = language path test-langs: - nvim --headless -u tests/minimal.lua -c "PlenaryBustedDirectory tests/langs/${LP} {minimal_init = 'tests/minimal.lua'}" - -test-langs-tab: - nvim --headless -u tests/minimal_tab.lua -c "PlenaryBustedDirectory tests/langs_tab {minimal_init = 'tests/minimal_tab.lua'}" + nvim --headless -u tests/minimal.lua -c "PlenaryBustedDirectory tests/langs/${LP} { minimal_init = 'tests/minimal.lua' }" test-chold: nvim --headless -u tests/minimal.lua -c "PlenaryBustedDirectory tests/chold {minimal_init = 'tests/minimal.lua'}" +# M string = mode 'start'|'end'|'hold' +test-chold-m: + nvim --headless -u tests/minimal.lua -c "PlenaryBustedDirectory tests/chold/${M}_spec.lua {minimal_init = 'tests/minimal.lua'}" + +test-chold-r: + nvim --headless -u tests/minimal.lua -c "PlenaryBustedDirectory tests/chold/hold_split_recursive_spec.lua {minimal_init = 'tests/minimal.lua'}" + test: - make test-langs && make test-langs-tab && make test-chold + make test-langs && make test-chold lint-fix: - stylua ./lua/treesj + stylua ./lua/treesj ./tests/langs/ + +docs: + ~/projects/code/github/panvimdoc/panvimdoc.sh \ + --project-name treesj \ + --input-file ./README.md \ + --vim-version 0.8.0 \ + --toc true \ + --description "" \ + --dedup-subheadings true \ + --demojify false \ + --treesitter true \ + --ignore-rawblocks false \ + --doc-mapping true \ + --doc-mapping-project-name true \ + --shift-heading-level-by 0 \ + --increment-heading-level-by 0 \ diff --git a/README.md b/README.md index 4f68d30..0168ddd 100644 --- a/README.md +++ b/README.md @@ -1,31 +1,70 @@ -# TreeSJ: split or join blocks of code +# TreeSJ -Neovim plugin for splitting/joining blocks of code like arrays, hashes, statements, objects, dictionaries, etc. Written in Lua, using [Tree-Sitter](https://tree-sitter.github.io/tree-sitter/). +Neovim plugin for splitting/joining blocks of code like arrays, hashes, +statements, objects, dictionaries, etc. -Inspired by and partly repeats the functionality of [splitjoin.vim](https://github.com/AndrewRadev/splitjoin.vim). +Written in Lua, using [Tree-Sitter](https://tree-sitter.github.io/tree-sitter/). -> _⚡Disclaimer: The plugin is under active development. Documentation will be added when all planned features are implemented. Feel free to open an issue or PR 💪_ +Inspired by and partly repeats the functionality of +[splitjoin.vim](https://github.com/AndrewRadev/splitjoin.vim). + + Theme: [Catppuccin](https://github.com/catppuccin/nvim), Font: JetBrains Mono + + +- [Features](#features) +- [Requirements](#requirements) +- [Installation](#installation) +- [Settings](#settings) +- [Commands](#commands) +- [How plugin works](#how-plugin-works) +- [Configuration](#configuration) + - [Languages](#languages) + - [Basic node](#basic-node) + - [Advanced node](#advanced-node) + - [TreeSJ instance](#treesj-instance) + + + + + ## Features -- **Can be called from anywhere in the block**: No need to move cursor to specified place to split/join block of code; +- **Can be called from anywhere in the block**: No need to move cursor to + specified place to split/join block of code; - **Make cursor sticky**: The cursor follows the text on which it was called; -- **Autodetect mode**: Toggle-mode present. Split or join blocks by same key mapping; +- **Autodetect mode**: Toggle-mode present. Split or join blocks by same key + mapping; - **Do it recursively**: Expand or collapse all nested nodes? Yes, you can; -- **Recognize nested languages**: Filetype doesn't matter, detect language with treesitter; +- **Recognize nested languages**: Filetype doesn't matter, detect language with + treesitter; - **Repeat formatting with `dot`**: `.` support for each action. +- **Smart**: Different behavior depending on the context. ## Requirements -1. [Neovim 0.8+](https://github.com/neovim/neovim/releases) -2. [nvim-treesitter](https://github.com/nvim-treesitter/nvim-treesitter) +- [Neovim 0.8+](https://github.com/neovim/neovim/releases) +- [nvim-treesitter](https://github.com/nvim-treesitter/nvim-treesitter) ## Installation +With [lazy.nvim](https://github.com/folke/lazy.nvim): + +```lua +return { + 'Wansmer/treesj', + keys = { 'm', 'j', 's' }, + dependencies = { 'nvim-treesitter/nvim-treesitter' }, + config = function() + require('treesj').setup({--[[ your config ]]}) + end, +} +``` + With [packer.nvim](https://github.com/wbthomason/packer.nvim): ```lua @@ -38,9 +77,7 @@ use({ }) ``` -## Configuration - -### Plugin configuration +## Settings Default configuration: @@ -70,18 +107,82 @@ tsj.setup({ -- Notify about possible problems or not notify = true, langs = langs, + -- Use `dot` for repeat action dot_repeat = true, }) ``` -Also, TreeSJ provide user commands: +## Commands + +TreeSJ provide user commands: + +- `:TSJToggle` - toggle node under cursor (split if one-line and join if + multiline); +- `:TSJSplit` - split node under cursor; +- `:TSJJoin` - join node under cursor; + +Similar with lua: + +```bash +:lua require('treesj').toggle() +:lua require('treesj').split() +:lua require('treesj').join() +``` + +In the lua version, you can optionally pass a preset that will overwrite the +default preset values. It should contain `split` or `join` keys. Key `both` +will be ignored. + +**Warning**: If you are passing a preset, repeating with a dot will not work. + +E.g.: + +```lua +-- For use default preset and it work with dot +vim.keymap.set('n', 'm', require('treesj').toggle) +-- For extending default preset with `recursive = true`, but this doesn't work with dot +vim.keymap.set('n', 'M', function() + require('treesj').toggle({ split = { recursive = true } }) +end) +``` + +## How plugin works + +When you run the plugin, TreeSJ detects the node under the cursor, recognizes +the language, and looks for it in the presets. If the current node is not +configured, TreeSJ checks the parent node, and so on, until a configured node is +found. + +Presets for node can be two types: + +- With preset for self - if this type is found, the node will be formatted; +- With referens for nested nodes or fields - in this case, search will be + continued among this node descendants; + +**Example**: + +> "|" - meaning cursor + +```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 +``` -1. `:TSJToggle` - toggle node under cursor (split if one-line and join if multiline); -2. `:TSJSplit` - split node under cursor; -3. `:TSJJoin` - join node under cursor; +# Configuration -### Languages configuration +## Languages By default, TreeSJ has presets for these languages: @@ -111,9 +212,14 @@ By default, TreeSJ has presets for these languages: - **Nix**; - **Kotlin**; -For adding your favorite language, add it to `langs` sections in your configuration. Also, see how [to implement fallback](https://github.com/Wansmer/treesj/discussions/19) to splitjoin.vim. +For adding your favorite language, add it to `langs` sections in your +configuration. Also, see how [to implement +fallback](https://github.com/Wansmer/treesj/discussions/19) to splitjoin.vim. -To find out what nodes are called in your language, analyze your code with [nvim-treesitter/playground](https://github.com/nvim-treesitter/playground) or look in the [source code of the parsers](https://tree-sitter.github.io/tree-sitter/). +To find out what nodes are called in your language, analyze your code with +[nvim-treesitter/playground](https://github.com/nvim-treesitter/playground) or +look in the [source code of the +parsers](https://tree-sitter.github.io/tree-sitter/). **Example:** @@ -127,104 +233,98 @@ local langs = { } ``` -If you have completely configured your language, and it works as well as you expected, feel free to open PR and share it. (Please, read [manual](/tests/README.md) before PR) +If you have completely configured your language, and it works as well as you +expected, feel free to open PR and share it. +(Please, read [manual](/tests/README.md) before PR) -### Nodes configuration +## Basic node Default preset for node: ```lua -local somenode = { - -- Use for split and join. Will merge to both resulting presets - -- If you need various values for different modes, - -- it can be overridden in modes sections +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 = { - -- string[]: TreeSJ will stop if node contains node from list + ---If a node contains descendants with a type from the list, it will not be formatted + ---@type string[] no_format_with = { 'comment' }, - - -- string: Separator for arrays, objects, hash e.c.t. - -- Will auto add to option 'omit' for 'both' + ---Separator for arrays, objects, hash e.c.t. (usually ',') + ---@type string separator = '', - - -- boolean: Set last separator or not + ---Set last separator or not + ---@type boolean last_separator = false, - - -- list[string|function]: Nodes in list will be joined for previous node - -- (e.g. tag_name in HTML start_tag or separator (',') in JS object) - -- NOTE: Must be same for both modes - omit = {}, - - -- boolean: Non-bracket nodes (e.g., with 'then|()' ... 'end' instead of { ... }|< ... >|[ ... ]) - -- NOTE: Must be same for both modes - non_bracket_node = false, - - -- If true, empty brackets, empty tags, or node which only contains nodes from 'omit' no will handling - -- (ignored, when non_bracket_node = true) + ---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 = {}, - -- function|nil function (child: TreeSJ): void - -- Custom callback for transforming text of children nodes. Can be different for split and join - foreach = nil, - - -- nil|table { left = string, right = string } - -- Adding first and last custom nodes, e.g., [], {}, e.t.c, if needed (e.g., see YAML) - add_framing_nodes = nil, - - -- boolean|function function (tsnode): boolean - -- Set `false` if node should't be splitted or joined. Can be different for both modes + --[[ 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(tsj: TreeSJ): void + format_resulted_lines = nil, + + --[[ The options below should be the same for both modes. ]] + ---The text of the node will be merged with the previous one, without wrapping to a new line + ---@type table List-like table with types 'string' (type of node) or 'function' (function(child: TreeSJ): boolean). + omit = {}, + ---Non-bracket nodes (e.g., with 'then|()' ... 'end' instead of { ... }|< ... >|[ ... ]) + ---If value is table, should be contains follow keys: { left = 'text', right = 'text' }. Empty string uses by default + ---@type boolean|table + non_bracket_node = false, }, - -- Use only for join. If contains field from 'both', -- field here have higher priority join = { - - -- Adding space in framing brackets or last/end element + ---Adding space in framing brackets or last/end element + ---@type boolean space_in_brackets = false, - - -- Count of spaces between nodes - space_separator = 1, - - -- string: Add instruction separator like ';' in statement block - -- Will auto add to option 'omit' for 'both' + ---Insert space between nodes or not + ---@type boolean + space_separator = true, + ---Adds instruction separator like ';' in statement block. + ---It's not the same as `separator`: `separator` is a separate node, `force_insert` is a last symbol of code instruction. + ---@type string force_insert = '', - - -- list[string|function]: The insert symbol will be omitted if node contains in this list + ---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 (';')) + ---@type table List-like table with types 'string' (type of node) or 'function' (function(child: TreeSJ): boolean). no_insert_if = {}, - - -- boolean: All nested configured nodes will process according to their presets - recursive = true, - - -- [string]: Type of configured node that must be ignored - recursive_ignore = {}, }, - -- Use only for split. If contains field from 'both', -- field here have higher priority split = { - -- boolean: All nested configured nodes will process according to their presets + ---All nested configured nodes will process according to their presets + ---@type boolean recursive = false, - - -- [string]: Type of configured node that must be ignored - -- E.g., you probably don't want the parameters of each nested function to be expanded. - recursive_ignore = {}, - - -- string: 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()). - + ---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()). + ---@type 'normal'|'inner' last_indent = 'normal', - -- string: 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()). + ---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()). + ---@type 'normal'|'inner' inner_indent = 'inner', }, - -- If 'true', node will be completely removed from langs preset + ---If 'true', node will be completely removed from langs preset + ---@type boolean disable = false, - - -- 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 + ---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 + ---@type string[]|table See `advanced node configuration` target_nodes = {}, } ``` @@ -249,15 +349,15 @@ Takes a table with the settings to be overwritten as an argument. **Usage example**: ```lua -local tsj_utils = require('treesj.langs.utils') +local lang_utils = require('treesj.langs.utils') local langs = { javascript = { - object = tsj_utils.set_preset_for_dict(), - array = tsj_utils.set_preset_for_list(), - formal_parameters = tsj_utils.set_preset_for_args(), - arguments = tsj_utils.set_preset_for_args(), - statement_block = tsj_utils.set_preset_for_statement({ + 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', @@ -268,16 +368,18 @@ local langs = { }), }, lua = { - table_constructor = tsj_utils.set_preset_for_dict(), - arguments = tsj_utils.set_preset_for_args(), - parameters = tsj_utils.set_preset_for_args(), + table_constructor = lang_utils.set_preset_for_dict(), + arguments = lang_utils.set_preset_for_args(), + parameters = lang_utils.set_preset_for_args(), }, } ``` -Also, you can use whole preset for language if your language has the same types of nodes: +Also, you can use whole preset for language if your language has the same types +of nodes: -> For example, `css` and `scss` have the same structure, and you can use already configured preset +> For example, `css` and `scss` have the same structure, and you can use already +> configured preset ```lua local tsj_utils = require('treesj.langs.utils') @@ -291,32 +393,808 @@ local langs = { } ``` -## How it works +## Advanced node -When you run the plugin, TreeSJ detects the node under the cursor, recognizes the language, and looks for it in the presets. -If the current node is not configured, TreeSJ checks the parent node, and so on, until a configured node is found. +Although most nodes have similar parameters and can be configured declarative, +sometimes you need to change the values, text, or order of children on the fly. -Presets for node can be two types: +To do this, some options accept functions as a value, which are passed instances +of [TSNode](https://neovim.io/doc/user/treesitter.html#treesitter-node), +[TreeSJ](#treesj-instance), or an array of rows to insert. -1. With preset for self - if this type is found, the node will be formatted; -2. With referens for nested nodes - in this case, search will be continued among this node descendants; +#### Option `enable` -**Example**: +The `enable` option can be a boolean value or a function. The function takes the +found [TSNode](https://neovim.io/doc/user/treesitter.html#treesitter-node) node +as arguments and should return a boolean value. -> "|" - meaning cursor +
+Example of usage -```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 +The problem: -// 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 +```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" +) +``` + +This can be implemented with: + +```lua +local go = { + import_spec = lang_utils.set_preset_for_args({ + both = { + -- If the parent is a 'import_spec_list', then skip this node and + -- look for a suitable one for formatting further + enable = function(tsn) + return tsn:parent():type() ~= 'import_spec_list' + end, + }, + split = { + -- If the parent was something else, then wrap the import in parentheses, + -- which actually converts the 'import_spec' into the 'import_spec_list' + format_tree = function(tsj) + tsj:wrap({ left = '(', right = ')' }) + end, + }, + }), + import_spec_list = lang_utils.set_preset_for_args({ + join = { + enable = function(tsn) + -- If the node contains more than one named child node, then disable + return tsn:named_child_count() < 2 + end, + format_tree = function(tsj) + -- If there was only one named element, then remove the brackets + tsj:remove_child({ '(', ')' }) + end, + }, + }), +} +``` + +
+ +#### Option `no_insert_if` + +The `preset[join].no_insert_if` option takes an array with node types or +functions. The function takes a TreeSJ as a parameter (each child of the root +node in turn) and should return a boolean if that child matches the condition. + +The utilities have helper functions that you will need most often: + +`lang_utils.helpers.if_penultimate` + +`lang_utils.helpers.if_second` + +`lang_utils.helpers.by_index(index)` + +`lang_utils.helpers.has_parent(parent_type)` + +`lang_utils.helpers.match(pattern)` + +
+ +Example of usage + +The problem: + +```kotlin +// Kotlin's 'statements' should be separated with ';' after each child +// when it joins, but for the last named child it is not necessary, +// and we want to skip it + +// from +call_expression("arg1") { + call1(1, 2) + call2(1, 2) +} + +// to | here no ';', great +call_expression("arg1") { call1(1, 2); call2(1, 2) } +``` + +This can be implemented with: + +```lua +local lang_utils = require('treesj.langs.utils') + +local kotlin = { + statements = lang_utils.set_preset_for_non_bracket({ + join = { + force_insert = ';', + no_insert_if = { + lang_utils.no_insert.if_penultimate, + }, + }, + }), +} +``` + +
+ +#### Option `omit` + +The `preset[both]omit` option accepts a list of node types or functions. If at +the time the tree is built, the type of the child matches one of the listed +ones, then this child remains unchanged. (does not wrap to a new line in case of +a split, or its position and spaces do not change in the case of a join). + +When some value of list is `function` the principle of operation is the same as +that of `no_insert_if`. + +#### Option `non_bracket_node` + +Some languages have nodes that can be split and joined, but they don't have +brackets or other framing elements. + +In this case, it is necessary not only to simulate the framing nodes, but also +to calculate a new range for inserting rows. + +`preset[both].non_bracket_node` can be a boolean value (in which case wrapping +node imitators are created with an empty value) or take a table that +specifies what text should wrap the actual base node. + +E.g., table value: `{ left = 'text', right = 'text' }` + +
+ +Example of usage + +The problem: + +```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 ``` + +This can be implemented with: + +```lua +local lang_utils = require('treesj.langs.utils') + +local lua = { + block = { + both = { + non_bracket_node = true, + -- non_bracket_node = { left = '', right = '' }, - it is similar + }, + join = { + space_in_brackets = true, + }, + }, +} +``` + +
+ +#### Option `target_nodes` + +In most cases, `target_nodes` is a list of node types to redirect the search for +the configured node deeper. But in reality it is treated like a dictionary: + +```lua +-- these values are equivalent +target_nodes = { 'block', 'statement' } +target_nodes = { ['block'] = 'block', ['statement'] = 'statement' } +``` + +The key must be a node type or a field name. The value is the name of any +configured node whose preset is to be used. + +If the field name is specified in the keys, then it has the highest priority +over node types. + +This also means that you can redirect found fields or nodes for processing with +other (including custom) presets. + +```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' } + } +} +``` + +
+ +Example of usage + +The problem: + +```rust +match x { + // | - it is a field `value` and now it `integer_literal` + _ => 12 + // `integer_literal` is not configured and can't be configured + // but you can transform this field into a `block` node +} + +match x { + _ => { + 12 + } +} + +``` + +This can be implemented with: + +```lua +local rust = { + match_arm = { + target_nodes = { 'value' }, + }, + value = lang_utils.set_preset_for_statement({ + split = { + format_tree = function(tsj) + if tsj:type() ~= 'block' then + tsj:wrap({ left = '{', right = '}' }) + end + end, + }, + join = { + no_insert_if = { lang_utils.helpers.if_penultimate }, + format_tree = function(tsj) + local node = tsj:tsnode() + local parents = { 'match_arm', 'closure_expression' } + local has_parent = vim.tbl_contains(parents, node:parent():type()) + if has_parent and node:named_child_count() == 1 then + tsj:remove_child({ '{', '}' }) + end + end, + }, + }), +} +``` + +
+ +#### Option `format_tree` + +`format_tree` is a function that takes a TreeSJ root node. In this function, you +can work with the context and add or remove elements. + +
+ +Example of usage + +The problem: + +Python's `import_from_statement` does not have a container for a list of imported modules. + +Here you need to add parentheses to the middle and end of TreeSJ when splitting and remove these parentheses when joining. + +```python +# from +from re import search, match,sub + +# to this and back +from re import ( + search, + match, + sub, +) +``` + +This can be implemented with: + +```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, + }, + }), +} +``` + +
+ +#### Option `format_resulted_lines` + +The `format_resulted_lines` function takes as an argument an array of strings +that will replace the content of the base node. + +The function should return an array of strings that may have been modified. + +If the mode is "join", then after executing this function, these strings will be +concatenated. + +E.g.: + +```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 of usage + +The problem: + +Python's `import_from_statement` does not have a container for a list of +imported modules. + +Here you need to add parentheses to the middle and end of TreeSJ when splitting +and remove these parentheses when joining. + +```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') +``` + +This can be implemented with: + +```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, + }, + }), +} +``` + +
+ +## TreeSJ instance + +After the node for formatting is found, an instance of the TreeSJ class is +created. Each of its children and descendants is also an instance of this class. +The methods of this class can be used to change formatting behavior on the fly +(see advanced node configuration). + +### TreeSJ Lifecycle + +- **Checking the found Node**: There is a check that there is no syntax error in + the node, there are no descendants with types from `preset[mode].no_format_with` + and `preset[mode].enable` is true. +- **Creating root TreeSJ**: A node for formatting has been found and checked, + and an instance of TreeSJ is created based on it. +- **Build tree**: It iterates all the children of the base node and creates + the TreeSJ children. If the `preset[mode].recursive` is true, then a check is made + to see if the child or its children are configured, if so, a tree is built + for it and its children. +- **Remove or insert last separator**: if a separator is specified in the + preset. +- **Run `preset[mode].format_tree`**: custom function from preset. +- **Mode-based preparation**: spacing or indenting, adding a + `preset.join.force_insert`, forming a list of strings to replace the base node + content. +- **Run `preset[mode].format_resulted_lines`**: custom function from preset. + +### Methods + +
+ +Show/Hide methods... + +#### has_children + +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. + +```lua +---@param types? string[] +---@return boolean +function TreeSJ:has_children(types) +``` + +#### iter_children + +Iterate all TreeSJ children. +Use: `... for child, index in tsj:iter_children() do ...` + +```lua +---@return function, table +function TreeSJ:iter_children() +``` + +#### children + +Get the children list of the current TreeSJ. Returns all children if `types` are +omitted, otherwise returns all children of the listed types. + +```lua +---@param types? string[] List-like table with child's types for filtering +---@return TreeSJ[] +function TreeSJ:children(types) +``` + +#### root + +Get root TreeSJ node of current TreeSJ + +```lua +---@return TreeSJ TreeSJ instance +function TreeSJ:root() +``` + +#### parent + +Get parent TreeSJ + +```lua +---@return TreeSJ|nil +function TreeSJ:parent() +``` + +#### child + +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)`. + +```lua +---@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) +``` + +#### create_child + +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. + +```lua +---@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) +``` + +#### update_children + +Updating children list of current TreeSJ + +```lua +---@param children TreeSJ[] +function TreeSJ:update_children(children) +``` + +This function must be called every time you update the list of children from +outside, for example: + +```lua +-- When a function should be called +local children = tsj:children() +local child = tsj:create_child({ text = 'end' }) +table.insert(children, child) +tsj:update_children(children) -- important + +-- Here it is not necessary +tsj:create_child({ text = 'end' }, #tsj:children() + 1) +``` + +#### remove_child + +Removes children by the passed types or index. + +```lua +---@param types_or_index string|string[]|integer Type, types, or index of child to remove +function TreeSJ:remove_child(types_or_index) +``` + +#### wrap + +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. + +```lua +---@param data table { left = string, right = string } +---@param mode? 'wrap'|'inline' 'wrap' by default +function TreeSJ:wrap(data, mode) +``` + +#### swap_children + +Helps to swap elements by their indexes + +```lua +---@param index1 integer +---@param index2 integer +function TreeSJ:swap_children(index1, index2) +``` + +#### tsnode + +Get [TSNode](https://neovim.io/doc/user/treesitter.html#treesitter-node) or +TSNode imitator of current TreeSJ. If you plan to use tsnode methods in the +future, you first need to check that the returned value is not an imitator. + +```lua +---@return TSNode|table TSNode or TSNode imitator +function TreeSJ:tsnode() +``` + +#### prev + +Get left side TreeSJ + +```lua +---@return TreeSJ|nil +function TreeSJ:prev() +``` + +#### next + +Get right side TreeSJ + +```lua +---@return TreeSJ|nil +function TreeSJ:next() +``` + +#### type + +Get node type of current TreeSJ. + +```lua +---@return string +function TreeSJ:type() +``` + +#### text + +Get text of current TreeSJ. +At the time of the execution of the `format_tree` function, the text will always +be returned, not the table. + +```lua +---@return string|table +function TreeSJ:text() +``` + +#### update_text + +Updating text of current TreeSJ. If the mode "split" and "recursively" is +active, then it can be an array. In such a case, you need to update the text in +its children directly. + +```lua +---@param new_text string|string[] +function TreeSJ:update_text(new_text) +``` + +When working in recursive mode, you need to check that the nodes in which you +want to change the text do not have children for recursive processing. In this +case, the text will be glued from the children of the node, and you need to +change the text in them. + +E.g.: + +```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, +} +``` + +#### will_be_formatted + +Returns true if the current TreeSJ will be formatted. +The conditions are met: recursion is active, the current element has a preset, or among its descendants there are nodes that will be processed. + +```lua +---@return boolean +function TreeSJ:will_be_formatted() +``` + +#### is_ignore + +Checks if the current TreeSJ child must be ignored while recursive formatting. + +```lua +---@return boolean +function TreeSJ:is_ignore() +``` + +#### has_to_format + +Checks if the TreeSJ contains children that need to be formatted + +```lua +---@return boolean +function TreeSJ:has_to_format() +``` + +#### is_first + +Checks if the current node is first among sibling + +```lua +---@return boolean +function TreeSJ:is_first() +``` + +#### is_last + +Checks if the current node is last among sibling + +```lua +---@return boolean +function TreeSJ:is_last() +``` + +#### is_framing + +Checks if the current node is first or is last among sibling + +```lua +---@return boolean +function TreeSJ:is_framing() +``` + +#### is_omit + +Checks if the text of current TreeSJ's type contains at `preset[mode].omit` + +```lua +---@return boolean +function TreeSJ:is_omit() +``` + +#### is_imitator + +Checks if the current TreeSJ is node-imitator + +```lua +---@return boolean +function TreeSJ:is_imitator() +``` + +#### preset + +Get preset for current TreeSJ + +```lua +---@param mode? 'split'|'join' Current mode (split|join) +---@return table|nil +function TreeSJ:preset(mode) +``` + +#### parent_preset + +Get the preset of the TreeSJ parent + +```lua +---@param mode? 'split'|'join' Current mode (split|join) +---@return table|nil +function TreeSJ:parent_preset(mode) +``` + +#### update_preset + +Updates the presets for the current TreeSJ. + +```lua +---@param new_preset table +---@param mode? 'split'|'join' +function TreeSJ:update_preset(new_preset, mode) +``` + +
diff --git a/doc/treesj.txt b/doc/treesj.txt index 9eee70f..591cd4b 100644 --- a/doc/treesj.txt +++ b/doc/treesj.txt @@ -1 +1 @@ -Empty file to generation docs +Empty file to generation docs \ No newline at end of file diff --git a/lua/treesj/chold/init.lua b/lua/treesj/chold/init.lua index f3ae117..07ff4db 100644 --- a/lua/treesj/chold/init.lua +++ b/lua/treesj/chold/init.lua @@ -1,168 +1,198 @@ local settings = require('treesj.settings').settings +local search = require('treesj.search') +local tu = require('treesj.treesj.utils') local u = require('treesj.utils') -local cu = require('treesj.chold.utils') -local JOIN = 'join' -local SPLIT = 'split' +local BEHAVIOR = settings.cursor_behavior +local special_types = { + 'left_non_bracket', + 'right_non_bracket', + 'left_bracket', + 'right_bracket', +} + +local function prev_not_deleted(child) + local tsn = child:tsnode() + local prev_tsn = tsn:prev_sibling() + while prev_tsn do + local not_removed = u.some(child:parent():children(), function(el) + return el:tsnode() == prev_tsn + end) + if not_removed then + return prev_tsn + end + prev_tsn = prev_tsn:prev_sibling() + end + return nil +end ----Calculating new position for cursor considering current mode ----@class CHold ----@field pos table Start position of cursor (0-base index) ----@field _new_pos table Computed cursor position (1-base index) -local CHold = {} -CHold.__index = CHold +local function observed_range(child) + local tsn = child:tsnode() + local prev_tsn + if + child:prev() + and child:prev():is_imitator() + and vim.tbl_contains(special_types, child:prev():type()) + then + prev_tsn = child:prev():tsnode() + else + prev_tsn = prev_not_deleted(child) + end + local sr, sc, er, ec = tsn:range() ----Create new CHold instance ----@return CHold -function CHold.new() - local pos = cu.get_cursor() - return setmetatable({ - pos = pos, - _new_pos = { - col = pos.col, - row = pos.row + 1, - }, - _done = false, - }, CHold) + if prev_tsn then + _, _, sr, sc = prev_tsn:range() + end + + return { sr + 1, sc, er + 1, ec } end ----Update new position for cursor ----@param tsj TreeSJ TreeSJ instance ----@param mode string Current mode -function CHold:update(tsj, mode) - if not self:is_done() then - if settings.cursor_behavior == 'start' then - self:_calc_for_start(tsj) - elseif settings.cursor_behavior == 'end' then - self:_calc_for_end(tsj, mode) - elseif cu.is_not_need_change(self, tsj) then - self:done() - elseif cu.is_after_node(self, tsj) then - self:_calc_when_after(tsj, mode) - else - if mode == JOIN then - self:_calc_for_join(tsj) +local function in_range(cursor, range, mode) + local cr, cc = unpack(cursor) + local sr, sc, er, ec = unpack(range) + + if mode == 'join' then + if sr <= cr and cr <= er then + if sr == cr then + return cc >= sc + elseif cr == er then + return cc < ec else - self:_calc_for_split(tsj) + return true end end + return false + else + return sc <= cc and cc < ec end end ----Complute new position for cursor ----@param tsj TreeSJ TreeSJ instance ----@param mode string Current mode (split|join) -function CHold:compute(tsj, mode) - for child in tsj:iter_children() do - self:update(child, mode) - end +local function pos_in_node(cursor, child) + local range = { child:tsnode():range() } + local cursor_col = cursor[1] ~= range[1] + 1 and -1 or cursor[2] + return cursor_col - range[2] +end + +local function calc_new_pos(cursor, child, mode) + local ws = mode == 'join' and #tu.get_whitespace(child) + or tu.calc_indent(child) + local pos = pos_in_node(cursor, child) + pos = pos < -ws and -ws or pos + return pos + ws end ----Calculate '_new_pos' when settings.cursor_behavior is 'start' ----@param tsj TreeSJ TreeSJ instance -function CHold:_calc_for_start(tsj) - local rr = u.readable_range(tsj:root():range()) - self:_update_pos({ row = rr.row.start + 1, col = rr.col.start }) - self:done() +local function need_check(child) + return not child:is_imitator() + or (vim.tbl_contains(special_types, child:type()) and child:is_framing()) end ----Calculate '_new_pos' when settings.cursor_behavior is 'end' ----@param tsj TreeSJ TreeSJ instance -function CHold:_calc_for_end(tsj, mode) - if tsj:is_last() then - local lines = tsj:root():get_lines() - if mode == SPLIT then - self:_update_pos({ - row = self._new_pos.row + #lines - 1, - col = #lines[#lines] - 1, - }) - self:done() +local function get_cursor_for_join(tsj, rowcol, cursor) + local len = 0 + local row, col = unpack(rowcol) + + for child in tsj:iter_children() do + local is_in_range = need_check(child) + and in_range(cursor, observed_range(child), 'join') + + if is_in_range then + local pos = calc_new_pos(cursor, child, 'join') + col = col + len + pos + break else - local rr = u.readable_range(tsj:root():range()) - self:_update_pos({ - col = rr.col.start + #lines[1] - 1, - row = rr.row.start + 1, - }) - self:done() + len = len + #child:text() end end + + return row, col end ----Calculate '_new_pos' when cursor position is after node ----@param tsj TreeSJ TreeSJ instance -function CHold:_calc_when_after(tsj, mode) - if tsj:is_last() then - local rr = u.readable_range(tsj:root():range()) - local after = self.pos.col - rr.col.end_ - local lines = tsj:root():get_lines() - if mode == SPLIT then - self:_update_pos({ - row = self._new_pos.row + #lines - 1, - col = #lines[#lines] + after, - }) - self:done() - else - self:_update_pos({ - col = rr.col.start + #lines[1] + after, - row = rr.row.start + 1, - }) - self:done() +local function get_cursor_for_split(tsj, rowcol, cursor) + local row, col = unpack(rowcol) + + for child in tsj:iter_children() do + local is_in_range = need_check(child) + and in_range(cursor, observed_range(child), 'split') + + if not child:is_first() then + local rows = is_in_range and 1 + or (type(child:text()) == 'string' and 1 or #child:text()) + col = 0 + row = child:is_omit() and row or row + rows + end + + if is_in_range then + local pos = calc_new_pos(cursor, child, 'split') + local len = child:is_omit() and #child:prev():text() or 0 + col = pos + col + len + break end end + + return row, col end ----Calculate '_new_pos' when settings.cursor_behavior is 'hold' and mode is 'join' ----@param tsj TreeSJ TreeSJ instance -function CHold:_calc_for_join(tsj) - local rr = u.readable_range(tsj:root():child(1):range()) - - if cu.in_node_range(self, tsj) then - self:_update_pos({ - row = rr.row.start + 1, - col = self._new_pos.col + cu.new_col_pos(self, tsj, JOIN), - }) - self:done() - return - end +local CHold = {} +CHold.__index = CHold - local len = #tsj:text() - local col = tsj:is_first() and rr.col.start + len or self._new_pos.col + len - self:_update_pos({ col = col }) +function CHold.new() + local pos = vim.api.nvim_win_get_cursor(0) + return setmetatable({ + row = pos[1], + col = pos[2], + original = pos, + }, CHold) end ----Calculate '_new_pos' when settings.cursor_behavior is 'hold' and mode is 'split' ----@param tsj TreeSJ TreeSJ instance -function CHold:_calc_for_split(tsj) - cu.increase_row(self, tsj) +function CHold:compute(tsj, mode) + -- local range = { search.range(tsj:root():tsnode(), tsj:root():preset()) } + local range = { search.range(tsj:tsnode(), tsj:preset()) } + + -- Use position for `start` behavior by default + local row, col = range[1] + 1, range[2] - if cu.in_node_range(self, tsj) then - local rr = u.readable_range(tsj:root():range()) - if not (self._new_pos.row - 1 == rr.row.start) then - self:_update_pos({ col = cu.new_col_pos(self, tsj, SPLIT) }) - self:done() + if BEHAVIOR == 'hold' then + local cursor = self:get_cursor() + -- Checking if the cursor needs to be moved + if cursor[1] == range[1] + 1 and cursor[2] < range[2] then + return + end + + -- Checking if the cursor is after a node + if cursor[1] == range[3] + 1 and cursor[2] >= range[4] then + local lines = tsj:_get_lines() + local shift = cursor[2] - range[4] + local start = range[2] + + if mode == 'split' then + start = 0 + row = row + #lines - 1 + end + + col = #lines[#lines] + shift + start else - self:done() + if mode == 'join' then + row, col = get_cursor_for_join(tsj, { row, col }, cursor) + else + row, col = get_cursor_for_split(tsj, { row, col }, cursor) + end end + elseif BEHAVIOR == 'end' then + local lines = tsj:_get_lines() + local text_len = #lines[#lines] + row = mode == 'join' and range[1] + 1 or range[1] + #lines + col = mode == 'join' and (range[2] + text_len - 1) or text_len - 1 end -end - ----Checking if new position for cursor is already calculated ----@return boolean -function CHold:is_done() - return self._done -end ----Set 'done' option to true -function CHold:done() - self._done = true + self:update_pos({ row = row, col = col }) end -function CHold:_update_pos(pos) - self._new_pos = vim.tbl_deep_extend('force', self._new_pos, pos) +function CHold:get_cursor() + return { self.row, self.col } end -function CHold:get_cursor() - return { self._new_pos.row, self._new_pos.col } +function CHold:update_pos(pos) + self.row = pos.row >= 1 and pos.row or self.row + self.col = pos.col >= 0 and pos.col or self.col end return CHold diff --git a/lua/treesj/chold/utils.lua b/lua/treesj/chold/utils.lua deleted file mode 100644 index c9eb4b1..0000000 --- a/lua/treesj/chold/utils.lua +++ /dev/null @@ -1,114 +0,0 @@ -local u = require('treesj.utils') -local M = {} -local SPLIT = 'split' - ----Return table with cursor position (index start zero) ----@return table -function M.get_cursor() - local c = vim.api.nvim_win_get_cursor(0) - return { row = c[1] - 1, col = c[2] } -end - ----Checking if cursor position need be change ----@param chold CHold CHold instance ----@param tsj TreeSJ TreeSJ instance ----@return boolean -function M.is_not_need_change(chold, tsj) - local rr = u.readable_range(tsj:root():child(1):range()) - return chold.pos.row == rr.row.start and chold.pos.col <= rr.col.end_ -end - ----Checking if cursor position is after node ----@param chold CHold ----@param tsj TreeSJ ----@return boolean -function M.is_after_node(chold, tsj) - local rr = u.readable_range(tsj:root():range()) - return chold.pos.row == rr.row.end_ and chold.pos.col >= rr.col.end_ -end - ----Checking if start position of cursor was place in current logic range of node ----@param chold CHold CHold instance ----@param tsj TreeSJ TreeSJ instance ----@return boolean -function M.in_node_range(chold, tsj) - local rr = u.readable_range(tsj:o_range()) - local result = false - - if rr.row.start <= chold.pos.row and chold.pos.row <= rr.row.end_ then - if chold.pos.row == rr.row.end_ then - result = chold.pos.col < rr.col.end_ - elseif chold.pos.row == rr.row.start then - result = chold.pos.col >= rr.col.start - else - result = true - end - end - - return result -end - ----Return position of cursor in current node. If this was before start column of node, returning negative value ----@param chold CHold CHold instance ----@param tsj TreeSJ TreeSJ instance ----@param mode string Current mode (split|join) ----@return integer -function M.pos_in_node(chold, tsj, mode) - local rr = u.readable_range(tsj:range()) - local pos = chold.pos.col - rr.col.start - local p = tsj:parent():preset(mode) - local space_sep = p and p.space_separator or 0 - - if mode == SPLIT then - local indent = -u.calc_indent(tsj) - pos = pos >= indent and pos or indent - else - local sep = -space_sep - pos = pos >= sep and pos or sep - end - - return pos -end - ----Calculate new position of cursor inside logic range of node ----@param chold CHold CHold instance ----@param tsj TreeSJ TreeSJ instance ----@param mode string Current mode (split|join) ----@return integer -function M.new_col_pos(chold, tsj, mode) - local pos = M.pos_in_node(chold, tsj, mode) - local is_need_prev_len = mode == SPLIT and tsj:is_omit() - local prev_len_corr = is_need_prev_len and #tsj:prev():text() or 0 - local ws = mode == SPLIT and u.calc_indent(tsj) or #u.get_whitespace(tsj) - return prev_len_corr + ws + pos -end - ----Checking if row must be increase and increasing it if needed ----@param tsj TreeSJ TreeSJ instance ----@param chold CHold CHold instance -function M.increase_row(chold, tsj) - local need_increase_row = not (tsj:is_omit() or tsj:is_first()) - - if need_increase_row then - local text = tsj:text() - local term = 1 - - if type(text) == 'table' then - if M.in_node_range(chold, tsj) then - local pos = M.new_col_pos(chold, tsj, 'split') - local len = 0 - local line_count = 0 - while pos > len do - line_count = line_count + 1 - len = len + #text[line_count] - end - term = line_count - else - term = #vim.tbl_flatten(text) - end - end - chold:_update_pos({ row = chold._new_pos.row + term }) - end -end - -return M diff --git a/lua/treesj/format.lua b/lua/treesj/format.lua index 4d7bdf6..037f0ac 100644 --- a/lua/treesj/format.lua +++ b/lua/treesj/format.lua @@ -1,8 +1,8 @@ local notify = require('treesj.notify') local search = require('treesj.search') local TreeSJ = require('treesj.treesj') -local NCHold = require('treesj.chold') -local u = require('treesj.utils') +local CHold = require('treesj.chold') +local tu = require('treesj.treesj.utils') local settings = require('treesj.settings').settings local msg = notify.msg @@ -17,14 +17,14 @@ local MAX_LENGTH = settings.max_join_length local M = {} -function M._format(mode) +function M._format(mode, override) local start_node = ts_utils.get_node_at_cursor(0) if not start_node then notify.info(msg.no_detect_node) return end - local found, tsn_data, node, p, sr, sc, er, ec, MODE + local found, tsn_data, node, p, sr, sc, er, ec, MODE, lang local viewed = {} -- If the node is marked as "disabled", continue searching from its parent. @@ -41,9 +41,14 @@ function M._format(mode) return end + if override then + tsn_data.preset = vim.tbl_deep_extend('force', tsn_data.preset, override) + end + node = tsn_data.tsnode p = tsn_data.preset - sr, sc, er, ec = u.range(node, p) + lang = tsn_data.lang + sr, sc, er, ec = search.range(node, p) MODE = mode or sr == er and SPLIT or JOIN p = p[MODE] @@ -54,12 +59,14 @@ function M._format(mode) table.insert(viewed, node) start_node = node:parent() else + -- Need to use a copy of the preset so that it can be updated on the fly + tsn_data.preset = vim.tbl_deep_extend('force', {}, tsn_data.preset) break end end if p and not p.format_empty_node then - if not p.non_bracket_node and u.is_empty_node(node, p) then + if not p.non_bracket_node and tu.is_empty_node(node, p) then return end end @@ -69,27 +76,41 @@ function M._format(mode) return end - if u.has_disabled_descendants(node, MODE) then + if search.has_disabled_descendants(node, MODE, lang) then local no_format_with = p and vim.inspect(p.no_format_with) or '' notify.info(msg.no_format_with, MODE, node:type(), no_format_with) return end + tsn_data.mode = MODE local treesj = TreeSJ.new(tsn_data) - treesj:build_tree(MODE) - treesj[MODE](treesj) - local replacement = treesj:get_lines() + treesj:_build_tree() + + local ok_format, err = pcall(treesj._format, treesj) + if not ok_format then + notify.warn(err) + return + end + + local replacement = treesj:_get_lines() if MODE == JOIN and #replacement[1] > MAX_LENGTH then notify.info(msg.extra_longer:format(MAX_LENGTH)) return end - local cursor = NCHold.new() + local cursor = CHold.new() cursor:compute(treesj, MODE) local new_cursor = cursor:get_cursor() - vim.api.nvim_buf_set_text(0, sr, sc, er, ec, replacement) + local insert_ok, e = + pcall(vim.api.nvim_buf_set_text, 0, sr, sc, er, ec, replacement) + + if not insert_ok then + notify(e) + return + end + pcall(vim.api.nvim_win_set_cursor, 0, new_cursor) end diff --git a/lua/treesj/init.lua b/lua/treesj/init.lua index 8ef28f0..48ea143 100644 --- a/lua/treesj/init.lua +++ b/lua/treesj/init.lua @@ -8,16 +8,16 @@ M.setup = function(opts) settings._create_commands() end -M.__toggle = function() - require('treesj.format')._format() +M.__toggle = function(_, preset) + require('treesj.format')._format(nil, preset) end -M.__split = function() - require('treesj.format')._format('split') +M.__split = function(_, preset) + require('treesj.format')._format('split', preset) end -M.__join = function() - require('treesj.format')._format('join') +M.__join = function(_, preset) + require('treesj.format')._format('join', preset) end local function set_opfunc_and_format(dir) @@ -25,24 +25,25 @@ local function set_opfunc_and_format(dir) vim.api.nvim_feedkeys('g@l', 'nx', true) end -local function format(dir) - if settings.settings.dot_repeat then +local function format(data) + local dir, preset = data.dir, data.preset + if settings.settings.dot_repeat and not preset then set_opfunc_and_format(dir) else - M['__' .. dir]() + M['__' .. dir](_, preset) end end -M.toggle = function() - format('toggle') +M.toggle = function(preset) + format({ dir = 'toggle', preset = preset }) end -M.join = function() - format('join') +M.join = function(preset) + format({ dir = 'toggle', preset = preset }) end -M.split = function() - format('split') +M.split = function(preset) + format({ dir = 'toggle', preset = preset }) end return M diff --git a/lua/treesj/langs/c.lua b/lua/treesj/langs/c.lua index 8252ce1..5c197ea 100644 --- a/lua/treesj/langs/c.lua +++ b/lua/treesj/langs/c.lua @@ -1,18 +1,19 @@ -local utils = require('treesj.langs.utils') +local lang_utils = require('treesj.langs.utils') return { - parameter_list = utils.set_preset_for_args(), - argument_list = utils.set_preset_for_args(), - initializer_list = utils.set_preset_for_list(), - compound_statement = utils.set_preset_for_statement({ + parameter_list = lang_utils.set_preset_for_args(), + argument_list = lang_utils.set_preset_for_args(), + initializer_list = lang_utils.set_preset_for_list(), + compound_statement = lang_utils.set_preset_for_statement({ both = { - separator = ';', - last_separator = true, no_format_with = { 'compound_statement' }, recursive = false, }, + join = { + force_insert = ';', + }, }), - enumerator_list = utils.set_preset_for_list(), + enumerator_list = lang_utils.set_preset_for_list(), if_statement = { target_nodes = { 'compound_statement' } }, declaration = { target_nodes = { 'parameter_list', 'argument_list', 'initializer_list' }, diff --git a/lua/treesj/langs/cpp.lua b/lua/treesj/langs/cpp.lua index a1fd9e6..d1d959f 100644 --- a/lua/treesj/langs/cpp.lua +++ b/lua/treesj/langs/cpp.lua @@ -1,9 +1,9 @@ -local utils = require('treesj.langs.utils') +local lang_utils = require('treesj.langs.utils') local c = require('treesj.langs.c') -return utils.merge_preset(c, { - template_argument_list = utils.set_preset_for_args(), - template_parameter_list = utils.set_preset_for_args(), +return lang_utils.merge_preset(c, { + template_argument_list = lang_utils.set_preset_for_args(), + template_parameter_list = lang_utils.set_preset_for_args(), template_declaration = { target_nodes = { 'template_parameter_list' } }, template_type = { target_nodes = { 'template_argument_list' } }, }) diff --git a/lua/treesj/langs/css.lua b/lua/treesj/langs/css.lua index 02f7c44..ef494fb 100644 --- a/lua/treesj/langs/css.lua +++ b/lua/treesj/langs/css.lua @@ -1,17 +1,17 @@ -local u = require('treesj.langs.utils') +local lang_utils = require('treesj.langs.utils') return { - block = u.set_preset_for_statement({ + block = lang_utils.set_preset_for_statement({ join = { force_insert = '', }, }), - keyframe_block_list = u.set_preset_for_statement({ + keyframe_block_list = lang_utils.set_preset_for_statement({ join = { force_insert = '', }, }), - arguments = u.set_preset_for_args(), + arguments = lang_utils.set_preset_for_args(), call_expression = { target_nodes = { 'arguments' }, }, diff --git a/lua/treesj/langs/default_preset.lua b/lua/treesj/langs/default_preset.lua index 7385a1c..f7f6f62 100644 --- a/lua/treesj/langs/default_preset.lua +++ b/lua/treesj/langs/default_preset.lua @@ -1,73 +1,85 @@ return { - -- Use for split and join. Will merge to both resulting presets - -- If you need various values for different modes, - -- it can be overridden in modes sections + -- `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 = { - -- string[]: TreeSJ will stop if node contains node from list + ---If a node contains descendants with a type from the list, it will not be formatted + ---@type string[] no_format_with = { 'comment' }, - -- string: Separator for arrays, objects, hash e.c.t. - -- Will auto add to option 'omit' for 'both' + ---Separator for arrays, objects, hash e.c.t. (usually ',') + ---@type string separator = '', - -- boolean: Set last separator or not + ---Set last separator or not + ---@type boolean last_separator = false, - -- list[string|function]: Nodes in list will be joined for previous node - -- (e.g. tag_name in HTML start_tag or separator (',') in JS object) - -- NOTE: Must be same for both modes - omit = {}, - -- boolean: Non-bracket nodes (e.g., with 'then|()' ... 'end' instead of { ... }|< ... >|[ ... ]) - -- NOTE: Must be same for both modes - non_bracket_node = false, - -- If true, empty brackets, empty tags, or node which only contains nodes from 'omit' no will handling - -- (ignored, when non_bracket_node = true) + ---If true, empty brackets, empty tags, or node which only contains nodes from 'omit' no will handling + ---@type boolean format_empty_node = true, - -- function|nil function (child: TreeSJ): void - -- Custom callback for transforming text of children nodes. Can be different for split and join - foreach = nil, - -- nil|table { left = string, right = string } - -- Adding first and last custom nodes, e.g., [], {}, e.t.c, if needed (e.g., see YAML) - add_framing_nodes = nil, - -- boolean|function function (tsnode): boolean - -- Set `false` if node should't be splitted or joined. Can be different for both modes + ---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(tsj: TreeSJ): void + format_resulted_lines = nil, + + --[[ The options below should be the same for both modes. ]] + ---The text of the node will be merged with the previous one, without wrapping to a new line + ---@type table List-like table with types 'string' (type of node) or 'function' (function(child: TreeSJ): boolean). + omit = {}, + ---Non-bracket nodes (e.g., with 'then|()' ... 'end' instead of { ... }|< ... >|[ ... ]) + ---If value is table, should be contains follow keys: { left = 'text', right = 'text' }. Empty string uses by default + ---@type boolean|table + non_bracket_node = false, }, -- Use only for join. If contains field from 'both', -- field here have higher priority join = { - -- Adding space in framing brackets or last/end element + ---Adding space in framing brackets or last/end element + ---@type boolean space_in_brackets = false, - -- Count of spaces between nodes - space_separator = 1, - -- string: Add instruction separator like ';' in statement block - -- Will auto add to option 'omit' for 'both' + ---Insert space between nodes or not + ---@type boolean + space_separator = true, + ---Adds instruction separator like ';' in statement block. + ---It's not the same as `separator`: `separator` is a separate node, `force_insert` is a last symbol of code instruction. + ---@type string force_insert = '', - -- list[string|function]: The insert symbol will be omitted if node contains in this list + ---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 (';')) + ---@type table List-like table with types 'string' (type of node) or 'function' (function(child: TreeSJ): boolean). no_insert_if = {}, - -- boolean: All nested configured nodes will process according to their presets - recursive = true, - -- [string]: Type of configured node that must be ignored - recursive_ignore = {}, }, -- Use only for split. If contains field from 'both', -- field here have higher priority split = { - -- boolean: All nested configured nodes will process according to their presets + ---All nested configured nodes will process according to their presets + ---@type boolean recursive = false, - -- [string]: Type of configured node that must be ignored - -- E.g., you probably don't want the parameters of each nested function to be expanded. - recursive_ignore = {}, - -- string: 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()). + ---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()). + ---@type 'normal'|'inner' last_indent = 'normal', - -- string: 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()). + ---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()). + ---@type 'normal'|'inner' inner_indent = 'inner', }, - -- If 'true', node will be completely removed from langs preset + ---If 'true', node will be completely removed from langs preset + ---@type boolean disable = false, - -- 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 + ---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 + ---@type string[]|table See `advanced node configuration` target_nodes = {}, } diff --git a/lua/treesj/langs/go.lua b/lua/treesj/langs/go.lua index b6280fa..947f5e8 100644 --- a/lua/treesj/langs/go.lua +++ b/lua/treesj/langs/go.lua @@ -1,43 +1,43 @@ -local u = require('treesj.langs.utils') +local lang_utils = require('treesj.langs.utils') return { - literal_value = u.set_preset_for_list(), - parameter_list = u.set_preset_for_args({ + literal_value = lang_utils.set_preset_for_list(), + parameter_list = lang_utils.set_preset_for_args({ split = { last_separator = true, }, }), - argument_list = u.set_preset_for_args({ + argument_list = lang_utils.set_preset_for_args({ split = { last_separator = true, }, }), - block = u.set_preset_for_statement({ + block = lang_utils.set_preset_for_statement({ join = { no_insert_if = { - u.no_insert.if_penultimate, + lang_utils.helpers.if_penultimate, }, }, }), - import_spec = u.set_preset_for_args({ + import_spec = lang_utils.set_preset_for_args({ both = { enable = function(tsn) return tsn:parent():type() ~= 'import_spec_list' end, }, split = { - add_framing_nodes = { left = '(', right = ')' }, + format_tree = function(tsj) + tsj:wrap({ left = '(', right = ')' }) + end, }, }), - import_spec_list = u.set_preset_for_args({ + import_spec_list = lang_utils.set_preset_for_args({ join = { enable = function(tsn) return tsn:named_child_count() < 2 end, - foreach = function(tsj) - if tsj:is_framing() then - tsj:_update_text('') - end + format_tree = function(tsj) + tsj:remove_child({ '(', ')' }) end, }, }), diff --git a/lua/treesj/langs/html.lua b/lua/treesj/langs/html.lua index 8d34b0e..9eee19f 100644 --- a/lua/treesj/langs/html.lua +++ b/lua/treesj/langs/html.lua @@ -1,20 +1,20 @@ -local u = require('treesj.langs.utils') +local lang_utils = require('treesj.langs.utils') return { - start_tag = u.set_default_preset({ + start_tag = lang_utils.set_default_preset({ both = { omit = { 'tag_name' }, }, }), - self_closing_tag = u.set_default_preset({ + self_closing_tag = lang_utils.set_default_preset({ both = { omit = { 'tag_name' }, no_format_with = {}, }, }), - element = u.set_default_preset({ + element = lang_utils.set_default_preset({ join = { - space_separator = 0, + space_separator = false, }, }), } diff --git a/lua/treesj/langs/java.lua b/lua/treesj/langs/java.lua index 4cd8a88..6a0417b 100644 --- a/lua/treesj/langs/java.lua +++ b/lua/treesj/langs/java.lua @@ -1,13 +1,13 @@ -local u = require('treesj.langs.utils') +local lang_utils = require('treesj.langs.utils') return { - argument_list = u.set_preset_for_args(), - formal_parameters = u.set_preset_for_args(), - block = u.set_preset_for_statement(), - constructor_body = u.set_preset_for_statement(), - array_initializer = u.set_preset_for_list(), - annotation_argument_list = u.set_preset_for_args(), - enum_body = u.set_preset_for_dict(), + argument_list = lang_utils.set_preset_for_args(), + formal_parameters = lang_utils.set_preset_for_args(), + block = lang_utils.set_preset_for_statement(), + constructor_body = lang_utils.set_preset_for_statement(), + array_initializer = lang_utils.set_preset_for_list(), + annotation_argument_list = lang_utils.set_preset_for_args(), + enum_body = lang_utils.set_preset_for_dict(), enum_declaration = { target_nodes = { 'enum_body' }, }, diff --git a/lua/treesj/langs/javascript.lua b/lua/treesj/langs/javascript.lua index 3ea2252..fbf2803 100644 --- a/lua/treesj/langs/javascript.lua +++ b/lua/treesj/langs/javascript.lua @@ -1,23 +1,99 @@ -local u = require('treesj.langs.utils') +local lang_utils = require('treesj.langs.utils') + +local rec_ignore = { 'arguments', 'formal_parameters' } +local arrow_body_format_join = function(tsj) + local parent = tsj:tsnode():parent():type() + if parent == 'arrow_function' and tsj:tsnode():named_child_count() == 1 then + tsj:remove_child({ '{', '}' }) + tsj:update_preset({ force_insert = '', space_in_brackets = false }, 'join') + local ret = tsj:child('return_statement') + + if ret then + if ret:has_to_format() then + ret:remove_child({ 'return', ';' }) + local obj = ret:child('object') + if obj then + tsj:wrap({ left = '(', right = ')' }, 'inline') + end + else + local text = ret:text():gsub('^return ', ''):gsub(';$', '') + ret:update_text(text) + end + end + end +end return { - object = u.set_preset_for_dict(), - object_pattern = u.set_preset_for_dict(), - array = u.set_preset_for_list(), - array_pattern = u.set_preset_for_list(), - formal_parameters = u.set_preset_for_args(), - arguments = u.set_preset_for_args(), - named_imports = u.set_preset_for_dict(), - export_clause = u.set_preset_for_dict(), - statement_block = u.set_preset_for_statement({ + object = lang_utils.set_preset_for_dict({ + split = { recursive_ignore = rec_ignore }, + }), + object_pattern = lang_utils.set_preset_for_dict({ + both = { recursive_ignore = rec_ignore }, + }), + array = lang_utils.set_preset_for_list({ + split = { recursive_ignore = rec_ignore }, + }), + array_pattern = lang_utils.set_preset_for_list({ + split = { recursive_ignore = rec_ignore }, + }), + formal_parameters = lang_utils.set_preset_for_args(), + arguments = lang_utils.set_preset_for_args(), + named_imports = lang_utils.set_preset_for_dict(), + export_clause = lang_utils.set_preset_for_dict(), + statement_block = lang_utils.set_preset_for_statement({ + split = { + recursive_ignore = rec_ignore, + }, join = { no_insert_if = { 'function_declaration', 'try_statement', 'if_statement', }, + format_tree = arrow_body_format_join, + }, + }), + body = lang_utils.set_preset_for_statement({ + split = { + recursive_ignore = rec_ignore, + format_tree = function(tsj) + if tsj:type() ~= 'statement_block' then + tsj:wrap({ left = '{', right = '}' }) + + local ph = tsj:child('parenthesized_expression') + local not_seq = ph and not ph:child('sequence_expression') + + if not_seq then + if ph:will_be_formatted() then + ph:remove_child({ '(', ')' }) + else + local text = ph:text():gsub('^%(', ''):gsub('%)$', '') + ph:update_text(text) + end + end + + 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, + }, + join = { + space_in_brackets = false, + force_insert = '', + format_tree = arrow_body_format_join, }, }), + arrow_function = { target_nodes = { 'body' } }, lexical_declaration = { target_nodes = { 'array', 'object' }, }, @@ -67,17 +143,17 @@ return { 'object', }, }, - jsx_opening_element = u.set_default_preset({ + jsx_opening_element = lang_utils.set_default_preset({ both = { omit = { 'identifier', 'nested_identifier' }, }, }), - jsx_element = u.set_default_preset({ + jsx_element = lang_utils.set_default_preset({ join = { - space_separator = 0, + space_separator = false, }, }), - jsx_self_closing_element = u.set_default_preset({ + jsx_self_closing_element = lang_utils.set_default_preset({ both = { omit = { 'identifier', 'nested_identifier', '>' }, no_format_with = {}, diff --git a/lua/treesj/langs/json.lua b/lua/treesj/langs/json.lua index e7a7cd1..72d4047 100644 --- a/lua/treesj/langs/json.lua +++ b/lua/treesj/langs/json.lua @@ -1,12 +1,12 @@ -local u = require('treesj.langs.utils') +local lang_utils = require('treesj.langs.utils') return { - object = u.set_preset_for_dict({ + object = lang_utils.set_preset_for_dict({ split = { last_separator = false, }, }), - array = u.set_preset_for_list({ + array = lang_utils.set_preset_for_list({ split = { last_separator = false, }, diff --git a/lua/treesj/langs/jsonc.lua b/lua/treesj/langs/jsonc.lua index 483166a..57fe4d7 100644 --- a/lua/treesj/langs/jsonc.lua +++ b/lua/treesj/langs/jsonc.lua @@ -1,4 +1,4 @@ -local u = require('treesj.langs.utils') +local lang_utils = require('treesj.langs.utils') local json = require('treesj.langs.json') -return u.merge_preset(json, {}) +return lang_utils.merge_preset(json, {}) diff --git a/lua/treesj/langs/kotlin.lua b/lua/treesj/langs/kotlin.lua index b352f2a..03cd8b7 100644 --- a/lua/treesj/langs/kotlin.lua +++ b/lua/treesj/langs/kotlin.lua @@ -1,21 +1,21 @@ -local u = require('treesj.langs.utils') +local lang_utils = require('treesj.langs.utils') return { - collection_literal = u.set_default_preset({ + collection_literal = lang_utils.set_default_preset({ both = { separator = ',', }, }), - value_arguments = u.set_default_preset({ + value_arguments = lang_utils.set_default_preset({ both = { separator = ',', }, }), - statements = u.set_preset_for_non_bracket({ + statements = lang_utils.set_preset_for_non_bracket({ join = { force_insert = ';', no_insert_if = { - u.no_insert.if_penultimate, + lang_utils.helpers.if_penultimate, }, }, }), diff --git a/lua/treesj/langs/lua.lua b/lua/treesj/langs/lua.lua index 45d9fe7..0b76ab1 100644 --- a/lua/treesj/langs/lua.lua +++ b/lua/treesj/langs/lua.lua @@ -1,10 +1,14 @@ -local u = require('treesj.langs.utils') +local lang_utils = require('treesj.langs.utils') + +local split_recursive_ignore = { + split = { recursive_ignore = { 'arguments', 'parameters' } }, +} return { - table_constructor = u.set_preset_for_dict(), - arguments = u.set_preset_for_args(), - parameters = u.set_preset_for_args(), - block = u.set_preset_for_non_bracket(), + table_constructor = lang_utils.set_preset_for_dict(split_recursive_ignore), + arguments = lang_utils.set_preset_for_args(), + parameters = lang_utils.set_preset_for_args(), + block = lang_utils.set_preset_for_non_bracket(split_recursive_ignore), variable_declaration = { target_nodes = { 'table_constructor', 'block' }, }, diff --git a/lua/treesj/langs/nix.lua b/lua/treesj/langs/nix.lua index f254d8a..385195d 100644 --- a/lua/treesj/langs/nix.lua +++ b/lua/treesj/langs/nix.lua @@ -1,7 +1,7 @@ -local u = require('treesj.langs.utils') +local lang_utils = require('treesj.langs.utils') return { - list_expression = u.set_preset_for_list({ + list_expression = lang_utils.set_preset_for_list({ both = { separator = '', }, @@ -9,14 +9,14 @@ return { attrset_expression = { target_nodes = { 'binding_set' }, }, - binding_set = u.set_preset_for_dict({ + binding_set = lang_utils.set_preset_for_dict({ both = { non_bracket_node = true, - separator = ';', - last_separator = true, + separator = '', + force_insert = ';', }, }), - formals = u.set_preset_for_args({ + formals = lang_utils.set_preset_for_args({ both = { omit = { 'formal', 'ellipses' }, }, @@ -29,7 +29,7 @@ return { space_in_brackets = true, }, }), - let_expression = u.set_default_preset({ + let_expression = lang_utils.set_default_preset({ both = { omit = { 'binding_set' }, }, @@ -40,7 +40,7 @@ return { }, join = { space_in_brackets = true, - space_separator = 1, + space_separator = true, }, }), } diff --git a/lua/treesj/langs/php.lua b/lua/treesj/langs/php.lua index f6b1d52..5bdad5c 100644 --- a/lua/treesj/langs/php.lua +++ b/lua/treesj/langs/php.lua @@ -1,22 +1,22 @@ -local u = require('treesj.langs.utils') +local lang_utils = require('treesj.langs.utils') return { - array_creation_expression = u.set_preset_for_dict({ + array_creation_expression = lang_utils.set_preset_for_dict({ join = { space_in_brackets = false, }, }), - arguments = u.set_preset_for_args({ + arguments = lang_utils.set_preset_for_args({ split = { last_separator = true, }, }), - formal_parameters = u.set_preset_for_args({ + formal_parameters = lang_utils.set_preset_for_args({ split = { last_separator = true, }, }), - compound_statement = u.set_preset_for_statement({ + compound_statement = lang_utils.set_preset_for_statement({ join = { no_insert_if = { 'function_definition', diff --git a/lua/treesj/langs/pug.lua b/lua/treesj/langs/pug.lua index 72b8164..ee61f83 100644 --- a/lua/treesj/langs/pug.lua +++ b/lua/treesj/langs/pug.lua @@ -1,7 +1,7 @@ -local u = require('treesj.langs.utils') +local lang_utils = require('treesj.langs.utils') return { - attributes = u.set_default_preset(), + attributes = lang_utils.set_default_preset(), tag = { target_nodes = { 'attributes' }, }, diff --git a/lua/treesj/langs/python.lua b/lua/treesj/langs/python.lua index 527bdcf..24bccaa 100644 --- a/lua/treesj/langs/python.lua +++ b/lua/treesj/langs/python.lua @@ -1,6 +1,6 @@ -local u = require('treesj.langs.utils') +local lang_utils = require('treesj.langs.utils') -local no_space_in_brackets = u.set_preset_for_list({ +local no_space_in_brackets = lang_utils.set_preset_for_list({ join = { space_in_brackets = false, }, @@ -10,18 +10,39 @@ return { dictionary = no_space_in_brackets, list = no_space_in_brackets, set = no_space_in_brackets, - tuple = u.set_preset_for_list({ + tuple = lang_utils.set_preset_for_list({ join = { space_in_brackets = false, last_separator = true, }, }), - argument_list = u.set_preset_for_args(), - parameters = u.set_preset_for_args(), - parenthesized_expression = u.set_preset_for_args({}), - list_comprehension = u.set_preset_for_args(), - set_comprehension = u.set_preset_for_args(), - dictionary_comprehension = u.set_preset_for_args(), + import_from_statement = lang_utils.set_preset_for_args({ + both = { + omit = { lang_utils.helpers.if_second, 'import', ' (' }, + }, + split = { + last_separator = true, + format_tree = function(tsj) + if not tsj:has_children({ '(', ')' }) then + tsj:create_child({ text = ' (' }, 4) + tsj:create_child({ text = ')' }, #tsj:children() + 1) + local penult = tsj:child(-2) + penult:update_text(penult:text() .. ',') + end + end, + }, + join = { + format_tree = function(tsj) + tsj:remove_child({ '(', ')' }) + end, + }, + }), + argument_list = lang_utils.set_preset_for_args(), + parameters = lang_utils.set_preset_for_args(), + parenthesized_expression = lang_utils.set_preset_for_args({}), + list_comprehension = lang_utils.set_preset_for_args(), + set_comprehension = lang_utils.set_preset_for_args(), + dictionary_comprehension = lang_utils.set_preset_for_args(), assignment = { target_nodes = { 'tuple', diff --git a/lua/treesj/langs/r.lua b/lua/treesj/langs/r.lua index 31038ac..4b8cd98 100644 --- a/lua/treesj/langs/r.lua +++ b/lua/treesj/langs/r.lua @@ -1,7 +1,7 @@ -local u = require('treesj.langs.utils') +local lang_utils = require('treesj.langs.utils') return { - arguments = u.set_preset_for_args({ + arguments = lang_utils.set_preset_for_args({ both = { non_bracket_node = true, }, @@ -10,7 +10,7 @@ return { }, }), - formal_parameters = u.set_preset_for_args({ + formal_parameters = lang_utils.set_preset_for_args({ split = { recursive_ignore = { 'subset' }, }, diff --git a/lua/treesj/langs/ruby.lua b/lua/treesj/langs/ruby.lua index 0f48420..7293770 100644 --- a/lua/treesj/langs/ruby.lua +++ b/lua/treesj/langs/ruby.lua @@ -1,53 +1,161 @@ -local u = require('treesj.langs.utils') +local lang_utils = require('treesj.langs.utils') +local utils = require('treesj.utils') return { - array = u.set_preset_for_list(), - hash = u.set_preset_for_list(), - method_parameters = u.set_preset_for_args(), - argument_list = u.set_preset_for_args(), - block = u.set_preset_for_dict({ - split = { - omit = { 'block_parameters' }, - separator = '', - foreach = function(child) - local text = child:text() - if child:is_framing() and type(text) == 'string' then - local replace = { ['{'] = 'do', ['}'] = 'end' } - if replace[text] then - child:_update_text(replace[text]) - end - end + array = lang_utils.set_preset_for_list(), + hash = lang_utils.set_preset_for_list(), + method_parameters = lang_utils.set_preset_for_args(), + argument_list = lang_utils.set_preset_for_args({ + both = { + enable = function(tsn) + return tsn:parent():type() ~= 'return' end, }, }), - do_block = u.set_preset_for_dict({ + block = lang_utils.set_preset_for_dict({ join = { separator = '', recursive = false, - foreach = function(child) - local text = child:text() - if child:is_framing() and type(text) == 'string' then - local replace = { ['do'] = '{', ['end'] = '}' } - if replace[text] then - child:_update_text(replace[text]) - end + format_tree = function(tsj) + if tsj:has_children({ 'do', 'end' }) then + tsj:child('do'):update_text('{') + tsj:child('end'):update_text('}') + end + end, + }, + split = { + omit = { 'block_parameters' }, + separator = '', + format_tree = function(tsj) + if tsj:has_children({ '{', '}' }) then + tsj:child('{'):update_text('do') + tsj:child('}'):update_text('end') end end, }, }), - string_array = u.set_preset_for_list({ + string_array = lang_utils.set_preset_for_list({ split = { last_separator = false, }, }), - body_statement = u.set_preset_for_non_bracket({ + body_statement = lang_utils.set_preset_for_non_bracket({ join = { force_insert = ';', no_insert_if = { - u.no_insert.if_penultimate, + lang_utils.helpers.if_penultimate, }, }, }), + if_modifier = lang_utils.set_default_preset({ + join = { enable = false }, + split = { + omit = { lang_utils.helpers.if_second }, + format_tree = function(tsj) + local if_node = tsj:child('if') + local end_ = tsj:create_child({ text = 'end', type = 'end' }) + tsj:update_children({ if_node, if_node:next(), tsj:child(1), end_ }) + end, + }, + }), + ['if'] = lang_utils.set_default_preset({ + split = { enable = false }, + join = { + enable = function(tsn) + local check = { + tsn:field('consequence')[1], + tsn:field('alternative')[1], + } + + return utils.every(check, function(el) + return not el and true or el:named_child_count() == 1 + end) + end, + space_in_brackets = true, + format_tree = function(tsj) + if tsj:child('else') then + local if_ = tsj:child('if') + local else_ = tsj:child('else') + if else_:has_to_format() then + local text = else_:child(1):text() + else_:child(1):update_text(text:gsub('^else', ':')) + else + local text = else_:text() + else_:update_text(text:gsub('^else', ':')) + end + if_:update_text('? ') + tsj:update_children({ tsj:child(2), if_, tsj:child('then'), else_ }) + else + local if_node = tsj:child('if') + tsj:update_children({ tsj:child('then'), if_node, if_node:next() }) + end + end, + }, + }), + conditional = lang_utils.set_default_preset({ + join = { enable = false }, + split = { + omit = { lang_utils.helpers.if_second }, + format_tree = function(tsj) + tsj:create_child({ text = 'end', type = 'end' }, #tsj:children() + 1) + tsj:child('?'):update_text('if ') + tsj:child(':'):update_text('else') + tsj:swap_children(1, 2) + end, + format_resulted_lines = function(lines) + return vim.tbl_map(function(line) + if line:match('%s.else$') then + -- TODO: create helper `unindent` + local rgx = '^' .. (' '):rep(vim.fn.shiftwidth()) + return line:gsub(rgx, '') + else + return line + end + end, lines) + end, + }, + }), + when = lang_utils.set_default_preset({ + both = { + omit = { lang_utils.helpers.if_second }, + }, + join = { + space_in_brackets = true, + enable = function(tsn) + return tsn:field('body')[1]:named_child_count() == 1 + end, + format_tree = function(tsj) + tsj:create_child({ type = 'then', text = 'then' }, -1) + end, + }, + split = { + last_indent = 'inner', + format_tree = function(tsj) + if tsj:has_children({ 'then' }) then + local text = tsj:child('then'):text() + tsj:child('then'):update_text(text:gsub('then%s', '')) + end + end, + }, + }), + right = lang_utils.set_default_preset({ + both = { + enable = function(tsn) + return not (tsn:type() == 'begin' and tsn:named_child_count() > 1) + end, + }, + split = { + format_tree = function(tsj) + tsj:wrap({ left = 'begin', right = 'end' }) + end, + }, + join = { + format_tree = function(tsj) + tsj:remove_child({ 'begin', 'end' }) + end, + }, + }), + operator_assignment = { target_nodes = { 'right' } }, method = { target_nodes = { 'body_statement' }, }, diff --git a/lua/treesj/langs/rust.lua b/lua/treesj/langs/rust.lua index 5ec4362..b7bf118 100644 --- a/lua/treesj/langs/rust.lua +++ b/lua/treesj/langs/rust.lua @@ -1,42 +1,76 @@ -local u = require('treesj.langs.utils') +local lang_utils = require('treesj.langs.utils') return { - field_declaration_list = u.set_preset_for_dict(), - declaration_list = u.set_preset_for_statement(), - field_initializer_list = u.set_preset_for_dict(), - struct_pattern = u.set_preset_for_dict({ + field_declaration_list = lang_utils.set_preset_for_dict(), + declaration_list = lang_utils.set_preset_for_statement(), + field_initializer_list = lang_utils.set_preset_for_dict(), + struct_pattern = lang_utils.set_preset_for_dict({ both = { omit = { '{' }, }, }), - parameters = u.set_preset_for_args({ + parameters = lang_utils.set_preset_for_args({ split = { last_separator = true, }, }), - arguments = u.set_preset_for_args({ + arguments = lang_utils.set_preset_for_args({ split = { last_separator = true, }, }), - tuple_type = u.set_preset_for_args({ + tuple_type = lang_utils.set_preset_for_args({ split = { last_separator = true, }, }), - enum_variant_list = u.set_preset_for_list(), - tuple_expression = u.set_preset_for_args({ + enum_variant_list = lang_utils.set_preset_for_list(), + tuple_expression = lang_utils.set_preset_for_args({ split = { last_separator = true, }, }), - block = u.set_preset_for_statement({ + block = lang_utils.set_preset_for_statement({ join = { - no_insert_if = { u.no_insert.if_penultimate }, + no_insert_if = { lang_utils.helpers.if_penultimate }, + format_tree = function(tsj) + local node = tsj:tsnode() + local parents = { 'match_arm', 'closure_expression' } + local has_parent = vim.tbl_contains(parents, node:parent():type()) + if has_parent and node:named_child_count() == 1 then + tsj:remove_child({ '{', '}' }) + end + end, }, }), - use_list = u.set_preset_for_list(), - array_expression = u.set_preset_for_list(), + value = lang_utils.set_preset_for_statement({ + split = { + format_tree = function(tsj) + if tsj:type() ~= 'block' then + tsj:wrap({ left = '{', right = '}' }) + end + end, + }, + join = { + no_insert_if = { lang_utils.helpers.if_penultimate }, + format_tree = function(tsj) + local node = tsj:tsnode() + local parents = { 'match_arm', 'closure_expression' } + local has_parent = vim.tbl_contains(parents, node:parent():type()) + if has_parent and node:named_child_count() == 1 then + tsj:remove_child({ '{', '}' }) + end + end, + }, + }), + match_arm = { + target_nodes = { 'value' }, + }, + closure_expression = { + target_nodes = { ['body'] = 'value' }, + }, + use_list = lang_utils.set_preset_for_list(), + array_expression = lang_utils.set_preset_for_list(), let_declaration = { target_nodes = { 'field_declaration_list', diff --git a/lua/treesj/langs/scss.lua b/lua/treesj/langs/scss.lua index 9d46a00..08d347e 100644 --- a/lua/treesj/langs/scss.lua +++ b/lua/treesj/langs/scss.lua @@ -1,4 +1,4 @@ -local u = require('treesj.langs.utils') +local lang_utils = require('treesj.langs.utils') local css = require('treesj.langs.css') -return u.merge_preset(css, {}) +return lang_utils.merge_preset(css, {}) diff --git a/lua/treesj/langs/svelte.lua b/lua/treesj/langs/svelte.lua index 308347b..7f30142 100644 --- a/lua/treesj/langs/svelte.lua +++ b/lua/treesj/langs/svelte.lua @@ -1,4 +1,4 @@ -local u = require('treesj.langs.utils') +local lang_utils = require('treesj.langs.utils') local html = require('treesj.langs.html') -return u.merge_preset(html, {}) +return lang_utils.merge_preset(html, {}) diff --git a/lua/treesj/langs/toml.lua b/lua/treesj/langs/toml.lua index 3a5bc20..3ba06a0 100644 --- a/lua/treesj/langs/toml.lua +++ b/lua/treesj/langs/toml.lua @@ -1,7 +1,7 @@ -local u = require('treesj.langs.utils') +local lang_utils = require('treesj.langs.utils') return { - array = u.set_preset_for_list({ + array = lang_utils.set_preset_for_list({ split = { last_separator = false, }, diff --git a/lua/treesj/langs/tsx.lua b/lua/treesj/langs/tsx.lua index 92b89d5..649622d 100644 --- a/lua/treesj/langs/tsx.lua +++ b/lua/treesj/langs/tsx.lua @@ -1,4 +1,4 @@ -local u = require('treesj.langs.utils') +local lang_utils = require('treesj.langs.utils') local ts = require('treesj.langs.typescript') -return u.merge_preset(ts, {}) +return lang_utils.merge_preset(ts, {}) diff --git a/lua/treesj/langs/typescript.lua b/lua/treesj/langs/typescript.lua index d76d447..92ddb1b 100644 --- a/lua/treesj/langs/typescript.lua +++ b/lua/treesj/langs/typescript.lua @@ -1,18 +1,18 @@ -local u = require('treesj.langs.utils') +local lang_utils = require('treesj.langs.utils') local js = require('treesj.langs.javascript') -return u.merge_preset(js, { - object_type = u.set_preset_for_dict({ +return lang_utils.merge_preset(js, { + object_type = lang_utils.set_preset_for_dict({ both = { separator = ';', last_separator = true }, }), - object_pattern = u.set_preset_for_dict(), - tuple_type = u.set_preset_for_dict(), - enum_body = u.set_preset_for_dict(), - type_parameters = u.set_preset_for_args({ + object_pattern = lang_utils.set_preset_for_dict(), + tuple_type = lang_utils.set_preset_for_dict(), + enum_body = lang_utils.set_preset_for_dict(), + type_parameters = lang_utils.set_preset_for_args({ split = { last_separator = true }, join = { space_in_brackets = false }, }), - type_arguments = u.set_preset_for_args({ + type_arguments = lang_utils.set_preset_for_args({ split = { last_separator = true }, join = { space_in_brackets = false }, }), diff --git a/lua/treesj/langs/utils.lua b/lua/treesj/langs/utils.lua index d9a2689..69421aa 100644 --- a/lua/treesj/langs/utils.lua +++ b/lua/treesj/langs/utils.lua @@ -37,26 +37,32 @@ local function convert_to_dict(tbl) return result end ----Merge 'both' fielf to 'split' and 'join' if needed +---Merge 'both' field to 'split' and 'join' if needed ---@param preset table +---@param info table ---@return table -function M._premerge(preset) +function M._premerge(preset, info) if preset.disable then - return { disable = preset.disable } + return { disable = preset.disable, __info = info } end if preset.target_nodes and not vim.tbl_isempty(preset.target_nodes) then - return { target_nodes = convert_to_dict(preset.target_nodes) } + return { target_nodes = convert_to_dict(preset.target_nodes), __info = info } end local both = preset.both or {} - local split = preset.split or {} - local join = preset.join or {} - - return { - split = vim.tbl_deep_extend('force', both, split), - join = vim.tbl_deep_extend('force', both, join), + local modes = { + split = preset.split or {}, + join = preset.join or {}, } + + for mode, opts in pairs(modes) do + info.mode = mode + opts.__info = info + modes[mode] = vim.tbl_deep_extend('force', both, opts) + end + + return modes end ---Add 'separator' and 'force_insert' to 'omit' @@ -84,8 +90,8 @@ end ---Add missing options to preset ---@param preset table ---@return table -function M._add_missing(preset) - return vim.tbl_deep_extend('force', M._premerge(DEFAULT_PRESET), preset) +function M._add_missing(preset, info) + return vim.tbl_deep_extend('force', M._premerge(DEFAULT_PRESET, info), preset) end ---Prepare presets @@ -94,8 +100,9 @@ end function M._prepare_presets(languages) for lang, presets in pairs(languages) do for node, preset in pairs(presets) do - preset = M._premerge(preset) - preset = M._add_missing(preset) + local info = { lang = lang, node = node, mode = 'both' } + preset = M._premerge(preset, info) + preset = M._add_missing(preset, info) preset = M._update_omit(preset) presets[node] = preset end @@ -173,23 +180,35 @@ M.set_preset_for_non_bracket = set_preset({ }, }) -M.no_insert = {} -M.omit = {} +M.helpers = {} -local function if_penultimate(tsj) - local next = tsj:next() +M.helpers.if_penultimate = function(child) + local next = child:next() return next and next:is_last() or false end -local function if_second(tsj) - local prev = tsj:prev() +M.helpers.if_second = function(child) + local prev = child:prev() return prev and prev:is_first() or false end -M.no_insert.if_penultimate = if_penultimate -M.no_insert.if_second = if_second +M.helpers.by_index = function(i) + return function(child) + return child:parent() and child:parent():child(i) == child + end +end -M.omit.if_penultimate = if_penultimate -M.omit.if_second = if_second +M.helpers.has_parent = function(parent_type) + return function(child) + return child:parent() and child:parent():type() == parent_type + end +end + +M.helpers.match = function(pattern) + return function(child) + local text = child:text() + return type(text) == 'string' and text:match(pattern) or false + end +end return M diff --git a/lua/treesj/langs/vue.lua b/lua/treesj/langs/vue.lua index 2f498aa..8d51263 100644 --- a/lua/treesj/langs/vue.lua +++ b/lua/treesj/langs/vue.lua @@ -1,7 +1,7 @@ -local u = require('treesj.langs.utils') +local lang_utils = require('treesj.langs.utils') local html = require('treesj.langs.html') -return u.merge_preset(html, { +return lang_utils.merge_preset(html, { element = { join = { recursive = false, diff --git a/lua/treesj/langs/yaml.lua b/lua/treesj/langs/yaml.lua index ecc2104..4b6b5e2 100644 --- a/lua/treesj/langs/yaml.lua +++ b/lua/treesj/langs/yaml.lua @@ -1,58 +1,57 @@ -local u = require('treesj.langs.utils') +local lang_utils = require('treesj.langs.utils') return { - flow_sequence = u.set_preset_for_list({ + flow_sequence = { + join = { enable = false }, split = { + non_bracket_node = true, last_separator = false, - foreach = function(child) - if child:is_first() or child:text() == ',' then - child:_update_text('') - elseif child:is_last() then - child:remove() - else - child:_update_text('- ' .. child:text()) + last_indent = 'inner', + no_insert_if = { lang_utils.helpers.if_penultimate }, + format_tree = function(tsj) + tsj:remove_child({ ',', '[', ']' }) + for _, flow_node in ipairs(tsj:children({ 'flow_node' })) do + flow_node:update_text('- ' .. flow_node:text()) end + tsj:remove_child(-1) end, }, - }), - flow_mapping = u.set_preset_for_list({ + }, + flow_mapping = { + join = { enable = false }, split = { - last_separator = false, + non_bracket_node = true, recursive = true, - foreach = function(child) - if child:is_first() or child:text() == ',' then - child:_update_text('') - elseif child:is_last() then - child:remove() - end + last_indent = 'inner', + format_tree = function(tsj) + tsj:remove_child({ ',', '{', '}' }) + tsj:remove_child(-1) end, }, - }), - block_sequence = u.set_preset_for_list({ + }, + block_sequence = { + split = { enable = false }, join = { - non_bracket_node = true, - add_framing_nodes = { left = ' [', right = ']' }, - last_separator = false, - foreach = function(child) - local text = child:text() - text = string.gsub(text, '^- ', '') - if not child:is_framing() then - child:_update_text(text .. ',') + space_in_brackets = true, + non_bracket_node = { left = ' [', right = ']' }, + force_insert = ',', + no_insert_if = { lang_utils.helpers.if_penultimate }, + format_tree = function(tsj) + local items = tsj:children({ 'block_sequence_item' }) + for _, item in ipairs(items) do + local text = item:text():gsub('^- ', '') + item:update_text(text) end end, }, - }), - block_mapping = u.set_preset_for_list({ + }, + block_mapping = { + split = { enable = false }, join = { - non_bracket_node = true, - add_framing_nodes = { left = ' {', right = '}' }, - last_separator = false, - foreach = function(child) - local text = child:text() - if not child:is_framing() then - child:_update_text(text .. ',') - end - end, + space_in_brackets = true, + non_bracket_node = { left = ' {', right = '}' }, + force_insert = ',', + no_insert_if = { lang_utils.helpers.if_penultimate }, }, - }), + }, } diff --git a/lua/treesj/notify.lua b/lua/treesj/notify.lua index b7147e7..dd6c7b4 100644 --- a/lua/treesj/notify.lua +++ b/lua/treesj/notify.lua @@ -17,6 +17,8 @@ M.msg = { version_not_support = 'Current version of neovim is "0.%s". TreeSJ requires version "0.8" or higher', node_not_received = 'Node not received', node_is_disable = 'Action "%s" for node "%s" is disabled in preset', + custom_func = 'Something went wrong in function "%s" from preset for "%s": %s', + wrong_resut = 'Function "%s" from preset for "%s" returned wrong format for new lines', } ---Wraper for vim.notify and nvim-notify diff --git a/lua/treesj/search.lua b/lua/treesj/search.lua index 2f659e1..3af7948 100644 --- a/lua/treesj/search.lua +++ b/lua/treesj/search.lua @@ -1,33 +1,69 @@ -local u = require('treesj.utils') local notify = require('treesj.notify') +local langs = require('treesj.settings').settings.langs +local u = require('treesj.utils') local msg = notify.msg +local ts_ok, parsers = pcall(require, 'nvim-treesitter.parsers') +if not ts_ok then + notify.error(msg.ts_not_found) + return +end + local M = {} +---Get lunguage for node +---@param node TSNode TSNode instance +---@return string +local function get_node_lang(node) + local range = { node:range() } + local lang_tree = parsers.get_parser() + local current_tree = lang_tree:language_for_range(range) + return current_tree:lang() +end + +---Return the preset for received node. +---If mode passed, return preset for specified mode +---@param tsn_type string TSNode type +---@param lang? string TSNode lang. Requires if `node` is string +---@param mode? string Current mode (split|join) +---@return table|nil +local function get_preset(tsn_type, lang, mode) + if lang and not langs[lang] then + return nil + end + + local presets = langs[lang] + local preset = presets and presets[tsn_type] + + return preset and (preset[mode] or preset) +end + ---Recursively searches for the configured node among the ancestors ----@param node userdata TSNode instance +---@param node TSNode TSNode instance ---@param lang string Language of TSNode ----@return userdata|nil -function M.search_node_up(node, lang) +---@return TSNode|nil, table|nil +local function search_node_up(node, lang) if not node then return nil end - if not u.get_preset(node:type(), lang) then + local preset = get_preset(node:type(), lang) + + if not (node:named() and preset) then node = node:parent() - return M.search_node_up(node, lang) + return search_node_up(node, lang) end - return node + return node, preset end ---Recursively searches for a configured node inside the current node and ---returns the first configured node found ----@param node userdata|nil TSNode instance +---@param node TSNode|nil TSNode instance ---@param lang string TSNode lang ---@param targets table List of target node types ----@return userdata|nil, table|nil -function M.search_inside_node(node, lang, targets) +---@return TSNode|nil, table|nil +local function search_inside_node(node, lang, targets) if not node then return nil, nil end @@ -35,13 +71,13 @@ function M.search_inside_node(node, lang, targets) local target_node, use_preset for child in node:iter_children() do - local target_type = targets[child:type()] - use_preset = target_type and u.get_self_preset(target_type, lang) + local target_type = child:named() and targets[child:type()] + use_preset = target_type and M.get_self_preset(target_type, lang) if use_preset then target_node = child else - target_node, use_preset = M.search_inside_node(child, lang, targets) + target_node, use_preset = search_inside_node(child, lang, targets) end if target_node then @@ -52,20 +88,36 @@ function M.search_inside_node(node, lang, targets) return target_node, use_preset end +local function get_node_from_field(node, lang, targets) + for node_type, use_preset in pairs(targets) do + local fields = node:field(node_type) + local preset = M.get_self_preset(use_preset, lang) + + if not vim.tbl_isempty(fields) and preset then + return fields[1], preset + end + end + return nil, nil +end + ---Get target node and node data ----@param node userdata TSNode instance +---@param node TSNode|nil TSNode instance ---@param lang string TSNode language ---@return table|nil -function M.search_node(node, lang) +local function search_node(node, lang) local viewed = {} - local tsn_data = { lang = lang, parent = nil } + local tsn_data = { + lang = lang, + from_self = false, + parent = nil, + mode = nil, + } local preset while node do - node = M.search_node_up(node, lang) - preset = node and u.get_preset(node:type(), lang) + node, preset = search_node_up(node, lang) - if not node then + if not (node and preset) then return nil end @@ -78,10 +130,10 @@ function M.search_node(node, lang) local with_target = node table.insert(viewed, with_target) - node, preset = M.get_node_from_field(node, lang, targets) + node, preset = get_node_from_field(node, lang, targets) if not node then - node, preset = M.search_inside_node(with_target, lang, targets) + node, preset = search_inside_node(with_target, lang, targets) end if node then @@ -97,33 +149,21 @@ function M.search_node(node, lang) return vim.tbl_extend('force', tsn_data, { tsnode = node, preset = preset }) end -function M.get_node_from_field(node, lang, targets) - for node_type, use_preset in pairs(targets) do - local fields = node:field(node_type) - local preset = u.get_self_preset(use_preset, lang) - - if not vim.tbl_isempty(fields) and preset then - return fields[1], preset - end - end - return nil, nil -end - ---Return the closest configured node if found or nil ----@param node userdata|nil TSNode instance +---@param node TSNode|nil TSNode instance ---@return table function M.get_configured_node(node) if not node then error(msg.node_not_received, 0) end - local lang = u.get_node_lang(node) - if not u.is_lang_support(lang) then + local lang = get_node_lang(node) + if not langs[lang] then error(msg.no_configured_lang:format(lang), 0) end local start_node_type = node:type() - local data = M.search_node(node, lang) + local data = search_node(node, lang) if not data or not data.tsnode then error(msg.no_configured_node:format(start_node_type, lang), 0) @@ -132,4 +172,116 @@ function M.get_configured_node(node) return data end +---Return the preset for current node if it no contains field 'target_nodes' +---@param tsn_type string TSNode type +---@param lang string TSNode lang +---@return table|nil +function M.get_self_preset(tsn_type, lang) + local p = get_preset(tsn_type, lang) + if p and not p.target_nodes then + return p + end + return nil +end + +---Recursively iterates over each one until the state is satisfied +---@param tsnode TSNode TSNode instance +---@param cb function Callback: boolean +---@return boolean +function M.check_descendants(tsnode, cb) + cb = cb or function() end + local function _check(node, f) + local result = false + for child in node:iter_children() do + if f(child) then + return true + end + if child:child_count() >= 1 then + result = _check(child, f) + else + result = f(child) + end + if result then + return true + end + end + return result + end + return _check(tsnode, cb) +end + +---Checking if the node contains descendants to format +---@param tsnode TSNode TSNode instance +---@param ignore table|nil List of types to be ignored +---@param lang string Current lang +---@return boolean +function M.has_node_to_format(tsnode, ignore, lang) + local function configured_and_must_be_formatted(tsn) + local has_preset = tsn:named() and M.get_self_preset(tsn:type(), lang) + local ignored = vim.tbl_contains(ignore, tsn:type()) + return has_preset and not ignored + end + + return M.check_descendants(tsnode, configured_and_must_be_formatted) +end + +---Checking if the node contains disabled descendants to format +---@param tsnode TSNode TSNode instance +---@param mode 'split'|'join' Current mode (split|join) +---@param lang string Current lang +---@return boolean +function M.has_disabled_descendants(tsnode, mode, lang) + local p = get_preset(tsnode:type(), lang, mode) + if not p then + return false + end + local function contains_in_no_format_with(tsn) + return vim.tbl_contains(p.no_format_with, tsn:type()) + end + return M.check_descendants(tsnode, contains_in_no_format_with) +end + +---Returned range of node considering the presence of brackets +---@param tsn TSNode|table TSNode instance or TSNode imitator +---@param p? table +---@return integer, integer, integer, integer +function M.range(tsn, p) + local function get_last_symbol_range(n) + local len = n:child_count() + while len > 0 do + n = n:child(len - 1) + len = n:child_count() + end + local _, _, er, ec = n:range() + return er, ec + end + + local function get_framing_for_non_bracket(n) + local first = n:prev_sibling() or n:parent():prev_sibling() + local last = n:next_sibling() or n:parent():next_sibling() + return first, last + end + + local non_bracket_node = u.get_nested_key_value(p, 'non_bracket_node') + + -- Some parsers give incorrect range, when `tsn:range()` (e.g. `yaml`). + -- That's why using end_row and end_column of last children text. + local sr, sc = tsn:range() + local er, ec = get_last_symbol_range(tsn) + + if p and non_bracket_node then + local first, last = get_framing_for_non_bracket(tsn) + if first then + local r = { first:range() } + sr, sc, _, _ = r[3], r[4] + end + if last then + local r = { last:range() } + _, _, er, ec = _, _, r[1], r[2] + end + end + + return sr, sc, er, ec +end + return M diff --git a/lua/treesj/settings.lua b/lua/treesj/settings.lua index 69a40c0..bec8fd6 100644 --- a/lua/treesj/settings.lua +++ b/lua/treesj/settings.lua @@ -52,15 +52,17 @@ M.settings = DEFAULT_SETTINGS local function merge_settings(default_settings, opts) opts = opts or {} - -- TODO: rewrite + if opts.langs then for lang, presets in pairs(opts.langs) do for node, preset in pairs(presets) do - presets[node] = lu._premerge(preset) + local info = { lang = lang, node = node, mode = 'both' } + presets[node] = lu._premerge(preset, info) end opts.langs[lang] = presets end end + local settings = vim.tbl_deep_extend('force', default_settings, opts) settings.langs = lu._prepare_presets(settings.langs) settings.langs = lu._skip_disabled(settings.langs) diff --git a/lua/treesj/treesj/init.lua b/lua/treesj/treesj/init.lua index 0d28aa4..a933035 100644 --- a/lua/treesj/treesj/init.lua +++ b/lua/treesj/treesj/init.lua @@ -1,195 +1,284 @@ +local notify = require('treesj.notify') +local msg = notify.msg local u = require('treesj.utils') local tu = require('treesj.treesj.utils') +local search = require('treesj.search') ---TreeSJ - wrapper over TS Node ---@class TreeSJ ---@field _root boolean If the current node is the root ----@field _tsnode userdata TSNode instance +---@field _tsnode TSNode|table TSNode instance or TSNode imitator ---@field _lang string TSNode language ----@field _imitator boolean Imitator first/last node for non-bracket blocks +---@field _imitator boolean Tree if _tsnode is imitator ---@field _parent TreeSJ|nil TreeSJ instance. Parent of current TreeSJ node ---@field _prev TreeSJ|nil TreeSJ instance. Previous sibling of current TreeSJ node ---@field _next TreeSJ|nil TreeSJ instance. Next sibling of current TreeSJ node ----@field _preset table|nil Preset for current TreeSJ if exist ----@field _text string|string[] Formatted tsnode text ----@field _has_node_to_format boolean Has or not check_descendants for format +---@field _preset table|nil Preset for current TreeSJ if exist. Include both modes +---@field _text string|string[] Formatted tsnode text. Can be string[] when `recursive` is true in preset ---@field _children TreeSJ[] List of children ----@field _observed_range integer[] Range of node consider whitespaces ---@field _root_indent integer|nil Start indent to calculate other insdent when split ----@field _remove boolean Marker if node should be removed from tree +---@field _mode 'split'|'join' Current mode +---@field _copy_from_self boolean Marker that the current instance is a copy of itself, +---wrapped with TreeSJ:wrap({...}, 'wrap' ) local TreeSJ = {} TreeSJ.__index = TreeSJ ---New TreeSJ instance ----@param tsn_data table TSNode data { tsnode = TSNode|table, preset = table|nil, lang = string, parent = TreeSJ|nil} +---@param tsn_data {tsnode=TSNode|table, preset=table|nil, lang=string, parent=TreeSJ|nil, from_self=boolean, mode=string} function TreeSJ.new(tsn_data) - local root_preset = tsn_data.parent and tsn_data.parent:root():preset() or nil local tsnode = tsn_data.tsnode + local preset = tsn_data.preset + local lang = tsn_data.lang + local parent = tsn_data.parent + local from_self = tsn_data.from_self - local is_tsn = tsnode:type() ~= 'imitator' - local hntf = is_tsn and u.has_node_to_format(tsnode, root_preset) or false - local text = is_tsn and u.get_node_text(tsn_data.tsnode) or tsnode:text() - local range = is_tsn and tu.get_observed_range(tsnode) or { tsnode:range() } + local is_tsn = tu.is_tsnode(tsnode) + local text = is_tsn and tu.get_node_text(tsnode) or tsnode:text() local ri if not tsn_data.parent then + local range = { tsnode:range() } ri = vim.fn.indent(range[1] + 1) end return setmetatable({ _root = not tsn_data.parent, _tsnode = tsnode, - _lang = tsn_data.lang, + _lang = lang, _imitator = not is_tsn, - _parent = tsn_data.parent, + _parent = parent, _prev = nil, _next = nil, - _preset = tsn_data.preset, + _preset = preset, _text = text, - _has_node_to_format = hntf, _children = {}, - _observed_range = range, _root_indent = ri, - _remove = false, + _mode = tsn_data.mode, + _copy_from_self = from_self, }, TreeSJ) end ----Recursive parse current node children and building TreeSJ ----@param mode string -function TreeSJ:build_tree(mode) - local preset = self:preset(mode) - local children = u.collect_children(self:tsnode(), preset and preset.filter) - local prev - - local framing = preset and preset.add_framing_nodes +---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. +---@param data {text=string, type=string|nil, copy_from=TreeSJ|nil}. 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) + local tsnode, preset + local from_self = false + local copy = data.copy_from + + if copy and (getmetatable(copy) == getmetatable(self)) then + tsnode = copy:tsnode() + preset = tsnode:named() + and search.get_self_preset(tsnode:type(), self._lang) + or nil + from_self = copy == self + else + tsnode = tu.imitate_tsn(self, data) + end - if self:non_bracket() or framing then - local left = framing and framing.left - local right = framing and framing.right + local child = TreeSJ.new({ + tsnode = tsnode, + preset = preset, + lang = self._lang, + parent = self, + mode = self._mode, + from_self = from_self, + }) + + if copy then + tu.handle_indent(child) + child:_build_tree() + end - -- TODO: find right condition - if framing and framing.mode == 'pack' then - children = { self:tsnode() } + if index then + local children = self:children() + local max_index = #children + 1 + local min_index = 1 + index = tu.fix_index(index, #children) + + if min_index <= index and index <= max_index then + table.insert(children, index, child) + self:update_children(children) + else + return end - - tu.add_first_last_imitator(self:tsnode(), children, left, right) end - for _, child in ipairs(children) do - local tsn_data = { - tsnode = child, - preset = u.get_self_preset(child:type(), self._lang), - lang = self._lang, - parent = self, - } - - local tsj = TreeSJ.new(tsn_data) - - tsj:_set_prev(prev) - if tsj:prev() then - tsj:prev():_set_next(tsj) - end + return child +end - if not tsj:is_ignore('split') and tsj:has_preset() then - local is_norm = tsj:root():preset('split').inner_indent == 'normal' - local need_sw = not (tsj:is_omit() or tsj:parent():is_omit() or is_norm) +--[[ Work with children ]] - local sw = need_sw and vim.fn.shiftwidth() or 0 +---Iterate all TreeSJ instance children. +---Use: `... for child, index in tsj:iter_children() do ...` +---@return function, TreeSJ[] +function TreeSJ:iter_children() + local index = 0 + local function iterator(tbl) + index = index + 1 + return tbl[index], index + end + return iterator, self._children +end - tsj._root_indent = tsj:get_prev_indent() + sw +---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)`. +---@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) + if type(type_or_index) == 'number' then + type_or_index = tu.fix_index(type_or_index, #self:children()) + return self:children()[type_or_index] + else + for child in self:iter_children() do + if child:type() == type_or_index then + return child + end end + end +end - if child:type() ~= 'imitator' then - tsj:build_tree(mode) +---Removes children by the passed types or index. +---@param types_or_index string|string[]|integer Type, types, or index of child to remove +function TreeSJ:remove_child(types_or_index) + if type(types_or_index) == 'number' then + types_or_index = tu.fix_index(types_or_index, #self._children) + table.remove(self._children, types_or_index) + self:update_children(self._children) + else + local remove = type(types_or_index) == 'table' and types_or_index + or { types_or_index } + local check = function(child) + return not vim.tbl_contains(remove, child:type()) end - - table.insert(self._children, tsj) - prev = tsj + self:update_children(vim.tbl_filter(check, self._children)) end end ----Checking if the current treesj node is non-bracket block +---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. +---@param types? string[] ---@return boolean -function TreeSJ:non_bracket() - return self:has_preset() - and u.get_nested_key_value(self:preset(), 'non_bracket_node') - or false +function TreeSJ:has_children(types) + if not types then + return #self:children() > 0 + else + return u.every(types, function(t) + return self:child(t) + end) + end end ----Get indent from previous configured ancestor node -function TreeSJ:get_prev_indent() - if self:parent():has_preset() and not self:parent():is_ignore('split') then - return self:parent()._root_indent +---Get the children of the current TreeSJ. +---Returns all children if `types` are omitted, otherwise returns all children of the listed types. +---@param types? string[] List-like table with child's types for filtering +---@return TreeSJ[] +function TreeSJ:children(types) + local children = vim.list_extend({}, self._children) + if types then + children = vim.tbl_filter(function(child) + return vim.tbl_contains(types, child:type()) + end, children) end - if self:parent() then - return self:parent():get_prev_indent() + return children +end + +---Updated children list of current TreeSJ +---@param children TreeSJ[] +function TreeSJ:update_children(children) + if type(children) ~= 'table' then + return end + self._children = tu.linking_tree(children) end ----Get child of TreeSJ by index ----@param index integer ----@return TreeSJ -function TreeSJ:child(index) - return self._children[index] +---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. +---@param data table { left = string, right = string } +---@param mode? 'wrap'|'inline' 'wrap' by default +function TreeSJ:wrap(data, mode) + mode = mode and mode or 'wrap' + local left = self:create_child({ text = data.left, type = 'left_bracket' }) + local right = self:create_child({ text = data.right, type = 'right_bracket' }) + local children = mode == 'wrap' + and { self:create_child({ copy_from = self }) } + or self:children() + + table.insert(children, 1, left) + table.insert(children, right) + + self:update_children(children) end ----Get root of TreeSJ ----@return TreeSJ TreeSJ instance -function TreeSJ:root() - return self._root and self or self:parent():root() +---Helps to swap elements by their indexes +---@param index1 integer +---@param index2 integer +function TreeSJ:swap_children(index1, index2) + local children = self:children() + local first = children[index1] + local second = children[index2] + children[index1] = second + children[index2] = first + self:update_children(children) end ----Merge TreeSJ to one line for replace start text -function TreeSJ:join() - if self:has_preset() or self:has_to_format() then - local root = self:root() +--[[ Work with TreeSJ data ]] - if self:has_to_format() and root:preset('join').recursive then - for child in self:iter_children() do - if not child:is_ignore('join') then - child:join() - end - end - end +---Get node type of current TreeSJ +---@return string +function TreeSJ:type() + return self._tsnode:type() +end - self:_update_text(tu._join(self)) +---Get range of current node +---@return integer[] +function TreeSJ:range() + if self:non_bracket() then + local sr, sc, er, ec + sr, sc = self:child(1):tsnode():range() + _, _, er, ec = self:child(#self._children):tsnode():range() + return { sr, sc, er, ec } end + return { self._tsnode:range() } end ----Merge TreeSJ to lines for replace start text -function TreeSJ:split() - if self:has_preset() or self:has_to_format() then - local root = self:root() - - if self:has_to_format() and root:preset('split').recursive then - for child in self:iter_children() do - if not child:is_ignore('split') then - child:split() - end - end - end - - local lines = tu.remove_empty_middle_lines(vim.tbl_flatten(tu._split(self))) +---Get updated text of current node +---@return string|table +function TreeSJ:text() + return self._text +end - self:_update_text(lines) - end +---Updated text of current node +---@param new_text string|string[] +function TreeSJ:update_text(new_text) + self._text = new_text end ----Checking if the current node must be ignored while recursive formatting ----@param mode string Current mode (split|join) ----@return boolean -function TreeSJ:is_ignore(mode) - local p = self:root():preset(mode) - return p and vim.tbl_contains(p.recursive_ignore, self:type()) or false +---Get root treesj-node of current TreeSJ +---@return TreeSJ TreeSJ instance +function TreeSJ:root() + return self._root and self or self:parent():root() end ----Get TSNode of current ----@return userdata +---Get TSNode or TSNode imitator of current +---@return TSNode|table TSNode or TSNode imitator function TreeSJ:tsnode() return self._tsnode end ----Get parent node +---Get parent TreeSJ ---@return TreeSJ|nil function TreeSJ:parent() return self._parent @@ -207,62 +296,100 @@ function TreeSJ:next() return self._next end ----Set left side node ----@param node TreeSJ TreeSJ instance -function TreeSJ:_set_prev(node) - self._prev = node +--[[ Work with TreeSJ conditions ]] + +---Checking if the current node is first among sibling +---@return boolean +function TreeSJ:is_first() + return not u.tobool(self:prev()) end ----Set right side node ----@param node TreeSJ TreeSJ instance -function TreeSJ:_set_next(node) - self._next = node +---Checking if the current node is last among sibling +---@return boolean +function TreeSJ:is_last() + return not u.tobool(self:next()) end ----Get type of current node ----@return string -function TreeSJ:type() - return self._tsnode:type() +---Checking if the current node is first or is last among sibling +---@return boolean +function TreeSJ:is_framing() + return self:is_last() or self:is_first() end ----Get range of current node ----@return integer[] -function TreeSJ:range() - if self:non_bracket() then - local sr, sc, er, ec - sr, sc = self:child(1):tsnode():range() - _, _, er, ec = self:child(#self._children):tsnode():range() - return { sr, sc, er, ec } - end - return { self._tsnode:range() } +---Checking if the text of current node contains at 'preset.omit' +---@return boolean +function TreeSJ:is_omit() + local omit = u.get_nested_key_value(self:parent_preset(), 'omit') + return omit and tu.check_match(omit, self) or false end ----Get observed range of current node ----@return integer[] -function TreeSJ:o_range() - return self._observed_range +---Checking if the current TreeSJ is node-imitator +---@return boolean +function TreeSJ:is_imitator() + return self._imitator end ----Get updated text of current node ----@return string|string[] -function TreeSJ:text() - return self._text +---Checking if the current TreeSJ node is non-bracket block +---@return boolean +function TreeSJ:non_bracket() + local preset = self:preset(self._mode) + return u.tobool(preset and preset.non_bracket_node) end ----Updated text of current node ----@param new_text string|string[] -function TreeSJ:_update_text(new_text) - self._text = new_text +---Checking if the current node must be ignored while recursive formatting +---@return boolean +function TreeSJ:is_ignore() + local mode = self._mode + local p = self:root():preset(mode) + return p and vim.tbl_contains(p.recursive_ignore, self:type()) or false end ----True if current node contains descendants to format +---Checks if the TreeSJ contains descendants that need to be formatted ---@return boolean function TreeSJ:has_to_format() - return self._has_node_to_format + local ignore = self:root():preset(self._mode).recursive_ignore + + for child in self:iter_children() do + if not child:is_imitator() and child:tsnode():named() then + local tsnode = child:tsnode() + local hp = child:has_preset(self._mode) + + -- It needs to be applied in a loop to handle cases where any of the nodes were copied from themselves + if hp or search.has_node_to_format(tsnode, ignore, self._lang) then + return true + end + end + end + + return false end ----Get preset for for current node ----@param mode? string|nil Current mode (split|join) +---Returns true if the current TreeSJ will be formatted +---@return boolean +function TreeSJ:will_be_formatted() + local root = self:root() + + if self == root then + return true + end + + local mode = self._mode + return root:preset(mode).recursive + and (self:has_preset(mode) or self:has_to_format()) +end + +--[[ Work with preset ]] + +---Checking if the current TreeSJ is configured +---@param mode? 'split'|'join' Current mode (split|join) +---@return boolean +function TreeSJ:has_preset(mode) + local has = self._preset and (mode and self._preset[mode] or self._preset) + return u.tobool(has) +end + +---Get preset for current TreeSJ +---@param mode? 'split'|'join' Current mode (split|join) ---@return table|nil function TreeSJ:preset(mode) if self:has_preset() then @@ -271,8 +398,8 @@ function TreeSJ:preset(mode) return nil end ----Get parent preset ----@param mode? string Current mode (split|join) +---Get the preset of the TreeSJ parent +---@param mode? 'split'|'join' Current mode (split|join) ---@return table|nil function TreeSJ:parent_preset(mode) local parent = self:parent() @@ -282,65 +409,146 @@ function TreeSJ:parent_preset(mode) return nil end ----Checking if the current node is configured ----@return boolean -function TreeSJ:has_preset() - return u.tobool(self._preset) +---Updates the presets for the current node. +---@param new_preset table +---@param mode? 'split'|'join' +function TreeSJ:update_preset(new_preset, mode) + if self._preset then + if mode then + self._preset[mode] = + vim.tbl_deep_extend('force', self._preset[mode], new_preset) + else + self._preset = vim.tbl_deep_extend('force', self._preset, new_preset) + end + end end ----Checking if the current node is first among sibling ----@return boolean -function TreeSJ:is_first() - return not u.tobool(self:prev()) -end +--[[ Private, not use in presets ]] ----Checking if the current node is last among sibling ----@return boolean -function TreeSJ:is_last() - return not u.tobool(self:next()) -end +---Recursive parse current node children and building TreeSJ +function TreeSJ:_build_tree() + local mode = self._mode + local children = tu.collect_children(self:tsnode(), tu.skip_empty_nodes) ----Checking if the current node is first or is last among sibling ----@return boolean -function TreeSJ:is_framing() - return self:is_last() or self:is_first() + for _, child in ipairs(children) do + local preset + + if child:named() then + preset = search.get_self_preset(child:type(), self._lang) + end + + local tsj = TreeSJ.new({ + tsnode = child, + preset = preset, + lang = self._lang, + parent = self, + mode = mode, + from_self = false, + }) + + tu.handle_indent(tsj) + + if tu.is_tsnode(child) then + tsj:_build_tree() + end + + table.insert(self._children, tsj) + end + + self:update_children(self:children()) + + local preset = self:preset(mode) + if preset then + tu.handle_framing_nodes(self, preset) + tu.handle_last_separator(self, preset) + + local format_tree = preset.format_tree + -- Don't run `format_tree` if node is copied from itself and uses the same preset, + -- because it will be endless recursion + local is_run = not self._copy_from_self and true + or (self:parent_preset(mode).__info.node ~= preset.__info.node) + + if type(format_tree) == 'function' and is_run then + local ok, error = pcall(preset.format_tree, self) + if not ok then + notify.warn( + msg.custom_func:format('format_tree', preset.__info.node, error) + ) + end + end + end end ----Checking if the text of current node contains at 'preset.omit' ----@return boolean -function TreeSJ:is_omit() - local omit = u.get_nested_key_value(self:parent_preset(), 'omit') - return omit and u.check_match(omit, self) or false +---Merge TreeSJ to one line for replace start text +function TreeSJ:_format() + if self:has_preset() or self:has_to_format() then + local mode = self._mode + local root = self:root() + + if self:has_to_format() and root:preset(mode).recursive then + for child in self:iter_children() do + if not child:is_ignore() then + child:_format() + end + end + end + + local preset = self:preset(mode) + local lines + + if mode == 'join' then + lines = tu._join(self) + else + lines = tu.remove_empty_middle_lines(vim.tbl_flatten(tu._split(self))) + end + + local format_lines = preset and preset.format_resulted_lines + + if format_lines then + local ok, output = pcall(format_lines, lines) + local correct = type(output) == 'table' and u.every(output, u.is_string) + + if not (ok and correct) then + local mess = (not correct and ok) and msg.wrong_resut or msg.custom_func + mess = mess:format('format_resulted_lines', preset.__info.node, output) + error(mess, 0) + end + + lines = output + end + + lines = mode == 'split' and lines or table.concat(lines) + self:update_text(lines) + end end ----Checking if the current TreeSJ is node-imitator ----@return boolean -function TreeSJ:is_imitator() - return self._imitator +---Set left side node +---@param node TreeSJ TreeSJ instance +function TreeSJ:_set_prev(node) + self._prev = node end ----Checking if the current TreeSJ is node-imitator ----@return boolean -function TreeSJ:remove() - self._remove = true +---Set right side node +---@param node TreeSJ TreeSJ instance +function TreeSJ:_set_next(node) + self._next = node end ---Return formatted lines of TreeSJ ---@return string[] -function TreeSJ:get_lines() +function TreeSJ:_get_lines() local text = self:text() return type(text) == 'table' and text or { text } end ----Iterate all TreeSJ instance children ----@return function, table -function TreeSJ:iter_children() - local index = 0 - local function iterator(tbl) - index = index + 1 - return tbl[index] +---Get indent from previous configured ancestor node +function TreeSJ:_get_prev_indent() + if self:parent():has_preset() and not self:parent():is_ignore() then + return self:parent()._root_indent + end + if self:parent() then + return self:parent():_get_prev_indent() end - return iterator, self._children end return TreeSJ diff --git a/lua/treesj/treesj/utils.lua b/lua/treesj/treesj/utils.lua index 280ead0..daf4524 100644 --- a/lua/treesj/treesj/utils.lua +++ b/lua/treesj/treesj/utils.lua @@ -1,169 +1,380 @@ +local query = require('vim.treesitter.query') +local search = require('treesj.search') local u = require('treesj.utils') -local JOIN = 'join' -local SPLIT = 'split' - local M = {} ----Return observed range by tsnode ----@param tsnode userdata TSNode instance ----@return integer[] -function M.get_observed_range(tsnode) - local rr = u.readable_range({ tsnode:range() }) - local prev = tsnode:prev_sibling() - if prev then - local prr = u.readable_range({ prev:range() }) - rr.col.start = prr.row.start == rr.row.start and prr.col.end_ or 0 - end - return { rr.row.start, rr.col.start, rr.row.end_, rr.col.end_ } +---Checking if tsn is TSNode instance. False if it imitator of tsn +---@param tsn TSNode|table +---@return boolean +function M.is_tsnode(tsn) + return type(tsn) == 'userdata' end ----Makes first/last imitator node for TreeSJ. Using only for non-bracket blocks. ----@param tsn userdata|nil ----@param parent userdata ----@param pos string last|first ----@param text? string -function M.imitate_tsn(tsn, parent, pos, text) - text = text or '' +---Returned true if node is not empty +---@param tsn TSNode TSNode instance +---@return boolean +function M.skip_empty_nodes(tsn) + local text = vim.trim(query.get_node_text(tsn, 0)) + return not u.is_empty(text) +end - local imitator = {} - imitator.__index = imitator - local sr, sc, er, ec - if tsn then - sr, sc, er, ec = tsn:range() - elseif pos == 'first' then - sr, sc = parent:range() - er, ec = sr, sc - elseif pos == 'last' then - _, _, er, ec = parent:range() - sr, sc = er, ec +---Get list-like table with children of node +---This function is pretty much copied from 'nvim-treesitter' +---(TSRange:collect_children) +---@param tsnode TSNode|table TSNode instance or TSNode imitator +---@param filter? function Function for filtering output list +---@return table +function M.collect_children(tsnode, filter) + local children = {} + + for child in tsnode:iter_children() do + if not filter or filter(child) then + table.insert(children, child) + end end - function imitator:range() - if pos == 'first' then - return er, ec, er, ec - else - return sr, sc, sr, sc + return children +end + +---Return text of node +---@param node TSNode from TSNode +---@return string +function M.get_node_text(node) + -- TODO: concat is deprecated in 0.9+. Refactor later + local lines = query.get_node_text(node, 0, { concat = false }) + local trimed_lines = {} + local sep = ' ' + if type(lines) == 'string' then + lines = vim.split(lines, '\n') + end + for _, line in ipairs(lines) do + line = vim.trim(line) + if not u.is_empty(line) then + table.insert(trimed_lines, line) end end + return table.concat(trimed_lines, sep) +end - function imitator:type() - return 'imitator' +---Checking if the found node is empty +---@param tsnode TSNode TSNode instance +---@param preset table Preset for TSNode +---@return boolean +function M.is_empty_node(tsnode, preset) + local framing_count = 2 + local function is_omit(child) + return vim.tbl_contains(preset.omit, child:type()) end - function imitator:text() - return text + local function is_named(child) + return child:named() end - return imitator + local cc = tsnode:child_count() + local children = M.collect_children(tsnode, is_named) + local contains_only_framing = cc == framing_count + return u.every(children, is_omit) or contains_only_framing end ----Add first and last imitator nodas to children list for non-bracket blocks ----@param node userdata TSNode instance ----@param children table ----@param left? string ----@param right? string -function M.add_first_last_imitator(node, children, left, right) - local first, last = u.get_non_bracket_first_last(node) - table.insert(children, 1, M.imitate_tsn(first, node, 'first', left)) - table.insert(children, M.imitate_tsn(last, node, 'last', right)) +---Calculation of the real index if a negative value was passed +---@param i integer +---@param len integer Length of the list for which the index is calculated +---@return integer +function M.fix_index(i, len) + return i < 0 and (len + 1 + i) or i end ----Add some text to start of base text. If the base is table, prepend text to first element of table ----@param target_text string|string[] ----@param text string ----@return string|string[] -local function prepend_text(target_text, text) - if type(target_text) == 'table' then - target_text = vim.list_extend({}, target_text, 1, #target_text) - target_text[1] = text .. target_text[1] - else - target_text = text .. target_text +---Add prev/next links for every child of TreeSJ children list +---@param children TreeSJ[] +---@return TreeSJ[] +function M.linking_tree(children) + local special_types = { + 'left_non_bracket', + 'right_non_bracket', + 'left_bracket', + 'right_bracket', + } + + for i, child in ipairs(children) do + local prev, next = children[i - 1], children[i + 1] + child:_set_prev(prev) + child:_set_next(next) + + -- TODO: find next non imitator node + if + child:is_imitator() and not vim.tbl_contains(special_types, child:type()) + then + child:tsnode():_set_range(prev, next) + end end - return target_text + return children end ----Set whitespaces before node ----@param child TreeSJ -local function set_whitespace(child) - local spacing = u.get_whitespace(child) - local text = prepend_text(child:text(), spacing) - child:_update_text(text) +---Setting value of indent to configured nodes +---@param tsj TreeSJ TreeSJ instance +function M.handle_indent(tsj) + if tsj._mode == 'split' and tsj:has_preset() and not tsj:is_ignore() then + local is_norm = tsj:root():preset('split').inner_indent == 'normal' + local need_sw = not (tsj:is_omit() or tsj:parent():is_omit() or is_norm) + + local sw = need_sw and vim.fn.shiftwidth() or 0 + + tsj._root_indent = tsj:_get_prev_indent() + sw + end end --- TODO: rewrite ----Checking if need to set instruction separator ----@param child TreeSJ TreeSJ instance ----@param p table Preset -local function is_instruction_sep_need(child, p) - if not p then - return false +---Add or remove last separator in node +---@param tsj TreeSJ TreeSJ instance +---@param preset table +function M.handle_last_separator(tsj, preset) + local penult = tsj:child(-2) + local sep = preset.separator + + if penult and not penult:is_framing() and sep ~= '' then + local has = penult:type() == sep + local need = preset.last_separator + + if has and not need then + tsj:remove_child(-2) + elseif not has and need then + tsj:create_child({ type = sep, text = sep }, -1) + end end +end - local next = child:next() - local is_next_sep = next and next:text() == p.force_insert or false +local function get_bracket_imitator_range(tsj, side) + local tsn = tsj:tsnode() + local sr, sc, er, ec = tsn:range() + local sibling - if child:is_framing() or u.is_empty(p.force_insert) or is_next_sep then + if side == 'left' then + er, ec = sr, sc + sibling = tsn:prev_sibling() or tsn:parent():prev_sibling() + else + sr, sc = er, ec + sibling = tsn:next_sibling() or tsn:parent():next_sibling() + end + + if sibling then + if side == 'left' then + _, _, er, ec = sibling:range() + sr, sc = er, ec + else + sr, sc = sibling:range() + er, ec = sr, sc + end + end + + return sr, sc, er, ec +end + +---Create imitator of TSNode +---@param tsj TreeSJ TreeSJ instance +---@param data table { text = '', type = '' } +---@return table +function M.imitate_tsn(tsj, data) + local imitator = {} + imitator.__index = imitator + local text = data.text and data.text or '' + local ts_type = data.type and data.type or data.text + local sr, sc, er, ec = search.range(tsj:tsnode()) + + local types = { + ['left_non_bracket'] = { get_bracket_imitator_range(tsj, 'left') }, + ['right_non_bracket'] = { get_bracket_imitator_range(tsj, 'right') }, + ['left_bracket'] = { sr, sc, sr, sc }, + ['right_bracket'] = { er, ec, er, ec }, + } + + if types[ts_type] then + sr, sc, er, ec = unpack(types[ts_type]) + else + sr, sc = er, ec + end + + function imitator:_set_range(prev, next) + local nsr, nsc, ner, nec = sr, sc, er, ec + if prev then + _, _, nsr, nsc = prev:tsnode():range() + end + + if next then + ner, nec = next:tsnode():range() + end + + self._range = { nsr, nsc, ner, nec } + end + + function imitator:prev_sibling() + return nil + end + + function imitator:next_sibling() + return nil + end + + function imitator:range() + return unpack(self._range) + end + + function imitator:type() + return ts_type + end + + function imitator:named() return false end - local has = vim.endswith(child:text(), p.force_insert) - local need = not u.check_match(p.no_insert_if, child) + function imitator:field() + return nil + end + + function imitator:text() + return text + end - return need and not has + return setmetatable({ + _parent = tsj, + _range = { sr, sc, sr, sc }, + _type = ts_type, + }, imitator) end ----Checking if the text need and not has or has and not need last separator ----@param text string Current text of child ----@param p table Preset ----@return boolean, boolean -local function is_has_and_need(text, p) - return vim.endswith(text, p.separator), p.last_separator +---Creating and insert framing nodes to children list of configured TreeSJ +---@param tsj TreeSJ +---@param preset table +function M.handle_framing_nodes(tsj, preset) + if tsj:non_bracket() then + local left_type, right_type = 'left_non_bracket', 'right_non_bracket' + local left, right = '', '' + + if type(preset.non_bracket_node) == 'table' then + left = preset.non_bracket_node.left + right = preset.non_bracket_node.right + end + + tsj:create_child({ text = left, type = left_type }, 1) + tsj:create_child({ text = right, type = right_type }, #tsj:children() + 1) + end end ----Add or remove last separator ----@param child TreeSJ TreeSJ instance ----@param p table|nil Preset for parent -local function set_last_sep_if_need(child, p) - if not p then - return +---Get whitespace between nodes +---@param tsj TreeSJ TreeSJ instance +---@return string +function M.get_whitespace(tsj) + local function is_on_same_line(prev, curent) + return prev and prev:range()[3] == curent:range()[1] or false end - if not child:is_first() and child:next() and child:next():is_last() then - local content = child:text() - local text = type(content) == 'table' and content[#content] or content + local function get_sibling_spacing(prev, current) + return current:range()[2] - prev:range()[4] + end - local has, need = is_has_and_need(text, p) + local p = tsj:parent():preset('join') + local s_count = p and (p.space_separator and 1 or 0) or 1 + local is_sep = (p and p.separator ~= '') and tsj:text() == p.separator - if has and not need then - text = text:sub(1, #text - #p.separator) - elseif need and not has then - text = text .. p.separator - end + if tsj:is_first() or is_sep then + s_count = 0 + elseif (not p or tsj:is_omit()) and is_on_same_line(tsj:prev(), tsj) then + s_count = get_sibling_spacing(tsj:prev(), tsj) + elseif p and (tsj:prev():is_first() or tsj:is_last()) then + s_count = p.space_in_brackets and 1 or 0 + end - if type(content) == 'table' then - content[#content] = text - else - content = text + return (' '):rep(s_count) +end + +---Checking if tsj meets condition in list of string and functions +---Returned 'true' if type of tsj contains among strings or some of 'function(tsj)' returned 'true' +---@param tbl table List with 'string' and 'function' +---@param tjs TreeSJ TreeSJ instance +function M.check_match(tbl, tjs) + local function is_func(item) + return type(item) == 'function' + end + + local contains = vim.tbl_contains(tbl, tjs:type()) + local cbs = vim.tbl_filter(is_func, tbl) + + if not contains and #cbs > 0 then + return u.some(cbs, function(cb) + return cb(tjs) + end) + else + return contains + end +end + +---Checking if the current node is last with `is_omtit = false` +---@param tsj TreeSJ TreeSJ instance +---@return boolean +local function is_last_no_omit(tsj) + local parent = tsj:parent() + if parent and parent:has_preset() then + local last_no_omit = parent:child(1) + for child in parent:iter_children() do + last_no_omit = not child:is_omit() and child or last_no_omit end + return tsj == last_no_omit + end + return false +end - child:_update_text(content) +---Computed indent for node when mode is 'split' +---@param tsj TreeSJ TreeSJ instance +---@return integer +function M.calc_indent(tsj) + local parent = tsj:parent() + if tsj:is_first() or tsj:is_omit() or not parent then + return 0 end + + local pp = parent:preset('split') + local start_indent = parent._root_indent + local shiftwidth = vim.fn.shiftwidth() + local common_indent = start_indent + shiftwidth + local is_last = is_last_no_omit(tsj) and pp.last_indent == 'normal' + local is_same = pp.inner_indent == 'normal' + + return (is_last or is_same) and start_indent or common_indent end ----Set indent when 'split' ----@param child TreeSJ TreeSJ instance -local function set_indent(child) - local indent = u.calc_indent(child) - local sep = ' ' +---Collapse extra spacing: if elem ends with space and next elem starts with space +---@param lines string[] +---@return string[] +local function collapse_spacing(lines) + for i, str in ipairs(lines) do + str = str:gsub('^%s+', ' '):gsub('%s+$', ' ') + local next = lines[i + 1] + if next and vim.endswith(str, ' ') and vim.startswith(next, ' ') then + lines[i] = string.gsub(str, ' $', '') + end + end + return lines +end - if not vim.bo.expandtab then - indent = indent / vim.fn.shiftwidth() - sep = '\t' +---Add some text to start of base text. If the base is table, prepend text to first element of table +---@param target_text string|string[] +---@param text string +---@return string|string[] +local function prepend_text(target_text, text) + if type(target_text) == 'table' then + target_text = vim.list_extend({}, target_text, 1, #target_text) + target_text[1] = table.concat(collapse_spacing({ text, target_text[1] })) + else + target_text = table.concat(collapse_spacing({ text, target_text })) end + return target_text +end - local text = prepend_text(child:text(), (sep):rep(indent)) - child:_update_text(text) +---Set whitespaces before node +---@param child TreeSJ +local function set_whitespace(child) + local spacing = M.get_whitespace(child) + local text = prepend_text(child:text(), spacing) + child:update_text(text) end ---Append text to last item in list. If last item is a table, merge to last of this table. @@ -204,63 +415,66 @@ local function merge_text_to_prev_line(lines, to_merge) end end ----Collapse extra spacing: if elem ends with space and next elem starts with space ----@param lines string[] -local function collapse_spacing(lines) - for i, str in ipairs(lines) do - local next = lines[i + 1] - if next and (vim.endswith(str, ' ') and vim.startswith(next, ' ')) then - lines[i] = string.gsub(str, ' $', '') - end +---Sets instruction separator (force_insert) if need +---@param child TreeSJ TreeSJ instance +local function handle_force_insert(child) + local p = child:parent():preset('join') + if not p or p.force_insert == '' then + return + end + + local next = child:next() + local is_next_sep = next and next:text() == p.force_insert or false + + if is_next_sep or child:is_framing() then + return + end + + local has = vim.endswith(child:text(), p.force_insert) + local need = not M.check_match(p.no_insert_if, child) + + if need and not has then + child:update_text(child:text() .. p.force_insert) end end ---Make result line for 'join' ---@param tsj TreeSJ TreeSJ instance ----@return string +---@return string[] function M._join(tsj) local lines = {} for child in tsj:iter_children() do if tsj:has_preset() then - local p = tsj:preset(JOIN) - - local cb = p.foreach - if cb then - cb(child) - end + handle_force_insert(child) + end + set_whitespace(child) + table.insert(lines, child:text()) + end - if not child._remove then - if is_instruction_sep_need(child, p) then - child:_update_text(child:text() .. p.force_insert) - end + return collapse_spacing(lines) +end - set_last_sep_if_need(child, p) - set_whitespace(child) +---Set indent when 'split' +---@param child TreeSJ TreeSJ instance +local function set_indent(child) + local indent = M.calc_indent(child) + local sep = ' ' - table.insert(lines, child:text()) - end - else - set_whitespace(child) - table.insert(lines, child:text()) - end + if not vim.bo.expandtab then + indent = indent / vim.fn.shiftwidth() + sep = '\t' end - collapse_spacing(lines) - - return table.concat(lines) + local text = prepend_text(child:text(), (sep):rep(indent)) + child:update_text(text) end ---Handling for configured node when mode is SPLIT ----@param tsj TreeSJ TreeSJ instance ---@param child TreeSJ child of tsj ---@param lines table List-like table -local function process_configured(tsj, child, lines) - local p = tsj:preset(SPLIT) - - set_last_sep_if_need(child, p) - - if child:is_omit() then +local function process_configured(child, lines) + if child:is_omit() and not child:is_first() then set_whitespace(child) merge_text_to_prev_line(lines, child:text()) else @@ -317,14 +531,7 @@ function M._split(tsj) for child in tsj:iter_children() do if tsj:has_preset() then - local cb = tsj:preset('split').foreach - if cb then - cb(child) - end - - if not child._remove then - process_configured(tsj, child, lines) - end + process_configured(child, lines) elseif tsj:has_to_format() then process_configured_container(child, lines) else @@ -332,6 +539,7 @@ function M._split(tsj) table.insert(lines, child:text()) end end + return lines end diff --git a/lua/treesj/utils.lua b/lua/treesj/utils.lua index 1a0492a..5e0a18a 100644 --- a/lua/treesj/utils.lua +++ b/lua/treesj/utils.lua @@ -1,14 +1,3 @@ -local query = require('vim.treesitter.query') -local langs = require('treesj.settings').settings.langs -local notify = require('treesj.notify') -local msg = notify.msg - -local ts_ok, parsers = pcall(require, 'nvim-treesitter.parsers') -if not ts_ok then - notify.error(msg.ts_not_found) - return -end - local M = {} ---Convert any type to boolean @@ -37,7 +26,7 @@ end ---@param cb function Callback for checking every item ---@return boolean function M.every(tbl, cb) - if not vim.tbl_islist(tbl) or M.is_empty(tbl) then + if type(tbl) ~= 'table' or not vim.tbl_islist(tbl) or M.is_empty(tbl) then return false end @@ -69,62 +58,6 @@ function M.some(tbl, cb) return false end ----Get lunguage for node ----@param node userdata TSNode instance ----@return string -function M.get_node_lang(node) - local range = { node:range() } - local lang_tree = parsers.get_parser() - local current_tree = lang_tree:language_for_range(range) - return current_tree:lang() -end - ----Checking if language is configured ----@param lang string Language ----@return boolean -function M.is_lang_support(lang) - return M.tobool(langs[lang]) -end - ----Return the preset for received node. ----If mode passed, return preset for specified mode ----@param tsn_type string TSNode type ----@param lang? string TSNode lang. Requires if `node` is string ----@param mode? string Current mode (split|join) ----@return table|nil -function M.get_preset(tsn_type, lang, mode) - if lang and not M.is_lang_support(lang) then - return nil - end - - local presets = langs[lang] - local preset = presets and presets[tsn_type] - - return preset and (preset[mode] or preset) -end - ----Return the preset for current node if it no contains field 'target_nodes' ----@param tsn_type string TSNode type ----@param lang string TSNode lang ----@return table|nil -function M.get_self_preset(tsn_type, lang) - local p = M.get_preset(tsn_type, lang) - if p and not p.target_nodes then - return p - end - return nil -end - ----Return list-like table with keys of option 'target_nodes' ----@param tsn_type string TSNode type ----@param lang string TSNode lang ----@return table|nil -function M.get_targets(tsn_type, lang) - local p = M.get_preset(tsn_type, lang) - local targets = p and p.target_nodes - return (targets and not M.is_empty(targets)) and targets -end - ---Recursively finding key in table and return its value if found or nil ---@param tbl table|nil Dict-like table ---@param target_key string Name of target key @@ -148,289 +81,12 @@ function M.get_nested_key_value(tbl, target_key) return nil end ----Returned true if node is not empty ----@param tsn userdata TSNode instance ----@return boolean -function M.skip_empty_nodes(tsn) - local text = vim.trim(query.get_node_text(tsn, 0)) - return not M.is_empty(text) -end - ----Get list-like table with children of node ----This function is pretty much copied from 'nvim-treesitter' ----(TSRange:collect_children) ----@param node userdata TSNode instance ----@param filter? function[] List of function for filtering output list ----@return table -function M.collect_children(node, filter) - filter = filter or {} - table.insert(filter, M.skip_empty_nodes) - local children = {} - - for child in node:iter_children() do - local fn = function(cb) - return cb(child) - end - if M.every(filter, fn) then - table.insert(children, child) - end - end - - return children -end - ----Return text of node ----@param node TSNode from userdata ----@return string -function M.get_node_text(node) - local lines = query.get_node_text(node, 0, { concat = false }) - local trimed_lines = {} - local sep = ' ' - if type(lines) == 'string' then - lines = vim.split(lines, '\n') - end - for _, line in ipairs(lines) do - line = vim.trim(line) - if not M.is_empty(line) then - table.insert(trimed_lines, line) - end - end - return table.concat(trimed_lines, sep) -end - ----Checking if the found node is empty ----@param tsn userdata TSNode instance ----@param preset table Preset for TSNode ----@return boolean -function M.is_empty_node(tsn, preset) - local framing_count = 2 - local function is_omit(child) - return vim.tbl_contains(preset.omit, child:type()) - end - - local function is_named(child) - return child:named() - end - - local cc = tsn:child_count() - local children = M.collect_children(tsn, { is_named }) - local contains_only_framing = cc == framing_count - return M.every(children, is_omit) or contains_only_framing -end - ----Recursively iterates over each one until the state is satisfied ----@param tsnode userdata TSNode instance ----@param cb function Callback: boolean ----@return boolean -function M.check_descendants(tsnode, cb) - cb = cb or function() end - local function _check(node, f) - local result = false - for child in node:iter_children() do - if f(child) then - return true - end - if child:child_count() >= 1 then - result = _check(child, f) - else - result = f(child) - end - if result then - return true - end - end - return result - end - return _check(tsnode, cb) -end - ----Checking if the node contains descendants to format ----@param tsnode userdata TSNode instance ----@param root_preset table|nil Preset of root node for check 'recursive_ignore' ----@return boolean -function M.has_node_to_format(tsnode, root_preset) - local function configured_and_must_be_formatted(tsn) - local lang = M.get_node_lang(tsn) - local p = M.get_preset(tsn:type(), lang) - local recursive_ignore = - M.get_nested_key_value(root_preset, 'recursive_ignore') - local ignore = recursive_ignore - and vim.tbl_contains(recursive_ignore, tsn:type()) - or false - return M.tobool(p and not (p.target_nodes or ignore)) - end - - return M.check_descendants(tsnode, configured_and_must_be_formatted) -end - ----Checking if the node contains disabled descendants to format ----@param tsnode userdata TSNode instance ----@param mode string Current mode (split|join) ----@return boolean -function M.has_disabled_descendants(tsnode, mode) - local lang = M.get_node_lang(tsnode) - local p = M.get_preset(tsnode:type(), lang, mode) - if not p then - return false - end - local function contains_in_no_format_with(tsn) - return vim.tbl_contains(p.no_format_with, tsn:type()) - end - return M.check_descendants(tsnode, contains_in_no_format_with) -end - ----Convert range (integer[]) to human-readable ----@param range integer[] Range ----@return table -function M.readable_range(range) - return { - row = { - start = range[1], - end_ = range[3] or range[1], - }, - col = { - start = range[2], - end_ = range[4] or range[2], - }, - } -end - ----Checking if the previos and current nodes place on same line ----@param prev TreeSJ|nil Previous TreeSJ instance ----@param curent TreeSJ Current TreeSJ instance ----@return boolean -local function is_on_same_line(prev, curent) - return prev and prev:range()[3] == curent:range()[1] or false +function M.is_string(el) + return type(el) == 'string' end ----Get spacing between siblings (siblings must be placed by same line) ----@param prev TreeSJ ----@param current TreeSJ ----@return integer -local function get_sibling_spacing(prev, current) - return current:range()[2] - prev:range()[4] -end - ----Get whitespace between nodes ----@param tsj TreeSJ TreeSJ instance ----@return string -function M.get_whitespace(tsj) - local p = tsj:parent():preset('join') - local s_count = p and p.space_separator or 1 - local is_sep = (p and p.separator ~= '') and tsj:text() == p.separator - - if tsj:is_first() or is_sep then - s_count = 0 - elseif (not p or tsj:is_omit()) and is_on_same_line(tsj:prev(), tsj) then - s_count = get_sibling_spacing(tsj:prev(), tsj) - elseif p and (tsj:prev():is_first() or tsj:is_last()) then - s_count = p.space_in_brackets and 1 or 0 - end - - return (' '):rep(s_count) -end - ----Checking if the current node is last with `is_omtit = false` ----@param tsj TreeSJ TreeSJ instance ----@return boolean -local function is_last_no_omit(tsj) - local parent = tsj:parent() - if parent and parent:has_preset() then - local last_no_omit = parent:child(1) - for child in parent:iter_children() do - last_no_omit = not child:is_omit() and child or last_no_omit - end - return tsj == last_no_omit - end - return false -end - ----Computed indent for node when mode is 'split' ----@param tsj TreeSJ TreeSJ instance ----@return integer -function M.calc_indent(tsj) - local parent = tsj:parent() - if tsj:is_first() or tsj:is_omit() or not parent then - return 0 - end - - local pp = parent:preset('split') - local start_indent = parent._root_indent - local shiftwidth = vim.fn.shiftwidth() - local common_indent = start_indent + shiftwidth - local is_last = is_last_no_omit(tsj) and pp.last_indent == 'normal' - local is_same = pp.inner_indent == 'normal' - - return (is_last or is_same) and start_indent or common_indent -end - ----Get base nodes for first/last imitator node in non-bracket blocks ----@param tsn userdata TSNode instance ----@return userdata|nil, userdata|nil -function M.get_non_bracket_first_last(tsn) - local first = tsn:prev_sibling() or tsn:parent():prev_sibling() - local last = tsn:next_sibling() or tsn:parent():next_sibling() - return first, last -end - ----Get real end_row and end_column of node ----@param tsn userdata ----@return integer, integer -local function get_last_sym_range(tsn) - local len = tsn:child_count() - while len > 0 do - tsn = tsn:child(len - 1) - len = tsn:child_count() - end - local _, _, er, ec = tsn:range() - return er, ec -end - ----Returned range of node considering the presence of brackets ----@param tsn userdata ----@param p? table -function M.range(tsn, p) - local non_bracket_node = M.get_nested_key_value(p, 'non_bracket_node') - - -- Some parsers give incorrect range, when `tsn:range()` (e.g. `yaml`). - -- That's why using end_row and end_column of last children text. - local sr, sc = tsn:range() - local er, ec = get_last_sym_range(tsn) - - if p and non_bracket_node then - local first, last = M.get_non_bracket_first_last(tsn) - if first then - local r = { first:range() } - sr, sc, _, _ = r[3], r[4] - end - if last then - local r = { last:range() } - _, _, er, ec = _, _, r[1], r[2] - end - end - - return sr, sc, er, ec -end - -local function is_func(item) - return type(item) == 'function' -end - ----Checking if tsj meets condition in list of string and functions ----Returned 'true' if type of tsj contains among strings or some of 'function(tsj)' returned 'true' ----@param tbl table List with 'string' and 'function' ----@param tjs TreeSJ TreeSJ instance -function M.check_match(tbl, tjs) - local contains = vim.tbl_contains(tbl, tjs:type()) - local cbs = vim.tbl_filter(is_func, tbl) - - if not contains and #cbs > 0 then - return M.some(cbs, function(cb) - return cb(tjs) - end) - else - return contains - end +function M.is_table(el) + return type(el) == 'table' end -return M +return M \ No newline at end of file diff --git a/tests/README.md b/tests/README.md index e692962..ecfdc3d 100644 --- a/tests/README.md +++ b/tests/README.md @@ -2,43 +2,47 @@ 1. Add preset for new language to `/lua/treesj/langs/%{name_of_language}.lua`; 2. Update `configured_langs` list in [/lua/treesj/langs/init.lua](/lua/treesj/langs/init.lua); -3. Create new file in `/tests/sample/` with name `index.${type_of_file}` - it - will be file with examples of result `split` and `join`; -4. Duplicate file `template.lua`, remane it to `${you_language}_spec.lua` and add describe and data for tests; -5. Update list of supported languages in project [README.md](/README.md); +3. Create new file in `/tests/sample/` with name `index.${type_of_file}` – it will be a file with examples of results of running `split()` and `join()`; +4. Duplicate the folder `/tests/template/`, then rename it to `/tests/${you_language}/` and add descriptions and data for tests in `split_spec.lua` and `join_spec.lua`; +5. Update the list of supported languages in project [README.md](/README.md); ## Data for tests -**File**: `/tests/langs/${you_language}_spec.lua` +**File**: `/tests/langs/${you_language}/[split|join]_spec.lua` ```lua +-- ... local tests_data = { { path = PATH, -- path to file with examples of format (/tests/sample/index.${type_of_file}) - mode = MODE, -- mode, for which current test - lang = LANG, -- lang, for which current test - desc = 'lang "%s", node "NAME_OF_NODE", preset default', -- test describe + mode = MODE, -- mode, for every current test + lang = LANG, -- lang, for every current test + desc = 'lang "%s", node "NAME_OF_NODE", preset default', -- test description cursor = { 1, 0 }, -- start cursor position { row, column } (row is 1-based index, column is 0-based) expected = { 0, 0 }, -- range of expected result { row start (0-based), row end (0-based, but not inclusive)} result = { 0, 0 }, -- range of result running plugin where it will placed { row start (0-based), row end (0-based, but not inclusive)} - settings = {}, -- for overriding default settings (for whole plugin, no only preset. For change preset, use new _spec file) }, } + +local treesj = require('treesj') +local opts = {} -- If you need to specify options for TreeSJ other than default, put it here. +treesj.setup(opts) +-- ... ``` -### Expected result and real result +## Expected result and real result **File**: `/tests/sample/index.${type_of_file}` ```javascript // RESULT OF JOIN (node "object", preset default) -const obj = { one: 'one', two: [ 1, 2 ], three: { one: 'one', two: [ 1, 2 ] } }; +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 ] }, + one: "one", + two: [1, 2], + three: { one: "one", two: [1, 2] }, }; ``` @@ -54,7 +58,6 @@ local data_for_split = { cursor = { 2, 16 }, expected = { 3, 8 }, result = { 1, 6 }, - settings = {}, }, } @@ -67,16 +70,47 @@ local data_for_join = { cursor = { 5, 9 }, expected = { 1, 2 }, result = { 4, 5 }, - settings = {}, }, } ``` - -**NOTE**: If count of test in one file more than 16, it can be processed very slow. In this case, it will be good to place tests for split and join to separate files (e.g., like tests for javascript) - ## Execution 1. File with examples will be open with minimal vim config, cursor will be set to row and column according `data.cursor`; 2. Result from range of `data.expected` will be saved for compare; 3. TreeSJ will be start for node under cursor; 4. Result of formatting will be saved and compare with expected line by line. + +## Running tests + +Commands to running tests located at [Makefile](/Makefile) + +Before first run tests, call: + +```bash +make preinstall-ts-parsers +``` + +This will download all parsers for configured languages. + +For running all tests, call: + +```bash +make test +``` + +This will run the following tests: for every configured language and for `chold` + +For running tests for all langs, call: + +```bash +make test-langs +``` + +and for specific language, call: + +```bash +make test-langs LP=lang_name +``` + +Where LP it is a `language path`, and it should be same as you named your +folder with tests (e.g., `LP=javascript`). diff --git a/tests/chold/chold_end_spec.lua b/tests/chold/chold_end_spec.lua deleted file mode 100644 index 478683d..0000000 --- a/tests/chold/chold_end_spec.lua +++ /dev/null @@ -1,83 +0,0 @@ -local tu = require('tests.utils') -local PATH = './tests/chold/cursor.js' - -local data = { - { - path = PATH, - mode = 'split', - desc = 'cursor_behavior = "end", mode = "%s", pos inside block', - cursor = { 4, 16 }, - expected = { 8, 0 }, - result = {}, - settings = { cursor_behavior = 'end' }, - }, - { - path = PATH, - mode = 'split', - desc = 'cursor_behavior = "end", mode = "%s", pos before block', - cursor = { 4, 0 }, - expected = { 8, 0 }, - result = {}, - settings = { cursor_behavior = 'end' }, - }, - { - path = PATH, - mode = 'split', - desc = 'cursor_behavior = "end", mode = "%s", pos on first symbol of block', - cursor = { 4, 12 }, - expected = { 8, 0 }, - result = {}, - settings = { cursor_behavior = 'end' }, - }, - { - path = PATH, - mode = 'split', - desc = 'cursor_behavior = "end", mode = "%s", pos on last symbol of block', - cursor = { 4, 78 }, - expected = { 8, 0 }, - result = {}, - settings = { cursor_behavior = 'end' }, - }, - { - path = PATH, - mode = 'join', - desc = 'cursor_behavior = "end", mode = "%s", pos inside block', - cursor = { 8, 4 }, - expected = { 7, 78 }, - result = {}, - settings = { cursor_behavior = 'end' }, - }, - { - path = PATH, - mode = 'join', - desc = 'cursor_behavior = "end", mode = "%s", pos before block', - cursor = { 7, 0 }, - expected = { 7, 78 }, - result = {}, - settings = { cursor_behavior = 'end' }, - }, - { - path = PATH, - mode = 'join', - desc = 'cursor_behavior = "end", mode = "%s", pos on first symbol of block', - cursor = { 7, 12 }, - expected = { 7, 78 }, - result = {}, - settings = { cursor_behavior = 'end' }, - }, - { - path = PATH, - mode = 'join', - desc = 'cursor_behavior = "end", mode = "%s", pos on last symbol of block', - cursor = { 11, 0 }, - expected = { 7, 78 }, - result = {}, - settings = { cursor_behavior = 'end' }, - }, -} - -describe('TreeSJ CHOLD:', function() - for _, value in ipairs(data) do - tu._test_chold(value) - end -end) diff --git a/tests/chold/chold_hold_spec.lua b/tests/chold/chold_hold_spec.lua deleted file mode 100644 index 37e8a8a..0000000 --- a/tests/chold/chold_hold_spec.lua +++ /dev/null @@ -1,156 +0,0 @@ -local tu = require('tests.utils') -local PATH_JS = './tests/chold/cursor.js' -local PATH_LUA = './tests/chold/cursor.lua' - -local data = { - { - path = PATH_JS, - mode = 'split', - desc = 'cursor_behavior = "hold", mode = "%s", pos inside block', - cursor = { 4, 16 }, - expected = { 5, 4 }, - result = {}, - settings = { cursor_behavior = 'hold' }, - }, - { - path = PATH_JS, - mode = 'split', - desc = 'cursor_behavior = "hold", mode = "%s", pos before block', - cursor = { 4, 0 }, - expected = { 4, 0 }, - result = {}, - settings = { cursor_behavior = 'hold' }, - }, - { - path = PATH_JS, - mode = 'split', - desc = 'cursor_behavior = "hold", mode = "%s", pos on first sym of block', - cursor = { 4, 12 }, - expected = { 4, 12 }, - result = {}, - settings = { cursor_behavior = 'hold' }, - }, - { - path = PATH_JS, - mode = 'split', - desc = 'cursor_behavior = "hold", mode = "%s", pos on last sym of block', - cursor = { 4, 78 }, - expected = { 8, 0 }, - result = {}, - settings = { cursor_behavior = 'hold' }, - }, - { - path = PATH_JS, - mode = 'split', - desc = 'cursor_behavior = "hold", mode = "%s", pos on penultimate symbol of block', - cursor = { 4, 77 }, - expected = { 8, 0 }, - result = {}, - settings = { cursor_behavior = 'hold' }, - }, - { - path = PATH_JS, - mode = 'split', - desc = 'cursor_behavior = "hold", mode = "%s", pos after block', - cursor = { 4, 79 }, - expected = { 8, 1 }, - result = {}, - settings = { cursor_behavior = 'hold' }, - }, - { - path = PATH_LUA, - mode = 'split', - desc = 'cursor_behavior = "hold", mode = "%s", pos inside non-bracket block', - cursor = { 2, 63 }, - expected = { 4, 7 }, - result = {}, - settings = { cursor_behavior = 'hold' }, - }, - { - path = PATH_LUA, - mode = 'split', - desc = 'cursor_behavior = "hold", mode = "%s", pos on last element of non-bracket block', - cursor = { 11, 27 }, - expected = { 13, 1 }, - result = {}, - settings = { cursor_behavior = 'hold' }, - }, - { - path = PATH_JS, - mode = 'join', - desc = 'cursor_behavior = "hold", mode = "%s", pos inside block', - cursor = { 8, 4 }, - expected = { 7, 16 }, - result = {}, - settings = { cursor_behavior = 'hold' }, - }, - { - path = PATH_JS, - mode = 'join', - desc = 'cursor_behavior = "hold", mode = "%s", pos before block', - cursor = { 7, 3 }, - expected = { 7, 3 }, - result = {}, - settings = { cursor_behavior = 'hold' }, - }, - { - path = PATH_JS, - mode = 'join', - desc = 'cursor_behavior = "hold", mode = "%s", pos on first sym of block', - cursor = { 7, 12 }, - expected = { 7, 12 }, - result = {}, - settings = { cursor_behavior = 'hold' }, - }, - { - path = PATH_JS, - mode = 'join', - desc = 'cursor_behavior = "hold", mode = "%s", pos on last sym of block', - cursor = { 11, 0 }, - expected = { 7, 78 }, - result = {}, - settings = { cursor_behavior = 'hold' }, - }, - { - path = PATH_JS, - mode = 'join', - desc = 'cursor_behavior = "hold", mode = "%s", pos on penultimate symbol of block', - cursor = { 10, 38 }, - expected = { 7, 77 }, - result = {}, - settings = { cursor_behavior = 'hold' }, - }, - { - path = PATH_JS, - mode = 'join', - desc = 'cursor_behavior = "hold", mode = "%s", pos after block', - cursor = { 11, 1 }, - expected = { 7, 79 }, - result = {}, - settings = { cursor_behavior = 'hold' }, - }, - { - path = PATH_LUA, - mode = 'join', - desc = 'cursor_behavior = "hold", mode = "%s", pos inside non-bracket block', - cursor = { 7, 5 }, - expected = { 5, 61 }, - result = {}, - settings = { cursor_behavior = 'hold' }, - }, - { - path = PATH_LUA, - mode = 'join', - desc = 'cursor_behavior = "hold", mode = "%s", pos on last element of non-bracket block', - cursor = { 16, 1 }, - expected = { 14, 27 }, - result = {}, - settings = { cursor_behavior = 'hold' }, - }, -} - -describe('TreeSJ CHOLD:', function() - for _, value in ipairs(data) do - tu._test_chold(value) - end -end) diff --git a/tests/chold/chold_start_spec.lua b/tests/chold/chold_start_spec.lua deleted file mode 100644 index ae06ebc..0000000 --- a/tests/chold/chold_start_spec.lua +++ /dev/null @@ -1,83 +0,0 @@ -local tu = require('tests.utils') -local PATH = './tests/chold/cursor.js' - -local data = { - { - path = PATH, - mode = 'split', - desc = 'cursor_behavior = "start", mode = "%s", pos inside block', - cursor = { 4, 16 }, - expected = { 4, 12 }, - result = {}, - settings = { cursor_behavior = 'start' }, - }, - { - path = PATH, - mode = 'split', - desc = 'cursor_behavior = "start", mode = "%s", pos before block', - cursor = { 4, 0 }, - expected = { 4, 12 }, - result = {}, - settings = { cursor_behavior = 'start' }, - }, - { - path = PATH, - mode = 'split', - desc = 'cursor_behavior = "start", mode = "%s", pos on first sym of block', - cursor = { 4, 12 }, - expected = { 4, 12 }, - result = {}, - settings = { cursor_behavior = 'start' }, - }, - { - path = PATH, - mode = 'split', - desc = 'cursor_behavior = "start", mode = "%s", pos on last sym of block', - cursor = { 4, 78 }, - expected = { 4, 12 }, - result = {}, - settings = { cursor_behavior = 'start' }, - }, - { - path = PATH, - mode = 'join', - desc = 'cursor_behavior = "start", mode = "%s", pos inside block', - cursor = { 8, 4 }, - expected = { 7, 12 }, - result = {}, - settings = { cursor_behavior = 'start' }, - }, - { - path = PATH, - mode = 'join', - desc = 'cursor_behavior = "start", mode = "%s", pos before block', - cursor = { 7, 0 }, - expected = { 7, 12 }, - result = {}, - settings = { cursor_behavior = 'start' }, - }, - { - path = PATH, - mode = 'join', - desc = 'cursor_behavior = "start", mode = "%s", pos on first sym of block', - cursor = { 7, 12 }, - expected = { 7, 12 }, - result = {}, - settings = { cursor_behavior = 'start' }, - }, - { - path = PATH, - mode = 'join', - desc = 'cursor_behavior = "start", mode = "%s", pos on last sym of block', - cursor = { 11, 0 }, - expected = { 7, 12 }, - result = {}, - settings = { cursor_behavior = 'start' }, - }, -} - -describe('TreeSJ CHOLD:', function() - for _, value in ipairs(data) do - tu._test_chold(value) - end -end) diff --git a/tests/chold/end_join_spec.lua b/tests/chold/end_join_spec.lua new file mode 100644 index 0000000..b847192 --- /dev/null +++ b/tests/chold/end_join_spec.lua @@ -0,0 +1,48 @@ +local tu = require('tests.utils') +local PATH = './tests/chold/cursor.js' + +local data = { + { + path = PATH, + mode = 'join', + desc = 'cursor_behavior = "end", mode = "%s", pos inside block', + cursor = { 8, 4 }, + expected = { 7, 78 }, + result = {}, + }, + { + path = PATH, + mode = 'join', + desc = 'cursor_behavior = "end", mode = "%s", pos before block', + cursor = { 7, 0 }, + expected = { 7, 78 }, + result = {}, + }, + { + path = PATH, + mode = 'join', + desc = 'cursor_behavior = "end", mode = "%s", pos on first symbol of block', + cursor = { 7, 12 }, + expected = { 7, 78 }, + result = {}, + }, + { + path = PATH, + mode = 'join', + desc = 'cursor_behavior = "end", mode = "%s", pos on last symbol of block', + cursor = { 11, 0 }, + expected = { 7, 78 }, + result = {}, + }, +} + +local treesj = require('treesj') +treesj.setup({ + cursor_behavior = 'end' +}) + +describe('TreeSJ CHOLD:', function() + for _, value in ipairs(data) do + tu._test_chold(value, treesj) + end +end) diff --git a/tests/chold/end_split_spec.lua b/tests/chold/end_split_spec.lua new file mode 100644 index 0000000..b001dcf --- /dev/null +++ b/tests/chold/end_split_spec.lua @@ -0,0 +1,48 @@ +local tu = require('tests.utils') +local PATH = './tests/chold/cursor.js' + +local data = { + { + path = PATH, + mode = 'split', + desc = 'cursor_behavior = "end", mode = "%s", pos inside block', + cursor = { 4, 16 }, + expected = { 8, 0 }, + result = {}, + }, + { + path = PATH, + mode = 'split', + desc = 'cursor_behavior = "end", mode = "%s", pos before block', + cursor = { 4, 0 }, + expected = { 8, 0 }, + result = {}, + }, + { + path = PATH, + mode = 'split', + desc = 'cursor_behavior = "end", mode = "%s", pos on first symbol of block', + cursor = { 4, 12 }, + expected = { 8, 0 }, + result = {}, + }, + { + path = PATH, + mode = 'split', + desc = 'cursor_behavior = "end", mode = "%s", pos on last symbol of block', + cursor = { 4, 78 }, + expected = { 8, 0 }, + result = {}, + }, +} + +local treesj = require('treesj') +treesj.setup({ + cursor_behavior = 'end', +}) + +describe('TreeSJ CHOLD:', function() + for _, value in ipairs(data) do + tu._test_chold(value, treesj) + end +end) diff --git a/tests/chold/hold_join_spec.lua b/tests/chold/hold_join_spec.lua new file mode 100644 index 0000000..af65c85 --- /dev/null +++ b/tests/chold/hold_join_spec.lua @@ -0,0 +1,80 @@ +local tu = require('tests.utils') +local PATH_JS = './tests/chold/cursor.js' +local PATH_LUA = './tests/chold/cursor.lua' + +local data = { + { + path = PATH_JS, + mode = 'join', + desc = 'cursor_behavior = "hold", mode = "%s", pos inside block', + cursor = { 8, 4 }, + expected = { 7, 16 }, + result = {}, + }, + { + path = PATH_JS, + mode = 'join', + desc = 'cursor_behavior = "hold", mode = "%s", pos before block', + cursor = { 7, 3 }, + expected = { 7, 3 }, + result = {}, + }, + { + path = PATH_JS, + mode = 'join', + desc = 'cursor_behavior = "hold", mode = "%s", pos on first sym of block', + cursor = { 7, 12 }, + expected = { 7, 12 }, + result = {}, + }, + { + path = PATH_JS, + mode = 'join', + desc = 'cursor_behavior = "hold", mode = "%s", pos on last sym of block', + cursor = { 11, 0 }, + expected = { 7, 78 }, + result = {}, + }, + { + path = PATH_JS, + mode = 'join', + desc = 'cursor_behavior = "hold", mode = "%s", pos on penultimate symbol of block', + cursor = { 10, 38 }, + expected = { 7, 77 }, + result = {}, + }, + { + path = PATH_JS, + mode = 'join', + desc = 'cursor_behavior = "hold", mode = "%s", pos after block', + cursor = { 11, 1 }, + expected = { 7, 79 }, + result = {}, + }, + { + path = PATH_LUA, + mode = 'join', + desc = 'cursor_behavior = "hold", mode = "%s", pos inside non-bracket block', + cursor = { 7, 5 }, + expected = { 5, 61 }, + result = {}, + }, + { + path = PATH_LUA, + mode = 'join', + -- TODO: redescribe, it is not last elem, it is after + desc = 'cursor_behavior = "hold", mode = "%s", pos on last element of non-bracket block', + cursor = { 16, 1 }, + expected = { 14, 27 }, + result = {}, + }, +} + +local treesj = require('treesj') +treesj.setup({ cursor_behavior = 'hold' }) + +describe('TreeSJ CHOLD:', function() + for _, value in ipairs(data) do + tu._test_chold(value, treesj) + end +end) diff --git a/tests/chold/chold_hold_rec_split_spec.lua b/tests/chold/hold_split_recursive_spec.lua similarity index 89% rename from tests/chold/chold_hold_rec_split_spec.lua rename to tests/chold/hold_split_recursive_spec.lua index 402ef33..b41abdd 100644 --- a/tests/chold/chold_hold_rec_split_spec.lua +++ b/tests/chold/hold_split_recursive_spec.lua @@ -27,7 +27,6 @@ local data = { cursor = { 4, 77 }, expected = { 17, 0 }, result = {}, - settings = settings, }, { path = PATH, @@ -36,7 +35,6 @@ local data = { cursor = { 4, 75 }, expected = { 10, 0 }, result = {}, - settings = settings, }, { path = PATH, @@ -45,7 +43,6 @@ local data = { cursor = { 14, 25 }, expected = { 19, 3 }, result = {}, - settings = settings, }, { path = PATH, @@ -54,7 +51,6 @@ local data = { cursor = { 14, 38 }, expected = { 24, 3 }, result = {}, - settings = settings, }, { path = PATH, @@ -63,7 +59,6 @@ local data = { cursor = { 14, 51 }, expected = { 29, 3 }, result = {}, - settings = settings, }, { path = PATH, @@ -72,7 +67,6 @@ local data = { cursor = { 14, 64 }, expected = { 35, 0 }, result = {}, - settings = settings, }, { path = PATH, @@ -81,7 +75,6 @@ local data = { cursor = { 41, 33 }, expected = { 42, 9 }, result = {}, - settings = settings, }, { path = PATH, @@ -90,12 +83,14 @@ local data = { cursor = { 37, 3 }, expected = { 17, 64 }, result = {}, - settings = settings, }, } +local treesj = require('treesj') +treesj.setup(settings) + describe('TreeSJ CHOLD:', function() for _, value in ipairs(data) do - tu._test_chold(value) + tu._test_chold(value, treesj) end end) diff --git a/tests/chold/hold_split_spec.lua b/tests/chold/hold_split_spec.lua new file mode 100644 index 0000000..2f43026 --- /dev/null +++ b/tests/chold/hold_split_spec.lua @@ -0,0 +1,87 @@ +local tu = require('tests.utils') +local PATH_JS = './tests/chold/cursor.js' +local PATH_LUA = './tests/chold/cursor.lua' + +local data = { + { + path = PATH_JS, + mode = 'split', + desc = 'cursor_behavior = "hold", mode = "%s", pos inside block', + cursor = { 4, 16 }, + expected = { 5, 4 }, + result = {}, + }, + { + path = PATH_JS, + mode = 'split', + desc = 'cursor_behavior = "hold", mode = "%s", pos before block', + cursor = { 4, 0 }, + expected = { 4, 0 }, + result = {}, + }, + { + path = PATH_JS, + mode = 'split', + desc = 'cursor_behavior = "hold", mode = "%s", pos on first sym of block', + cursor = { 4, 12 }, + expected = { 4, 12 }, + result = {}, + }, + { + path = PATH_JS, + mode = 'split', + desc = 'cursor_behavior = "hold", mode = "%s", pos on last sym of block', + cursor = { 4, 78 }, + expected = { 8, 0 }, + result = {}, + }, + { + path = PATH_JS, + mode = 'split', + desc = 'cursor_behavior = "hold", mode = "%s", pos on penultimate symbol of block', + cursor = { 4, 77 }, + expected = { 8, 0 }, + result = {}, + }, + { + path = PATH_JS, + mode = 'split', + desc = 'cursor_behavior = "hold", mode = "%s", pos after block', + cursor = { 4, 79 }, + expected = { 8, 1 }, + result = {}, + }, + { + path = PATH_LUA, + mode = 'split', + desc = 'cursor_behavior = "hold", mode = "%s", pos inside non-bracket block', + cursor = { 2, 63 }, + expected = { 4, 7 }, + result = {}, + }, + { + path = PATH_LUA, + mode = 'split', + desc = 'cursor_behavior = "hold", mode = "%s", pos on last element of non-bracket block', + cursor = { 11, 27 }, + expected = { 13, 1 }, + result = {}, + }, + { + path = PATH_LUA, + mode = 'split', + desc = 'cursor_behavior = "hold", mode = "%s", pos on space before first element of non-bracket block', + cursor = { 11, 12 }, + expected = { 12, 1 }, + result = {}, + }, +} + +local treesj = require('treesj') +treesj.setup({ cursor_behavior = 'hold' }) + +describe('TreeSJ CHOLD:', function() + for _, value in ipairs(data) do + tu._test_chold(value, treesj) + end +end) diff --git a/tests/chold/start_join_spec.lua b/tests/chold/start_join_spec.lua new file mode 100644 index 0000000..5c3aede --- /dev/null +++ b/tests/chold/start_join_spec.lua @@ -0,0 +1,46 @@ +local tu = require('tests.utils') +local PATH = './tests/chold/cursor.js' + +local data = { + { + path = PATH, + mode = 'join', + desc = 'cursor_behavior = "start", mode = "%s", pos inside block', + cursor = { 8, 4 }, + expected = { 7, 12 }, + result = {}, + }, + { + path = PATH, + mode = 'join', + desc = 'cursor_behavior = "start", mode = "%s", pos before block', + cursor = { 7, 0 }, + expected = { 7, 12 }, + result = {}, + }, + { + path = PATH, + mode = 'join', + desc = 'cursor_behavior = "start", mode = "%s", pos on first sym of block', + cursor = { 7, 12 }, + expected = { 7, 12 }, + result = {}, + }, + { + path = PATH, + mode = 'join', + desc = 'cursor_behavior = "start", mode = "%s", pos on last sym of block', + cursor = { 11, 0 }, + expected = { 7, 12 }, + result = {}, + }, +} + +local treesj = require('treesj') +treesj.setup({ cursor_behavior = 'start' }) + +describe('TreeSJ CHOLD:', function() + for _, value in ipairs(data) do + tu._test_chold(value, treesj) + end +end) diff --git a/tests/chold/start_split_spec.lua b/tests/chold/start_split_spec.lua new file mode 100644 index 0000000..b589d81 --- /dev/null +++ b/tests/chold/start_split_spec.lua @@ -0,0 +1,46 @@ +local tu = require('tests.utils') +local PATH = './tests/chold/cursor.js' + +local data = { + { + path = PATH, + mode = 'split', + desc = 'cursor_behavior = "start", mode = "%s", pos inside block', + cursor = { 4, 16 }, + expected = { 4, 12 }, + result = {}, + }, + { + path = PATH, + mode = 'split', + desc = 'cursor_behavior = "start", mode = "%s", pos before block', + cursor = { 4, 0 }, + expected = { 4, 12 }, + result = {}, + }, + { + path = PATH, + mode = 'split', + desc = 'cursor_behavior = "start", mode = "%s", pos on first sym of block', + cursor = { 4, 12 }, + expected = { 4, 12 }, + result = {}, + }, + { + path = PATH, + mode = 'split', + desc = 'cursor_behavior = "start", mode = "%s", pos on last sym of block', + cursor = { 4, 78 }, + expected = { 4, 12 }, + result = {}, + }, +} + +local treesj = require('treesj') +treesj.setup({ cursor_behavior = 'start' }) + +describe('TreeSJ CHOLD:', function() + for _, value in ipairs(data) do + tu._test_chold(value, treesj) + end +end) diff --git a/tests/langs/c/join_spec.lua b/tests/langs/c/join_spec.lua new file mode 100644 index 0000000..8ed7887 --- /dev/null +++ b/tests/langs/c/join_spec.lua @@ -0,0 +1,62 @@ +local tu = require('tests.utils') + +local PATH = './tests/sample/index.c' +local LANG = 'c' + +local data_for_join = { + { + path = PATH, + mode = 'join', + lang = LANG, + desc = 'lang "%s", node "parameter_list", preset default', + cursor = { 4, 0 }, + expected = { 1, 2 }, + result = { 3, 4 }, + }, + { + path = PATH, + mode = 'join', + lang = LANG, + desc = 'lang "%s", node "argument_list", preset default', + cursor = { 13, 0 }, + expected = { 10, 11 }, + result = { 12, 13 }, + }, + { + path = PATH, + mode = 'join', + lang = LANG, + desc = 'lang "%s", node "initializer_list", preset default', + cursor = { 22, 0 }, + expected = { 19, 20 }, + result = { 21, 22 }, + }, + { + path = PATH, + mode = 'join', + lang = LANG, + desc = 'lang "%s", node "compound_statement", preset default', + cursor = { 33, 12 }, + expected = { 30, 31 }, + result = { 32, 33 }, + }, + { + path = PATH, + mode = 'join', + lang = LANG, + desc = 'lang "%s", node "enumerator_list", preset default', + cursor = { 40, 0 }, + expected = { 37, 38 }, + result = { 39, 40 }, + }, +} + +local treesj = require('treesj') +local opts = {} +treesj.setup(opts) + +describe('TreeSJ JOIN:', function() + for _, value in ipairs(data_for_join) do + tu._test_format(value, treesj) + end +end) diff --git a/tests/langs/c/split_spec.lua b/tests/langs/c/split_spec.lua new file mode 100644 index 0000000..113fe8d --- /dev/null +++ b/tests/langs/c/split_spec.lua @@ -0,0 +1,62 @@ +local tu = require('tests.utils') + +local PATH = './tests/sample/index.c' +local LANG = 'c' + +local data_for_split = { + { + path = PATH, + mode = 'split', + lang = LANG, + desc = 'lang "%s", node "parameter_list", preset default', + cursor = { 2, 0 }, + expected = { 3, 8 }, + result = { 1, 6 }, + }, + { + path = PATH, + mode = 'split', + lang = LANG, + desc = 'lang "%s", node "argument_list", preset default', + cursor = { 11, 0 }, + expected = { 12, 17 }, + result = { 10, 15 }, + }, + { + path = PATH, + mode = 'split', + lang = LANG, + desc = 'lang "%s", node "initializer_list", preset default', + cursor = { 20, 0 }, + expected = { 21, 28 }, + result = { 19, 26 }, + }, + { + path = PATH, + mode = 'split', + lang = LANG, + desc = 'lang "%s", node "compound_statement", preset default', + cursor = { 31, 12 }, + expected = { 32, 35 }, + result = { 30, 33 }, + }, + { + path = PATH, + mode = 'split', + lang = LANG, + desc = 'lang "%s", node "enumerator_list", preset default', + cursor = { 38, 0 }, + expected = { 39, 44 }, + result = { 37, 42 }, + }, +} + +local treesj = require('treesj') +local opts = {} +treesj.setup(opts) + +describe('TreeSJ SPLIT:', function() + for _, value in ipairs(data_for_split) do + tu._test_format(value, treesj) + end +end) diff --git a/tests/langs/c_spec.lua b/tests/langs/c_spec.lua deleted file mode 100644 index 9f29eee..0000000 --- a/tests/langs/c_spec.lua +++ /dev/null @@ -1,122 +0,0 @@ -local tu = require('tests.utils') - -local PATH = './tests/sample/index.c' -local LANG = 'c' - -local data_for_split = { - { - path = PATH, - mode = 'split', - lang = LANG, - desc = 'lang "%s", node "parameter_list", preset default', - cursor = { 2, 0 }, - expected = { 3, 8 }, - result = { 1, 6 }, - settings = {}, - }, - { - path = PATH, - mode = 'split', - lang = LANG, - desc = 'lang "%s", node "argument_list", preset default', - cursor = { 11, 0 }, - expected = { 12, 17 }, - result = { 10, 15 }, - settings = {}, - }, - { - path = PATH, - mode = 'split', - lang = LANG, - desc = 'lang "%s", node "initializer_list", preset default', - cursor = { 20, 0 }, - expected = { 21, 28 }, - result = { 19, 26 }, - settings = {}, - }, - { - path = PATH, - mode = 'split', - lang = LANG, - desc = 'lang "%s", node "compound_statement", preset default', - cursor = { 31, 12 }, - expected = { 32, 35 }, - result = { 30, 33 }, - settings = {}, - }, - { - path = PATH, - mode = 'split', - lang = LANG, - desc = 'lang "%s", node "enumerator_list", preset default', - cursor = { 38, 0 }, - expected = { 39, 44 }, - result = { 37, 42 }, - settings = {}, - }, -} - -local data_for_join = { - { - path = PATH, - mode = 'join', - lang = LANG, - desc = 'lang "%s", node "parameter_list", preset default', - cursor = { 4, 0 }, - expected = { 1, 2 }, - result = { 3, 4 }, - settings = {}, - }, - { - path = PATH, - mode = 'join', - lang = LANG, - desc = 'lang "%s", node "argument_list", preset default', - cursor = { 13, 0 }, - expected = { 10, 11 }, - result = { 12, 13 }, - settings = {}, - }, - { - path = PATH, - mode = 'join', - lang = LANG, - desc = 'lang "%s", node "initializer_list", preset default', - cursor = { 22, 0 }, - expected = { 19, 20 }, - result = { 21, 22 }, - settings = {}, - }, - { - path = PATH, - mode = 'join', - lang = LANG, - desc = 'lang "%s", node "compound_statement", preset default', - cursor = { 33, 12 }, - expected = { 30, 31 }, - result = { 32, 33 }, - settings = {}, - }, - { - path = PATH, - mode = 'join', - lang = LANG, - desc = 'lang "%s", node "enumerator_list", preset default', - cursor = { 40, 0 }, - expected = { 37, 38 }, - result = { 39, 40 }, - settings = {}, - }, -} - -describe('TreeSJ SPLIT:', function() - for _, value in ipairs(data_for_split) do - tu._test_format(value) - end -end) - -describe('TreeSJ JOIN:', function() - for _, value in ipairs(data_for_join) do - tu._test_format(value) - end -end) diff --git a/tests/langs/cpp/join_spec.lua b/tests/langs/cpp/join_spec.lua new file mode 100644 index 0000000..5850c1d --- /dev/null +++ b/tests/langs/cpp/join_spec.lua @@ -0,0 +1,80 @@ +local tu = require('tests.utils') + +local PATH = './tests/sample/index.cpp' +local LANG = 'cpp' + +local data_for_join = { + { + path = PATH, + mode = 'join', + lang = LANG, + desc = 'lang "%s", node "parameter_list", preset default', + cursor = { 4, 0 }, + expected = { 1, 2 }, + result = { 3, 4 }, + }, + { + path = PATH, + mode = 'join', + lang = LANG, + desc = 'lang "%s", node "argument_list", preset default', + cursor = { 13, 0 }, + expected = { 10, 11 }, + result = { 12, 13 }, + }, + { + path = PATH, + mode = 'join', + lang = LANG, + desc = 'lang "%s", node "template_parameter_list", preset default', + cursor = { 23, 0 }, + expected = { 19, 21 }, + result = { 22, 24 }, + }, + { + path = PATH, + mode = 'join', + lang = LANG, + desc = 'lang "%s", node "template_argument_list", preset default', + cursor = { 32, 0 }, + expected = { 29, 30 }, + result = { 31, 32 }, + }, + { + path = PATH, + mode = 'join', + lang = LANG, + desc = 'lang "%s", node "enumerator_list", preset default', + cursor = { 40, 0 }, + expected = { 37, 38 }, + result = { 39, 40 }, + }, + { + path = PATH, + mode = 'join', + lang = LANG, + desc = 'lang "%s", node "initializer_list", preset default', + cursor = { 49, 0 }, + expected = { 46, 47 }, + result = { 48, 49 }, + }, + { + path = PATH, + mode = 'join', + lang = LANG, + desc = 'lang "%s", node "compound_statement", preset default', + cursor = { 60, 12 }, + expected = { 57, 58 }, + result = { 59, 60 }, + }, +} + +local treesj = require('treesj') +local opts = {} +treesj.setup(opts) + +describe('TreeSJ JOIN:', function() + for _, value in ipairs(data_for_join) do + tu._test_format(value, treesj) + end +end) diff --git a/tests/langs/cpp/split_spec.lua b/tests/langs/cpp/split_spec.lua new file mode 100644 index 0000000..cfe80a2 --- /dev/null +++ b/tests/langs/cpp/split_spec.lua @@ -0,0 +1,80 @@ +local tu = require('tests.utils') + +local PATH = './tests/sample/index.cpp' +local LANG = 'cpp' + +local data_for_split = { + { + path = PATH, + mode = 'split', + lang = LANG, + desc = 'lang "%s", node "parameter_list", preset default', + cursor = { 2, 0 }, + expected = { 3, 8 }, + result = { 1, 6 }, + }, + { + path = PATH, + mode = 'split', + lang = LANG, + desc = 'lang "%s", node "argument_list", preset default', + cursor = { 11, 0 }, + expected = { 12, 17 }, + result = { 10, 15 }, + }, + { + path = PATH, + mode = 'split', + lang = LANG, + desc = 'lang "%s", node "template_parameter_list", preset default', + cursor = { 20, 0 }, + expected = { 22, 27 }, + result = { 19, 24 }, + }, + { + path = PATH, + mode = 'split', + lang = LANG, + desc = 'lang "%s", node "template_argument_list", preset default', + cursor = { 30, 0 }, + expected = { 31, 35 }, + result = { 29, 33 }, + }, + { + path = PATH, + mode = 'split', + lang = LANG, + desc = 'lang "%s", node "enumerator_list", preset default', + cursor = { 38, 0 }, + expected = { 39, 44 }, + result = { 37, 42 }, + }, + { + path = PATH, + mode = 'split', + lang = LANG, + desc = 'lang "%s", node "initializer_list", preset default', + cursor = { 47, 0 }, + expected = { 48, 55 }, + result = { 46, 53 }, + }, + { + path = PATH, + mode = 'split', + lang = LANG, + desc = 'lang "%s", node "compound_statement", preset default', + cursor = { 58, 12 }, + expected = { 59, 62 }, + result = { 57, 60 }, + }, +} + +local treesj = require('treesj') +local opts = {} +treesj.setup(opts) + +describe('TreeSJ SPLIT:', function() + for _, value in ipairs(data_for_split) do + tu._test_format(value, treesj) + end +end) diff --git a/tests/langs/cpp_spec.lua b/tests/langs/cpp_spec.lua deleted file mode 100644 index ccb4f39..0000000 --- a/tests/langs/cpp_spec.lua +++ /dev/null @@ -1,162 +0,0 @@ -local tu = require('tests.utils') - -local PATH = './tests/sample/index.cpp' -local LANG = 'cpp' - -local data_for_split = { - { - path = PATH, - mode = 'split', - lang = LANG, - desc = 'lang "%s", node "parameter_list", preset default', - cursor = { 2, 0 }, - expected = { 3, 8 }, - result = { 1, 6 }, - settings = {}, - }, - { - path = PATH, - mode = 'split', - lang = LANG, - desc = 'lang "%s", node "argument_list", preset default', - cursor = { 11, 0 }, - expected = { 12, 17 }, - result = { 10, 15 }, - settings = {}, - }, - { - path = PATH, - mode = 'split', - lang = LANG, - desc = 'lang "%s", node "template_parameter_list", preset default', - cursor = { 20, 0 }, - expected = { 22, 27 }, - result = { 19, 24 }, - settings = {}, - }, - { - path = PATH, - mode = 'split', - lang = LANG, - desc = 'lang "%s", node "template_argument_list", preset default', - cursor = { 30, 0 }, - expected = { 31, 35 }, - result = { 29, 33 }, - settings = {}, - }, - { - path = PATH, - mode = 'split', - lang = LANG, - desc = 'lang "%s", node "enumerator_list", preset default', - cursor = { 38, 0 }, - expected = { 39, 44 }, - result = { 37, 42 }, - settings = {}, - }, - { - path = PATH, - mode = 'split', - lang = LANG, - desc = 'lang "%s", node "initializer_list", preset default', - cursor = { 47, 0 }, - expected = { 48, 55 }, - result = { 46, 53 }, - settings = {}, - }, - { - path = PATH, - mode = 'split', - lang = LANG, - desc = 'lang "%s", node "compound_statement", preset default', - cursor = { 58, 12 }, - expected = { 59, 62 }, - result = { 57, 60 }, - settings = {}, - }, -} - -local data_for_join = { - { - path = PATH, - mode = 'join', - lang = LANG, - desc = 'lang "%s", node "parameter_list", preset default', - cursor = { 4, 0 }, - expected = { 1, 2 }, - result = { 3, 4 }, - settings = {}, - }, - { - path = PATH, - mode = 'join', - lang = LANG, - desc = 'lang "%s", node "argument_list", preset default', - cursor = { 13, 0 }, - expected = { 10, 11 }, - result = { 12, 13 }, - settings = {}, - }, - { - path = PATH, - mode = 'join', - lang = LANG, - desc = 'lang "%s", node "template_parameter_list", preset default', - cursor = { 23, 0 }, - expected = { 19, 21 }, - result = { 22, 24 }, - settings = {}, - }, - { - path = PATH, - mode = 'join', - lang = LANG, - desc = 'lang "%s", node "template_argument_list", preset default', - cursor = { 32, 0 }, - expected = { 29, 30 }, - result = { 31, 32 }, - settings = {}, - }, - { - path = PATH, - mode = 'join', - lang = LANG, - desc = 'lang "%s", node "enumerator_list", preset default', - cursor = { 40, 0 }, - expected = { 37, 38 }, - result = { 39, 40 }, - settings = {}, - }, - { - path = PATH, - mode = 'join', - lang = LANG, - desc = 'lang "%s", node "initializer_list", preset default', - cursor = { 49, 0 }, - expected = { 46, 47 }, - result = { 48, 49 }, - settings = {}, - }, - { - path = PATH, - mode = 'join', - lang = LANG, - desc = 'lang "%s", node "compound_statement", preset default', - cursor = { 60, 12 }, - expected = { 57, 58 }, - result = { 59, 60 }, - settings = {}, - }, -} - -describe('TreeSJ SPLIT:', function() - for _, value in ipairs(data_for_split) do - tu._test_format(value) - end -end) - -describe('TreeSJ JOIN:', function() - for _, value in ipairs(data_for_join) do - tu._test_format(value) - end -end) diff --git a/tests/langs/css/join_spec.lua b/tests/langs/css/join_spec.lua new file mode 100644 index 0000000..744c28d --- /dev/null +++ b/tests/langs/css/join_spec.lua @@ -0,0 +1,44 @@ +local tu = require('tests.utils') + +local PATH = './tests/sample/index.css' +local LANG = 'css' + +local data_for_join = { + { + path = PATH, + mode = 'join', + lang = LANG, + desc = 'lang "%s", node "block", preset default', + cursor = { 6, 9 }, + expected = { 1, 2 }, + result = { 4, 5 }, + }, + { + path = PATH, + mode = 'join', + lang = LANG, + desc = 'lang "%s", node "keyframe_block_list", preset default', + cursor = { 17, 4 }, + expected = { 12, 13 }, + result = { 15, 16 }, + }, + { + path = PATH, + mode = 'join', + lang = LANG, + desc = 'lang "%s", node "arguments", preset default', + cursor = { 33, 4 }, + expected = { 24, 25 }, + result = { 30, 31 }, + }, +} + +local treesj = require('treesj') +local opts = {} +treesj.setup(opts) + +describe('TreeSJ JOIN:', function() + for _, value in ipairs(data_for_join) do + tu._test_format(value, treesj) + end +end) diff --git a/tests/langs/css/split_spec.lua b/tests/langs/css/split_spec.lua new file mode 100644 index 0000000..92367f3 --- /dev/null +++ b/tests/langs/css/split_spec.lua @@ -0,0 +1,44 @@ +local tu = require('tests.utils') + +local PATH = './tests/sample/index.css' +local LANG = 'css' + +local data_for_split = { + { + path = PATH, + mode = 'split', + lang = LANG, + desc = 'lang "%s", node "block", preset default', + cursor = { 2, 20 }, + expected = { 4, 10 }, + result = { 1, 7 }, + }, + { + path = PATH, + mode = 'split', + lang = LANG, + desc = 'lang "%s", node "keyframe_block_list", preset default', + cursor = { 13, 25 }, + expected = { 15, 20 }, + result = { 12, 17 }, + }, + { + path = PATH, + mode = 'split', + lang = LANG, + desc = 'lang "%s", node "arguments", preset default', + cursor = { 25, 23 }, + expected = { 30, 48 }, + result = { 24, 42 }, + }, +} + +local treesj = require('treesj') +local opts = {} +treesj.setup(opts) + +describe('TreeSJ SPLIT:', function() + for _, value in ipairs(data_for_split) do + tu._test_format(value, treesj) + end +end) diff --git a/tests/langs/css_spec.lua b/tests/langs/css_spec.lua deleted file mode 100644 index 3be2dfe..0000000 --- a/tests/langs/css_spec.lua +++ /dev/null @@ -1,82 +0,0 @@ -local tu = require('tests.utils') - -local PATH = './tests/sample/index.css' -local LANG = 'css' - -local data_for_split = { - { - path = PATH, - mode = 'split', - lang = LANG, - desc = 'lang "%s", node "block", preset default', - cursor = { 2, 20 }, - expected = { 4, 10 }, - result = { 1, 7 }, - settings = {}, - }, - { - path = PATH, - mode = 'split', - lang = LANG, - desc = 'lang "%s", node "keyframe_block_list", preset default', - cursor = { 13, 25 }, - expected = { 15, 20 }, - result = { 12, 17 }, - settings = {}, - }, - { - path = PATH, - mode = 'split', - lang = LANG, - desc = 'lang "%s", node "arguments", preset default', - cursor = { 25, 23 }, - expected = { 30, 48 }, - result = { 24, 42 }, - settings = {}, - }, -} - -local data_for_join = { - { - path = PATH, - mode = 'join', - lang = LANG, - desc = 'lang "%s", node "block", preset default', - cursor = { 6, 9 }, - expected = { 1, 2 }, - result = { 4, 5 }, - settings = {}, - }, - { - path = PATH, - mode = 'join', - lang = LANG, - desc = 'lang "%s", node "keyframe_block_list", preset default', - cursor = { 17, 4 }, - expected = { 12, 13 }, - result = { 15, 16 }, - settings = {}, - }, - { - path = PATH, - mode = 'join', - lang = LANG, - desc = 'lang "%s", node "arguments", preset default', - cursor = { 33, 4 }, - expected = { 24, 25 }, - result = { 30, 31 }, - settings = {}, - }, -} - -describe('TreeSJ SPLIT:', function() - for _, value in ipairs(data_for_split) do - tu._test_format(value) - end -end) - -describe('TreeSJ JOIN:', function() - for _, value in ipairs(data_for_join) do - tu._test_format(value) - end -end) diff --git a/tests/langs/go/join_spec.lua b/tests/langs/go/join_spec.lua new file mode 100644 index 0000000..8bb2a82 --- /dev/null +++ b/tests/langs/go/join_spec.lua @@ -0,0 +1,71 @@ +local tu = require('tests.utils') + +local PATH = './tests/sample/index.go' +local LANG = 'go' + +local data_for_join = { + { + path = PATH, + mode = 'join', + lang = LANG, + desc = 'lang "%s", block "literal_value" list, preset default', + cursor = { 10, 3 }, + expected = { 3, 4 }, + result = { 6, 7 }, + }, + { + path = PATH, + mode = 'join', + lang = LANG, + desc = 'lang "%s", block "literal_value" dict, preset default', + cursor = { 19, 9 }, + expected = { 15, 16 }, + result = { 18, 19 }, + }, + { + path = PATH, + mode = 'join', + lang = LANG, + desc = 'lang "%s", block "block", preset default', + cursor = { 29, 12 }, + expected = { 24, 25 }, + result = { 27, 28 }, + }, + { + path = PATH, + mode = 'join', + lang = LANG, + desc = 'lang "%s", block "parameter_list", preset default', + cursor = { 40, 10 }, + expected = { 33, 36 }, + result = { 38, 41 }, + }, + { + path = PATH, + mode = 'join', + lang = LANG, + desc = 'lang "%s", block "argument_list", preset default', + cursor = { 54, 3 }, + expected = { 47, 48 }, + result = { 50, 51 }, + }, + { + path = PATH, + mode = 'join', + lang = LANG, + desc = 'lang "%s", block "import_spec_list to import_spec", preset default', + cursor = { 61, 8 }, + expected = { 57, 58 }, + result = { 60, 61 }, + }, +} + +local treesj = require('treesj') +local opts = {} +treesj.setup(opts) + +describe('TreeSJ JOIN:', function() + for _, value in ipairs(data_for_join) do + tu._test_format(value, treesj) + end +end) diff --git a/tests/langs/go/split_spec.lua b/tests/langs/go/split_spec.lua new file mode 100644 index 0000000..d94cdcd --- /dev/null +++ b/tests/langs/go/split_spec.lua @@ -0,0 +1,71 @@ +local tu = require('tests.utils') + +local PATH = './tests/sample/index.go' +local LANG = 'go' + +local data_for_split = { + { + path = PATH, + mode = 'split', + lang = LANG, + desc = 'lang "%s", block "literal_value" list, preset default', + cursor = { 4, 19 }, + expected = { 6, 13 }, + result = { 3, 10 }, + }, + { + path = PATH, + mode = 'split', + lang = LANG, + desc = 'lang "%s", block "literal_value" dict, preset default', + cursor = { 16, 2 }, + expected = { 18, 22 }, + result = { 15, 19 }, + }, + { + path = PATH, + mode = 'split', + lang = LANG, + desc = 'lang "%s", block "block", preset default', + cursor = { 25, 12 }, + expected = { 27, 31 }, + result = { 24, 28 }, + }, + { + path = PATH, + mode = 'split', + lang = LANG, + desc = 'lang "%s", block "parameter_list", preset default', + cursor = { 34, 27 }, + expected = { 38, 45 }, + result = { 33, 40 }, + }, + { + path = PATH, + mode = 'split', + lang = LANG, + desc = 'lang "%s", block "argument_list", preset default', + cursor = { 48, 22 }, + expected = { 50, 55 }, + result = { 47, 52 }, + }, + { + path = PATH, + mode = 'split', + lang = LANG, + desc = 'lang "%s", block "import_spec to import_spec_list", preset default', + cursor = { 58, 11 }, + expected = { 60, 63 }, + result = { 57, 60 }, + }, +} + +local treesj = require('treesj') +local opts = {} +treesj.setup(opts) + +describe('TreeSJ SPLIT:', function() + for _, value in ipairs(data_for_split) do + tu._test_format(value, treesj) + end +end) diff --git a/tests/langs/go_spec.lua b/tests/langs/go_spec.lua deleted file mode 100644 index 37858c1..0000000 --- a/tests/langs/go_spec.lua +++ /dev/null @@ -1,142 +0,0 @@ -local tu = require('tests.utils') - -local PATH = './tests/sample/index.go' -local LANG = 'go' - -local data_for_split = { - { - path = PATH, - mode = 'split', - lang = LANG, - desc = 'lang "%s", block "literal_value" list, preset default', - cursor = { 4, 19 }, - expected = { 6, 13 }, - result = { 3, 10 }, - settings = {}, - }, - { - path = PATH, - mode = 'split', - lang = LANG, - desc = 'lang "%s", block "literal_value" dict, preset default', - cursor = { 16, 2 }, - expected = { 18, 22 }, - result = { 15, 19 }, - settings = {}, - }, - { - path = PATH, - mode = 'split', - lang = LANG, - desc = 'lang "%s", block "block", preset default', - cursor = { 25, 12 }, - expected = { 27, 31 }, - result = { 24, 28 }, - settings = {}, - }, - { - path = PATH, - mode = 'split', - lang = LANG, - desc = 'lang "%s", block "parameter_list", preset default', - cursor = { 34, 27 }, - expected = { 38, 45 }, - result = { 33, 40 }, - settings = {}, - }, - { - path = PATH, - mode = 'split', - lang = LANG, - desc = 'lang "%s", block "argument_list", preset default', - cursor = { 48, 22 }, - expected = { 50, 55 }, - result = { 47, 52 }, - settings = {}, - }, - { - path = PATH, - mode = 'split', - lang = LANG, - desc = 'lang "%s", block "import_spec to import_spec_list", preset default', - cursor = { 58, 11 }, - expected = { 60, 63 }, - result = { 57, 60 }, - settings = {}, - }, -} - -local data_for_join = { - { - path = PATH, - mode = 'join', - lang = LANG, - desc = 'lang "%s", block "literal_value" list, preset default', - cursor = { 10, 3 }, - expected = { 3, 4 }, - result = { 6, 7 }, - settings = {}, - }, - { - path = PATH, - mode = 'join', - lang = LANG, - desc = 'lang "%s", block "literal_value" dict, preset default', - cursor = { 19, 9 }, - expected = { 15, 16 }, - result = { 18, 19 }, - settings = {}, - }, - { - path = PATH, - mode = 'join', - lang = LANG, - desc = 'lang "%s", block "block", preset default', - cursor = { 29, 12 }, - expected = { 24, 25 }, - result = { 27, 28 }, - settings = {}, - }, - { - path = PATH, - mode = 'join', - lang = LANG, - desc = 'lang "%s", block "parameter_list", preset default', - cursor = { 40, 10 }, - expected = { 33, 36 }, - result = { 38, 41 }, - settings = {}, - }, - { - path = PATH, - mode = 'join', - lang = LANG, - desc = 'lang "%s", block "argument_list", preset default', - cursor = { 54, 3 }, - expected = { 47, 48 }, - result = { 50, 51 }, - settings = {}, - }, - { - path = PATH, - mode = 'join', - lang = LANG, - desc = 'lang "%s", block "import_spec_list to import_spec", preset default', - cursor = { 61, 8 }, - expected = { 57, 58 }, - result = { 60, 61 }, - settings = {}, - }, -} - -describe('TreeSJ SPLIT:', function() - for _, value in ipairs(data_for_split) do - tu._test_format(value) - end -end) - -describe('TreeSJ JOIN:', function() - for _, value in ipairs(data_for_join) do - tu._test_format(value) - end -end) diff --git a/tests/langs/html/html_last_indent_spec.lua b/tests/langs/html/html_last_indent_spec.lua index 58aed00..1fbb11b 100644 --- a/tests/langs/html/html_last_indent_spec.lua +++ b/tests/langs/html/html_last_indent_spec.lua @@ -3,25 +3,6 @@ local tu = require('tests.utils') local PATH = './tests/sample/index.html' local LANG = 'html' -local settings = { - langs = { - html = { - start_tag = { - split = { - omit = { 'tag_name', '>' }, - last_indent = 'inner', - }, - }, - self_closing_tag = { - split = { - omit = { 'tag_name', '/>' }, - last_indent = 'inner', - }, - }, - }, - }, -} - local data_for_split = { { path = PATH, @@ -31,7 +12,6 @@ local data_for_split = { cursor = { 78, 10 }, expected = { 79, 82 }, result = { 77, 80 }, - settings = settings, }, { path = PATH, @@ -41,7 +21,6 @@ local data_for_split = { cursor = { 85, 29 }, expected = { 86, 89 }, result = { 84, 87 }, - settings = settings, }, } @@ -54,7 +33,6 @@ local data_for_join = { cursor = { 81, 19 }, expected = { 77, 78 }, result = { 79, 80 }, - settings = settings, }, { path = PATH, @@ -64,18 +42,38 @@ local data_for_join = { cursor = { 88, 19 }, expected = { 84, 85 }, result = { 86, 87 }, - settings = settings, }, } +local treesj = require('treesj') +local opts = { + langs = { + html = { + start_tag = { + split = { + omit = { 'tag_name', '>' }, + last_indent = 'inner', + }, + }, + self_closing_tag = { + split = { + omit = { 'tag_name', '/>' }, + last_indent = 'inner', + }, + }, + }, + }, +} +treesj.setup(opts) + describe('TreeSJ SPLIT:', function() for _, value in ipairs(data_for_split) do - tu._test_format(value) + tu._test_format(value, treesj) end end) describe('TreeSJ JOIN:', function() for _, value in ipairs(data_for_join) do - tu._test_format(value) + tu._test_format(value, treesj) end end) diff --git a/tests/langs/html/html_no_empty_spec.lua b/tests/langs/html/html_no_empty_spec.lua index 5d6ffd1..e591167 100644 --- a/tests/langs/html/html_no_empty_spec.lua +++ b/tests/langs/html/html_no_empty_spec.lua @@ -3,28 +3,6 @@ local tu = require('tests.utils') local PATH = './tests/sample/index.html' local LANG = 'html' -local settings = { - langs = { - html = { - element = { - both = { - format_empty_node = false, - }, - }, - start_tag = { - both = { - format_empty_node = false, - }, - }, - self_closing_tag = { - both = { - format_empty_node = false, - }, - }, - }, - }, -} - local data_for_split = { { path = PATH, @@ -34,7 +12,6 @@ local data_for_split = { cursor = { 57, 15 }, expected = { 56, 57 }, result = { 56, 57 }, - settings = settings, }, { path = PATH, @@ -44,7 +21,6 @@ local data_for_split = { cursor = { 64, 6 }, expected = { 63, 64 }, result = { 63, 64 }, - settings = settings, }, { path = PATH, @@ -54,7 +30,6 @@ local data_for_split = { cursor = { 71, 9 }, expected = { 70, 71 }, result = { 70, 71 }, - settings = settings, }, } @@ -67,7 +42,6 @@ local data_for_join = { cursor = { 61, 8 }, expected = { 59, 61 }, result = { 59, 61 }, - settings = settings, }, { path = PATH, @@ -77,7 +51,6 @@ local data_for_join = { cursor = { 68, 7 }, expected = { 66, 68 }, result = { 66, 68 }, - settings = settings, }, { path = PATH, @@ -87,18 +60,41 @@ local data_for_join = { cursor = { 74, 6 }, expected = { 73, 75 }, result = { 73, 75 }, - settings = settings, }, } +local treesj = require('treesj') +local opts = { + langs = { + html = { + element = { + both = { + format_empty_node = false, + }, + }, + start_tag = { + both = { + format_empty_node = false, + }, + }, + self_closing_tag = { + both = { + format_empty_node = false, + }, + }, + }, + }, +} +treesj.setup(opts) + describe('TreeSJ SPLIT:', function() for _, value in ipairs(data_for_split) do - tu._test_format(value) + tu._test_format(value, treesj) end end) describe('TreeSJ JOIN:', function() for _, value in ipairs(data_for_join) do - tu._test_format(value) + tu._test_format(value, treesj) end end) diff --git a/tests/langs/html/html_spec.lua b/tests/langs/html/html_spec.lua index 3c7a6cb..fc67156 100644 --- a/tests/langs/html/html_spec.lua +++ b/tests/langs/html/html_spec.lua @@ -12,7 +12,6 @@ local data_for_split = { cursor = { 13, 20 }, expected = { 14, 18 }, result = { 12, 16 }, - settings = {}, }, { path = PATH, @@ -22,7 +21,6 @@ local data_for_split = { cursor = { 21, 20 }, expected = { 22, 26 }, result = { 20, 24 }, - settings = {}, }, { path = PATH, @@ -32,7 +30,6 @@ local data_for_split = { cursor = { 29, 35 }, expected = { 30, 33 }, result = { 28, 31 }, - settings = {}, }, { path = PATH, @@ -42,7 +39,6 @@ local data_for_split = { cursor = { 36, 15 }, expected = { 38, 40 }, result = { 35, 37 }, - settings = {}, }, { path = PATH, @@ -52,7 +48,6 @@ local data_for_split = { cursor = { 43, 6 }, expected = { 45, 47 }, result = { 42, 44 }, - settings = {}, }, { path = PATH, @@ -62,7 +57,6 @@ local data_for_split = { cursor = { 50, 6 }, expected = { 52, 54 }, result = { 49, 51 }, - settings = {}, }, } @@ -75,7 +69,6 @@ local data_for_join = { cursor = { 17, 12 }, expected = { 12, 13 }, result = { 14, 15 }, - settings = {}, }, { path = PATH, @@ -85,7 +78,6 @@ local data_for_join = { cursor = { 25, 11 }, expected = { 20, 21 }, result = { 22, 23 }, - settings = {}, }, { path = PATH, @@ -95,7 +87,6 @@ local data_for_join = { cursor = { 32, 8 }, expected = { 28, 29 }, result = { 30, 31 }, - settings = {}, }, { path = PATH, @@ -105,7 +96,6 @@ local data_for_join = { cursor = { 40, 9 }, expected = { 35, 36 }, result = { 38, 39 }, - settings = {}, }, { path = PATH, @@ -115,7 +105,6 @@ local data_for_join = { cursor = { 46, 5 }, expected = { 42, 43 }, result = { 45, 46 }, - settings = {}, }, { path = PATH, @@ -125,18 +114,21 @@ local data_for_join = { cursor = { 53, 6 }, expected = { 49, 50 }, result = { 52, 53 }, - settings = {}, }, } +local treesj = require('treesj') +local opts = {} +treesj.setup(opts) + describe('TreeSJ SPLIT:', function() for _, value in ipairs(data_for_split) do - tu._test_format(value) + tu._test_format(value, treesj) end end) describe('TreeSJ JOIN:', function() for _, value in ipairs(data_for_join) do - tu._test_format(value) + tu._test_format(value, treesj) end end) diff --git a/tests/langs/java/join_spec.lua b/tests/langs/java/join_spec.lua new file mode 100644 index 0000000..d9f4ba3 --- /dev/null +++ b/tests/langs/java/join_spec.lua @@ -0,0 +1,80 @@ +local tu = require('tests.utils') + +local PATH = './tests/sample/index.java' +local LANG = 'java' + +local data_for_join = { + { + path = PATH, + mode = 'join', + lang = LANG, + desc = 'lang "%s", node "array_initializer", preset default', + cursor = { 10, 5 }, + expected = { 5, 6 }, + result = { 8, 9 }, + }, + { + path = PATH, + mode = 'join', + lang = LANG, + desc = 'lang "%s", node "formal_parameters", preset default', + cursor = { 24, 9 }, + expected = { 15, 19 }, + result = { 21, 25 }, + }, + { + path = PATH, + mode = 'join', + lang = LANG, + desc = 'lang "%s", node "constructor_body", preset default', + cursor = { 37, 25 }, + expected = { 32, 33 }, + result = { 35, 36 }, + }, + { + path = PATH, + mode = 'join', + lang = LANG, + desc = 'lang "%s", node "block", preset default', + cursor = { 46, 7 }, + expected = { 41, 42 }, + result = { 44, 45 }, + }, + { + path = PATH, + mode = 'join', + lang = LANG, + desc = 'lang "%s", node "argument_list", preset default', + cursor = { 55, 18 }, + expected = { 50, 51 }, + result = { 53, 54 }, + }, + { + path = PATH, + mode = 'join', + lang = LANG, + desc = 'lang "%s", node "annotation_argument_list", preset default', + cursor = { 67, 14 }, + expected = { 61, 63 }, + result = { 65, 67 }, + }, + { + path = PATH, + mode = 'join', + lang = LANG, + desc = 'lang "%s", node "enum_body", preset default', + cursor = { 78, 6 }, + expected = { 72, 73 }, + result = { 75, 76 }, + }, +} + +local treesj = require('treesj') +local opts = {} +treesj.setup(opts) + +describe('TreeSJ JOIN:', function() + for _, value in ipairs(data_for_join) do + tu._test_format(value, treesj) + end +end) diff --git a/tests/langs/java/split_spec.lua b/tests/langs/java/split_spec.lua new file mode 100644 index 0000000..28103d3 --- /dev/null +++ b/tests/langs/java/split_spec.lua @@ -0,0 +1,80 @@ +local tu = require('tests.utils') + +local PATH = './tests/sample/index.java' +local LANG = 'java' + +local data_for_split = { + { + path = PATH, + mode = 'split', + lang = LANG, + desc = 'lang "%s", node "array_initializer", preset default', + cursor = { 6, 16 }, + expected = { 8, 13 }, + result = { 5, 10 }, + }, + { + path = PATH, + mode = 'split', + lang = LANG, + desc = 'lang "%s", node "formal_parameters", preset default', + cursor = { 16, 33 }, + expected = { 21, 30 }, + result = { 15, 24 }, + }, + { + path = PATH, + mode = 'split', + lang = LANG, + desc = 'lang "%s", node "constructor_body", preset default', + cursor = { 33, 85 }, + expected = { 35, 39 }, + result = { 32, 36 }, + }, + { + path = PATH, + mode = 'split', + lang = LANG, + desc = 'lang "%s", node "block", preset default', + cursor = { 42, 7 }, + expected = { 44, 47 }, + result = { 41, 44 }, + }, + { + path = PATH, + mode = 'split', + lang = LANG, + desc = 'lang "%s", node "argument_list", preset default', + cursor = { 51, 30 }, + expected = { 53, 57 }, + result = { 50, 54 }, + }, + { + path = PATH, + mode = 'split', + lang = LANG, + desc = 'lang "%s", node "annotation_argument_list", preset default', + cursor = { 62, 24 }, + expected = { 65, 70 }, + result = { 61, 66 }, + }, + { + path = PATH, + mode = 'split', + lang = LANG, + desc = 'lang "%s", node "enum_body", preset default', + cursor = { 73, 26 }, + expected = { 75, 80 }, + result = { 72, 77 }, + }, +} + +local treesj = require('treesj') +local opts = {} +treesj.setup(opts) + +describe('TreeSJ SPLIT:', function() + for _, value in ipairs(data_for_split) do + tu._test_format(value, treesj) + end +end) diff --git a/tests/langs/java_spec.lua b/tests/langs/java_spec.lua deleted file mode 100644 index 7bb320f..0000000 --- a/tests/langs/java_spec.lua +++ /dev/null @@ -1,162 +0,0 @@ -local tu = require('tests.utils') - -local PATH = './tests/sample/index.java' -local LANG = 'java' - -local data_for_split = { - { - path = PATH, - mode = 'split', - lang = LANG, - desc = 'lang "%s", node "array_initializer", preset default', - cursor = { 6, 16 }, - expected = { 8, 13 }, - result = { 5, 10 }, - settings = {}, - }, - { - path = PATH, - mode = 'split', - lang = LANG, - desc = 'lang "%s", node "formal_parameters", preset default', - cursor = { 16, 33 }, - expected = { 21, 30 }, - result = { 15, 24 }, - settings = {}, - }, - { - path = PATH, - mode = 'split', - lang = LANG, - desc = 'lang "%s", node "constructor_body", preset default', - cursor = { 33, 85 }, - expected = { 35, 39 }, - result = { 32, 36 }, - settings = {}, - }, - { - path = PATH, - mode = 'split', - lang = LANG, - desc = 'lang "%s", node "block", preset default', - cursor = { 42, 7 }, - expected = { 44, 47 }, - result = { 41, 44 }, - settings = {}, - }, - { - path = PATH, - mode = 'split', - lang = LANG, - desc = 'lang "%s", node "argument_list", preset default', - cursor = { 51, 30 }, - expected = { 53, 57 }, - result = { 50, 54 }, - settings = {}, - }, - { - path = PATH, - mode = 'split', - lang = LANG, - desc = 'lang "%s", node "annotation_argument_list", preset default', - cursor = { 62, 24 }, - expected = { 65, 70 }, - result = { 61, 66 }, - settings = {}, - }, - { - path = PATH, - mode = 'split', - lang = LANG, - desc = 'lang "%s", node "enum_body", preset default', - cursor = { 73, 26 }, - expected = { 75, 80 }, - result = { 72, 77 }, - settings = {}, - }, -} - -local data_for_join = { - { - path = PATH, - mode = 'join', - lang = LANG, - desc = 'lang "%s", node "array_initializer", preset default', - cursor = { 10, 5 }, - expected = { 5, 6 }, - result = { 8, 9 }, - settings = {}, - }, - { - path = PATH, - mode = 'join', - lang = LANG, - desc = 'lang "%s", node "formal_parameters", preset default', - cursor = { 24, 9 }, - expected = { 15, 19 }, - result = { 21, 25 }, - settings = {}, - }, - { - path = PATH, - mode = 'join', - lang = LANG, - desc = 'lang "%s", node "constructor_body", preset default', - cursor = { 37, 25 }, - expected = { 32, 33 }, - result = { 35, 36 }, - settings = {}, - }, - { - path = PATH, - mode = 'join', - lang = LANG, - desc = 'lang "%s", node "block", preset default', - cursor = { 46, 7 }, - expected = { 41, 42 }, - result = { 44, 45 }, - settings = {}, - }, - { - path = PATH, - mode = 'join', - lang = LANG, - desc = 'lang "%s", node "argument_list", preset default', - cursor = { 55, 18 }, - expected = { 50, 51 }, - result = { 53, 54 }, - settings = {}, - }, - { - path = PATH, - mode = 'join', - lang = LANG, - desc = 'lang "%s", node "annotation_argument_list", preset default', - cursor = { 67, 14 }, - expected = { 61, 63 }, - result = { 65, 67 }, - settings = {}, - }, - { - path = PATH, - mode = 'join', - lang = LANG, - desc = 'lang "%s", node "enum_body", preset default', - cursor = { 78, 6 }, - expected = { 72, 73 }, - result = { 75, 76 }, - settings = {}, - }, -} - -describe('TreeSJ SPLIT:', function() - for _, value in ipairs(data_for_split) do - tu._test_format(value) - end -end) - -describe('TreeSJ JOIN:', function() - for _, value in ipairs(data_for_join) do - tu._test_format(value) - end -end) diff --git a/tests/langs/javascript/javascript_join_spec.lua b/tests/langs/javascript/join_spec.lua similarity index 61% rename from tests/langs/javascript/javascript_join_spec.lua rename to tests/langs/javascript/join_spec.lua index 14fdcd5..5754697 100644 --- a/tests/langs/javascript/javascript_join_spec.lua +++ b/tests/langs/javascript/join_spec.lua @@ -12,7 +12,6 @@ local data_for_join = { cursor = { 8, 4 }, expected = { 3, 4 }, result = { 6, 7 }, - settings = {}, }, { path = PATH, @@ -22,7 +21,6 @@ local data_for_join = { cursor = { 18, 3 }, expected = { 13, 14 }, result = { 16, 17 }, - settings = {}, }, { path = PATH, @@ -32,7 +30,6 @@ local data_for_join = { cursor = { 32, 2 }, expected = { 25, 26 }, result = { 30, 31 }, - settings = {}, }, { path = PATH, @@ -42,7 +39,6 @@ local data_for_join = { cursor = { 45, 3 }, expected = { 39, 40 }, result = { 42, 43 }, - settings = {}, }, { path = PATH, @@ -52,7 +48,6 @@ local data_for_join = { cursor = { 54, 5 }, expected = { 49, 50 }, result = { 52, 53 }, - settings = {}, }, { path = PATH, @@ -62,7 +57,6 @@ local data_for_join = { cursor = { 64, 7 }, expected = { 60, 61 }, result = { 63, 64 }, - settings = {}, }, { path = PATH, @@ -72,7 +66,6 @@ local data_for_join = { cursor = { 73, 6 }, expected = { 69, 70 }, result = { 72, 73 }, - settings = {}, }, { path = PATH, @@ -82,7 +75,6 @@ local data_for_join = { cursor = { 82, 0 }, expected = { 78, 79 }, result = { 81, 82 }, - settings = {}, }, { path = PATH, @@ -92,7 +84,6 @@ local data_for_join = { cursor = { 93, 3 }, expected = { 88, 89 }, result = { 91, 92 }, - settings = {}, }, { path = PATH, @@ -102,7 +93,6 @@ local data_for_join = { cursor = { 103, 12 }, expected = { 98, 99 }, result = { 101, 102 }, - settings = {}, }, { path = PATH, @@ -112,12 +102,69 @@ local data_for_join = { cursor = { 112, 1 }, expected = { 108, 109 }, result = { 111, 112 }, - settings = {}, + }, + { + path = PATH, + mode = 'join', + lang = LANG, + desc = 'lang "%s", field "body" in "arrow_function" with "call_expression", preset default', + cursor = { 123, 19 }, + expected = { 118, 119 }, + result = { 121, 122 }, + }, + { + path = PATH, + mode = 'join', + lang = LANG, + desc = 'lang "%s", field "body" in "arrow_function" with "identifier", preset default', + cursor = { 131, 13 }, + expected = { 126, 127 }, + result = { 129, 130 }, + }, + { + path = PATH, + mode = 'join', + lang = LANG, + desc = 'lang "%s", field "body" in "arrow_function" with "parenthesized_expression", preset default', + cursor = { 138, 26 }, + expected = { 134, 135 }, + result = { 137, 138 }, + }, + { + path = PATH, + mode = 'join', + lang = LANG, + desc = 'lang "%s", field "body" in "arrow_function" with "array", preset default', + cursor = { 148, 0 }, + expected = { 142, 143 }, + result = { 145, 146 }, + }, + { + path = PATH, + mode = 'join', + lang = LANG, + desc = 'lang "%s", field "body" in "arrow_function" with "parenthesized_expression" with "sequence_expression", preset default', + cursor = { 155, 12 }, + expected = { 150, 151 }, + result = { 153, 154 }, + }, + { + path = PATH, + mode = 'join', + lang = LANG, + desc = 'lang "%s", field "body" in "arrow_function" with "statement_block" with >1 named child, preset default', + cursor = { 164, 15 }, + expected = { 158, 159 }, + result = { 161, 162 }, }, } +local treesj = require('treesj') +local opts = {} +treesj.setup(opts) + describe('TreeSJ JOIN:', function() for _, value in ipairs(data_for_join) do - tu._test_format(value) + tu._test_format(value, treesj) end end) diff --git a/tests/langs/javascript/jsx_last_indent_spec.lua b/tests/langs/javascript/jsx_last_indent_spec.lua index 93758d5..2337c88 100644 --- a/tests/langs/javascript/jsx_last_indent_spec.lua +++ b/tests/langs/javascript/jsx_last_indent_spec.lua @@ -25,7 +25,6 @@ local data_for_split = { cursor = { 48, 32 }, expected = { 49, 54 }, result = { 47, 52 }, - settings = settings, }, } @@ -38,18 +37,32 @@ local data_for_join = { cursor = { 52, 25 }, expected = { 47, 48 }, result = { 49, 50 }, - settings = settings, }, } +local treesj = require('treesj') +local opts = { + langs = { + javascript = { + jsx_self_closing_element = { + split = { + omit = { 'identifier', 'nested_identifier', '/', '>' }, + last_indent = 'inner', + }, + }, + }, + }, +} +treesj.setup(opts) + describe('TreeSJ SPLIT:', function() for _, value in ipairs(data_for_split) do - tu._test_format(value) + tu._test_format(value, treesj) end end) describe('TreeSJ JOIN:', function() for _, value in ipairs(data_for_join) do - tu._test_format(value) + tu._test_format(value, treesj) end end) diff --git a/tests/langs/javascript/jsx_spec.lua b/tests/langs/javascript/jsx_spec.lua index 7c30075..4464a43 100644 --- a/tests/langs/javascript/jsx_spec.lua +++ b/tests/langs/javascript/jsx_spec.lua @@ -12,7 +12,6 @@ local data_for_split = { cursor = { 3, 19 }, expected = { 4, 12 }, result = { 2, 10 }, - settings = {}, }, { path = PATH, @@ -22,7 +21,6 @@ local data_for_split = { cursor = { 14, 17 }, expected = { 15, 20 }, result = { 13, 18 }, - settings = {}, }, { path = PATH, @@ -32,7 +30,6 @@ local data_for_split = { cursor = { 24, 20 }, expected = { 25, 31 }, result = { 23, 29 }, - settings = {}, }, { path = PATH, @@ -42,7 +39,6 @@ local data_for_split = { cursor = { 33, 16 }, expected = { 34, 40 }, result = { 32, 38 }, - settings = {}, }, { path = PATH, @@ -52,7 +48,6 @@ local data_for_split = { cursor = { 42, 83 }, expected = { 43, 46 }, result = { 41, 44 }, - settings = {}, }, { path = PATH, @@ -62,7 +57,6 @@ local data_for_split = { cursor = { 63, 11 }, expected = { 69, 73 }, result = { 62, 66 }, - settings = {}, }, } @@ -75,7 +69,6 @@ local data_for_join = { cursor = { 6, 8 }, expected = { 2, 3 }, result = { 4, 5 }, - settings = {}, }, { path = PATH, @@ -85,7 +78,6 @@ local data_for_join = { cursor = { 17, 4 }, expected = { 13, 14 }, result = { 15, 16 }, - settings = {}, }, { path = PATH, @@ -95,7 +87,6 @@ local data_for_join = { cursor = { 27, 12 }, expected = { 23, 24 }, result = { 25, 26 }, - settings = {}, }, { path = PATH, @@ -105,7 +96,6 @@ local data_for_join = { cursor = { 36, 14 }, expected = { 32, 33 }, result = { 34, 35 }, - settings = {}, }, { path = PATH, @@ -115,7 +105,6 @@ local data_for_join = { cursor = { 45, 9 }, expected = { 41, 42 }, result = { 43, 44 }, - settings = {}, }, { path = PATH, @@ -125,18 +114,21 @@ local data_for_join = { cursor = { 70, 11 }, expected = { 62, 63 }, result = { 69, 70 }, - settings = {}, }, } +local treesj = require('treesj') +local opts = {} +treesj.setup(opts) + describe('TreeSJ SPLIT:', function() for _, value in ipairs(data_for_split) do - tu._test_format(value) + tu._test_format(value, treesj) end end) describe('TreeSJ JOIN:', function() for _, value in ipairs(data_for_join) do - tu._test_format(value) + tu._test_format(value, treesj) end end) diff --git a/tests/langs/javascript/javascript_rec_spec.lua b/tests/langs/javascript/split_recursive_spec.lua similarity index 68% rename from tests/langs/javascript/javascript_rec_spec.lua rename to tests/langs/javascript/split_recursive_spec.lua index 3666919..778ce93 100644 --- a/tests/langs/javascript/javascript_rec_spec.lua +++ b/tests/langs/javascript/split_recursive_spec.lua @@ -3,30 +3,6 @@ local tu = require('tests.utils') local PATH = './tests/sample/index_recursive.js' local LANG = 'javascript' -local recursive = { - split = { - recursive = true, - recursive_ignore = { - 'arguments', - 'parameters', - 'formal_parameters', - }, - }, -} - -local settings = { - langs = { - javascript = { - object = { - split = recursive.split, - }, - statement_block = { - split = recursive.split, - }, - }, - }, -} - local data_for_split = { { path = PATH, @@ -36,7 +12,6 @@ local data_for_split = { cursor = { 2, 17 }, expected = { 4, 16 }, result = { 1, 13 }, - settings = settings, }, { path = PATH, @@ -46,7 +21,6 @@ local data_for_split = { cursor = { 19, 15 }, expected = { 21, 30 }, result = { 18, 27 }, - settings = settings, }, { path = PATH, @@ -56,7 +30,6 @@ local data_for_split = { cursor = { 33, 1 }, expected = { 35, 40 }, result = { 32, 37 }, - settings = settings, }, { path = PATH, @@ -66,12 +39,59 @@ local data_for_split = { cursor = { 43, 25 }, expected = { 45, 48 }, result = { 42, 45 }, - settings = settings, + }, + { + path = PATH, + mode = 'split', + lang = LANG, + desc = 'lang "%s", field "body" in "arrow_function" with "parenthesized_expression", preset with recursive = true', + cursor = { 51, 23 }, + expected = { 53, 58 }, + result = { 50, 55 }, + }, + { + path = PATH, + mode = 'split', + lang = LANG, + desc = 'lang "%s", field "body" in "arrow_function" with "array", preset with recursive = true', + cursor = { 61, 23 }, + expected = { 63, 70 }, + result = { 60, 67 }, + }, +} + +local treesj = require('treesj') + +local recursive = { + split = { + recursive = true, + recursive_ignore = { + 'arguments', + 'parameters', + 'formal_parameters', + }, + }, +} + +local opts = { + langs = { + javascript = { + object = { + split = recursive.split, + }, + statement_block = { + split = recursive.split, + }, + body = { + split = recursive.split, + }, + }, }, } +treesj.setup(opts) describe('TreeSJ SPLIT:', function() for _, value in ipairs(data_for_split) do - tu._test_format(value) + tu._test_format(value, treesj) end end) diff --git a/tests/langs/javascript/javascript_split_spec.lua b/tests/langs/javascript/split_spec.lua similarity index 57% rename from tests/langs/javascript/javascript_split_spec.lua rename to tests/langs/javascript/split_spec.lua index 75eeb35..dbbafae 100644 --- a/tests/langs/javascript/javascript_split_spec.lua +++ b/tests/langs/javascript/split_spec.lua @@ -12,7 +12,6 @@ local data_for_split = { cursor = { 4, 16 }, expected = { 6, 11 }, result = { 3, 8 }, - settings = {}, }, { path = PATH, @@ -22,7 +21,6 @@ local data_for_split = { cursor = { 14, 17 }, expected = { 16, 22 }, result = { 13, 19 }, - settings = {}, }, { path = PATH, @@ -32,7 +30,6 @@ local data_for_split = { cursor = { 26, 15 }, expected = { 30, 35 }, result = { 25, 30 }, - settings = {}, }, { path = PATH, @@ -42,7 +39,6 @@ local data_for_split = { cursor = { 40, 8 }, expected = { 42, 47 }, result = { 39, 44 }, - settings = {}, }, { path = PATH, @@ -52,7 +48,6 @@ local data_for_split = { cursor = { 50, 24 }, expected = { 52, 58 }, result = { 49, 55 }, - settings = {}, }, { path = PATH, @@ -62,7 +57,6 @@ local data_for_split = { cursor = { 61, 7 }, expected = { 63, 67 }, result = { 60, 64 }, - settings = {}, }, { path = PATH, @@ -72,7 +66,6 @@ local data_for_split = { cursor = { 70, 6 }, expected = { 72, 76 }, result = { 69, 73 }, - settings = {}, }, { path = PATH, @@ -82,7 +75,6 @@ local data_for_split = { cursor = { 79, 0 }, expected = { 81, 86 }, result = { 78, 83 }, - settings = {}, }, { path = PATH, @@ -92,7 +84,6 @@ local data_for_split = { cursor = { 89, 12 }, expected = { 91, 96 }, result = { 88, 93 }, - settings = {}, }, { path = PATH, @@ -102,7 +93,6 @@ local data_for_split = { cursor = { 99, 12 }, expected = { 101, 106 }, result = { 98, 103 }, - settings = {}, }, { path = PATH, @@ -112,12 +102,78 @@ local data_for_split = { cursor = { 109, 1 }, expected = { 111, 116 }, result = { 108, 113 }, - settings = {}, + }, + { + path = PATH, + mode = 'split', + lang = LANG, + desc = 'lang "%s", field "body" in "arrow_function" with "call_expression", preset default', + cursor = { 119, 26 }, + expected = { 121, 124 }, + result = { 118, 121 }, + }, + { + path = PATH, + mode = 'split', + lang = LANG, + desc = 'lang "%s", field "body" in "arrow_function" with "identifier", preset default', + cursor = { 127, 28 }, + expected = { 129, 132 }, + result = { 126, 129 }, + }, + { + path = PATH, + mode = 'split', + lang = LANG, + desc = 'lang "%s", field "body" in "arrow_function" with "parenthesized_expression", preset default', + cursor = { 135, 26 }, + expected = { 137, 140 }, + result = { 134, 137 }, + }, + { + path = PATH, + mode = 'split', + lang = LANG, + desc = 'lang "%s", field "body" in "arrow_function" with "object" in "parenthesized_expression", preset default', + cursor = { 135, 26 }, + expected = { 137, 140 }, + result = { 134, 137 }, + }, + { + path = PATH, + mode = 'split', + lang = LANG, + desc = 'lang "%s", field "body" in "arrow_function" with "array", preset default', + cursor = { 143, 23 }, + expected = { 145, 148 }, + result = { 142, 145 }, + }, + { + path = PATH, + mode = 'split', + lang = LANG, + desc = 'lang "%s", field "body" in "arrow_function" with "parenthesized_expression" with "sequence_expression", preset default', + cursor = { 151, 29 }, + expected = { 153, 156 }, + result = { 150, 153 }, + }, + { + path = PATH, + mode = 'split', + lang = LANG, + desc = 'lang "%s", field "body" in "arrow_function" with "statement_block" with >1 named child, preset default', + cursor = { 159, 50 }, + expected = { 161, 164 }, + result = { 158, 161 }, }, } +local treesj = require('treesj') +local opts = {} +treesj.setup(opts) + describe('TreeSJ SPLIT:', function() for _, value in ipairs(data_for_split) do - tu._test_format(value) + tu._test_format(value, treesj) end end) diff --git a/tests/langs/jsonc_spec.lua b/tests/langs/json/join_spec.lua similarity index 50% rename from tests/langs/jsonc_spec.lua rename to tests/langs/json/join_spec.lua index 1951bf9..37239b0 100644 --- a/tests/langs/jsonc_spec.lua +++ b/tests/langs/json/join_spec.lua @@ -1,62 +1,53 @@ local tu = require('tests.utils') -local PATH = './tests/sample/index.jsonc' -local LANG = 'jsonc' +local PATH = './tests/sample/index.json' +local LANG = 'json' -local data_for_split = { +local data_for_join = { { path = PATH, - mode = 'split', + mode = 'join', lang = LANG, desc = 'lang "%s", node "object", preset default', - cursor = { 17, 19 }, - expected = { 4, 8 }, - result = { 16, 20 }, - settings = {}, + cursor = { 6, 18 }, + expected = { 18, 19 }, + result = { 4, 5 }, }, { path = PATH, - mode = 'split', + mode = 'join', lang = LANG, desc = 'lang "%s", node "array", preset default', - cursor = { 18, 28 }, - expected = { 8, 12 }, - result = { 17, 21 }, - settings = {}, + cursor = { 10, 12 }, + expected = { 19, 20 }, + result = { 8, 9 }, }, -} - -local data_for_join = { { path = PATH, mode = 'join', lang = LANG, - desc = 'lang "%s", node "object", preset default', - cursor = { 6, 18 }, - expected = { 16, 17 }, + desc = 'lang "%s", node "pair with target object", preset default', + cursor = { 5, 6 }, + expected = { 18, 19 }, result = { 4, 5 }, - settings = {}, }, { path = PATH, mode = 'join', lang = LANG, desc = 'lang "%s", node "array", preset default', - cursor = { 10, 12 }, - expected = { 17, 18 }, + cursor = { 9, 6 }, + expected = { 19, 20 }, result = { 8, 9 }, - settings = {}, }, } -describe('TreeSJ SPLIT:', function() - for _, value in ipairs(data_for_split) do - tu._test_format(value) - end -end) +local treesj = require('treesj') +local opts = {} +treesj.setup(opts) describe('TreeSJ JOIN:', function() for _, value in ipairs(data_for_join) do - tu._test_format(value) + tu._test_format(value, treesj) end end) diff --git a/tests/langs/json/split_spec.lua b/tests/langs/json/split_spec.lua new file mode 100644 index 0000000..6d843b6 --- /dev/null +++ b/tests/langs/json/split_spec.lua @@ -0,0 +1,53 @@ +local tu = require('tests.utils') + +local PATH = './tests/sample/index.json' +local LANG = 'json' + +local data_for_split = { + { + path = PATH, + mode = 'split', + lang = LANG, + desc = 'lang "%s", node "object", preset default', + cursor = { 19, 28 }, + expected = { 4, 8 }, + result = { 18, 22 }, + }, + { + path = PATH, + mode = 'split', + lang = LANG, + desc = 'lang "%s", node "array", preset default', + cursor = { 20, 28 }, + expected = { 8, 12 }, + result = { 19, 23 }, + }, + { + path = PATH, + mode = 'split', + lang = LANG, + desc = 'lang "%s", node "paif with target object", preset default', + cursor = { 19, 6 }, + expected = { 4, 8 }, + result = { 18, 22 }, + }, + { + path = PATH, + mode = 'split', + lang = LANG, + desc = 'lang "%s", node "pair with target array", preset default', + cursor = { 20, 6 }, + expected = { 8, 12 }, + result = { 19, 23 }, + }, +} + +local treesj = require('treesj') +local opts = {} +treesj.setup(opts) + +describe('TreeSJ SPLIT:', function() + for _, value in ipairs(data_for_split) do + tu._test_format(value, treesj) + end +end) diff --git a/tests/langs/json_spec.lua b/tests/langs/json_spec.lua deleted file mode 100644 index 4885796..0000000 --- a/tests/langs/json_spec.lua +++ /dev/null @@ -1,102 +0,0 @@ -local tu = require('tests.utils') - -local PATH = './tests/sample/index.json' -local LANG = 'json' - -local data_for_split = { - { - path = PATH, - mode = 'split', - lang = LANG, - desc = 'lang "%s", node "object", preset default', - cursor = { 19, 28 }, - expected = { 4, 8 }, - result = { 18, 22 }, - settings = {}, - }, - { - path = PATH, - mode = 'split', - lang = LANG, - desc = 'lang "%s", node "array", preset default', - cursor = { 20, 28 }, - expected = { 8, 12 }, - result = { 19, 23 }, - settings = {}, - }, - { - path = PATH, - mode = 'split', - lang = LANG, - desc = 'lang "%s", node "paif with target object", preset default', - cursor = { 19, 6 }, - expected = { 4, 8 }, - result = { 18, 22 }, - settings = {}, - }, - { - path = PATH, - mode = 'split', - lang = LANG, - desc = 'lang "%s", node "pair with target array", preset default', - cursor = { 20, 6 }, - expected = { 8, 12 }, - result = { 19, 23 }, - settings = {}, - }, -} - -local data_for_join = { - { - path = PATH, - mode = 'join', - lang = LANG, - desc = 'lang "%s", node "object", preset default', - cursor = { 6, 18 }, - expected = { 18, 19 }, - result = { 4, 5 }, - settings = {}, - }, - { - path = PATH, - mode = 'join', - lang = LANG, - desc = 'lang "%s", node "array", preset default', - cursor = { 10, 12 }, - expected = { 19, 20 }, - result = { 8, 9 }, - settings = {}, - }, - { - path = PATH, - mode = 'join', - lang = LANG, - desc = 'lang "%s", node "pair with target object", preset default', - cursor = { 5, 6 }, - expected = { 18, 19 }, - result = { 4, 5 }, - settings = {}, - }, - { - path = PATH, - mode = 'join', - lang = LANG, - desc = 'lang "%s", node "array", preset default', - cursor = { 9, 6 }, - expected = { 19, 20 }, - result = { 8, 9 }, - settings = {}, - }, -} - -describe('TreeSJ SPLIT:', function() - for _, value in ipairs(data_for_split) do - tu._test_format(value) - end -end) - -describe('TreeSJ JOIN:', function() - for _, value in ipairs(data_for_join) do - tu._test_format(value) - end -end) diff --git a/tests/langs/jsonc/join_spec.lua b/tests/langs/jsonc/join_spec.lua new file mode 100644 index 0000000..6ba107a --- /dev/null +++ b/tests/langs/jsonc/join_spec.lua @@ -0,0 +1,35 @@ +local tu = require('tests.utils') + +local PATH = './tests/sample/index.jsonc' +local LANG = 'jsonc' + +local data_for_join = { + { + path = PATH, + mode = 'join', + lang = LANG, + desc = 'lang "%s", node "object", preset default', + cursor = { 6, 18 }, + expected = { 16, 17 }, + result = { 4, 5 }, + }, + { + path = PATH, + mode = 'join', + lang = LANG, + desc = 'lang "%s", node "array", preset default', + cursor = { 10, 12 }, + expected = { 17, 18 }, + result = { 8, 9 }, + }, +} + +local treesj = require('treesj') +local opts = {} +treesj.setup(opts) + +describe('TreeSJ JOIN:', function() + for _, value in ipairs(data_for_join) do + tu._test_format(value, treesj) + end +end) diff --git a/tests/langs/jsonc/split_spec.lua b/tests/langs/jsonc/split_spec.lua new file mode 100644 index 0000000..1a3f171 --- /dev/null +++ b/tests/langs/jsonc/split_spec.lua @@ -0,0 +1,35 @@ +local tu = require('tests.utils') + +local PATH = './tests/sample/index.jsonc' +local LANG = 'jsonc' + +local data_for_split = { + { + path = PATH, + mode = 'split', + lang = LANG, + desc = 'lang "%s", node "object", preset default', + cursor = { 17, 19 }, + expected = { 4, 8 }, + result = { 16, 20 }, + }, + { + path = PATH, + mode = 'split', + lang = LANG, + desc = 'lang "%s", node "array", preset default', + cursor = { 18, 28 }, + expected = { 8, 12 }, + result = { 17, 21 }, + }, +} + +local treesj = require('treesj') +local opts = {} +treesj.setup(opts) + +describe('TreeSJ SPLIT:', function() + for _, value in ipairs(data_for_split) do + tu._test_format(value, treesj) + end +end) diff --git a/tests/langs/kotlin/join_spec.lua b/tests/langs/kotlin/join_spec.lua new file mode 100644 index 0000000..3593f9a --- /dev/null +++ b/tests/langs/kotlin/join_spec.lua @@ -0,0 +1,44 @@ +local tu = require('tests.utils') + +local PATH = './tests/sample/index.kt' +local LANG = 'kotlin' + +local data_for_join = { + { + path = PATH, + mode = 'join', + lang = LANG, + desc = 'lang "%s", node "collection_literal", preset default', + cursor = { 6, 25 }, + expected = { 3, 4 }, + result = { 5, 6 }, + }, + { + path = PATH, + mode = 'join', + lang = LANG, + desc = 'lang "%s", node "value_arguments", preset default', + cursor = { 17, 3 }, + expected = { 12, 13 }, + result = { 14, 15 }, + }, + { + path = PATH, + mode = 'join', + lang = LANG, + desc = 'lang "%s", node "statements", preset default', + cursor = { 24, 24 }, + expected = { 21, 22 }, + result = { 23, 24 }, + }, +} + +local treesj = require('treesj') +local opts = {} +treesj.setup(opts) + +describe('TreeSJ JOIN:', function() + for _, value in ipairs(data_for_join) do + tu._test_format(value, treesj) + end +end) diff --git a/tests/langs/kotlin/split_spec.lua b/tests/langs/kotlin/split_spec.lua new file mode 100644 index 0000000..ffd8dbd --- /dev/null +++ b/tests/langs/kotlin/split_spec.lua @@ -0,0 +1,44 @@ +local tu = require('tests.utils') + +local PATH = './tests/sample/index.kt' +local LANG = 'kotlin' + +local data_for_split = { + { + path = PATH, + mode = 'split', + lang = LANG, + desc = 'lang "%s", node "collection_literal", preset default', + cursor = { 4, 27 }, + expected = { 5, 10 }, + result = { 3, 8 }, + }, + { + path = PATH, + mode = 'split', + lang = LANG, + desc = 'lang "%s", node "value_arguments", preset default', + cursor = { 13, 5 }, + expected = { 14, 19 }, + result = { 12, 17 }, + }, + { + path = PATH, + mode = 'split', + lang = LANG, + desc = 'lang "%s", node "statements", preset default', + cursor = { 22, 25 }, + expected = { 23, 27 }, + result = { 21, 25 }, + }, +} + +local treesj = require('treesj') +local opts = {} +treesj.setup(opts) + +describe('TreeSJ SPLIT:', function() + for _, value in ipairs(data_for_split) do + tu._test_format(value, treesj) + end +end) diff --git a/tests/langs/kotlin_spec.lua b/tests/langs/kotlin_spec.lua deleted file mode 100644 index d937870..0000000 --- a/tests/langs/kotlin_spec.lua +++ /dev/null @@ -1,82 +0,0 @@ -local tu = require('tests.utils') - -local PATH = './tests/sample/index.kt' -local LANG = 'kotlin' - -local data_for_split = { - { - path = PATH, - mode = 'split', - lang = LANG, - desc = 'lang "%s", node "collection_literal", preset default', - cursor = { 4, 27 }, - expected = { 5, 10 }, - result = { 3, 8 }, - settings = {}, - }, - { - path = PATH, - mode = 'split', - lang = LANG, - desc = 'lang "%s", node "value_arguments", preset default', - cursor = { 13, 5 }, - expected = { 14, 19 }, - result = { 12, 17 }, - settings = {}, - }, - { - path = PATH, - mode = 'split', - lang = LANG, - desc = 'lang "%s", node "statements", preset default', - cursor = { 22, 25 }, - expected = { 23, 27 }, - result = { 21, 25 }, - settings = {}, - }, -} - -local data_for_join = { - { - path = PATH, - mode = 'join', - lang = LANG, - desc = 'lang "%s", node "collection_literal", preset default', - cursor = { 6, 25 }, - expected = { 3, 4 }, - result = { 5, 6 }, - settings = {}, - }, - { - path = PATH, - mode = 'join', - lang = LANG, - desc = 'lang "%s", node "value_arguments", preset default', - cursor = { 17, 3 }, - expected = { 12, 13 }, - result = { 14, 15 }, - settings = {}, - }, - { - path = PATH, - mode = 'join', - lang = LANG, - desc = 'lang "%s", node "statements", preset default', - cursor = { 24, 24 }, - expected = { 21, 22 }, - result = { 23, 24 }, - settings = {}, - }, -} - -describe('TreeSJ SPLIT:', function() - for _, value in ipairs(data_for_split) do - tu._test_format(value) - end -end) - -describe('TreeSJ JOIN:', function() - for _, value in ipairs(data_for_join) do - tu._test_format(value) - end -end) diff --git a/tests/langs/lua/join_spec.lua b/tests/langs/lua/join_spec.lua new file mode 100644 index 0000000..4612544 --- /dev/null +++ b/tests/langs/lua/join_spec.lua @@ -0,0 +1,80 @@ +local tu = require('tests.utils') + +local PATH = './tests/sample/index.lua' +local LANG = 'lua' + +local data_for_join = { + { + path = PATH, + mode = 'join', + lang = LANG, + desc = 'lang "%s", node "table_constructor" (list), preset default', + cursor = { 8, 4 }, + expected = { 3, 4 }, + result = { 6, 7 }, + }, + { + path = PATH, + mode = 'join', + lang = LANG, + desc = 'lang "%s", node "table_constructor" (dict), preset default', + cursor = { 19, 4 }, + expected = { 14, 15 }, + result = { 17, 18 }, + }, + { + path = PATH, + mode = 'join', + lang = LANG, + desc = 'lang "%s", node "table_constructor" (mixed type), preset default', + cursor = { 30, 5 }, + expected = { 25, 26 }, + result = { 28, 29 }, + }, + { + path = PATH, + mode = 'join', + lang = LANG, + desc = 'lang "%s", node "arguments", preset default', + cursor = { 42, 7 }, + expected = { 37, 38 }, + result = { 37, 38 }, + }, + { + path = PATH, + mode = 'join', + lang = LANG, + desc = 'lang "%s", node "parameters", preset default', + cursor = { 54, 4 }, + expected = { 46, 47 }, + result = { 51, 52 }, + }, + { + path = PATH, + mode = 'join', + lang = LANG, + desc = 'lang "%s", node "block" in function_declaration contains nested functions, preset default', + cursor = { 83, 15 }, + expected = { 79, 80 }, + result = { 82, 83 }, + }, + { + path = PATH, + mode = 'join', + lang = LANG, + desc = 'lang "%s", node "table_constructor" is empty, preset default', + cursor = { 125, 0 }, + expected = { 120, 121 }, + result = { 123, 124 }, + }, +} + +local treesj = require('treesj') +local opts = {} +treesj.setup(opts) + +describe('TreeSJ JOIN:', function() + for _, value in ipairs(data_for_join) do + tu._test_format(value, treesj) + end +end) diff --git a/tests/langs/lua_no_empty_spec.lua b/tests/langs/lua/lua_no_empty_spec.lua similarity index 77% rename from tests/langs/lua_no_empty_spec.lua rename to tests/langs/lua/lua_no_empty_spec.lua index f26fca0..63924e0 100644 --- a/tests/langs/lua_no_empty_spec.lua +++ b/tests/langs/lua/lua_no_empty_spec.lua @@ -24,7 +24,6 @@ local data_for_split = { cursor = { 128, 14 }, expected = { 127, 128 }, result = { 127, 128 }, - settings = settings, }, } @@ -37,18 +36,31 @@ local data_for_join = { cursor = { 132, 0 }, expected = { 130, 132 }, result = { 130, 132 }, - settings = settings, }, } +local treesj = require('treesj') +local opts = { + langs = { + lua = { + table_constructor = { + both = { + format_empty_node = false, + }, + }, + }, + }, +} +treesj.setup(opts) + describe('TreeSJ SPLIT:', function() for _, value in ipairs(data_for_split) do - tu._test_format(value) + tu._test_format(value, treesj) end end) describe('TreeSJ JOIN:', function() for _, value in ipairs(data_for_join) do - tu._test_format(value) + tu._test_format(value, treesj) end end) diff --git a/tests/langs/lua_rec_spec.lua b/tests/langs/lua/lua_rec_spec.lua similarity index 82% rename from tests/langs/lua_rec_spec.lua rename to tests/langs/lua/lua_rec_spec.lua index fd33e52..4c2edbc 100644 --- a/tests/langs/lua_rec_spec.lua +++ b/tests/langs/lua/lua_rec_spec.lua @@ -35,7 +35,6 @@ local data_for_split = { cursor = { 80, 15 }, expected = { 82, 92 }, result = { 79, 89 }, - settings = settings, }, { path = PATH, @@ -45,7 +44,6 @@ local data_for_split = { cursor = { 95, 13 }, expected = { 97, 104 }, result = { 94, 101 }, - settings = settings, }, { path = PATH, @@ -55,12 +53,26 @@ local data_for_split = { cursor = { 107, 13 }, expected = { 109, 118 }, result = { 106, 115 }, - settings = settings, }, } +local treesj = require('treesj') +local opts = { + langs = { + lua = { + block = { + split = recursive.split, + }, + table_constructor = { + split = recursive.split, + }, + }, + }, +} +treesj.setup(opts) + describe('TreeSJ SPLIT:', function() for _, value in ipairs(data_for_split) do - tu._test_format(value) + tu._test_format(value, treesj) end end) diff --git a/tests/langs/lua/split_spec.lua b/tests/langs/lua/split_spec.lua new file mode 100644 index 0000000..e15e59c --- /dev/null +++ b/tests/langs/lua/split_spec.lua @@ -0,0 +1,89 @@ +local tu = require('tests.utils') + +local PATH = './tests/sample/index.lua' +local LANG = 'lua' + +local data_for_split = { + { + path = PATH, + mode = 'split', + lang = LANG, + desc = 'lang "%s", node "table_constructor" (list), preset default', + cursor = { 4, 16 }, + expected = { 6, 11 }, + result = { 3, 8 }, + }, + { + path = PATH, + mode = 'split', + lang = LANG, + desc = 'lang "%s", node "table_constructor" (dict), preset default', + cursor = { 15, 18 }, + expected = { 17, 23 }, + result = { 14, 20 }, + }, + { + path = PATH, + mode = 'split', + lang = LANG, + desc = 'lang "%s", node "table_constructor" (mixed type), preset default', + cursor = { 26, 19 }, + expected = { 28, 35 }, + result = { 25, 32 }, + }, + { + path = PATH, + mode = 'split', + lang = LANG, + desc = 'lang "%s", node "arguments", preset default', + cursor = { 38, 12 }, + expected = { 40, 44 }, + result = { 37, 41 }, + }, + { + path = PATH, + mode = 'split', + lang = LANG, + desc = 'lang "%s", node "parameters", preset default', + cursor = { 47, 23 }, + expected = { 51, 56 }, + result = { 46, 51 }, + }, + { + path = PATH, + mode = 'split', + lang = LANG, + desc = 'lang "%s", node "block" in if_statement, preset default', + cursor = { 61, 15 }, + expected = { 63, 68 }, + result = { 60, 65 }, + }, + { + path = PATH, + mode = 'split', + lang = LANG, + desc = 'lang "%s", node "block" in function_declaration, preset default', + cursor = { 71, 15 }, + expected = { 73, 77 }, + result = { 70, 74 }, + }, + { + path = PATH, + mode = 'split', + lang = LANG, + desc = 'lang "%s", node "table_constructor" is empty, preset default', + cursor = { 121, 14 }, + expected = { 123, 125 }, + result = { 120, 122 }, + }, +} + +local treesj = require('treesj') +local opts = {} +treesj.setup(opts) + +describe('TreeSJ SPLIT:', function() + for _, value in ipairs(data_for_split) do + tu._test_format(value, treesj) + end +end) diff --git a/tests/langs_tab/lua_spec.lua b/tests/langs/lua/with_tab_spec.lua similarity index 87% rename from tests/langs_tab/lua_spec.lua rename to tests/langs/lua/with_tab_spec.lua index 0567a74..cb72cd2 100644 --- a/tests/langs_tab/lua_spec.lua +++ b/tests/langs/lua/with_tab_spec.lua @@ -12,7 +12,6 @@ local data_for_split = { cursor = { 2, 14 }, expected = { 4, 7 }, result = { 1, 4 }, - settings = {}, }, { path = PATH, @@ -22,7 +21,6 @@ local data_for_split = { cursor = { 10, 15 }, expected = { 12, 19 }, result = { 9, 16 }, - settings = {}, }, } @@ -35,7 +33,6 @@ local data_for_join = { cursor = { 5, 14 }, expected = { 1, 2 }, result = { 4, 5 }, - settings = {}, }, { path = PATH, @@ -45,18 +42,23 @@ local data_for_join = { cursor = { 13, 15 }, expected = { 9, 10 }, result = { 12, 13 }, - settings = {}, }, } +local treesj = require('treesj') +local opts = {} +treesj.setup(opts) + +vim.opt.expandtab = false + describe('TreeSJ SPLIT:', function() for _, value in ipairs(data_for_split) do - tu._test_format(value) + tu._test_format(value, treesj) end end) describe('TreeSJ JOIN:', function() for _, value in ipairs(data_for_join) do - tu._test_format(value) + tu._test_format(value, treesj) end end) diff --git a/tests/langs/lua_spec.lua b/tests/langs/lua_spec.lua deleted file mode 100644 index 0328b0d..0000000 --- a/tests/langs/lua_spec.lua +++ /dev/null @@ -1,172 +0,0 @@ -local tu = require('tests.utils') - -local PATH = './tests/sample/index.lua' -local LANG = 'lua' - -local data_for_split = { - { - path = PATH, - mode = 'split', - lang = LANG, - desc = 'lang "%s", node "table_constructor" (list), preset default', - cursor = { 4, 16 }, - expected = { 6, 11 }, - result = { 3, 8 }, - settings = {}, - }, - { - path = PATH, - mode = 'split', - lang = LANG, - desc = 'lang "%s", node "table_constructor" (dict), preset default', - cursor = { 15, 18 }, - expected = { 17, 23 }, - result = { 14, 20 }, - settings = {}, - }, - { - path = PATH, - mode = 'split', - lang = LANG, - desc = 'lang "%s", node "table_constructor" (mixed type), preset default', - cursor = { 26, 19 }, - expected = { 28, 35 }, - result = { 25, 32 }, - settings = {}, - }, - { - path = PATH, - mode = 'split', - lang = LANG, - desc = 'lang "%s", node "arguments", preset default', - cursor = { 38, 12 }, - expected = { 40, 44 }, - result = { 37, 41 }, - settings = {}, - }, - { - path = PATH, - mode = 'split', - lang = LANG, - desc = 'lang "%s", node "parameters", preset default', - cursor = { 47, 23 }, - expected = { 51, 56 }, - result = { 46, 51 }, - settings = {}, - }, - { - path = PATH, - mode = 'split', - lang = LANG, - desc = 'lang "%s", node "block" in if_statement, preset default', - cursor = { 61, 15 }, - expected = { 63, 68 }, - result = { 60, 65 }, - settings = {}, - }, - { - path = PATH, - mode = 'split', - lang = LANG, - desc = 'lang "%s", node "block" in function_declaration, preset default', - cursor = { 71, 15 }, - expected = { 73, 77 }, - result = { 70, 74 }, - settings = {}, - }, - { - path = PATH, - mode = 'split', - lang = LANG, - desc = 'lang "%s", node "table_constructor" is empty, preset default', - cursor = { 121, 14 }, - expected = { 123, 125 }, - result = { 120, 122 }, - settings = {}, - }, -} - -local data_for_join = { - { - path = PATH, - mode = 'join', - lang = LANG, - desc = 'lang "%s", node "table_constructor" (list), preset default', - cursor = { 8, 4 }, - expected = { 3, 4 }, - result = { 6, 7 }, - settings = {}, - }, - { - path = PATH, - mode = 'join', - lang = LANG, - desc = 'lang "%s", node "table_constructor" (dict), preset default', - cursor = { 19, 4 }, - expected = { 14, 15 }, - result = { 17, 18 }, - settings = {}, - }, - { - path = PATH, - mode = 'join', - lang = LANG, - desc = 'lang "%s", node "table_constructor" (mixed type), preset default', - cursor = { 30, 5 }, - expected = { 25, 26 }, - result = { 28, 29 }, - settings = {}, - }, - { - path = PATH, - mode = 'join', - lang = LANG, - desc = 'lang "%s", node "arguments", preset default', - cursor = { 42, 7 }, - expected = { 37, 38 }, - result = { 37, 38 }, - settings = {}, - }, - { - path = PATH, - mode = 'join', - lang = LANG, - desc = 'lang "%s", node "parameters", preset default', - cursor = { 54, 4 }, - expected = { 46, 47 }, - result = { 51, 52 }, - settings = {}, - }, - { - path = PATH, - mode = 'join', - lang = LANG, - desc = 'lang "%s", node "block" in function_declaration contains nested functions, preset default', - cursor = { 83, 15 }, - expected = { 79, 80 }, - result = { 82, 83 }, - settings = {}, - }, - { - path = PATH, - mode = 'join', - lang = LANG, - desc = 'lang "%s", node "table_constructor" is empty, preset default', - cursor = { 125, 0 }, - expected = { 120, 121 }, - result = { 123, 124 }, - settings = {}, - }, -} - -describe('TreeSJ SPLIT:', function() - for _, value in ipairs(data_for_split) do - tu._test_format(value) - end -end) - -describe('TreeSJ JOIN:', function() - for _, value in ipairs(data_for_join) do - tu._test_format(value) - end -end) diff --git a/tests/langs/nix/join_spec.lua b/tests/langs/nix/join_spec.lua new file mode 100644 index 0000000..6cc79c8 --- /dev/null +++ b/tests/langs/nix/join_spec.lua @@ -0,0 +1,62 @@ +local tu = require('tests.utils') + +local PATH = './tests/sample/index.nix' +local LANG = 'nix' + +local data_for_join = { + { + path = PATH, + mode = 'join', + lang = LANG, + desc = 'lang "%s", node "list_expression", preset default', + cursor = { 10, 5 }, + expected = { 4, 5 }, + result = { 7, 8 }, + }, + { + path = PATH, + mode = 'join', + lang = LANG, + desc = 'lang "%s", node "binding_set", preset default', + cursor = { 23, 7 }, + expected = { 17, 18 }, + result = { 20, 21 }, + }, + { + path = PATH, + mode = 'join', + lang = LANG, + desc = 'lang "%s", node "formals", preset default', + cursor = { 37, 3 }, + expected = { 30, 31 }, + result = { 35, 36 }, + }, + { + path = PATH, + mode = 'join', + lang = LANG, + desc = 'lang "%s", node "let_expression", preset default', + cursor = { 49, 6 }, + expected = { 44, 45 }, + result = { 48, 49 }, + }, + { + path = PATH, + mode = 'join', + lang = LANG, + desc = 'lang "%s", node "let_expression" with "attrset_expression", preset default', + cursor = { 61, 6 }, + expected = { 56, 57 }, + result = { 60, 61 }, + }, +} + +local treesj = require('treesj') +local opts = {} +treesj.setup(opts) + +describe('TreeSJ JOIN:', function() + for _, value in ipairs(data_for_join) do + tu._test_format(value, treesj) + end +end) diff --git a/tests/langs/nix/split_spec.lua b/tests/langs/nix/split_spec.lua new file mode 100644 index 0000000..91fd461 --- /dev/null +++ b/tests/langs/nix/split_spec.lua @@ -0,0 +1,62 @@ +local tu = require('tests.utils') + +local PATH = './tests/sample/index.nix' +local LANG = 'nix' + +local data_for_split = { + { + path = PATH, + mode = 'split', + lang = LANG, + desc = 'lang "%s", node "list_expression", preset default', + cursor = { 5, 12 }, + expected = { 7, 15 }, + result = { 4, 12 }, + }, + { + path = PATH, + mode = 'split', + lang = LANG, + desc = 'lang "%s", node "binding_set", preset default', + cursor = { 18, 12 }, + expected = { 20, 25 }, + result = { 17, 22 }, + }, + { + path = PATH, + mode = 'split', + lang = LANG, + desc = 'lang "%s", node "formals", preset default', + cursor = { 31, 10 }, + expected = { 35, 41 }, + result = { 30, 36 }, + }, + { + path = PATH, + mode = 'split', + lang = LANG, + desc = 'lang "%s", node "let_expression", preset default', + cursor = { 45, 6 }, + expected = { 48, 53 }, + result = { 44, 49 }, + }, + { + path = PATH, + mode = 'split', + lang = LANG, + desc = 'lang "%s", node "let_expression" with "attrset_expression", preset default', + cursor = { 57, 6 }, + expected = { 60, 69 }, + result = { 56, 65 }, + }, +} + +local treesj = require('treesj') +local opts = {} +treesj.setup(opts) + +describe('TreeSJ SPLIT:', function() + for _, value in ipairs(data_for_split) do + tu._test_format(value, treesj) + end +end) diff --git a/tests/langs/nix_spec.lua b/tests/langs/nix_spec.lua deleted file mode 100644 index 841298c..0000000 --- a/tests/langs/nix_spec.lua +++ /dev/null @@ -1,122 +0,0 @@ -local tu = require('tests.utils') - -local PATH = './tests/sample/index.nix' -local LANG = 'nix' - -local data_for_split = { - { - path = PATH, - mode = 'split', - lang = LANG, - desc = 'lang "%s", node "list_expression", preset default', - cursor = { 5, 12 }, - expected = { 7, 15 }, - result = { 4, 12 }, - settings = {}, - }, - { - path = PATH, - mode = 'split', - lang = LANG, - desc = 'lang "%s", node "binding_set", preset default', - cursor = { 18, 12 }, - expected = { 20, 25 }, - result = { 17, 22 }, - settings = {}, - }, - { - path = PATH, - mode = 'split', - lang = LANG, - desc = 'lang "%s", node "formals", preset default', - cursor = { 31, 10 }, - expected = { 35, 41 }, - result = { 30, 36 }, - settings = {}, - }, - { - path = PATH, - mode = 'split', - lang = LANG, - desc = 'lang "%s", node "let_expression", preset default', - cursor = { 45, 6 }, - expected = { 48, 53 }, - result = { 44, 49 }, - settings = {}, - }, - { - path = PATH, - mode = 'split', - lang = LANG, - desc = 'lang "%s", node "let_expression" with "attrset_expression", preset default', - cursor = { 57, 6 }, - expected = { 60, 69 }, - result = { 56, 65 }, - settings = {}, - }, -} - -local data_for_join = { - { - path = PATH, - mode = 'join', - lang = LANG, - desc = 'lang "%s", node "list_expression", preset default', - cursor = { 10, 5 }, - expected = { 4, 5 }, - result = { 7, 8 }, - settings = {}, - }, - { - path = PATH, - mode = 'join', - lang = LANG, - desc = 'lang "%s", node "binding_set", preset default', - cursor = { 23, 7 }, - expected = { 17, 18 }, - result = { 20, 21 }, - settings = {}, - }, - { - path = PATH, - mode = 'join', - lang = LANG, - desc = 'lang "%s", node "formals", preset default', - cursor = { 37, 3 }, - expected = { 30, 31 }, - result = { 35, 36 }, - settings = {}, - }, - { - path = PATH, - mode = 'join', - lang = LANG, - desc = 'lang "%s", node "let_expression", preset default', - cursor = { 49, 6 }, - expected = { 44, 45 }, - result = { 48, 49 }, - settings = {}, - }, - { - path = PATH, - mode = 'join', - lang = LANG, - desc = 'lang "%s", node "let_expression" with "attrset_expression", preset default', - cursor = { 61, 6 }, - expected = { 56, 57 }, - result = { 60, 61 }, - settings = {}, - }, -} - -describe('TreeSJ SPLIT:', function() - for _, value in ipairs(data_for_split) do - tu._test_format(value) - end -end) - -describe('TreeSJ JOIN:', function() - for _, value in ipairs(data_for_join) do - tu._test_format(value) - end -end) diff --git a/tests/langs/php/join_spec.lua b/tests/langs/php/join_spec.lua new file mode 100644 index 0000000..f129c74 --- /dev/null +++ b/tests/langs/php/join_spec.lua @@ -0,0 +1,62 @@ +local tu = require('tests.utils') + +local PATH = './tests/sample/index.php' +local LANG = 'php' + +local data_for_join = { + { + path = PATH, + mode = 'join', + lang = LANG, + desc = 'lang "%s", node "array_creation_expression", preset default', + cursor = { 9, 2 }, + expected = { 4, 5 }, + result = { 7, 8 }, + }, + { + path = PATH, + mode = 'join', + lang = LANG, + desc = 'lang "%s", node "arguments", preset default', + cursor = { 19, 2 }, + expected = { 14, 15 }, + result = { 17, 18 }, + }, + { + path = PATH, + mode = 'join', + lang = LANG, + desc = 'lang "%s", node "formal_parameters", preset default', + cursor = { 31, 2 }, + expected = { 24, 27 }, + result = { 29, 32 }, + }, + { + path = PATH, + mode = 'join', + lang = LANG, + desc = 'lang "%s", node "compound_statement", preset default', + cursor = { 42, 27 }, + expected = { 38, 39 }, + result = { 41, 42 }, + }, + { + path = PATH, + mode = 'join', + lang = LANG, + desc = 'lang "%s", node "expression_statement" with target "array_creation_expression", preset default', + cursor = { 53, 0 }, + expected = { 49, 50 }, + result = { 52, 53 }, + }, +} + +local treesj = require('treesj') +local opts = {} +treesj.setup(opts) + +describe('TreeSJ JOIN:', function() + for _, value in ipairs(data_for_join) do + tu._test_format(value, treesj) + end +end) diff --git a/tests/langs/php/split_spec.lua b/tests/langs/php/split_spec.lua new file mode 100644 index 0000000..c12f7f9 --- /dev/null +++ b/tests/langs/php/split_spec.lua @@ -0,0 +1,62 @@ +local tu = require('tests.utils') + +local PATH = './tests/sample/index.php' +local LANG = 'php' + +local data_for_split = { + { + path = PATH, + mode = 'split', + lang = LANG, + desc = 'lang "%s", node "array_creation_expression", preset default', + cursor = { 5, 9 }, + expected = { 7, 12 }, + result = { 4, 9 }, + }, + { + path = PATH, + mode = 'split', + lang = LANG, + desc = 'lang "%s", node "arguments", preset default', + cursor = { 15, 4 }, + expected = { 17, 22 }, + result = { 14, 19 }, + }, + { + path = PATH, + mode = 'split', + lang = LANG, + desc = 'lang "%s", node "formal_parameters", preset default', + cursor = { 25, 13 }, + expected = { 29, 36 }, + result = { 24, 31 }, + }, + { + path = PATH, + mode = 'split', + lang = LANG, + desc = 'lang "%s", node "compound_statement", preset default', + cursor = { 39, 27 }, + expected = { 41, 47 }, + result = { 38, 44 }, + }, + { + path = PATH, + mode = 'split', + lang = LANG, + desc = 'lang "%s", node "expression_statement" with target "array_creation_expression", preset default', + cursor = { 50, 0 }, + expected = { 52, 57 }, + result = { 49, 54 }, + }, +} + +local treesj = require('treesj') +local opts = {} +treesj.setup(opts) + +describe('TreeSJ SPLIT:', function() + for _, value in ipairs(data_for_split) do + tu._test_format(value, treesj) + end +end) diff --git a/tests/langs/php_spec.lua b/tests/langs/php_spec.lua deleted file mode 100644 index c29e7b8..0000000 --- a/tests/langs/php_spec.lua +++ /dev/null @@ -1,122 +0,0 @@ -local tu = require('tests.utils') - -local PATH = './tests/sample/index.php' -local LANG = 'php' - -local data_for_split = { - { - path = PATH, - mode = 'split', - lang = LANG, - desc = 'lang "%s", node "array_creation_expression", preset default', - cursor = { 5, 9 }, - expected = { 7, 12 }, - result = { 4, 9 }, - settings = {}, - }, - { - path = PATH, - mode = 'split', - lang = LANG, - desc = 'lang "%s", node "arguments", preset default', - cursor = { 15, 4 }, - expected = { 17, 22 }, - result = { 14, 19 }, - settings = {}, - }, - { - path = PATH, - mode = 'split', - lang = LANG, - desc = 'lang "%s", node "formal_parameters", preset default', - cursor = { 25, 13 }, - expected = { 29, 36 }, - result = { 24, 31 }, - settings = {}, - }, - { - path = PATH, - mode = 'split', - lang = LANG, - desc = 'lang "%s", node "compound_statement", preset default', - cursor = { 39, 27 }, - expected = { 41, 47 }, - result = { 38, 44 }, - settings = {}, - }, - { - path = PATH, - mode = 'split', - lang = LANG, - desc = 'lang "%s", node "expression_statement" with target "array_creation_expression", preset default', - cursor = { 50, 0 }, - expected = { 52, 57 }, - result = { 49, 54 }, - settings = {}, - }, -} - -local data_for_join = { - { - path = PATH, - mode = 'join', - lang = LANG, - desc = 'lang "%s", node "array_creation_expression", preset default', - cursor = { 9, 2 }, - expected = { 4, 5 }, - result = { 7, 8 }, - settings = {}, - }, - { - path = PATH, - mode = 'join', - lang = LANG, - desc = 'lang "%s", node "arguments", preset default', - cursor = { 19, 2 }, - expected = { 14, 15 }, - result = { 17, 18 }, - settings = {}, - }, - { - path = PATH, - mode = 'join', - lang = LANG, - desc = 'lang "%s", node "formal_parameters", preset default', - cursor = { 31, 2 }, - expected = { 24, 27 }, - result = { 29, 32 }, - settings = {}, - }, - { - path = PATH, - mode = 'join', - lang = LANG, - desc = 'lang "%s", node "compound_statement", preset default', - cursor = { 42, 27 }, - expected = { 38, 39 }, - result = { 41, 42 }, - settings = {}, - }, - { - path = PATH, - mode = 'join', - lang = LANG, - desc = 'lang "%s", node "expression_statement" with target "array_creation_expression", preset default', - cursor = { 53, 0 }, - expected = { 49, 50 }, - result = { 52, 53 }, - settings = {}, - }, -} - -describe('TreeSJ SPLIT:', function() - for _, value in ipairs(data_for_split) do - tu._test_format(value) - end -end) - -describe('TreeSJ JOIN:', function() - for _, value in ipairs(data_for_join) do - tu._test_format(value) - end -end) diff --git a/tests/langs/pug/join_spec.lua b/tests/langs/pug/join_spec.lua new file mode 100644 index 0000000..621e9b9 --- /dev/null +++ b/tests/langs/pug/join_spec.lua @@ -0,0 +1,26 @@ +local tu = require('tests.utils') + +local PATH = './tests/sample/index.pug' +local LANG = 'pug' + +local data_for_join = { + { + path = PATH, + mode = 'join', + lang = LANG, + desc = 'lang "%s", node "attributes", preset default', + cursor = { 6, 21 }, + expected = { 1, 2 }, + result = { 4, 5 }, + }, +} + +local treesj = require('treesj') +local opts = {} +treesj.setup(opts) + +describe('TreeSJ JOIN:', function() + for _, value in ipairs(data_for_join) do + tu._test_format(value, treesj) + end +end) diff --git a/tests/langs/pug_spec.lua b/tests/langs/pug/split_spec.lua similarity index 50% rename from tests/langs/pug_spec.lua rename to tests/langs/pug/split_spec.lua index 274ee90..f5a7057 100644 --- a/tests/langs/pug_spec.lua +++ b/tests/langs/pug/split_spec.lua @@ -12,31 +12,15 @@ local data_for_split = { cursor = { 2, 26 }, expected = { 4, 8 }, result = { 1, 5 }, - settings = {}, }, } -local data_for_join = { - { - path = PATH, - mode = 'join', - lang = LANG, - desc = 'lang "%s", node "attributes", preset default', - cursor = { 6, 21 }, - expected = { 1, 2 }, - result = { 4, 5 }, - settings = {}, - }, -} +local treesj = require('treesj') +local opts = {} +treesj.setup(opts) describe('TreeSJ SPLIT:', function() for _, value in ipairs(data_for_split) do - tu._test_format(value) - end -end) - -describe('TreeSJ JOIN:', function() - for _, value in ipairs(data_for_join) do - tu._test_format(value) + tu._test_format(value, treesj) end end) diff --git a/tests/langs/python/python_join_spec.lua b/tests/langs/python/python_join_spec.lua index a96694d..8d01294 100644 --- a/tests/langs/python/python_join_spec.lua +++ b/tests/langs/python/python_join_spec.lua @@ -12,7 +12,6 @@ local data_for_join = { cursor = { 5, 8 }, expected = { 1, 2 }, result = { 3, 4 }, - settings = {}, }, { path = PATH, @@ -22,7 +21,6 @@ local data_for_join = { cursor = { 15, 5 }, expected = { 10, 11 }, result = { 12, 13 }, - settings = {}, }, { path = PATH, @@ -32,7 +30,6 @@ local data_for_join = { cursor = { 25, 3 }, expected = { 19, 20 }, result = { 21, 22 }, - settings = {}, }, { path = PATH, @@ -42,7 +39,6 @@ local data_for_join = { cursor = { 36, 5 }, expected = { 31, 32 }, result = { 33, 34 }, - settings = {}, }, { path = PATH, @@ -52,7 +48,6 @@ local data_for_join = { cursor = { 44, 18 }, expected = { 40, 41 }, result = { 42, 43 }, - settings = {}, }, { path = PATH, @@ -62,7 +57,6 @@ local data_for_join = { cursor = { 57, 4 }, expected = { 48, 49 }, result = { 54, 55 }, - settings = {}, }, { path = PATH, @@ -72,7 +66,6 @@ local data_for_join = { cursor = { 67, 25 }, expected = { 63, 64 }, result = { 65, 66 }, - settings = {}, }, { path = PATH, @@ -82,7 +75,6 @@ local data_for_join = { cursor = { 75, 5 }, expected = { 70, 71 }, result = { 72, 73 }, - settings = {}, }, { path = PATH, @@ -92,7 +84,6 @@ local data_for_join = { cursor = { 83, 3 }, expected = { 78, 79 }, result = { 80, 81 }, - settings = {}, }, { path = PATH, @@ -102,7 +93,6 @@ local data_for_join = { cursor = { 91, 0 }, expected = { 87, 88 }, result = { 90, 91 }, - settings = {}, }, { path = PATH, @@ -112,7 +102,6 @@ local data_for_join = { cursor = { 100, 0 }, expected = { 96, 97 }, result = { 99, 100 }, - settings = {}, }, { path = PATH, @@ -122,7 +111,6 @@ local data_for_join = { cursor = { 109, 0 }, expected = { 105, 106 }, result = { 108, 109 }, - settings = {}, }, { path = PATH, @@ -132,7 +120,6 @@ local data_for_join = { cursor = { 118, 0 }, expected = { 114, 115 }, result = { 117, 118 }, - settings = {}, }, { path = PATH, @@ -142,7 +129,6 @@ local data_for_join = { cursor = { 126, 0 }, expected = { 122, 123 }, result = { 125, 126 }, - settings = {}, }, { path = PATH, @@ -152,7 +138,6 @@ local data_for_join = { cursor = { 135, 0 }, expected = { 131, 132 }, result = { 134, 135 }, - settings = {}, }, { path = PATH, @@ -162,7 +147,6 @@ local data_for_join = { cursor = { 144, 0 }, expected = { 140, 141 }, result = { 143, 144 }, - settings = {}, }, { path = PATH, @@ -172,12 +156,24 @@ local data_for_join = { cursor = { 153, 0 }, expected = { 149, 150 }, result = { 152, 153 }, - settings = {}, + }, + { + path = PATH, + mode = 'join', + lang = LANG, + desc = 'lang "%s", node "import_from_statement", preset default', + cursor = { 165, 5 }, + expected = { 158, 159 }, + result = { 161, 162 }, }, } +local treesj = require('treesj') +local opts = {} +treesj.setup(opts) + describe('TreeSJ JOIN:', function() for _, value in ipairs(data_for_join) do - tu._test_format(value) + tu._test_format(value, treesj) end end) diff --git a/tests/langs/python/python_split_spec.lua b/tests/langs/python/python_split_spec.lua index cca5fd2..aa9613b 100644 --- a/tests/langs/python/python_split_spec.lua +++ b/tests/langs/python/python_split_spec.lua @@ -12,7 +12,6 @@ local data_for_split = { cursor = { 2, 15 }, expected = { 3, 8 }, result = { 1, 6 }, - settings = {}, }, { path = PATH, @@ -22,7 +21,6 @@ local data_for_split = { cursor = { 11, 19 }, expected = { 12, 17 }, result = { 10, 15 }, - settings = {}, }, { path = PATH, @@ -32,7 +30,6 @@ local data_for_split = { cursor = { 20, 4 }, expected = { 21, 29 }, result = { 19, 27 }, - settings = {}, }, { path = PATH, @@ -42,7 +39,6 @@ local data_for_split = { cursor = { 32, 10 }, expected = { 33, 38 }, result = { 31, 36 }, - settings = {}, }, { path = PATH, @@ -52,7 +48,6 @@ local data_for_split = { cursor = { 41, 17 }, expected = { 42, 46 }, result = { 40, 44 }, - settings = {}, }, { path = PATH, @@ -62,7 +57,6 @@ local data_for_split = { cursor = { 49, 18 }, expected = { 54, 58 }, result = { 48, 52 }, - settings = {}, }, { path = PATH, @@ -72,7 +66,6 @@ local data_for_split = { cursor = { 64, 25 }, expected = { 65, 68 }, result = { 63, 66 }, - settings = {}, }, { path = PATH, @@ -82,7 +75,6 @@ local data_for_split = { cursor = { 71, 12 }, expected = { 72, 76 }, result = { 70, 74 }, - settings = {}, }, { path = PATH, @@ -92,7 +84,6 @@ local data_for_split = { cursor = { 79, 16 }, expected = { 80, 85 }, result = { 78, 83 }, - settings = {}, }, { path = PATH, @@ -102,7 +93,6 @@ local data_for_split = { cursor = { 88, 0 }, expected = { 90, 94 }, result = { 87, 91 }, - settings = {}, }, { path = PATH, @@ -112,7 +102,6 @@ local data_for_split = { cursor = { 97, 1 }, expected = { 99, 103 }, result = { 96, 100 }, - settings = {}, }, { path = PATH, @@ -122,7 +111,6 @@ local data_for_split = { cursor = { 106, 0 }, expected = { 108, 112 }, result = { 105, 109 }, - settings = {}, }, { path = PATH, @@ -132,7 +120,6 @@ local data_for_split = { cursor = { 115, 0 }, expected = { 117, 120 }, result = { 114, 117 }, - settings = {}, }, { path = PATH, @@ -142,7 +129,6 @@ local data_for_split = { cursor = { 123, 0 }, expected = { 125, 129 }, result = { 122, 126 }, - settings = {}, }, { path = PATH, @@ -152,7 +138,6 @@ local data_for_split = { cursor = { 132, 0 }, expected = { 134, 138 }, result = { 131, 135 }, - settings = {}, }, { path = PATH, @@ -162,7 +147,6 @@ local data_for_split = { cursor = { 141, 0 }, expected = { 143, 147 }, result = { 140, 144 }, - settings = {}, }, { path = PATH, @@ -172,12 +156,24 @@ local data_for_split = { cursor = { 150, 0 }, expected = { 152, 156 }, result = { 149, 153 }, - settings = {}, + }, + { + path = PATH, + mode = 'split', + lang = LANG, + desc = 'lang "%s", node "import_from_statement", preset default', + cursor = { 159, 19 }, + expected = { 161, 166 }, + result = { 158, 163 }, }, } +local treesj = require('treesj') +local opts = {} +treesj.setup(opts) + describe('TreeSJ SPLIT:', function() for _, value in ipairs(data_for_split) do - tu._test_format(value) + tu._test_format(value, treesj) end end) diff --git a/tests/langs/r/r_join_spec.lua b/tests/langs/r/r_join_spec.lua index e2557e4..402f068 100644 --- a/tests/langs/r/r_join_spec.lua +++ b/tests/langs/r/r_join_spec.lua @@ -12,7 +12,6 @@ local data_for_join = { cursor = { 6, 2 }, expected = { 1, 2 }, result = { 4, 5 }, - settings = {}, }, { @@ -23,7 +22,6 @@ local data_for_join = { cursor = { 16, 3 }, expected = { 11, 12 }, result = { 14, 15 }, - settings = {}, }, { @@ -34,7 +32,6 @@ local data_for_join = { cursor = { 26, 0 }, expected = { 20, 23 }, result = { 25, 28 }, - settings = {}, }, { @@ -45,7 +42,6 @@ local data_for_join = { cursor = { 37, 7 }, expected = { 33, 34 }, result = { 36, 37 }, - settings = {}, }, { @@ -56,7 +52,6 @@ local data_for_join = { cursor = { 49, 1 }, expected = { 45, 46 }, result = { 48, 49 }, - settings = {}, }, { @@ -67,7 +62,6 @@ local data_for_join = { cursor = { 64, 5 }, expected = { 55, 56 }, result = { 58, 59 }, - settings = {}, }, { @@ -78,7 +72,6 @@ local data_for_join = { cursor = { 74, 8 }, expected = { 66, 67 }, result = { 69, 70 }, - settings = {}, }, { @@ -89,7 +82,6 @@ local data_for_join = { cursor = { 80, 0 }, expected = { 76, 77 }, result = { 79, 80 }, - settings = {}, }, { @@ -100,7 +92,6 @@ local data_for_join = { cursor = { 94, 10 }, expected = { 86, 91 }, result = { 93, 98 }, - settings = {}, }, { @@ -111,7 +102,6 @@ local data_for_join = { cursor = { 108, 2 }, expected = { 104, 105 }, result = { 107, 108 }, - settings = {}, }, { @@ -122,7 +112,6 @@ local data_for_join = { cursor = { 118, 0 }, expected = { 112, 114 }, result = { 116, 118 }, - settings = {}, }, { @@ -133,12 +122,15 @@ local data_for_join = { cursor = { 128, 0 }, expected = { 122, 124 }, result = { 126, 128 }, - settings = {}, }, } +local treesj = require('treesj') +local opts = {} +treesj.setup(opts) + describe('TreeSJ JOIN:', function() for _, value in ipairs(data_for_join) do - tu._test_format(value) + tu._test_format(value, treesj) end end) diff --git a/tests/langs/r/r_split_spec.lua b/tests/langs/r/r_split_spec.lua index af5e476..6ad6eaa 100644 --- a/tests/langs/r/r_split_spec.lua +++ b/tests/langs/r/r_split_spec.lua @@ -12,7 +12,6 @@ local data_for_split = { cursor = { 2, 2 }, expected = { 4, 9 }, result = { 1, 6 }, - settings = {}, }, { @@ -23,7 +22,6 @@ local data_for_split = { cursor = { 12, 6 }, expected = { 14, 18 }, result = { 11, 15 }, - settings = {}, }, { @@ -34,7 +32,6 @@ local data_for_split = { cursor = { 21, 0 }, expected = { 25, 31 }, result = { 20, 26 }, - settings = {}, }, { @@ -45,7 +42,6 @@ local data_for_split = { cursor = { 34, 7 }, expected = { 36, 43 }, result = { 33, 40 }, - settings = {}, }, { @@ -56,7 +52,6 @@ local data_for_split = { cursor = { 46, 1 }, expected = { 48, 53 }, result = { 45, 50 }, - settings = {}, }, { @@ -67,7 +62,6 @@ local data_for_split = { cursor = { 56, 17 }, expected = { 58, 64 }, result = { 55, 61 }, - settings = {}, }, { @@ -78,7 +72,6 @@ local data_for_split = { cursor = { 67, 23 }, expected = { 69, 74 }, result = { 66, 71 }, - settings = {}, }, { @@ -89,7 +82,6 @@ local data_for_split = { cursor = { 77, 0 }, expected = { 79, 84 }, result = { 76, 81 }, - settings = {}, }, { @@ -100,7 +92,6 @@ local data_for_split = { cursor = { 87, 10 }, expected = { 93, 102 }, result = { 86, 95 }, - settings = {}, }, { @@ -111,7 +102,6 @@ local data_for_split = { cursor = { 105, 2 }, expected = { 107, 110 }, result = { 104, 107 }, - settings = {}, }, { @@ -122,7 +112,6 @@ local data_for_split = { cursor = { 114, 0 }, expected = { 116, 120 }, result = { 112, 116 }, - settings = {}, }, { @@ -133,12 +122,15 @@ local data_for_split = { cursor = { 124, 0 }, expected = { 126, 130 }, result = { 122, 126 }, - settings = {}, }, } +local treesj = require('treesj') +local opts = {} +treesj.setup(opts) + describe('TreeSJ SPLIT:', function() for _, value in ipairs(data_for_split) do - tu._test_format(value) + tu._test_format(value, treesj) end end) diff --git a/tests/langs/ruby/join_spec.lua b/tests/langs/ruby/join_spec.lua new file mode 100644 index 0000000..82d6f78 --- /dev/null +++ b/tests/langs/ruby/join_spec.lua @@ -0,0 +1,116 @@ +local tu = require('tests.utils') + +local PATH = './tests/sample/index.rb' +local LANG = 'ruby' + +local data_for_join = { + { + path = PATH, + mode = 'join', + lang = LANG, + desc = 'lang "%s", node "array", preset default', + cursor = { 8, 4 }, + expected = { 1, 2 }, + result = { 4, 5 }, + }, + { + path = PATH, + mode = 'join', + lang = LANG, + desc = 'lang "%s", node "hash", preset default', + cursor = { 18, 15 }, + expected = { 13, 14 }, + result = { 16, 17 }, + }, + { + path = PATH, + mode = 'join', + lang = LANG, + desc = 'lang "%s", node "method_parameters", preset default', + cursor = { 28, 3 }, + expected = { 23, 24 }, + result = { 26, 27 }, + }, + { + path = PATH, + mode = 'join', + lang = LANG, + desc = 'lang "%s", node "argument_list", preset default', + cursor = { 37, 3 }, + expected = { 32, 33 }, + result = { 35, 36 }, + }, + { + path = PATH, + mode = 'join', + lang = LANG, + desc = 'lang "%s", node "string_array", preset default', + cursor = { 46, 4 }, + expected = { 41, 42 }, + result = { 44, 45 }, + }, + { + path = PATH, + mode = 'join', + lang = LANG, + desc = 'lang "%s", node "body_statement", preset default', + cursor = { 57, 4 }, + expected = { 51, 52 }, + result = { 54, 55 }, + }, + { + path = PATH, + mode = 'join', + lang = LANG, + desc = 'lang "%s", node "do_block to block", preset default', + cursor = { 64, 8 }, + expected = { 60, 61 }, + result = { 63, 64 }, + }, + { + path = PATH, + mode = 'join', + lang = LANG, + desc = 'lang "%s", node "if to if_modifier", preset default', + cursor = { 72, 1 }, + expected = { 68, 69 }, + result = { 71, 72 }, + }, + { + path = PATH, + mode = 'join', + lang = LANG, + desc = 'lang "%s", node "if to conditional", preset default', + cursor = { 80, 1 }, + expected = { 76, 77 }, + result = { 79, 80 }, + }, + { + path = PATH, + mode = 'join', + lang = LANG, + desc = 'lang "%s", node "when", preset default', + cursor = { 103, 1 }, + expected = { 97, 98 }, + result = { 102, 103 }, + }, + { + path = PATH, + mode = 'join', + lang = LANG, + desc = 'lang "%s", field "right" inside "operator_assignment", preset default', + cursor = { 114, 2 }, + expected = { 108, 109 }, + result = { 113, 114 }, + }, +} + +local treesj = require('treesj') +local opts = {} +treesj.setup(opts) + +describe('TreeSJ JOIN:', function() + for _, value in ipairs(data_for_join) do + tu._test_format(value, treesj) + end +end) diff --git a/tests/langs/ruby/split_spec.lua b/tests/langs/ruby/split_spec.lua new file mode 100644 index 0000000..e2c4bd0 --- /dev/null +++ b/tests/langs/ruby/split_spec.lua @@ -0,0 +1,116 @@ +local tu = require('tests.utils') + +local PATH = './tests/sample/index.rb' +local LANG = 'ruby' + +local data_for_split = { + { + path = PATH, + mode = 'split', + lang = LANG, + desc = 'lang "%s", node "array", preset default', + cursor = { 2, 17 }, + expected = { 4, 11 }, + result = { 1, 8 }, + }, + { + path = PATH, + mode = 'split', + lang = LANG, + desc = 'lang "%s", node "hash", preset default', + cursor = { 14, 17 }, + expected = { 16, 21 }, + result = { 13, 18 }, + }, + { + path = PATH, + mode = 'split', + lang = LANG, + desc = 'lang "%s", node "method_parameters", preset default', + cursor = { 24, 11 }, + expected = { 26, 30 }, + result = { 23, 27 }, + }, + { + path = PATH, + mode = 'split', + lang = LANG, + desc = 'lang "%s", node "argument_list", preset default', + cursor = { 33, 7 }, + expected = { 35, 39 }, + result = { 32, 36 }, + }, + { + path = PATH, + mode = 'split', + lang = LANG, + desc = 'lang "%s", node "string_array", preset default', + cursor = { 42, 7 }, + expected = { 44, 49 }, + result = { 41, 46 }, + }, + { + path = PATH, + mode = 'split', + lang = LANG, + desc = 'lang "%s", node "body_statement", preset default', + cursor = { 52, 33 }, + expected = { 54, 58 }, + result = { 51, 55 }, + }, + { + path = PATH, + mode = 'split', + lang = LANG, + desc = 'lang "%s", node "block to do_block", preset default', + cursor = { 61, 8 }, + expected = { 63, 66 }, + result = { 60, 63 }, + }, + { + path = PATH, + mode = 'split', + lang = LANG, + desc = 'lang "%s", node "if_modifier to if", preset default', + cursor = { 69, 5 }, + expected = { 71, 74 }, + result = { 68, 71 }, + }, + { + path = PATH, + mode = 'split', + lang = LANG, + desc = 'lang "%s", node "conditional to if", preset default', + cursor = { 77, 4 }, + expected = { 79, 84 }, + result = { 76, 81 }, + }, + { + path = PATH, + mode = 'split', + lang = LANG, + desc = 'lang "%s", node "when", preset default', + cursor = { 98, 4 }, + expected = { 102, 105 }, + result = { 97, 100 }, + }, + { + path = PATH, + mode = 'split', + lang = LANG, + desc = 'lang "%s", field "right" inside "operator_assignment", preset default', + cursor = { 109, 10 }, + expected = { 113, 116 }, + result = { 108, 111 }, + }, +} + +local treesj = require('treesj') +local opts = {} +treesj.setup(opts) + +describe('TreeSJ SPLIT:', function() + for _, value in ipairs(data_for_split) do + tu._test_format(value, treesj) + end +end) diff --git a/tests/langs/ruby_spec.lua b/tests/langs/ruby_spec.lua deleted file mode 100644 index 7d43a68..0000000 --- a/tests/langs/ruby_spec.lua +++ /dev/null @@ -1,162 +0,0 @@ -local tu = require('tests.utils') - -local PATH = './tests/sample/index.rb' -local LANG = 'ruby' - -local data_for_split = { - { - path = PATH, - mode = 'split', - lang = LANG, - desc = 'lang "%s", node "array", preset default', - cursor = { 2, 17 }, - expected = { 4, 11 }, - result = { 1, 8 }, - settings = {}, - }, - { - path = PATH, - mode = 'split', - lang = LANG, - desc = 'lang "%s", node "hash", preset default', - cursor = { 14, 17 }, - expected = { 16, 21 }, - result = { 13, 18 }, - settings = {}, - }, - { - path = PATH, - mode = 'split', - lang = LANG, - desc = 'lang "%s",node "method_parameters", preset default', - cursor = { 24, 11 }, - expected = { 26, 30 }, - result = { 23, 27 }, - settings = {}, - }, - { - path = PATH, - mode = 'split', - lang = LANG, - desc = 'lang "%s",node "argument_list", preset default', - cursor = { 33, 7 }, - expected = { 35, 39 }, - result = { 32, 36 }, - settings = {}, - }, - { - path = PATH, - mode = 'split', - lang = LANG, - desc = 'lang "%s",node "string_array", preset default', - cursor = { 42, 7 }, - expected = { 44, 49 }, - result = { 41, 46 }, - settings = {}, - }, - { - path = PATH, - mode = 'split', - lang = LANG, - desc = 'lang "%s",node "body_statement", preset default', - cursor = { 52, 33 }, - expected = { 54, 58 }, - result = { 51, 55 }, - settings = {}, - }, - { - path = PATH, - mode = 'split', - lang = LANG, - desc = 'lang "%s",node "block to do_block", preset default', - cursor = { 61, 8 }, - expected = { 63, 66 }, - result = { 60, 63 }, - settings = {}, - }, -} - -local data_for_join = { - { - path = PATH, - mode = 'join', - lang = LANG, - desc = 'lang "%s", node "array", preset default', - cursor = { 8, 4 }, - expected = { 1, 2 }, - result = { 4, 5 }, - settings = {}, - }, - { - path = PATH, - mode = 'join', - lang = LANG, - desc = 'lang "%s", node "hash", preset default', - cursor = { 18, 15 }, - expected = { 13, 14 }, - result = { 16, 17 }, - settings = {}, - }, - { - path = PATH, - mode = 'join', - lang = LANG, - desc = 'lang "%s",node "method_parameters", preset default', - cursor = { 28, 3 }, - expected = { 23, 24 }, - result = { 26, 27 }, - settings = {}, - }, - { - path = PATH, - mode = 'join', - lang = LANG, - desc = 'lang "%s",node "argument_list", preset default', - cursor = { 37, 3 }, - expected = { 32, 33 }, - result = { 35, 36 }, - settings = {}, - }, - { - path = PATH, - mode = 'join', - lang = LANG, - desc = 'lang "%s",node "string_array", preset default', - cursor = { 46, 4 }, - expected = { 41, 42 }, - result = { 44, 45 }, - settings = {}, - }, - { - path = PATH, - mode = 'join', - lang = LANG, - desc = 'lang "%s",node "body_statement", preset default', - cursor = { 57, 4 }, - expected = { 51, 52 }, - result = { 54, 55 }, - settings = {}, - }, - { - path = PATH, - mode = 'join', - lang = LANG, - desc = 'lang "%s",node "do_block to block", preset default', - cursor = { 64, 8 }, - expected = { 60, 61 }, - result = { 63, 64 }, - settings = {}, - }, -} - -describe('TreeSJ SPLIT:', function() - for _, value in ipairs(data_for_split) do - tu._test_format(value) - end -end) - -describe('TreeSJ JOIN:', function() - for _, value in ipairs(data_for_join) do - tu._test_format(value) - end -end) diff --git a/tests/langs/rust/rust_join_spec.lua b/tests/langs/rust/rust_join_spec.lua index ef0ccd6..dc772b2 100644 --- a/tests/langs/rust/rust_join_spec.lua +++ b/tests/langs/rust/rust_join_spec.lua @@ -12,7 +12,6 @@ local data_for_join = { cursor = { 9, 10 }, expected = { 5, 6 }, result = { 7, 8 }, - settings = {}, }, { path = PATH, @@ -22,7 +21,6 @@ local data_for_join = { cursor = { 16, 19 }, expected = { 13, 14 }, result = { 15, 16 }, - settings = {}, }, { path = PATH, @@ -32,7 +30,6 @@ local data_for_join = { cursor = { 26, 1 }, expected = { 21, 22 }, result = { 23, 24 }, - settings = {}, }, { path = PATH, @@ -42,7 +39,6 @@ local data_for_join = { cursor = { 33, 7 }, expected = { 29, 30 }, result = { 31, 32 }, - settings = {}, }, { path = PATH, @@ -52,7 +48,6 @@ local data_for_join = { cursor = { 42, 4 }, expected = { 37, 38 }, result = { 39, 40 }, - settings = {}, }, { path = PATH, @@ -62,7 +57,6 @@ local data_for_join = { cursor = { 51, 6 }, expected = { 46, 47 }, result = { 48, 49 }, - settings = {}, }, { path = PATH, @@ -72,7 +66,6 @@ local data_for_join = { cursor = { 60, 7 }, expected = { 55, 56 }, result = { 57, 58 }, - settings = {}, }, { path = PATH, @@ -82,7 +75,6 @@ local data_for_join = { cursor = { 68, 3 }, expected = { 64, 65 }, result = { 66, 67 }, - settings = {}, }, { path = PATH, @@ -92,7 +84,6 @@ local data_for_join = { cursor = { 77, 6 }, expected = { 72, 73 }, result = { 74, 75 }, - settings = {}, }, { path = PATH, @@ -102,7 +93,6 @@ local data_for_join = { cursor = { 86, 25 }, expected = { 82, 83 }, result = { 84, 85 }, - settings = {}, }, { path = PATH, @@ -112,7 +102,6 @@ local data_for_join = { cursor = { 100, 27 }, expected = { 90, 91 }, result = { 97, 98 }, - settings = {}, }, { path = PATH, @@ -122,12 +111,51 @@ local data_for_join = { cursor = { 112, 4 }, expected = { 107, 108 }, result = { 109, 110 }, - settings = {}, + }, + { + path = PATH, + mode = 'join', + lang = LANG, + desc = 'lang "%s", field "value" in match_arm, preset default', + cursor = { 124, 4 }, + expected = { 118, 119 }, + result = { 123, 124 }, + }, + { + path = PATH, + mode = 'join', + lang = LANG, + desc = 'lang "%s", node "block" with 2 named children in match_arm, preset default', + cursor = { 136, 4 }, + expected = { 130, 131 }, + result = { 135, 136 }, + }, + { + path = PATH, + mode = 'join', + lang = LANG, + desc = 'lang "%s", field "body" inside closure_expression, preset default', + cursor = { 146, 15 }, + expected = { 142, 143 }, + result = { 145, 146 }, + }, + { + path = PATH, + mode = 'join', + lang = LANG, + desc = 'lang "%s", node "block" inside closure_expression with 2 named children, preset default', + cursor = { 156, 5 }, + expected = { 150, 151 }, + result = { 153, 154 }, }, } +local treesj = require('treesj') +local opts = {} +treesj.setup(opts) + describe('TreeSJ JOIN:', function() for _, value in ipairs(data_for_join) do - tu._test_format(value) + tu._test_format(value, treesj) end end) diff --git a/tests/langs/rust/rust_split_spec.lua b/tests/langs/rust/rust_split_spec.lua index 9d416e2..dc7c914 100644 --- a/tests/langs/rust/rust_split_spec.lua +++ b/tests/langs/rust/rust_split_spec.lua @@ -12,7 +12,6 @@ local data_for_split = { cursor = { 6, 20 }, expected = { 7, 11 }, result = { 5, 9 }, - settings = {}, }, { path = PATH, @@ -22,7 +21,6 @@ local data_for_split = { cursor = { 14, 4 }, expected = { 15, 19 }, result = { 13, 17 }, - settings = {}, }, { path = PATH, @@ -32,7 +30,6 @@ local data_for_split = { cursor = { 22, 15 }, expected = { 23, 27 }, result = { 21, 25 }, - settings = {}, }, { path = PATH, @@ -42,7 +39,6 @@ local data_for_split = { cursor = { 30, 9 }, expected = { 31, 35 }, result = { 29, 33 }, - settings = {}, }, { path = PATH, @@ -52,7 +48,6 @@ local data_for_split = { cursor = { 38, 17 }, expected = { 39, 44 }, result = { 37, 42 }, - settings = {}, }, { path = PATH, @@ -62,7 +57,6 @@ local data_for_split = { cursor = { 47, 33 }, expected = { 48, 53 }, result = { 46, 51 }, - settings = {}, }, { path = PATH, @@ -72,7 +66,6 @@ local data_for_split = { cursor = { 56, 15 }, expected = { 57, 62 }, result = { 55, 60 }, - settings = {}, }, { path = PATH, @@ -82,7 +75,6 @@ local data_for_split = { cursor = { 65, 31 }, expected = { 66, 70 }, result = { 64, 68 }, - settings = {}, }, { path = PATH, @@ -92,7 +84,6 @@ local data_for_split = { cursor = { 73, 25 }, expected = { 74, 80 }, result = { 72, 78 }, - settings = {}, }, { path = PATH, @@ -102,7 +93,6 @@ local data_for_split = { cursor = { 83, 25 }, expected = { 84, 87 }, result = { 82, 85 }, - settings = {}, }, { path = PATH, @@ -112,7 +102,6 @@ local data_for_split = { cursor = { 91, 30 }, expected = { 97, 101 }, result = { 90, 94 }, - settings = {}, }, { path = PATH, @@ -122,12 +111,51 @@ local data_for_split = { cursor = { 108, 19 }, expected = { 109, 115 }, result = { 107, 113 }, - settings = {}, + }, + { + path = PATH, + mode = 'split', + lang = LANG, + desc = 'lang "%s", field "value" in match_arm, preset default', + cursor = { 119, 9 }, + expected = { 123, 126 }, + result = { 118, 121 }, + }, + { + path = PATH, + mode = 'split', + lang = LANG, + desc = 'lang "%s", node "block" in match_arm, preset default', + cursor = { 131, 11 }, + expected = { 135, 139 }, + result = { 130, 134 }, + }, + { + path = PATH, + mode = 'split', + lang = LANG, + desc = 'lang "%s", field "body" inside closure_expression, preset default', + cursor = { 143, 18 }, + expected = { 145, 148 }, + result = { 142, 145 }, + }, + { + path = PATH, + mode = 'split', + lang = LANG, + desc = 'lang "%s", node "block" inside closure_expression with 2 named children, preset default', + cursor = { 151, 20 }, + expected = { 153, 157 }, + result = { 150, 154 }, }, } +local treesj = require('treesj') +local opts = {} +treesj.setup(opts) + describe('TreeSJ SPLIT:', function() for _, value in ipairs(data_for_split) do - tu._test_format(value) + tu._test_format(value, treesj) end end) diff --git a/tests/langs/scss/join_spec.lua b/tests/langs/scss/join_spec.lua new file mode 100644 index 0000000..5a5a82f --- /dev/null +++ b/tests/langs/scss/join_spec.lua @@ -0,0 +1,53 @@ +local tu = require('tests.utils') + +local PATH = './tests/sample/index.scss' +local LANG = 'scss' + +local data_for_join = { + { + path = PATH, + mode = 'join', + lang = LANG, + desc = 'lang "%s", node "block", preset default', + cursor = { 6, 9 }, + expected = { 1, 2 }, + result = { 4, 5 }, + }, + { + path = PATH, + mode = 'join', + lang = LANG, + desc = 'lang "%s", node "keyframe_block_list", preset default', + cursor = { 17, 4 }, + expected = { 12, 13 }, + result = { 15, 16 }, + }, + { + path = PATH, + mode = 'join', + lang = LANG, + desc = 'lang "%s", node "arguments", preset default', + cursor = { 33, 4 }, + expected = { 24, 25 }, + result = { 30, 31 }, + }, + { + path = PATH, + mode = 'join', + lang = LANG, + desc = 'lang "%s", node "block" (nested), preset default', + cursor = { 56, 9 }, + expected = { 51, 52 }, + result = { 54, 55 }, + }, +} + +local treesj = require('treesj') +local opts = {} +treesj.setup(opts) + +describe('TreeSJ JOIN:', function() + for _, value in ipairs(data_for_join) do + tu._test_format(value, treesj) + end +end) diff --git a/tests/langs/scss/split_spec.lua b/tests/langs/scss/split_spec.lua new file mode 100644 index 0000000..ca18e36 --- /dev/null +++ b/tests/langs/scss/split_spec.lua @@ -0,0 +1,53 @@ +local tu = require('tests.utils') + +local PATH = './tests/sample/index.scss' +local LANG = 'scss' + +local data_for_split = { + { + path = PATH, + mode = 'split', + lang = LANG, + desc = 'lang "%s", node "block", preset default', + cursor = { 2, 20 }, + expected = { 4, 10 }, + result = { 1, 7 }, + }, + { + path = PATH, + mode = 'split', + lang = LANG, + desc = 'lang "%s", node "keyframe_block_list", preset default', + cursor = { 13, 25 }, + expected = { 15, 20 }, + result = { 12, 17 }, + }, + { + path = PATH, + mode = 'split', + lang = LANG, + desc = 'lang "%s", node "arguments", preset default', + cursor = { 25, 23 }, + expected = { 30, 48 }, + result = { 24, 42 }, + }, + { + path = PATH, + mode = 'split', + lang = LANG, + desc = 'lang "%s", node "block" (nested), preset default', + cursor = { 52, 18 }, + expected = { 54, 58 }, + result = { 51, 55 }, + }, +} + +local treesj = require('treesj') +local opts = {} +treesj.setup(opts) + +describe('TreeSJ SPLIT:', function() + for _, value in ipairs(data_for_split) do + tu._test_format(value, treesj) + end +end) diff --git a/tests/langs/scss_spec.lua b/tests/langs/scss_spec.lua deleted file mode 100644 index d0b4d74..0000000 --- a/tests/langs/scss_spec.lua +++ /dev/null @@ -1,102 +0,0 @@ -local tu = require('tests.utils') - -local PATH = './tests/sample/index.scss' -local LANG = 'scss' - -local data_for_split = { - { - path = PATH, - mode = 'split', - lang = LANG, - desc = 'lang "%s", node "block", preset default', - cursor = { 2, 20 }, - expected = { 4, 10 }, - result = { 1, 7 }, - settings = {}, - }, - { - path = PATH, - mode = 'split', - lang = LANG, - desc = 'lang "%s", node "keyframe_block_list", preset default', - cursor = { 13, 25 }, - expected = { 15, 20 }, - result = { 12, 17 }, - settings = {}, - }, - { - path = PATH, - mode = 'split', - lang = LANG, - desc = 'lang "%s", node "arguments", preset default', - cursor = { 25, 23 }, - expected = { 30, 48 }, - result = { 24, 42 }, - settings = {}, - }, - { - path = PATH, - mode = 'split', - lang = LANG, - desc = 'lang "%s", node "block" (nested), preset default', - cursor = { 52, 18 }, - expected = { 54, 58 }, - result = { 51, 55 }, - settings = {}, - }, -} - -local data_for_join = { - { - path = PATH, - mode = 'join', - lang = LANG, - desc = 'lang "%s", node "block", preset default', - cursor = { 6, 9 }, - expected = { 1, 2 }, - result = { 4, 5 }, - settings = {}, - }, - { - path = PATH, - mode = 'join', - lang = LANG, - desc = 'lang "%s", node "keyframe_block_list", preset default', - cursor = { 17, 4 }, - expected = { 12, 13 }, - result = { 15, 16 }, - settings = {}, - }, - { - path = PATH, - mode = 'join', - lang = LANG, - desc = 'lang "%s", node "arguments", preset default', - cursor = { 33, 4 }, - expected = { 24, 25 }, - result = { 30, 31 }, - settings = {}, - }, - { - path = PATH, - mode = 'join', - lang = LANG, - desc = 'lang "%s", node "block" (nested), preset default', - cursor = { 56, 9 }, - expected = { 51, 52 }, - result = { 54, 55 }, - settings = {}, - }, -} - -describe('TreeSJ SPLIT:', function() - for _, value in ipairs(data_for_split) do - tu._test_format(value) - end -end) - -describe('TreeSJ JOIN:', function() - for _, value in ipairs(data_for_join) do - tu._test_format(value) - end -end) diff --git a/tests/langs/svelte/join_spec.lua b/tests/langs/svelte/join_spec.lua new file mode 100644 index 0000000..f06034a --- /dev/null +++ b/tests/langs/svelte/join_spec.lua @@ -0,0 +1,35 @@ +local tu = require('tests.utils') + +local PATH = './tests/sample/index.svelte' +local LANG = 'svelte' + +local data_for_join = { + { + path = PATH, + mode = 'join', + lang = LANG, + desc = 'lang "%s", node "self_closing_tag", preset default', + cursor = { 7, 11 }, + expected = { 3, 4 }, + result = { 6, 7 }, + }, + { + path = PATH, + mode = 'join', + lang = LANG, + desc = 'lang "%s", node "element", preset default', + cursor = { 16, 6 }, + expected = { 11, 12 }, + result = { 14, 15 }, + }, +} + +local treesj = require('treesj') +local opts = {} +treesj.setup(opts) + +describe('TreeSJ JOIN:', function() + for _, value in ipairs(data_for_join) do + tu._test_format(value, treesj) + end +end) diff --git a/tests/langs/svelte/split_spec.lua b/tests/langs/svelte/split_spec.lua new file mode 100644 index 0000000..1927a11 --- /dev/null +++ b/tests/langs/svelte/split_spec.lua @@ -0,0 +1,35 @@ +local tu = require('tests.utils') + +local PATH = './tests/sample/index.svelte' +local LANG = 'svelte' + +local data_for_split = { + { + path = PATH, + mode = 'split', + lang = LANG, + desc = 'lang "%s", node "self_closing_tag", preset default', + cursor = { 4, 10 }, + expected = { 6, 9 }, + result = { 3, 6 }, + }, + { + path = PATH, + mode = 'split', + lang = LANG, + desc = 'lang "%s", node "element", preset default', + cursor = { 12, 10 }, + expected = { 14, 17 }, + result = { 11, 14 }, + }, +} + +local treesj = require('treesj') +local opts = {} +treesj.setup(opts) + +describe('TreeSJ SPLIT:', function() + for _, value in ipairs(data_for_split) do + tu._test_format(value, treesj) + end +end) diff --git a/tests/langs/svelte_spec.lua b/tests/langs/svelte_spec.lua deleted file mode 100644 index 4872d58..0000000 --- a/tests/langs/svelte_spec.lua +++ /dev/null @@ -1,62 +0,0 @@ -local tu = require('tests.utils') - -local PATH = './tests/sample/index.svelte' -local LANG = 'svelte' - -local data_for_split = { - { - path = PATH, - mode = 'split', - lang = LANG, - desc = 'lang "%s", node "self_closing_tag", preset default', - cursor = { 4, 10 }, - expected = { 6, 9 }, - result = { 3, 6 }, - settings = {}, - }, - { - path = PATH, - mode = 'split', - lang = LANG, - desc = 'lang "%s", node "element", preset default', - cursor = { 12, 10 }, - expected = { 14, 17 }, - result = { 11, 14 }, - settings = {}, - }, -} - -local data_for_join = { - { - path = PATH, - mode = 'join', - lang = LANG, - desc = 'lang "%s", node "self_closing_tag", preset default', - cursor = { 7, 11 }, - expected = { 3, 4 }, - result = { 6, 7 }, - settings = {}, - }, - { - path = PATH, - mode = 'join', - lang = LANG, - desc = 'lang "%s", node "element", preset default', - cursor = { 16, 6 }, - expected = { 11, 12 }, - result = { 14, 15 }, - settings = {}, - }, -} - -describe('TreeSJ SPLIT:', function() - for _, value in ipairs(data_for_split) do - tu._test_format(value) - end -end) - -describe('TreeSJ JOIN:', function() - for _, value in ipairs(data_for_join) do - tu._test_format(value) - end -end) diff --git a/tests/langs/template/join_spec.lua b/tests/langs/template/join_spec.lua new file mode 100644 index 0000000..2348545 --- /dev/null +++ b/tests/langs/template/join_spec.lua @@ -0,0 +1,26 @@ +local tu = require('tests.utils') + +local PATH = './tests/sample/index.TYPE_OF_FILE' +local LANG = 'NAME_OF_LANGUAGE' + +local data_for_join = { + { + path = PATH, + mode = 'join', + lang = LANG, + desc = 'lang "%s", node "block", preset default', + cursor = { 1, 0 }, + expected = { 0, 0 }, + result = { 0, 0 }, + }, +} + +local treesj = require('treesj') +local opts = {} +treesj.setup(opts) + +describe('TreeSJ JOIN:', function() + for _, value in ipairs(data_for_join) do + tu._test_format(value, treesj) + end +end) diff --git a/tests/langs/template.lua b/tests/langs/template/split_spec.lua similarity index 51% rename from tests/langs/template.lua rename to tests/langs/template/split_spec.lua index 7ffe11d..b875f18 100644 --- a/tests/langs/template.lua +++ b/tests/langs/template/split_spec.lua @@ -12,31 +12,15 @@ local data_for_split = { cursor = { 1, 0 }, expected = { 0, 0 }, result = { 0, 0 }, - settings = {}, }, } -local data_for_join = { - { - path = PATH, - mode = 'join', - lang = LANG, - desc = 'lang "%s", node "block", preset default', - cursor = { 1, 0 }, - expected = { 0, 0 }, - result = { 0, 0 }, - settings = {}, - }, -} +local treesj = require('treesj') +local opts = {} +treesj.setup(opts) describe('TreeSJ SPLIT:', function() for _, value in ipairs(data_for_split) do - tu._test_format(value) - end -end) - -describe('TreeSJ JOIN:', function() - for _, value in ipairs(data_for_join) do - tu._test_format(value) + tu._test_format(value, treesj) end end) diff --git a/tests/langs/toml/join_spec.lua b/tests/langs/toml/join_spec.lua new file mode 100644 index 0000000..47a9945 --- /dev/null +++ b/tests/langs/toml/join_spec.lua @@ -0,0 +1,35 @@ +local tu = require('tests.utils') + +local PATH = './tests/sample/index.toml' +local LANG = 'toml' + +local data_for_join = { + { + path = PATH, + mode = 'join', + lang = LANG, + desc = 'lang "%s", node "array", preset default', + cursor = { 4, 11 }, + expected = { 1, 2 }, + result = { 3, 4 }, + }, + { + path = PATH, + mode = 'join', + lang = LANG, + desc = 'lang "%s", node "array" (mix type), preset default', + cursor = { 16, 10 }, + expected = { 13, 14 }, + result = { 15, 16 }, + }, +} + +local treesj = require('treesj') +local opts = {} +treesj.setup(opts) + +describe('TreeSJ JOIN:', function() + for _, value in ipairs(data_for_join) do + tu._test_format(value, treesj) + end +end) diff --git a/tests/langs/toml/split_spec.lua b/tests/langs/toml/split_spec.lua new file mode 100644 index 0000000..bd63f4a --- /dev/null +++ b/tests/langs/toml/split_spec.lua @@ -0,0 +1,35 @@ +local tu = require('tests.utils') + +local PATH = './tests/sample/index.toml' +local LANG = 'toml' + +local data_for_split = { + { + path = PATH, + mode = 'split', + lang = LANG, + desc = 'lang "%s", node "array", preset default', + cursor = { 2, 13 }, + expected = { 3, 11 }, + result = { 1, 9 }, + }, + { + path = PATH, + mode = 'split', + lang = LANG, + desc = 'lang "%s", node "array" (mix type), preset default', + cursor = { 14, 10 }, + expected = { 15, 19 }, + result = { 13, 17 }, + }, +} + +local treesj = require('treesj') +local opts = {} +treesj.setup(opts) + +describe('TreeSJ SPLIT:', function() + for _, value in ipairs(data_for_split) do + tu._test_format(value, treesj) + end +end) diff --git a/tests/langs/toml_spec.lua b/tests/langs/toml_spec.lua deleted file mode 100644 index 01d8b4a..0000000 --- a/tests/langs/toml_spec.lua +++ /dev/null @@ -1,62 +0,0 @@ -local tu = require('tests.utils') - -local PATH = './tests/sample/index.toml' -local LANG = 'toml' - -local data_for_split = { - { - path = PATH, - mode = 'split', - lang = LANG, - desc = 'lang "%s", node "array", preset default', - cursor = { 2, 13 }, - expected = { 3, 11 }, - result = { 1, 9 }, - settings = {}, - }, - { - path = PATH, - mode = 'split', - lang = LANG, - desc = 'lang "%s", node "array" (mix type), preset default', - cursor = { 14, 10 }, - expected = { 15, 19 }, - result = { 13, 17 }, - settings = {}, - }, -} - -local data_for_join = { - { - path = PATH, - mode = 'join', - lang = LANG, - desc = 'lang "%s", node "array", preset default', - cursor = { 4, 11 }, - expected = { 1, 2 }, - result = { 3, 4 }, - settings = {}, - }, - { - path = PATH, - mode = 'join', - lang = LANG, - desc = 'lang "%s", node "array" (mix type), preset default', - cursor = { 16, 10 }, - expected = { 13, 14 }, - result = { 15, 16 }, - settings = {}, - }, -} - -describe('TreeSJ SPLIT:', function() - for _, value in ipairs(data_for_split) do - tu._test_format(value) - end -end) - -describe('TreeSJ JOIN:', function() - for _, value in ipairs(data_for_join) do - tu._test_format(value) - end -end) diff --git a/tests/langs/typescript/tsx_spec.lua b/tests/langs/typescript/tsx_spec.lua index 10f28bf..e1d624e 100644 --- a/tests/langs/typescript/tsx_spec.lua +++ b/tests/langs/typescript/tsx_spec.lua @@ -12,7 +12,6 @@ local data_for_split = { cursor = { 3, 19 }, expected = { 4, 12 }, result = { 2, 10 }, - settings = {}, }, { path = PATH, @@ -22,7 +21,6 @@ local data_for_split = { cursor = { 14, 17 }, expected = { 15, 20 }, result = { 13, 18 }, - settings = {}, }, { path = PATH, @@ -32,7 +30,6 @@ local data_for_split = { cursor = { 24, 20 }, expected = { 25, 31 }, result = { 23, 29 }, - settings = {}, }, { path = PATH, @@ -42,7 +39,6 @@ local data_for_split = { cursor = { 33, 16 }, expected = { 34, 40 }, result = { 32, 38 }, - settings = {}, }, { path = PATH, @@ -52,7 +48,6 @@ local data_for_split = { cursor = { 42, 83 }, expected = { 43, 46 }, result = { 41, 44 }, - settings = {}, }, } @@ -65,7 +60,6 @@ local data_for_join = { cursor = { 6, 8 }, expected = { 2, 3 }, result = { 4, 5 }, - settings = {}, }, { path = PATH, @@ -75,7 +69,6 @@ local data_for_join = { cursor = { 17, 4 }, expected = { 13, 14 }, result = { 15, 16 }, - settings = {}, }, { path = PATH, @@ -85,7 +78,6 @@ local data_for_join = { cursor = { 27, 12 }, expected = { 23, 24 }, result = { 25, 26 }, - settings = {}, }, { path = PATH, @@ -95,7 +87,6 @@ local data_for_join = { cursor = { 36, 14 }, expected = { 32, 33 }, result = { 34, 35 }, - settings = {}, }, { path = PATH, @@ -105,18 +96,21 @@ local data_for_join = { cursor = { 45, 9 }, expected = { 41, 42 }, result = { 43, 44 }, - settings = {}, }, } +local treesj = require('treesj') +local opts = {} +treesj.setup(opts) + describe('TreeSJ SPLIT:', function() for _, value in ipairs(data_for_split) do - tu._test_format(value) + tu._test_format(value, treesj) end end) describe('TreeSJ JOIN:', function() for _, value in ipairs(data_for_join) do - tu._test_format(value) + tu._test_format(value, treesj) end end) diff --git a/tests/langs/typescript/typescript_spec.lua b/tests/langs/typescript/typescript_spec.lua index 2cbabb1..0f9acee 100644 --- a/tests/langs/typescript/typescript_spec.lua +++ b/tests/langs/typescript/typescript_spec.lua @@ -12,7 +12,6 @@ local data_for_split = { cursor = { 2, 21 }, expected = { 4, 9 }, result = { 1, 6 }, - settings = {}, }, { path = PATH, @@ -22,7 +21,6 @@ local data_for_split = { cursor = { 12, 15 }, expected = { 14, 18 }, result = { 11, 15 }, - settings = {}, }, { path = PATH, @@ -32,7 +30,6 @@ local data_for_split = { cursor = { 21, 19 }, expected = { 23, 27 }, result = { 20, 24 }, - settings = {}, }, { path = PATH, @@ -42,7 +39,6 @@ local data_for_split = { cursor = { 30, 10 }, expected = { 32, 36 }, result = { 29, 33 }, - settings = {}, }, { path = PATH, @@ -52,7 +48,6 @@ local data_for_split = { cursor = { 39, 20 }, expected = { 41, 45 }, result = { 38, 42 }, - settings = {}, }, { path = PATH, @@ -62,7 +57,6 @@ local data_for_split = { cursor = { 48, 25 }, expected = { 50, 54 }, result = { 47, 51 }, - settings = {}, }, } @@ -75,7 +69,6 @@ local data_for_join = { cursor = { 6, 12 }, expected = { 1, 2 }, result = { 4, 5 }, - settings = {}, }, { path = PATH, @@ -85,7 +78,6 @@ local data_for_join = { cursor = { 17, 3 }, expected = { 11, 12 }, result = { 14, 15 }, - settings = {}, }, { path = PATH, @@ -95,7 +87,6 @@ local data_for_join = { cursor = { 25, 8 }, expected = { 20, 21 }, result = { 23, 24 }, - settings = {}, }, { path = PATH, @@ -105,7 +96,6 @@ local data_for_join = { cursor = { 34, 3 }, expected = { 29, 30 }, result = { 32, 33 }, - settings = {}, }, { path = PATH, @@ -115,7 +105,6 @@ local data_for_join = { cursor = { 43, 3 }, expected = { 38, 39 }, result = { 41, 42 }, - settings = {}, }, { path = PATH, @@ -125,18 +114,21 @@ local data_for_join = { cursor = { 52, 9 }, expected = { 47, 48 }, result = { 50, 51 }, - settings = {}, }, } +local treesj = require('treesj') +local opts = {} +treesj.setup(opts) + describe('TreeSJ SPLIT:', function() for _, value in ipairs(data_for_split) do - tu._test_format(value) + tu._test_format(value, treesj) end end) describe('TreeSJ JOIN:', function() for _, value in ipairs(data_for_join) do - tu._test_format(value) + tu._test_format(value, treesj) end end) diff --git a/tests/langs/vue/join_spec.lua b/tests/langs/vue/join_spec.lua new file mode 100644 index 0000000..b0b0cd1 --- /dev/null +++ b/tests/langs/vue/join_spec.lua @@ -0,0 +1,44 @@ +local tu = require('tests.utils') + +local PATH = './tests/sample/index.vue' +local LANG = 'vue' + +local data_for_join = { + { + path = PATH, + mode = 'join', + lang = LANG, + desc = 'lang "%s", node "start_tag", preset default', + cursor = { 8, 9 }, + expected = { 3, 4 }, + result = { 6, 7 }, + }, + { + path = PATH, + mode = 'join', + lang = LANG, + desc = 'lang "%s", node "self_closing_tag", preset default', + cursor = { 17, 8 }, + expected = { 12, 13 }, + result = { 15, 16 }, + }, + { + path = PATH, + mode = 'join', + lang = LANG, + desc = 'lang "%s", node "element", preset default', + cursor = { 26, 6 }, + expected = { 21, 22 }, + result = { 24, 25 }, + }, +} + +local treesj = require('treesj') +local opts = {} +treesj.setup(opts) + +describe('TreeSJ JOIN:', function() + for _, value in ipairs(data_for_join) do + tu._test_format(value, treesj) + end +end) diff --git a/tests/langs/vue/split_spec.lua b/tests/langs/vue/split_spec.lua new file mode 100644 index 0000000..add42a7 --- /dev/null +++ b/tests/langs/vue/split_spec.lua @@ -0,0 +1,44 @@ +local tu = require('tests.utils') + +local PATH = './tests/sample/index.vue' +local LANG = 'vue' + +local data_for_split = { + { + path = PATH, + mode = 'split', + lang = LANG, + desc = 'lang "%s", node "start_tag", preset default', + cursor = { 4, 18 }, + expected = { 6, 10 }, + result = { 3, 7 }, + }, + { + path = PATH, + mode = 'split', + lang = LANG, + desc = 'lang "%s", node "self_closing_tag", preset default', + cursor = { 13, 17 }, + expected = { 15, 19 }, + result = { 12, 16 }, + }, + { + path = PATH, + mode = 'split', + lang = LANG, + desc = 'lang "%s", node "element", preset default', + cursor = { 22, 59 }, + expected = { 24, 27 }, + result = { 21, 24 }, + }, +} + +local treesj = require('treesj') +local opts = {} +treesj.setup(opts) + +describe('TreeSJ SPLIT:', function() + for _, value in ipairs(data_for_split) do + tu._test_format(value, treesj) + end +end) diff --git a/tests/langs/vue_spec.lua b/tests/langs/vue_spec.lua deleted file mode 100644 index 1f2ab2a..0000000 --- a/tests/langs/vue_spec.lua +++ /dev/null @@ -1,82 +0,0 @@ -local tu = require('tests.utils') - -local PATH = './tests/sample/index.vue' -local LANG = 'vue' - -local data_for_split = { - { - path = PATH, - mode = 'split', - lang = LANG, - desc = 'lang "%s", node "start_tag", preset default', - cursor = { 4, 18 }, - expected = { 6, 10 }, - result = { 3, 7 }, - settings = {}, - }, - { - path = PATH, - mode = 'split', - lang = LANG, - desc = 'lang "%s", node "self_closing_tag", preset default', - cursor = { 13, 17 }, - expected = { 15, 19 }, - result = { 12, 16 }, - settings = {}, - }, - { - path = PATH, - mode = 'split', - lang = LANG, - desc = 'lang "%s", node "element", preset default', - cursor = { 22, 59 }, - expected = { 24, 27 }, - result = { 21, 24 }, - settings = {}, - }, -} - -local data_for_join = { - { - path = PATH, - mode = 'join', - lang = LANG, - desc = 'lang "%s", node "start_tag", preset default', - cursor = { 8, 9 }, - expected = { 3, 4 }, - result = { 6, 7 }, - settings = {}, - }, - { - path = PATH, - mode = 'join', - lang = LANG, - desc = 'lang "%s", node "self_closing_tag", preset default', - cursor = { 17, 8 }, - expected = { 12, 13 }, - result = { 15, 16 }, - settings = {}, - }, - { - path = PATH, - mode = 'join', - lang = LANG, - desc = 'lang "%s", node "element", preset default', - cursor = { 26, 6 }, - expected = { 21, 22 }, - result = { 24, 25 }, - settings = {}, - }, -} - -describe('TreeSJ SPLIT:', function() - for _, value in ipairs(data_for_split) do - tu._test_format(value) - end -end) - -describe('TreeSJ JOIN:', function() - for _, value in ipairs(data_for_join) do - tu._test_format(value) - end -end) diff --git a/tests/langs/yaml/join_spec.lua b/tests/langs/yaml/join_spec.lua new file mode 100644 index 0000000..926a81f --- /dev/null +++ b/tests/langs/yaml/join_spec.lua @@ -0,0 +1,44 @@ +local tu = require('tests.utils') + +local PATH = './tests/sample/index.yml' +local LANG = 'yaml' + +local data_for_join = { + { + path = PATH, + mode = 'join', + lang = LANG, + desc = 'lang "%s", node "block_mapping", preset default', + cursor = { 4, 8 }, + expected = { 0, 1 }, + result = { 2, 3 }, + }, + { + path = PATH, + mode = 'join', + lang = LANG, + desc = 'lang "%s", node "block_sequence", preset default', + cursor = { 10, 5 }, + expected = { 6, 7 }, + result = { 8, 9 }, + }, + { + path = PATH, + mode = 'join', + lang = LANG, + desc = 'lang "%s", node "block_mapping" (mixed), preset default', + cursor = { 16, 7 }, + expected = { 12, 13 }, + result = { 14, 15 }, + }, +} + +local treesj = require('treesj') +local opts = {} +treesj.setup(opts) + +describe('TreeSJ JOIN:', function() + for _, value in ipairs(data_for_join) do + tu._test_format(value, treesj) + end +end) diff --git a/tests/langs/yaml/split_spec.lua b/tests/langs/yaml/split_spec.lua new file mode 100644 index 0000000..2f54f2b --- /dev/null +++ b/tests/langs/yaml/split_spec.lua @@ -0,0 +1,44 @@ +local tu = require('tests.utils') + +local PATH = './tests/sample/index.yml' +local LANG = 'yaml' + +local data_for_split = { + { + path = PATH, + mode = 'split', + lang = LANG, + desc = 'lang "%s", node "flow_mapping", preset default', + cursor = { 1, 6 }, + expected = { 2, 5 }, + result = { 0, 3 }, + }, + { + path = PATH, + mode = 'split', + lang = LANG, + desc = 'lang "%s", node "flow_sequence", preset default', + cursor = { 7, 8 }, + expected = { 8, 11 }, + result = { 6, 9 }, + }, + { + path = PATH, + mode = 'split', + lang = LANG, + desc = 'lang "%s", node "flow_mapping" (mixed), preset default', + cursor = { 13, 8 }, + expected = { 14, 19 }, + result = { 12, 17 }, + }, +} + +local treesj = require('treesj') +local opts = {} +treesj.setup(opts) + +describe('TreeSJ SPLIT:', function() + for _, value in ipairs(data_for_split) do + tu._test_format(value, treesj) + end +end) diff --git a/tests/langs/yaml_spec.lua b/tests/langs/yaml_spec.lua deleted file mode 100644 index 8b25e35..0000000 --- a/tests/langs/yaml_spec.lua +++ /dev/null @@ -1,82 +0,0 @@ -local tu = require('tests.utils') - -local PATH = './tests/sample/index.yml' -local LANG = 'yaml' - -local data_for_split = { - { - path = PATH, - mode = 'split', - lang = LANG, - desc = 'lang "%s", node "flow_mapping", preset default', - cursor = { 1, 6 }, - expected = { 2, 5 }, - result = { 0, 3 }, - settings = {}, - }, - { - path = PATH, - mode = 'split', - lang = LANG, - desc = 'lang "%s", node "flow_sequence", preset default', - cursor = { 7, 8 }, - expected = { 8, 11 }, - result = { 6, 9 }, - settings = {}, - }, - { - path = PATH, - mode = 'split', - lang = LANG, - desc = 'lang "%s", node "flow_mapping" (mixed), preset default', - cursor = { 13, 8 }, - expected = { 14, 19 }, - result = { 12, 17 }, - settings = {}, - }, -} - -local data_for_join = { - { - path = PATH, - mode = 'join', - lang = LANG, - desc = 'lang "%s", node "block_mapping", preset default', - cursor = { 4, 8 }, - expected = { 0, 1 }, - result = { 2, 3 }, - settings = {}, - }, - { - path = PATH, - mode = 'join', - lang = LANG, - desc = 'lang "%s", node "block_sequence", preset default', - cursor = { 10, 5 }, - expected = { 6, 7 }, - result = { 8, 9 }, - settings = {}, - }, - { - path = PATH, - mode = 'join', - lang = LANG, - desc = 'lang "%s", node "block_mapping" (mixed), preset default', - cursor = { 16, 7 }, - expected = { 12, 13 }, - result = { 14, 15 }, - settings = {}, - }, -} - -describe('TreeSJ SPLIT:', function() - for _, value in ipairs(data_for_split) do - tu._test_format(value) - end -end) - -describe('TreeSJ JOIN:', function() - for _, value in ipairs(data_for_join) do - tu._test_format(value) - end -end) diff --git a/tests/minimal_tab.lua b/tests/minimal_tab.lua deleted file mode 100644 index 2b3bafc..0000000 --- a/tests/minimal_tab.lua +++ /dev/null @@ -1,43 +0,0 @@ --- Based on https://github.com/folke/lazy.nvim/blob/3bde7b5ba8b99941b314a75d8650a0a6c8552144/tests/init.lua - -local CWD = vim.loop.cwd() .. '/' - -vim.opt.shiftwidth = 2 -vim.opt.writebackup = false -vim.opt.swapfile = false -vim.opt.shadafile = 'NONE' -vim.opt.expandtab = false - -vim.cmd([[set runtimepath=$VIMRUNTIME]]) -vim.opt.runtimepath:append(CWD) -vim.opt.packpath = { CWD .. '.tests/site' } - -local dependencies = { - 'nvim-lua/plenary.nvim', - 'nvim-treesitter/nvim-treesitter', -} - -local function install_dep(plugin) - local name = plugin:match('.*/(.*)') - local package_root = CWD .. '.tests/site/pack/deps/start/' - if not vim.loop.fs_stat(package_root .. name) then - vim.fn.mkdir(package_root, 'p') - vim.fn.system({ - 'git', - 'clone', - '--depth=1', - 'https://github.com/' .. plugin .. '.git', - package_root .. '/' .. name, - }) - end -end - -for _, plugin in ipairs(dependencies) do - install_dep(plugin) -end - -require('plenary.busted') -require('nvim-treesitter.configs').setup({ - ensure_installed = require('treesj.langs').configured_langs, - sync_install = true, -}) diff --git a/tests/sample/index.js b/tests/sample/index.js index 9842a38..77b7d88 100644 --- a/tests/sample/index.js +++ b/tests/sample/index.js @@ -114,3 +114,52 @@ if (b <= a) { add(2, 1) + sum(2, 1); return (console.log(1), 1) >= 1; } + +// RESULT OF JOIN (field "body" in "arrow_function" with "call_expression", preset default) +const myFunc = (param) => console.log([ 1, 2, 3 ]); + +// RESULT OF SPLIT (field "body" in "arrow_function" with "call_expression", preset default) +const myFunc = (param) => { + return console.log([ 1, 2, 3 ]) +}; + +// RESULT OF JOIN (field "body" in "arrow_function" with "identifier", preset default) +const myFunc = (param) => param; + +// RESULT OF SPLIT (field "body" in "arrow_function" with "identifier", preset default) +const myFunc = (param) => { + return param +}; + +// RESULT OF JOIN (field "body" in "arrow_function" with "parenthesized_expression", preset default) +const myFunc = (param) => ({ one: 'one' }); + +// RESULT OF SPLIT (field "body" in "arrow_function" with "parenthesized_expression", preset default) +const myFunc = (param) => { + return { one: 'one' } +}; + +// RESULT OF JOIN (field "body" in "arrow_function" with "array", preset default) +const myFunc = (param) => [ 1, 2, 3 ]; + +// RESULT OF SPLIT (field "body" in "arrow_function" with "array", preset default) +const myFunc = (param) => { + return [ 1, 2, 3 ] +}; + +// RESULT OF JOIN (field "body" in "arrow_function" with "parenthesized_expression" with 'sequence_expression', preset default) +const myFunc = (param) => (1, 2); + +// RESULT OF SPLIT (field "body" in "arrow_function" with "parenthesized_expression" with 'sequence_expression', preset default) +const myFunc = (param) => { + return (1, 2) +}; + +// RESULT OF JOIN (field "body" in "arrow_function" with "statement_block" with >1 named child, preset default) +const myFunc = (param) => { doSomething(); andThisDoTo(); }; + +// RESULT OF SPLIT (field "body" in "arrow_function" with "parenthesized_expression" with 'sequence_expression', preset default) +const myFunc = (param) => { + doSomething(); + andThisDoTo(); +}; diff --git a/tests/sample/index.py b/tests/sample/index.py index 0dce967..4081294 100644 --- a/tests/sample/index.py +++ b/tests/sample/index.py @@ -155,5 +155,14 @@ def adder(y): for k, v in items } +# RESULT OF JOIN (node "import_from_statement", preset default) +from re import search, match,sub + +# RESULT OF SPLIT (node "import_from_statement", preset default) +from re import ( + search, + match, + sub, +) # code from https://learnxinyminutes.com/docs/python/ diff --git a/tests/sample/index.rb b/tests/sample/index.rb index 4d7a089..78a579d 100644 --- a/tests/sample/index.rb +++ b/tests/sample/index.rb @@ -64,3 +64,54 @@ def double(x) x.each do |y| puts y end + +# RESULT OF JOIN (node "if_modifier to if", preset default) +return false if true + +# RESULT OF SPLIT (node "if to if_modifier", preset default) +if true + return false +end + +# RESULT OF JOIN (node "conditional to if", preset default) +cond ? do_that('cond') : do_this('not nond') + +# RESULT OF SPLIT (node "if to conditional", preset default) +if cond + do_that('cond') +else + do_this('not nond') +end + +# RESULT OF JOIN (node "conditional to if", preset default) +cond ? do_that('cond') : do_this('not nond') + +# RESULT OF SPLIT (node "if to conditional", preset default) +if cond + do_that('cond') +else + do_this('not nond') +end + +# RESULT OF JOIN (node "when", preset default) +case +when true then print('false') +end + +# RESULT OF SPLIT (node "when", preset default) +case +when true + print('false') +end + +# RESULT OF JOIN (field "right" inside "operator_assignment", preset default) +def config + @config ||= method +end + +# RESULT OF SPLIT (field "right" inside "operator_assignment", preset default) +def config + @config ||= begin + method + end +end diff --git a/tests/sample/index.rs b/tests/sample/index.rs index 6474efc..48fd8a4 100644 --- a/tests/sample/index.rs +++ b/tests/sample/index.rs @@ -113,3 +113,45 @@ use path::to::{ Use, List, }; + +match x { + // RESULT OF JOIN (field "value" in match_arm, preset default) + _ => 12 +} + +match x { + // RESULT OF SPLIT (field "value" in match_arm, preset default) + _ => { + 12 + } +} + +match x { + // RESULT OF JOIN (node "block" with 2 named children in match_arm, preset default) + _ => { 12; 13 } +} + +match x { + // RESULT OF SPLIT (node "block" with 2 named children in match_arm, preset default) + _ => { + 12; + 13 + } +} + +// RESULT OF JOIN (field "body" inside closure_expression, preset default) +let a = b.map(|x| x * x); + +// RESULT OF SPLIT (field "body" inside closure_expression, preset default) +let a = b.map(|x| { + x * x +}); + +// RESULT OF JOIN (node "block" inside closure_expression with 2 named children, preset default) +let a = b.map(|x| { doSomething(); x * x } ); + +// RESULT OF SPLIT (node "block" inside closure_expression with 2 named children, preset default) +let a = b.map(|x| { + doSomething(); + x * x +} ); diff --git a/tests/sample/index.yml b/tests/sample/index.yml index 1e8934f..f2e6643 100644 --- a/tests/sample/index.yml +++ b/tests/sample/index.yml @@ -1,18 +1,18 @@ obj: { one: one, two: two } -obj: +obj: one: one two: two array: [ one, two ] -array: +array: - one - two -mixed: { pair: true, array: [ value1, value2 ] } +mixed: { pair: true, array: [ value1, value2 ] } -mixed: +mixed: pair: true array: - value1 diff --git a/tests/sample/index_recursive.js b/tests/sample/index_recursive.js index d82dd26..2be8c12 100644 --- a/tests/sample/index_recursive.js +++ b/tests/sample/index_recursive.js @@ -46,3 +46,25 @@ cell.siblings = [ ...new Set([ ...cell.siblings, ...currentPlaceSiblings ]) ]; cell.siblings = [ ...new Set([ ...cell.siblings, ...currentPlaceSiblings ]), ]; + +// RESULT OF JOIN (field "body" in "arrow_function" with "parenthesized_expression", preset with recursive = true) +const myFunc = (param) => ({ one: 'one' }); + +// RESULT OF SPLIT (field "body" in "arrow_function" with "parenthesized_expression", preset with recursive = true) +const myFunc = (param) => { + return { + one: 'one', + } +}; + +// RESULT OF JOIN (field "body" in "arrow_function" with "array", preset with recursive = true) +const myFunc = (param) => [ 1, 2, 3 ]; + +// RESULT OF SPLIT (field "body" in "arrow_function" with "array", preset with recursive = true) +const myFunc = (param) => { + return [ + 1, + 2, + 3, + ] +}; diff --git a/tests/utils.lua b/tests/utils.lua index 3814945..c585b27 100644 --- a/tests/utils.lua +++ b/tests/utils.lua @@ -7,9 +7,7 @@ local function open_ang_get_buf(path) return a.nvim_get_current_buf() end -function M._test_format(v) - local treesj = require('treesj') - treesj.setup(v.settings) +function M._test_format(v, treesj) local desc = v.desc:format(v.lang) it(desc, function() @@ -24,9 +22,9 @@ function M._test_format(v) end) end -function M._test_chold(v) - local treesj = require('treesj') - treesj.setup(v.settings) +function M._test_chold(v, treesj) + -- local treesj = require('treesj') + -- treesj.setup(v.settings) local desc = v.desc:format(v.mode) it(desc, function()