diff --git a/lua/nvim-ts-autotag/internal.lua b/lua/nvim-ts-autotag/internal.lua index ab3e572..2285958 100644 --- a/lua/nvim-ts-autotag/internal.lua +++ b/lua/nvim-ts-autotag/internal.lua @@ -1,28 +1,32 @@ local _, ts_utils = pcall(require, 'nvim-treesitter.ts_utils') -local get_node_text = require('nvim-ts-autotag.utils').get_node_text -local configs = require'nvim-treesitter.configs' -local parsers = require'nvim-treesitter.parsers' +local configs = require('nvim-treesitter.configs') +local parsers = require('nvim-treesitter.parsers') +local log = require('nvim-ts-autotag._log') +local utils = require('nvim-ts-autotag.utils') local M = {} +-- stylua: ignore M.tbl_filetypes = { 'html', 'javascript', 'typescript', 'javascriptreact', 'typescriptreact', 'svelte', 'vue', 'tsx', 'jsx', 'rescript', 'xml', 'php', 'markdown', - 'glimmer','handlebars','hbs', + 'glimmer', 'handlebars', 'hbs', 'htmldjango' } +-- stylua: ignore M.tbl_skipTag = { 'area', 'base', 'br', 'col', 'command', 'embed', 'hr', 'img', 'slot', - 'input', 'keygen', 'link', 'meta', 'param', 'source', 'track', 'wbr','menuitem' + 'input', 'keygen', 'link', 'meta', 'param', 'source', 'track', 'wbr', 'menuitem' } -local ERROR_TAG = "ERROR" +local ERROR_TAG = 'ERROR' +-- stylua: ignore local HTML_TAG = { - filetypes = {'html', 'php', 'xml', 'markdown', 'htmldjango'}, + filetypes = { 'html', 'php', 'xml', 'markdown', 'htmldjango' }, start_tag_pattern = 'start_tag', start_name_tag_pattern = 'tag_name', end_tag_pattern = "end_tag", @@ -30,84 +34,94 @@ local HTML_TAG = { close_tag_pattern = 'erroneous_end_tag', close_name_tag_pattern = 'erroneous_end_tag_name', element_tag = 'element', - skip_tag_pattern = {'quoted_attribute_value', 'end_tag'}, + skip_tag_pattern = { 'quoted_attribute_value', 'end_tag' }, } - +-- stylua: ignore local JSX_TAG = { - filetypes = { + filetypes = { 'typescriptreact', 'javascriptreact', 'javascript.jsx', - 'typescript.tsx', 'javascript', 'typescript', 'rescript'}, + 'typescript.tsx', 'javascript', 'typescript', 'rescript' + }, + start_tag_pattern = 'jsx_opening_element|start_tag', + start_name_tag_pattern = 'identifier|nested_identifier|tag_name|jsx_identifier', + end_tag_pattern = 'jsx_closing_element|end_tag', + end_name_tag_pattern = 'identifier|tag_name', + close_tag_pattern = 'jsx_closing_element|nested_identifier|jsx_identifier|erroneous_end_tag|end_tag', + close_name_tag_pattern = 'identifier|nested_identifier|jsx_identifier|erroneous_end_tag_name|tag_name', + element_tag = 'jsx_element|element', + skip_tag_pattern = { + 'jsx_closing_element', 'jsx_expression', 'string', 'jsx_attribute', 'end_tag', + 'string_fragment' + }, - start_tag_pattern = 'jsx_opening_element', - start_name_tag_pattern = 'identifier|nested_identifier|jsx_identifier', - end_tag_pattern = "jsx_closing_element", - end_name_tag_pattern = "identifier|nested_identifier|jsx_identifier", - close_tag_pattern = 'jsx_closing_element', - close_name_tag_pattern = 'identifier|nested_identifier|jsx_identifier', - element_tag = 'jsx_element', - skip_tag_pattern = {'jsx_closing_element','jsx_expression', 'string', 'jsx_attribute'}, } +-- stylua: ignore local HBS_TAG = { - filetypes = {'glimmer', 'handlebars','hbs'}, - start_tag_pattern = 'element_node_start', - start_name_tag_pattern = 'tag_name', - end_tag_pattern = "element_node_end", - end_name_tag_pattern = "tag_name", - close_tag_pattern = 'element_node_end', - close_name_tag_pattern = 'tag_name', - element_tag = 'element_node', - skip_tag_pattern = {'element_node_end', 'attribute_node', 'concat_statement' }, + filetypes = { 'glimmer', 'handlebars', 'hbs', 'htmldjango' }, + start_tag_pattern = 'element_node_start', + start_name_tag_pattern = 'tag_name', + end_tag_pattern = 'element_node_end', + end_name_tag_pattern = 'tag_name', + close_tag_pattern = 'element_node_end', + close_name_tag_pattern = 'tag_name', + element_tag = 'element_node', + skip_tag_pattern = { 'element_node_end', 'attribute_node', 'concat_statement' }, } +-- stylua: ignore local SVELTE_TAG = { - filetypes = {'svelte'}, + filetypes = { 'svelte' }, start_tag_pattern = 'start_tag', start_name_tag_pattern = 'tag_name', - end_tag_pattern = "end_tag", - end_name_tag_pattern = "tag_name", + end_tag_pattern = 'end_tag', + end_name_tag_pattern = 'tag_name', close_tag_pattern = 'ERROR', close_name_tag_pattern = 'ERROR', element_tag = 'element', - skip_tag_pattern = {'quoted_attribute_value', 'end_tag'}, + skip_tag_pattern = { 'quoted_attribute_value', 'end_tag' }, } local all_tag = { HBS_TAG, SVELTE_TAG, - JSX_TAG + JSX_TAG, } M.enable_rename = true -M.enable_close = true +M.enable_close = true -M.setup = function (opts) - opts = opts or {} +M.setup = function(opts) + opts = opts or {} M.tbl_filetypes = opts.filetypes or M.tbl_filetypes - M.tbl_skipTag = opts.skip_tag or M.tbl_skipTag + M.tbl_skipTag = opts.skip_tag or M.tbl_skipTag M.enable_rename = opts.enable_rename or M.enable_rename - M.enable_close = opts.enable_close or M.enable_close + M.enable_close = opts.enable_close or M.enable_close end local function is_in_table(tbl, val) - if tbl == nil then return false end + if tbl == nil then + return false + end for _, value in pairs(tbl) do - if val== value then return true end + if val == value then + return true + end end return false end -M.is_supported = function (lang) - return is_in_table(M.tbl_filetypes,lang) +M.is_supported = function(lang) + return is_in_table(M.tbl_filetypes, lang) end -local buffer_tag={} +local buffer_tag = {} local setup_ts_tag = function() local bufnr = vim.api.nvim_get_current_buf() - for _,value in pairs(all_tag) do - if is_in_table(value.filetypes,vim.bo.filetype) then + for _, value in pairs(all_tag) do + if is_in_table(value.filetypes, vim.bo.filetype) then buffer_tag[bufnr] = value return value end @@ -120,34 +134,43 @@ local function get_ts_tag() end local function find_child_match(opts) - local target = opts.target - local pattern = opts.pattern + local target = opts.target + local pattern = opts.pattern local skip_tag_pattern = opts.skip_tag_pattern - assert(target ~= nil, "find child target not nil :" .. pattern) - for node in target:iter_children() do - local node_type = node:type() - if node_type ~= nil and - node_type == pattern and - not is_in_table(skip_tag_pattern, node_type) - then - return node + if target == nil or pattern == nil then + return nil + end + local tbl_pattern = vim.split(pattern, '|') + for _, ptn in pairs(tbl_pattern) do + for node in target:iter_children() do + local node_type = node:type() + if node_type ~= nil + and node_type == ptn + and not is_in_table(skip_tag_pattern, node_type) + then + return node + end end end end local function find_parent_match(opts) - local target = opts.target - local max_depth = opts.max_depth or 10 - local pattern = opts.pattern + local target = opts.target + local max_depth = opts.max_depth or 10 + local pattern = opts.pattern local skip_tag_pattern = opts.skip_tag_pattern - assert(target ~= nil, "find parent target not nil :" .. pattern) - local cur_depth = 0 - local cur_node = target - local tbl_pattern = vim.split(pattern, "|") - for _,ptn in pairs(tbl_pattern) do + if target == nil or pattern == nil then + return nil + end + local tbl_pattern = vim.split(pattern, '|') + for _, ptn in pairs(tbl_pattern) do + local cur_node = target + local cur_depth = 0 while cur_node ~= nil do local node_type = cur_node:type() - if is_in_table(skip_tag_pattern, node_type) then return nil end + if is_in_table(skip_tag_pattern, node_type) then + return nil + end if node_type ~= nil and node_type == ptn then return cur_node elseif cur_depth < max_depth then @@ -158,61 +181,69 @@ local function find_parent_match(opts) end end end - return nil end + return nil +end local function get_tag_name(node) local tag_name = nil if node ~= nil then - tag_name = get_node_text(node, vim.api.nvim_get_current_buf())[1] + tag_name = utils.get_node_text(node)[1] + if tag_name and #tag_name > 3 then + tag_name = tag_name:gsub('', ''):gsub('<', '') + end end return tag_name end local function find_tag_node(opt) - local target = opt.target or ts_utils.get_node_at_cursor() - local tag_pattern = opt.tag_pattern + local target = opt.target or ts_utils.get_node_at_cursor() + local tag_pattern = opt.tag_pattern local name_tag_pattern = opt.name_tag_pattern local skip_tag_pattern = opt.skip_tag_pattern - local find_child = opt.find_child or false + local find_child = opt.find_child or false local node if find_child then - node = find_child_match({ - target = target, - pattern = tag_pattern, - skip_tag_pattern = skip_tag_pattern + node = find_child_match({ + target = target, + pattern = tag_pattern, + skip_tag_pattern = skip_tag_pattern, }) else - node = find_parent_match({ - target = target, - pattern = tag_pattern, - skip_tag_pattern = skip_tag_pattern + node = find_parent_match({ + target = target, + pattern = tag_pattern, + skip_tag_pattern = skip_tag_pattern, }) end - if node == nil then return nil end + if node == nil then + return nil + end local name_node = node local tbl_name_pattern = {} - if string.match(name_tag_pattern,"%|") then + if string.match(name_tag_pattern, '%|') then tbl_name_pattern = vim.split(name_tag_pattern, '|') for _, pattern in pairs(tbl_name_pattern) do name_node = find_child_match({ - target = node, - pattern = pattern + target = node, + pattern = pattern, }) - if name_node then return name_node end + if name_node then + return name_node + end end end tbl_name_pattern = vim.split(name_tag_pattern, '>') for _, pattern in pairs(tbl_name_pattern) do name_node = find_child_match({ - target = name_node, - pattern = pattern + target = name_node, + pattern = pattern, }) end -- check current node is have same name of tag_match - if is_in_table(tbl_name_pattern, node:type()) - then return node + if is_in_table(tbl_name_pattern, node:type()) then + return node end return name_node end @@ -222,36 +253,39 @@ local function find_child_tag_node(opt) return find_tag_node(opt) end - local function check_close_tag() local ts_tag = get_ts_tag() - if not ts_tag then return false end - local tag_node = find_tag_node({ - tag_pattern = ts_tag.start_tag_pattern, + if not ts_tag then + return false + end + local tag_node = find_tag_node({ + tag_pattern = ts_tag.start_tag_pattern, name_tag_pattern = ts_tag.start_name_tag_pattern, - skip_tag_pattern = ts_tag.skip_tag_pattern + skip_tag_pattern = ts_tag.skip_tag_pattern, }) - if tag_node ~=nil then + if tag_node ~= nil then local tag_name = get_tag_name(tag_node) if tag_name ~= nil and is_in_table(M.tbl_skipTag, tag_name) then return false end - -- case 6,9 check close on exist node - local element_node = find_parent_match({ - target = tag_node, - pattern = ts_tag.element_tag, - max_depth = 2 - }) if tag_node ~= nil then + -- case 6,9 check close on exist node + local element_node = find_parent_match({ + target = tag_node, + pattern = ts_tag.element_tag, + max_depth = 2, + }) local close_tag_node = find_child_tag_node({ - target = element_node, - tag_pattern = ts_tag.end_tag_pattern, - name_tag_pattern = ts_tag.end_name_tag_pattern, + target = element_node, + tag_pattern = ts_tag.end_tag_pattern, + name_tag_pattern = ts_tag.end_name_tag_pattern, }) if close_tag_node ~= nil then local start_row = tag_node:range() local close_start_row = close_tag_node:range() - if start_row == close_start_row and tag_name == get_tag_name(close_tag_node) then + if start_row == close_start_row + and tag_name == get_tag_name(close_tag_node) + then return false end end @@ -261,35 +295,43 @@ local function check_close_tag() return false end -M.close_tag = function () +M.close_tag = function() local buf_parser = parsers.get_parser() - if not buf_parser then return end + if not buf_parser then + return + end buf_parser:parse() local result, tag_name = check_close_tag() if result == true and tag_name ~= nil then - vim.cmd(string.format([[normal! a]],tag_name)) - vim.cmd[[normal! F>]] + vim.cmd(string.format([[normal! a]], tag_name)) + vim.cmd([[normal! F>]]) end end local function replace_text_node(node, tag_name) - if node == nil then return end + if node == nil then + return + end local start_row, start_col, end_row, end_col = node:range() if start_row == end_row then local line = vim.fn.getline(start_row + 1) - local newline = line:sub(0, start_col) .. tag_name .. line:sub(end_col + 1, string.len(line)) - vim.fn.setline(start_row + 1,{newline}) + local newline = line:sub(0, start_col) + .. tag_name + .. line:sub(end_col + 1, string.len(line)) + vim.fn.setline(start_row + 1, { newline }) end end - -local function validate_tag_regex(node,start_regex,end_regex) - if node == nil then return false end - local texts = get_node_text(node, vim.api.nvim_get_current_buf()) - if - string.match(texts[1],start_regex) - and string.match(texts[#texts],end_regex) - then return true end +local function validate_tag_regex(node, start_regex, end_regex) + if node == nil then + return false + end + local texts = utils.get_node_text(node) + if string.match(texts[1], start_regex) + and string.match(texts[#texts], end_regex) + then + return true + end return false end @@ -298,88 +340,134 @@ end -- end local function validate_start_tag(node) - return validate_tag_regex(node,"^%<%w","%>$") + return validate_tag_regex(node, '^%<%w', '%>$') end local function validate_close_tag(node) - return validate_tag_regex(node,"^%<%/%w","%>$") + return validate_tag_regex(node, '^%<%/%w', '%>$') end local function rename_start_tag() local ts_tag = get_ts_tag() - if not ts_tag then return end - local tag_node = find_tag_node({ - tag_pattern = ts_tag.start_tag_pattern, + if not ts_tag then + return + end + local tag_node = find_tag_node({ + tag_pattern = ts_tag.start_tag_pattern, name_tag_pattern = ts_tag.start_name_tag_pattern, + skip_tag_pattern = ts_tag.skip_tag_pattern }) - if tag_node == nil then return end - if not validate_start_tag(tag_node:parent()) then return end + if tag_node == nil then + return + end + if not validate_start_tag(tag_node:parent()) then + return + end + local tag_name = get_tag_name(tag_node) local parent_node = tag_node - tag_node = find_parent_match({ - target = parent_node, - pattern = ts_tag.element_tag .. "|" .. ERROR_TAG, - max_depth = 2 + tag_node = find_parent_match({ + target = parent_node, + pattern = ts_tag.element_tag .. '|' .. ERROR_TAG, + max_depth = 2, }) - if tag_node == nil then return end + if tag_node == nil then + return + end local close_tag_node = find_child_tag_node({ - target = tag_node, - tag_pattern = ts_tag.close_tag_pattern, - name_tag_pattern = ts_tag.close_name_tag_pattern, + target = tag_node, + tag_pattern = ts_tag.close_tag_pattern, + name_tag_pattern = ts_tag.close_name_tag_pattern, }) + if close_tag_node == nil then + close_tag_node = find_child_tag_node({ + target = tag_node:parent(), + tag_pattern = ts_tag.close_tag_pattern, + name_tag_pattern = ts_tag.close_name_tag_pattern, + }) + end + if close_tag_node ~= nil then local error_node = find_child_match({ target = tag_node, - pattern = ERROR_TAG + pattern = ERROR_TAG, }) if error_node == nil then + log.debug('do replace') local close_tag_name = get_tag_name(close_tag_node) + log.debug(close_tag_name) + + -- verify parent node is same of close_tag_node (test case: 22) + if close_tag_node ~= nil and tag_node ~= nil then + local tag_parent = get_tag_name(tag_node:parent()) + -- log.debug(utils.dump_node(tag_node:parent())) + if tag_parent == close_tag_name + and not utils.verify_node(tag_node:parent(), close_tag_name) + then + log.debug('skip it have same') + return + end + end + if tag_name ~= close_tag_name then replace_text_node(close_tag_node, tag_name) end else - local error_tag = get_tag_name(error_node) - if error_tag=='' then - replace_text_node(error_node, "") + -- tsx node is empty + if error_tag == '' then + replace_text_node(error_node, '') end -- have both parent node and child node is error if close_tag_node:type() == ERROR_TAG then - replace_text_node(error_node, "") + replace_text_node(error_node, '') end end - end end local function rename_end_tag() local ts_tag = get_ts_tag() - if not ts_tag then return end + if not ts_tag then + return + end local tag_node = find_tag_node({ tag_pattern = ts_tag.close_tag_pattern, name_tag_pattern = ts_tag.close_name_tag_pattern, }) + -- log.debug(tag_node:type()) + if tag_node == nil then + return + end + + -- we check if that node text match + if not (validate_close_tag(tag_node:parent()) or validate_close_tag(tag_node)) + then + return + end - if tag_node == nil then return end - if not validate_close_tag(tag_node:parent()) then return end local tag_name = get_tag_name(tag_node) - tag_node = find_parent_match({ - target = tag_node, - pattern = ts_tag.element_tag, - max_depth = 2 + tag_node = find_parent_match({ + target = tag_node, + pattern = ts_tag.element_tag, + max_depth = 2, }) - if tag_node == nil then return end + if tag_node == nil then + return + end local start_tag_node = find_child_tag_node({ - target = tag_node, - tag_pattern = ts_tag.start_tag_pattern, - name_tag_pattern = ts_tag.start_name_tag_pattern, + target = tag_node, + tag_pattern = ts_tag.start_tag_pattern, + name_tag_pattern = ts_tag.start_name_tag_pattern, }) - if not validate_start_tag(start_tag_node:parent()) then return end + if not validate_start_tag(start_tag_node:parent()) then + return + end if start_tag_node ~= nil then local start_tag_name = get_tag_name(start_tag_node) if tag_name ~= start_tag_name then @@ -390,10 +478,10 @@ end local function validate_rename() local cursor = vim.api.nvim_win_get_cursor(0) - local line = vim.fn.getline(cursor[1]) - local char = line:sub(cursor[2] + 1, cursor[2] + 1) + local line = vim.api.nvim_get_current_line() + local char = line:sub(cursor[2] + 1, cursor[2] + 1) -- only rename when last character is a word - if string.match(char,'%w') then + if string.match(char, '%w') then return true end return false @@ -407,27 +495,31 @@ M.rename_tag = function () end end -M.attach = function (bufnr,lang) +M.attach = function(bufnr, lang) M.lang = lang local config = configs.get_module('autotag') M.setup(config) if is_in_table(M.tbl_filetypes, vim.bo.filetype) then setup_ts_tag() if M.enable_close == true then - vim.cmd[[inoremap > >:lua require('nvim-ts-autotag.internal').close_tag()a]] + vim.cmd( + [[inoremap > >:lua require('nvim-ts-autotag.internal').close_tag()a]] + ) end if M.enable_rename == true then bufnr = bufnr or vim.api.nvim_get_current_buf() - vim.cmd(string.format( - [[autocmd! InsertLeave call v:lua.require('nvim-ts-autotag.internal').rename_tag() ]], - bufnr - )) + vim.cmd( + string.format( + [[autocmd! InsertLeave call v:lua.require('nvim-ts-autotag.internal').rename_tag() ]], + bufnr + ) + ) end end end -M.detach = function (bufnr) - bufnr = tonumber(bufnr) or vim.api.nvim_get_current_buf() +M.detach = function() + local bufnr = vim.api.nvim_get_current_buf() buffer_tag[bufnr] = nil end diff --git a/lua/nvim-ts-autotag/utils.lua b/lua/nvim-ts-autotag/utils.lua index f269215..17950ee 100644 --- a/lua/nvim-ts-autotag/utils.lua +++ b/lua/nvim-ts-autotag/utils.lua @@ -1,17 +1,31 @@ -local log = require('nvim-ts-autotag._log') local _, ts_utils = pcall(require, 'nvim-treesitter.ts_utils') +local log = require('nvim-ts-autotag._log') local get_node_text = vim.treesitter.query.get_node_text or ts_utils.get_node_text local M = {} -M.get_node_text = function(...) - local txt = get_node_text(...) - return vim.split(txt, '\n') +M.get_node_text = function(node) + local txt = get_node_text(node, vim.api.nvim_get_current_buf()) + return vim.split(txt, '\n') or {} end +M.verify_node = function(node, node_tag) + local txt = get_node_text(node, vim.api.nvim_get_current_buf()) + if + txt:match(string.format('^<%s>', node_tag)) + and txt:match(string.format('$', node_tag)) + then + return true + end + return false +end +M.get_cursor = function(bufnr) + local row, col = unpack(vim.api.nvim_win_get_cursor(bufnr or 0)) + return row - 1, col +end M.dump_node = function(node) local text = M.get_node_text(node) for _, txt in pairs(text) do - print(txt) + log.debug(txt) end end diff --git a/tests/closetag_spec.lua b/tests/closetag_spec.lua index 11a4bb4..c04e7bd 100644 --- a/tests/closetag_spec.lua +++ b/tests/closetag_spec.lua @@ -1,289 +1,209 @@ - if not _G.test_close then - return + return end -local parser_config = require "nvim-treesitter.parsers".get_parser_configs() -local ts = require 'nvim-treesitter.configs' +local ts = require('nvim-treesitter.configs') local helpers = {} - -parser_config.rescript = { - install_info = { - url = "https://github.com/nkrkv/nvim-treesitter-rescript", - files = {"src/parser.c", "src/scanner.c"}, - branch = "main", - }, - maintainers = { "@nkrkv" }, - filetype = "rescript", -} - - -ts.setup { - ensure_installed = 'maintained', - highlight = {enable = true}, -} +ts.setup({ + ensure_installed = _G.ts_filetypes, + highlight = { enable = true }, +}) local eq = assert.are.same function helpers.feed(text, feed_opts) - feed_opts = feed_opts or 'n' - local to_feed = vim.api.nvim_replace_termcodes(text, true, false, true) - vim.api.nvim_feedkeys(to_feed, feed_opts, true) + feed_opts = feed_opts or 'n' + local to_feed = vim.api.nvim_replace_termcodes(text, true, false, true) + vim.api.nvim_feedkeys(to_feed, feed_opts, true) end function helpers.insert(text) - helpers.feed('a' .. text, 'x') + helpers.feed('a' .. text, 'x') end local data = { - { - name = "1 html close tag" , - filepath = './sample/index.html', - filetype = "html", - linenr = 10, - key = [[>]], - before = [[|]] - }, - { - name = "2 html close tag" , - filepath = './sample/index.html', - filetype = "html", - linenr = 10, - key = [[>]], - before = [[
|
]] - }, - { - name = "3 html not close tag on close tag" , - filepath = './sample/index.html', - filetype = "html", - linenr = 10, - key = [[>]], - before = [[
aaaa
|]] - }, - { - name = "4 html not close on input tag" , - filepath = './sample/index.html', - filetype = "html", - linenr = 10, - key = [[>]], - before = [[| ]] - }, - { - name = "5 html not close inside quote" , - filepath = './sample/index.html', - filetype = "html", - linenr = 10, - key = [[>]], - before = [[
]], - after = [[
]] - }, - { - name = "6 html not close on exist tag" , - filepath = './sample/index.html', - filetype = "html", - linenr = 10, - key = [[>]], - before = [[
]], - after = [[
|
]] - }, - { - name = "7 typescriptreact close tag" , - filepath = './sample/index.tsx', - filetype = "typescriptreact", - linenr = 12, - key = [[>]], - before = [[|]] - }, - { - name = "8 typescriptreact close" , - filepath = './sample/index.tsx', - filetype = "typescriptreact", - linenr = 12, - key = [[>]], - before = [[
|
]] - }, - { - name = "9 typescriptreact not close on exist tag" , - filepath = './sample/index.tsx', - filetype = "typescriptreact", - linenr = 12, - key = [[>]], - before = [[
]], - after = [[
|
]] - }, - { - name = "10 typescriptreact close on inline script" , - filepath = './sample/index.tsx', - filetype = "typescriptreact", - linenr = 9, - key = [[>]], - before = [[const a = () =>
|
]] - }, - { + { + name = '1 html close tag', + filepath = './sample/index.html', + filetype = 'html', + linenr = 10, + key = [[>]], + before = [[|]], + }, + { + name = '2 html close tag', + filepath = './sample/index.html', + filetype = 'html', + linenr = 10, + key = [[>]], + before = [[
|
]], + }, + { + name = '3 html not close tag on close tag', + filepath = './sample/index.html', + filetype = 'html', + linenr = 10, + key = [[>]], + before = [[
aaaa
|]], + }, + { + name = '4 html not close on input tag', + filepath = './sample/index.html', + filetype = 'html', + linenr = 10, + key = [[>]], + before = [[| ]], + }, + { + name = '5 html not close inside quote', + filepath = './sample/index.html', + filetype = 'html', + linenr = 10, + key = [[>]], + before = [[
]], + after = [[
]], + }, + { + name = '6 html not close on exist tag', + filepath = './sample/index.html', + filetype = 'html', + linenr = 10, + key = [[>]], + before = [[
]], + after = [[
|
]], + }, + { + name = '7 typescriptreact close tag', + filepath = './sample/index.tsx', + filetype = 'typescriptreact', + linenr = 12, + key = [[>]], + before = [[| ]], + }, + { + name = '8 typescriptreact close', + filepath = './sample/index.tsx', + filetype = 'typescriptreact', + linenr = 12, + key = [[>]], + before = [[
|
]], + }, + { + name = '9 typescriptreact not close on exist tag', + filepath = './sample/index.tsx', + filetype = 'typescriptreact', + linenr = 12, + key = [[>]], + before = [[
]], + after = [[
|
]], + }, + { + name = '10 typescriptreact close on inline script', + filepath = './sample/index.tsx', + filetype = 'typescriptreact', + linenr = 9, + key = [[>]], + before = [[const a = () =>
|
]], + }, + { - name = "11 typescriptreact not close on close tag" , - filepath = './sample/index.tsx', - filetype = "typescriptreact", - linenr = 12, - key = [[>]], - before = [[|]] - }, - { - name = "12 typescriptreact not close on expresion" , - filepath = './sample/index.tsx', - filetype = "typescriptreact", - linenr = 12, - key = [[>]], - before = [[ ]], - after = [[ ]] - }, - { - name = "13 typescriptreact not close on typescript" , - filepath = './sample/index.tsx', - filetype = "typescriptreact", - linenr = 6, - key = [[>]], - before = [[const data:Array| ]] - }, + name = '11 typescriptreact not close on close tag', + filepath = './sample/index.tsx', + filetype = 'typescriptreact', + linenr = 12, + key = [[>]], + before = [[| ]], + }, + { + name = '12 typescriptreact not close on expresion', + filepath = './sample/index.tsx', + filetype = 'typescriptreact', + linenr = 12, + key = [[>]], + before = [[ ]], + after = [[ ]], + }, + { + name = '13 typescriptreact not close on typescript', + filepath = './sample/index.tsx', + filetype = 'typescriptreact', + linenr = 6, + key = [[>]], + before = [[const data:Array| ]], + }, - { - name = "14 typescriptreact not close on script" , - filepath = './sample/index.tsx', - filetype = "typescriptreact", - linenr = 6, - key = [[>]], - before = [[{(card.data | 0) &&
}]], - after = [[{(card.data >| 0) &&
}]] - }, - { - name = "15 vue auto close tag" , - filepath = './sample/index.vue', - filetype = "vue", - linenr = 4, - key = [[>]], - before = [[|]] - }, - { - name = "16 vue not close on script", - filepath = './sample/index.vue', - filetype = "vue", - linenr = 12, - key = [[>]], - before = [[const data:Array| ]] - }, - { - name = "17 typescriptreact nested indentifer " , - filepath = './sample/index.tsx', - filetype = "typescriptreact", - linenr = 12, - key = [[>]], - before = [[| ]] - }, - { - name = "18 php div " , - filepath = './sample/index.php', - filetype = "php", - linenr = 25, - key = [[>]], - before = [[| ]] - }, - { - name = "19 rescript close tag", - filepath = './sample/index.res', - filetype = 'rescript', - linenr = 12, - key = [[>]], - before = [[|]] - }, - { - name = "20 rescript close", - filepath = './sample/index.res', - filetype = 'rescript', - linenr = 13, - key = [[>]], - before = [[
|
]], - }, - { - name = "21 rescript not close on exist tag" , - filepath = './sample/index.res', - filetype = "rescript", - linenr = 14, - key = [[>]], - before = [[
]], - after = [[
|
]] - }, - { - name = "22 rescript not close on close tag" , - filepath = './sample/index.res', - filetype = "rescript", - linenr = 15, - key = [[>]], - before = [[|]] - }, - { - name = "23 rescrpt not close on expresion" , - filepath = './sample/index.res', - filetype = "rescript", - linenr = 15, - key = [[>]], - before = [[ ]], - after = [[ ]] - }, + { + name = '14 typescriptreact not close on script', + filepath = './sample/index.tsx', + filetype = 'typescriptreact', + linenr = 6, + key = [[>]], + before = [[{(card.data | 0) &&
}]], + after = [[{(card.data >| 0) &&
}]], + }, + { + name = '15 vue auto close tag', + filepath = './sample/index.vue', + filetype = 'vue', + linenr = 4, + key = [[>]], + before = [[|]], + }, + { + name = '16 vue not close on script', + filepath = './sample/index.vue', + filetype = 'vue', + linenr = 12, + key = [[>]], + before = [[const data:Array| ]], + }, + { + name = '17 typescriptreact nested indentifer ', + filepath = './sample/index.tsx', + filetype = 'typescriptreact', + linenr = 12, + key = [[>]], + before = [[| ]], + }, + { + name = '18 php div ', + filepath = './sample/index.php', + filetype = 'php', + linenr = 25, + key = [[>]], + before = [[| ]], + }, + -- { + -- name = '19 markdown div ', + -- filepath = './sample/index.md', + -- filetype = 'markdown', + -- linenr = 4, + -- key = [[>]], + -- before = [[| ]], + -- }, } -local run_data = {} -for _, value in pairs(data) do - if value.only == true then - table.insert(run_data, value) - break - end -end -if #run_data == 0 then run_data = data end -local _, ts_utils = pcall(require, 'nvim-treesitter.ts_utils') -_G.TU=ts_utils - -local function Test(test_data) - for _, value in pairs(test_data) do - it("test "..value.name, function() - local before = string.gsub(value.before , '%|' , "") - local after = string.gsub(value.after , '%|' , "") - local p_before = string.find(value.before , '%|') - local p_after = string.find(value.after , '%|') - local line =value.linenr - if vim.fn.filereadable(vim.fn.expand(value.filepath)) == 1 then - vim.cmd(":bd!") - vim.cmd(":e " .. value.filepath) - vim.bo.filetype = value.filetype - vim.fn.setline(line , before) - vim.fn.cursor(line, p_before -1) - -- autotag.closeTag() - helpers.insert(value.key) - local result = vim.fn.getline(line) - local pos = vim.fn.getpos('.') - eq(after, result , "\n\n [ERROR TEXT]: " .. value.name .. "\n") - eq(p_after, pos[3] +1, "\n\n [ERROR POS]: " .. value.name .. "\n") - else - eq(false, true, "\n\n file not exist " .. value.filepath .. "\n") - end - end) - end -end +local autotag = require('nvim-ts-autotag') +autotag.test = true +local run_data = _G.Test_filter(data) describe('[close tag]', function() - Test(run_data) + _G.Test_withfile(run_data, { + mode = 'i', + cursor_add = 0, + before_each = function(value) end, + }) end) diff --git a/tests/minimal.vim b/tests/minimal.vim index a94b845..b51881c 100644 --- a/tests/minimal.vim +++ b/tests/minimal.vim @@ -7,6 +7,7 @@ set rtp +=../playground/ runtime! plugin/plenary.vim runtime! plugin/nvim-treesitter.vim runtime! plugin/playground.vim +runtime! plugin/nvim-treesitter-rescript set noswapfile @@ -18,13 +19,18 @@ set noautoindent set nocindent set nosmartindent set indentexpr= +set foldlevel=9999 lua << EOF _G.__is_log=true _G.test_rename = true _G.test_close = true +_G.ts_filetypes = { + 'html', 'javascript', 'typescript', 'svelte', 'vue', 'tsx', 'php', 'glimmer', 'rescript' +} require("plenary/busted") +vim.cmd[[luafile ./tests/test-utils.lua]] require("nvim-ts-autotag").setup() EOF diff --git a/tests/renametag_spec.lua b/tests/renametag_spec.lua index 7eba727..84eb0aa 100644 --- a/tests/renametag_spec.lua +++ b/tests/renametag_spec.lua @@ -1,292 +1,273 @@ local ts = require 'nvim-treesitter.configs' -local parser_config = require "nvim-treesitter.parsers".get_parser_configs() -parser_config.rescript = { - install_info = { - url = "https://github.com/nkrkv/nvim-treesitter-rescript", - files = {"src/parser.c", "src/scanner.c"}, - branch = "main", - }, - maintainers = { "@nkrkv" }, - filetype = "rescript", -} - -local log=require('nvim-ts-autotag._log') +local log = require('nvim-ts-autotag._log') if not _G.test_rename then - return + return end local helpers = {} -ts.setup { - ensure_installed = 'maintained', - highlight = { - use_languagetree = true, - enable = true - }, -} -local eq = assert.are.same +ts.setup({ + ensure_installed = _G.ts_filetypes, + highlight = { + use_languagetree = true, + enable = true, + }, + fold = { enable = false }, +}) function helpers.feed(text, feed_opts) - feed_opts = feed_opts or 'n' - local to_feed = vim.api.nvim_replace_termcodes(text, true, false, true) - vim.api.nvim_feedkeys(to_feed, feed_opts, true) + feed_opts = feed_opts or 'n' + local to_feed = vim.api.nvim_replace_termcodes(text, true, false, true) + vim.api.nvim_feedkeys(to_feed, feed_opts, true) end function helpers.insert(text) - helpers.feed('i' .. text, 'x') + helpers.feed('i' .. text, 'x') end local data = { - { - name = "html rename open tag" , - filepath = './sample/index.html', - filetype = "html", - linenr = 10, - key = [[ciwlala]], - before = [[ dsadsa ]], - after = [[ dsadsa ]] - }, - { - name = "html rename open tag with attr" , - filepath = './sample/index.html', - filetype = "html", - linenr = 10, - key = [[ciwlala]], - before = [[ dsadsa ]], - after = [[ dsadsa ]] - }, - { - name = "html rename close tag with attr" , - filepath = './sample/index.html', - filetype = "html", - linenr = 10, - key = [[ciwlala]], - before = [[
dsadsa ]], - after = [[ dsadsa ]] - }, - { - name = "html not rename close tag on char <" , - filepath = './sample/index.html', - filetype = "html", - linenr = 10, - key = [[i<]], - before = [[
dsadsa |/button> ]], - after = [[ dsadsa | ]] - }, - { - name = "html not rename close tag with not valid" , - filepath = './sample/index.html', - filetype = "html", - linenr = 12, - key = [[ciwlala]], - before = { - [[]] - }, - after = [[
]], --- [[
"]] --- }, --- after = [[
]] --- }, - { - name = "html not rename close tag with not valid" , - filepath = './sample/index.html', - filetype = "html", - linenr = 12, - key = [[ciwlala]], - before = { - [[
]], - }, - after = [[
]] - }, - { - name = "typescriptreact rename open tag" , - filepath = './sample/index.tsx', - filetype = "typescriptreact", - linenr = 12, - key = [[ciwlala]], - before = [[ dsadsa
]], - after = [[ dsadsa ]] - }, - { - name = "typescriptreact rename open tag with attr" , - filepath = './sample/index.tsx', - filetype = "typescriptreact", - linenr = 12, - key = [[ciwlala]], - before = [[ dsadsa
]], - after = [[ dsadsa ]] - }, - { - name = "typescriptreact rename close tag with attr" , - filepath = './sample/index.tsx', - filetype = "html", - linenr = 12, - key = [[ciwlala]], - before = [[
dsadsa ]], - after = [[ dsadsa ]] - }, - { - name = "17 typescriptreact nested indentifer " , - filepath = './sample/index.tsx', - filetype = "typescriptreact", - linenr = 12, - key = [[ciwlala]], - before = [[ ]], - after = [[| ]] - }, { - name = "18 rename empty node " , - filepath = './sample/index.tsx', - filetype = "typescriptreact", - linenr = 12, - key = [[ilala]], - before = [[<|>
]], - after = [[<|lala>
]] + name = 'html rename open tag', + filepath = './sample/index.html', + filetype = 'html', + linenr = 10, + key = [[ciwlala]], + before = [[ dsadsa
]], + after = [[ dsadsa ]], }, { - name = "19 rename start tag on svelte " , - filepath = './sample/index.svelte', - filetype = "svelte", - linenr = 18, - key = [[ciwlala]], - before = [[<|data>]], - after = [[<|lala>]] + name = 'html rename open tag with attr', + filepath = './sample/index.html', + filetype = 'html', + linenr = 10, + key = [[ciwlala]], + before = [[ dsadsa ]], + after = [[ dsadsa ]], }, { - name = "20 rename end tag on svelte " , - filepath = './sample/index.svelte', - filetype = "svelte", - linenr = 18, - key = [[ciwlala]], - before = [[]], - after = [[]] + name = 'html rename close tag with attr', + filepath = './sample/index.html', + filetype = 'html', + linenr = 10, + key = [[ciwlala]], + before = [[
dsadsa ]], + after = [[ dsadsa ]], }, { - name = "21 rescript rename open tag" , - filepath = './sample/index.res', - filetype = "rescript", - linenr = 12, - key = [[ciwlala]], - before = [[ dsadsa
]], - after = [[ dsadsa ]] + name = 'html not rename close tag on char <', + filepath = './sample/index.html', + filetype = 'html', + linenr = 10, + key = [[i<]], + before = [[
dsadsa |/button> ]], + after = [[
dsadsa <|/button> ]], }, { - name = "22 rescript rename open tag with attr" , - filepath = './sample/index.res', - filetype = "rescript", - linenr = 12, - key = [[ciwlala]], - before = [[ dsadsa
]], - after = [[ dsadsa ]] - }, - { - name = "23 rescript rename close tag with attr" , - filepath = './sample/index.res', - filetype = "rescript", - linenr = 12, - key = [[ciwlala]], - before = [[
dsadsa ]], - after = [[ dsadsa ]] - }, - -- { - -- only = true, - -- name = "18 rename node to empty node " , - -- filepath = './sample/index.tsx', - -- filetype = "typescriptreact", - -- linenr = 12, - -- key = [[ciw]], - -- before = [[
]], - -- after = [[<|>
]] - -- }, - -- TODO close tag with empty - -- { - -- only = true, - -- name = "18 rename end empty node " , - -- filepath = './sample/index.tsx', - -- filetype = "typescriptreact", + name = 'html not rename close tag with not valid', + filepath = './sample/index.html', + filetype = 'html', + linenr = 12, + key = [[ciwlala]], + before = { + [[]], + }, + after = [[<>
]], - -- after = [[<|lala>
]] - -- }, - -- { - -- name = "19 rename end empty node " , - -- filepath = './sample/index.tsx', - -- filetype = "typescriptreact", - -- linenr = 12, - -- key = [[ilala]], - -- before = [[<>
]], - -- after = [[<|lala>
]] - -- } + -- key = [[ciwlala]], + -- before = { + -- [[
]], + -- [[
"]] + -- }, + -- after = [[
]] + -- }, + { + + name = 'html not rename close tag with not valid', + filepath = './sample/index.html', + filetype = 'html', + linenr = 12, + key = [[ciwlala]], + before = { + [[
]], + }, + after = [[
]], + }, + { + name = 'typescriptreact rename open tag', + filepath = './sample/index.tsx', + filetype = 'typescriptreact', + linenr = 12, + key = [[ciwlala]], + before = [[ dsadsa
]], + after = [[ dsadsa ]], + }, + { + name = 'typescriptreact rename open tag with attr', + filepath = './sample/index.tsx', + filetype = 'typescriptreact', + linenr = 12, + key = [[ciwlala]], + before = [[ dsadsa
]], + after = [[ dsadsa ]], + }, + { + name = 'typescriptreact rename close tag with attr', + filepath = './sample/index.tsx', + filetype = 'html', + linenr = 12, + key = [[ciwlala]], + before = [[
dsadsa ]], + after = [[ dsadsa ]], + }, + { + name = '17 typescriptreact nested indentifer ', + filepath = './sample/index.tsx', + filetype = 'typescriptreact', + linenr = 12, + key = [[ciwlala]], + before = [[ ]], + after = [[ ]], + }, + { + name = '18 rename empty node ', + filepath = './sample/index.tsx', + filetype = 'typescriptreact', + linenr = 12, + key = [[ilala]], + before = [[<|>
]], + after = [[
]], + }, + { + name = '19 rename start tag on svelte ', + filepath = './sample/index.svelte', + filetype = 'svelte', + linenr = 18, + key = [[ciwlala]], + before = [[<|data>]], + after = [[]], + }, + { + name = '20 rename end tag on svelte ', + filepath = './sample/index.svelte', + filetype = 'svelte', + linenr = 18, + key = [[ciwlala]], + before = [[]], + after = [[]], + }, + { + name = "21 rescript rename open tag", + filepath = './sample/index.res', + filetype = "rescript", + linenr = 12, + key = [[ciwlala]], + before = [[ dsadsa
]], + after = [[ dsadsa ]] + }, + { + name = "22 rescript rename open tag with attr", + filepath = './sample/index.res', + filetype = "rescript", + linenr = 12, + key = [[ciwlala]], + before = [[ dsadsa ]], + after = [[ dsadsa ]] + }, + { + name = "23 rescript rename close tag with attr", + filepath = './sample/index.res', + filetype = "rescript", + linenr = 12, + key = [[ciwlala]], + before = [[
dsadsa ]], + after = [[ dsadsa ]] + }, + { + name = '24 test check rename same with parent', + filepath = './sample/index.tsx', + filetype = 'typescriptreact', + linenr = 12, + key = 'ciwkey', + before = { + '', + ' ', + '', + ' ', + '', + }, + after = { + '', + ' ', + '', + ' ', + '', + }, + }, + { + name = '25 rename start have same node with parent', + filepath = './sample/index.tsx', + filetype = 'typescriptreact', + linenr = 12, + key = [[ciwlala]], + before = { + '
', + ' ', + ' test ', + '
', + '
', + }, + after = { + '
', + ' ', + ' test ', + ' ', + '
', + }, + }, + { + name = '26 rename should not rename tag on attribute node', + filepath = './sample/index.tsx', + filetype = 'typescriptreact', + linenr = 12, + key = [[ciwlala]], + before = { + '
', + '', + '
', + '
', + '
', + '
', + '
', + }, + after = { + '
', + '', + '
', + '
', + '
', + '
', + '
', + }, + } } -local run_data = {} -for _, value in pairs(data) do - if value.only == true then - table.insert(run_data, value) - break - end -end -if #run_data == 0 then run_data = data end local autotag = require('nvim-ts-autotag') autotag.test = true -local function Test(test_data) - for _, value in pairs(test_data) do - it("test "..value.name, function() - local text_before={} - local pos_before={ - linenr = value.linenr, - colnr=0 - } - if not vim.tbl_islist(value.before) then - value.before = {value.before} - end - local numlnr = 0 - for _, text in pairs(value.before) do - local txt = string.gsub(text, '%|' , "") - table.insert(text_before, txt ) - if string.match( text, "%|") then - pos_before.colnr = string.find(text, '%|') - pos_before.linenr = pos_before.linenr + numlnr - end - numlnr = numlnr + 1 - end - local after = string.gsub(value.after, '%|' , "") - vim.bo.filetype = value.filetype - if vim.fn.filereadable(vim.fn.expand(value.filepath)) == 1 then - vim.cmd(":bd!") - vim.cmd(":e " .. value.filepath) - local bufnr=vim.api.nvim_get_current_buf() - vim.api.nvim_buf_set_lines(bufnr, pos_before.linenr -1, pos_before.linenr +#text_before, false, text_before) - vim.fn.cursor(pos_before.linenr, pos_before.colnr) - -- autotag.renameTag() - helpers.feed(value.key, 'x') - helpers.feed("",'x') - vim.wait(10) - local result = vim.fn.getline(pos_before.linenr) - eq(after, result , "\n\n ERROR: " .. value.name .. "\n") - else - eq(false, true, "\n\n file not exist " .. value.filepath .. "\n") - end - end) - end -end +local run_data = _G.Test_filter(data) describe('[rename tag]', function() - Test(run_data) + _G.Test_withfile(run_data, { + cursor_add = 0, + before_each = function(value) end, + }) end) - diff --git a/tests/test-utils.lua b/tests/test-utils.lua new file mode 100644 index 0000000..0b86a90 --- /dev/null +++ b/tests/test-utils.lua @@ -0,0 +1,191 @@ +local utils = require('nvim-ts-autotag.utils') +local _, ts_utils = pcall(require, 'nvim-treesitter.ts_utils') +local log = require('nvim-ts-autotag._log') +local api = vim.api + +local helpers = {} + +function helpers.feed(text, feed_opts, is_replace) + feed_opts = feed_opts or 'n' + if not is_replace then + text = vim.api.nvim_replace_termcodes(text, true, false, true) + end + vim.api.nvim_feedkeys(text, feed_opts, true) +end + +function helpers.insert(text, is_replace) + helpers.feed('i' .. text, 'x', is_replace) +end + +utils.insert_char = function(text) + api.nvim_put({ text }, 'c', true, true) +end + +utils.feed = function(text, num) + local result = '' + for _ = 1, num, 1 do + result = result .. text + end + api.nvim_feedkeys( + api.nvim_replace_termcodes(result, true, false, true), + 'x', + true + ) +end + +_G.eq = assert.are.same + +_G.Test_filter = function(data) + local run_data = {} + for _, value in pairs(data) do + if value.only == true then + table.insert(run_data, value) + break + end + end + if #run_data == 0 then + run_data = data + end + return run_data +end + +local compare_text = function(linenr, text_after, name, cursor_add, end_cursor) + cursor_add = cursor_add or 0 + local new_text = vim.api.nvim_buf_get_lines( + 0, + linenr - 1, + linenr + #text_after - 1, + true + ) + for i = 1, #text_after, 1 do + local t = string.gsub(text_after[i], '%|', '') + if + t + and new_text[i] + and t:gsub('%s+$', '') ~= new_text[i]:gsub('%s+$', '') + then + eq(t, new_text[i], '\n\n text error: ' .. name .. '\n') + end + local p_after = string.find(text_after[i], '%|') + if p_after then + local row, col = utils.get_cursor() + if end_cursor then + eq(row, linenr + i - 2, '\n\n cursor row error: ' .. name .. '\n') + eq( + col + 1, + end_cursor, + '\n\n end cursor column error : ' .. name .. '\n' + ) + else + eq(row, linenr + i - 2, '\n\n cursor row error: ' .. name .. '\n') + p_after = p_after + cursor_add + eq( + col, + math.max(p_after - 2, 0), + '\n\n cursor column error : ' .. name .. '\n' + ) + end + end + end + return true +end + +_G.Test_withfile = function(test_data, cb) + for _, value in pairs(test_data) do + it('test ' .. value.name, function(done) + local text_before = {} + value.linenr = value.linenr or 1 + local pos_before = { + linenr = value.linenr, + colnr = 0, + } + if not vim.tbl_islist(value.before) then + value.before = { value.before } + end + for index, text in pairs(value.before) do + local txt = string.gsub(text, '%|', '') + table.insert(text_before, txt) + if string.match(text, '%|') then + if string.find(text, '%|') then + pos_before.colnr = string.find(text, '%|') + pos_before.linenr = value.linenr + index - 1 + end + end + end + if not vim.tbl_islist(value.after) then + value.after = { value.after } + end + vim.bo.filetype = value.filetype or 'text' + vim.cmd(':bd!') + if cb.before_each then + cb.before_each(value) + end + if vim.fn.filereadable(vim.fn.expand(value.filepath)) == 1 then + vim.cmd(':e ' .. value.filepath) + if value.filetype then + vim.bo.filetype = value.filetype + end + vim.cmd(':e') + else + vim.cmd(':new') + if value.filetype then + vim.bo.filetype = value.filetype + end + end + vim.api.nvim_buf_set_lines( + 0, + value.linenr - 1, + value.linenr + #text_before, + false, + text_before + ) + vim.api.nvim_win_set_cursor( + 0, + { pos_before.linenr, pos_before.colnr - 1 } + ) + log.debug('insert:' .. value.key) + + if type(value.key) == 'string' then + if cb.mode == 'i' then + helpers.insert(value.key, value.not_replace_term_code) + else + helpers.feed(value.key, 'x') + end + else + for _, key in pairs(value.key) do + helpers.feed(key, 'x') + vim.wait(1) + end + end + vim.wait(2) + helpers.feed('') + compare_text( + value.linenr, + value.after, + value.name, + cb.cursor_add, + value.end_cursor + ) + if cb.after_each then + cb.after_each(value) + end + vim.cmd(':bd!') + end) + end +end + +_G.dump_node = function(node) + local text = ts_utils.get_node_text(node) + for _, txt in pairs(text) do + print(txt) + end +end + +_G.dump_node_text = function(target) + for node in target:iter_children() do + local node_type = node:type() + local text = ts_utils.get_node_text(node) + log.debug('type:' .. node_type .. ' ') + log.debug(text) + end +end