mirror of
https://github.com/windwp/nvim-ts-autotag.git
synced 2025-01-01 12:49:15 -06:00
fix: not rename and close tag on some case
This commit is contained in:
parent
1062700edf
commit
25698e4033
@ -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('>', ''):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</%s>]],tag_name))
|
||||
vim.cmd[[normal! F>]]
|
||||
vim.cmd(string.format([[normal! a</%s>]], 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, "</" .. tag_name .. ">")
|
||||
-- tsx node is empty
|
||||
if error_tag == '</>' then
|
||||
replace_text_node(error_node, '</' .. tag_name .. '>')
|
||||
end
|
||||
-- have both parent node and child node is error
|
||||
if close_tag_node:type() == ERROR_TAG then
|
||||
replace_text_node(error_node, "</" .. tag_name .. ">")
|
||||
replace_text_node(error_node, '</' .. tag_name .. '>')
|
||||
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 <silent> <buffer> > ><c-c>:lua require('nvim-ts-autotag.internal').close_tag()<CR>a]]
|
||||
vim.cmd(
|
||||
[[inoremap <silent> <buffer> > ><c-c>:lua require('nvim-ts-autotag.internal').close_tag()<CR>a]]
|
||||
)
|
||||
end
|
||||
if M.enable_rename == true then
|
||||
bufnr = bufnr or vim.api.nvim_get_current_buf()
|
||||
vim.cmd(string.format(
|
||||
[[autocmd! InsertLeave <buffer=%s> call v:lua.require('nvim-ts-autotag.internal').rename_tag() ]],
|
||||
bufnr
|
||||
))
|
||||
vim.cmd(
|
||||
string.format(
|
||||
[[autocmd! InsertLeave <buffer=%s> 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
|
||||
|
||||
|
@ -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('</%s>$', 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
|
||||
|
||||
|
@ -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 = [[<div|]],
|
||||
after = [[<div>|</div>]]
|
||||
},
|
||||
{
|
||||
name = "2 html close tag" ,
|
||||
filepath = './sample/index.html',
|
||||
filetype = "html",
|
||||
linenr = 10,
|
||||
key = [[>]],
|
||||
before = [[<div clas="laa"|]],
|
||||
after = [[<div clas="laa">|</div>]]
|
||||
},
|
||||
{
|
||||
name = "3 html not close tag on close tag" ,
|
||||
filepath = './sample/index.html',
|
||||
filetype = "html",
|
||||
linenr = 10,
|
||||
key = [[>]],
|
||||
before = [[<div>aa</div|]],
|
||||
after = [[<div>aa</div>|]]
|
||||
},
|
||||
{
|
||||
name = "4 html not close on input tag" ,
|
||||
filepath = './sample/index.html',
|
||||
filetype = "html",
|
||||
linenr = 10,
|
||||
key = [[>]],
|
||||
before = [[<input| ]],
|
||||
after = [[<input>| ]]
|
||||
},
|
||||
{
|
||||
name = "5 html not close inside quote" ,
|
||||
filepath = './sample/index.html',
|
||||
filetype = "html",
|
||||
linenr = 10,
|
||||
key = [[>]],
|
||||
before = [[<div class="aa|"> </div> ]],
|
||||
after = [[<div class="aa>|"> </div> ]]
|
||||
},
|
||||
{
|
||||
name = "6 html not close on exist tag" ,
|
||||
filepath = './sample/index.html',
|
||||
filetype = "html",
|
||||
linenr = 10,
|
||||
key = [[>]],
|
||||
before = [[<div><div|</div></div>]],
|
||||
after = [[<div><div>|</div></div>]]
|
||||
},
|
||||
{
|
||||
name = "7 typescriptreact close tag" ,
|
||||
filepath = './sample/index.tsx',
|
||||
filetype = "typescriptreact",
|
||||
linenr = 12,
|
||||
key = [[>]],
|
||||
before = [[<Img|]],
|
||||
after = [[<Img>|</Img>]]
|
||||
},
|
||||
{
|
||||
name = "8 typescriptreact close" ,
|
||||
filepath = './sample/index.tsx',
|
||||
filetype = "typescriptreact",
|
||||
linenr = 12,
|
||||
key = [[>]],
|
||||
before = [[<div class="abc"|]],
|
||||
after = [[<div class="abc">|</div>]]
|
||||
},
|
||||
{
|
||||
name = "9 typescriptreact not close on exist tag" ,
|
||||
filepath = './sample/index.tsx',
|
||||
filetype = "typescriptreact",
|
||||
linenr = 12,
|
||||
key = [[>]],
|
||||
before = [[<div><div|</div></div>]],
|
||||
after = [[<div><div>|</div></div>]]
|
||||
},
|
||||
{
|
||||
name = "10 typescriptreact close on inline script" ,
|
||||
filepath = './sample/index.tsx',
|
||||
filetype = "typescriptreact",
|
||||
linenr = 9,
|
||||
key = [[>]],
|
||||
before = [[const a = () => <div|]],
|
||||
after = [[const a = () => <div>|</div>]]
|
||||
},
|
||||
{
|
||||
{
|
||||
name = '1 html close tag',
|
||||
filepath = './sample/index.html',
|
||||
filetype = 'html',
|
||||
linenr = 10,
|
||||
key = [[>]],
|
||||
before = [[<div| ]],
|
||||
after = [[<div>|</div>]],
|
||||
},
|
||||
{
|
||||
name = '2 html close tag',
|
||||
filepath = './sample/index.html',
|
||||
filetype = 'html',
|
||||
linenr = 10,
|
||||
key = [[>]],
|
||||
before = [[<div clas="laa"| ]],
|
||||
after = [[<div clas="laa">|</div>]],
|
||||
},
|
||||
{
|
||||
name = '3 html not close tag on close tag',
|
||||
filepath = './sample/index.html',
|
||||
filetype = 'html',
|
||||
linenr = 10,
|
||||
key = [[>]],
|
||||
before = [[<div>aa</div| ]],
|
||||
after = [[<div>aa</div>|]],
|
||||
},
|
||||
{
|
||||
name = '4 html not close on input tag',
|
||||
filepath = './sample/index.html',
|
||||
filetype = 'html',
|
||||
linenr = 10,
|
||||
key = [[>]],
|
||||
before = [[<input| ]],
|
||||
after = [[<input>| ]],
|
||||
},
|
||||
{
|
||||
name = '5 html not close inside quote',
|
||||
filepath = './sample/index.html',
|
||||
filetype = 'html',
|
||||
linenr = 10,
|
||||
key = [[>]],
|
||||
before = [[<div class="aa|"> </div> ]],
|
||||
after = [[<div class="aa>|"> </div> ]],
|
||||
},
|
||||
{
|
||||
name = '6 html not close on exist tag',
|
||||
filepath = './sample/index.html',
|
||||
filetype = 'html',
|
||||
linenr = 10,
|
||||
key = [[>]],
|
||||
before = [[<div><div|</div></div>]],
|
||||
after = [[<div><div>|</div></div>]],
|
||||
},
|
||||
{
|
||||
name = '7 typescriptreact close tag',
|
||||
filepath = './sample/index.tsx',
|
||||
filetype = 'typescriptreact',
|
||||
linenr = 12,
|
||||
key = [[>]],
|
||||
before = [[<Img| ]],
|
||||
after = [[<Img>|</Img> ]],
|
||||
},
|
||||
{
|
||||
name = '8 typescriptreact close',
|
||||
filepath = './sample/index.tsx',
|
||||
filetype = 'typescriptreact',
|
||||
linenr = 12,
|
||||
key = [[>]],
|
||||
before = [[<div class="abc"| ]],
|
||||
after = [[<div class="abc">|</div> ]],
|
||||
},
|
||||
{
|
||||
name = '9 typescriptreact not close on exist tag',
|
||||
filepath = './sample/index.tsx',
|
||||
filetype = 'typescriptreact',
|
||||
linenr = 12,
|
||||
key = [[>]],
|
||||
before = [[<div><div|</div></div>]],
|
||||
after = [[<div><div>|</div></div>]],
|
||||
},
|
||||
{
|
||||
name = '10 typescriptreact close on inline script',
|
||||
filepath = './sample/index.tsx',
|
||||
filetype = 'typescriptreact',
|
||||
linenr = 9,
|
||||
key = [[>]],
|
||||
before = [[const a = () => <div| ]],
|
||||
after = [[const a = () => <div>|</div> ]],
|
||||
},
|
||||
{
|
||||
|
||||
name = "11 typescriptreact not close on close tag" ,
|
||||
filepath = './sample/index.tsx',
|
||||
filetype = "typescriptreact",
|
||||
linenr = 12,
|
||||
key = [[>]],
|
||||
before = [[<button className="btn " onClick={()}> </button|]],
|
||||
after = [[<button className="btn " onClick={()}> </button>|]]
|
||||
},
|
||||
{
|
||||
name = "12 typescriptreact not close on expresion" ,
|
||||
filepath = './sample/index.tsx',
|
||||
filetype = "typescriptreact",
|
||||
linenr = 12,
|
||||
key = [[>]],
|
||||
before = [[<button className="btn " onClick={(|)}> </button> ]],
|
||||
after = [[<button className="btn " onClick={(>|)}> </button> ]]
|
||||
},
|
||||
{
|
||||
name = "13 typescriptreact not close on typescript" ,
|
||||
filepath = './sample/index.tsx',
|
||||
filetype = "typescriptreact",
|
||||
linenr = 6,
|
||||
key = [[>]],
|
||||
before = [[const data:Array<string| ]],
|
||||
after = [[const data:Array<string>| ]]
|
||||
},
|
||||
name = '11 typescriptreact not close on close tag',
|
||||
filepath = './sample/index.tsx',
|
||||
filetype = 'typescriptreact',
|
||||
linenr = 12,
|
||||
key = [[>]],
|
||||
before = [[<button className="btn " onClick={()}> </button| ]],
|
||||
after = [[<button className="btn " onClick={()}> </button>| ]],
|
||||
},
|
||||
{
|
||||
name = '12 typescriptreact not close on expresion',
|
||||
filepath = './sample/index.tsx',
|
||||
filetype = 'typescriptreact',
|
||||
linenr = 12,
|
||||
key = [[>]],
|
||||
before = [[<button className="btn " onClick={(|)}> </button> ]],
|
||||
after = [[<button className="btn " onClick={(>|)}> </button> ]],
|
||||
},
|
||||
{
|
||||
name = '13 typescriptreact not close on typescript',
|
||||
filepath = './sample/index.tsx',
|
||||
filetype = 'typescriptreact',
|
||||
linenr = 6,
|
||||
key = [[>]],
|
||||
before = [[const data:Array<string| ]],
|
||||
after = [[const data:Array<string>| ]],
|
||||
},
|
||||
|
||||
{
|
||||
name = "14 typescriptreact not close on script" ,
|
||||
filepath = './sample/index.tsx',
|
||||
filetype = "typescriptreact",
|
||||
linenr = 6,
|
||||
key = [[>]],
|
||||
before = [[{(card.data | 0) && <div></div>}]],
|
||||
after = [[{(card.data >| 0) && <div></div>}]]
|
||||
},
|
||||
{
|
||||
name = "15 vue auto close tag" ,
|
||||
filepath = './sample/index.vue',
|
||||
filetype = "vue",
|
||||
linenr = 4,
|
||||
key = [[>]],
|
||||
before = [[<Img|]],
|
||||
after = [[<Img>|</Img>]]
|
||||
},
|
||||
{
|
||||
name = "16 vue not close on script",
|
||||
filepath = './sample/index.vue',
|
||||
filetype = "vue",
|
||||
linenr = 12,
|
||||
key = [[>]],
|
||||
before = [[const data:Array<string| ]],
|
||||
after = [[const data:Array<string>| ]]
|
||||
},
|
||||
{
|
||||
name = "17 typescriptreact nested indentifer " ,
|
||||
filepath = './sample/index.tsx',
|
||||
filetype = "typescriptreact",
|
||||
linenr = 12,
|
||||
key = [[>]],
|
||||
before = [[<Opt.Input| ]],
|
||||
after = [[<Opt.Input>|</Opt.Input> ]]
|
||||
},
|
||||
{
|
||||
name = "18 php div " ,
|
||||
filepath = './sample/index.php',
|
||||
filetype = "php",
|
||||
linenr = 25,
|
||||
key = [[>]],
|
||||
before = [[<div| ]],
|
||||
after = [[<div>|</div> ]]
|
||||
},
|
||||
{
|
||||
name = "19 rescript close tag",
|
||||
filepath = './sample/index.res',
|
||||
filetype = 'rescript',
|
||||
linenr = 12,
|
||||
key = [[>]],
|
||||
before = [[<Img|]],
|
||||
after = [[<Img>|</Img>]]
|
||||
},
|
||||
{
|
||||
name = "20 rescript close",
|
||||
filepath = './sample/index.res',
|
||||
filetype = 'rescript',
|
||||
linenr = 13,
|
||||
key = [[>]],
|
||||
before = [[<div class="abc"|]],
|
||||
after = [[<div class="abc">|</div>]],
|
||||
},
|
||||
{
|
||||
name = "21 rescript not close on exist tag" ,
|
||||
filepath = './sample/index.res',
|
||||
filetype = "rescript",
|
||||
linenr = 14,
|
||||
key = [[>]],
|
||||
before = [[<div><div|</div></div>]],
|
||||
after = [[<div><div>|</div></div>]]
|
||||
},
|
||||
{
|
||||
name = "22 rescript not close on close tag" ,
|
||||
filepath = './sample/index.res',
|
||||
filetype = "rescript",
|
||||
linenr = 15,
|
||||
key = [[>]],
|
||||
before = [[<button onClick> </button|]],
|
||||
after = [[<button onClick> </button>|]]
|
||||
},
|
||||
{
|
||||
name = "23 rescrpt not close on expresion" ,
|
||||
filepath = './sample/index.res',
|
||||
filetype = "rescript",
|
||||
linenr = 15,
|
||||
key = [[>]],
|
||||
before = [[<button onClick>{|}</button> ]],
|
||||
after = [[<button onClick>{>|}</button> ]]
|
||||
},
|
||||
{
|
||||
name = '14 typescriptreact not close on script',
|
||||
filepath = './sample/index.tsx',
|
||||
filetype = 'typescriptreact',
|
||||
linenr = 6,
|
||||
key = [[>]],
|
||||
before = [[{(card.data | 0) && <div></div>}]],
|
||||
after = [[{(card.data >| 0) && <div></div>}]],
|
||||
},
|
||||
{
|
||||
name = '15 vue auto close tag',
|
||||
filepath = './sample/index.vue',
|
||||
filetype = 'vue',
|
||||
linenr = 4,
|
||||
key = [[>]],
|
||||
before = [[<Img| ]],
|
||||
after = [[<Img>|</Img>]],
|
||||
},
|
||||
{
|
||||
name = '16 vue not close on script',
|
||||
filepath = './sample/index.vue',
|
||||
filetype = 'vue',
|
||||
linenr = 12,
|
||||
key = [[>]],
|
||||
before = [[const data:Array<string| ]],
|
||||
after = [[const data:Array<string>| ]],
|
||||
},
|
||||
{
|
||||
name = '17 typescriptreact nested indentifer ',
|
||||
filepath = './sample/index.tsx',
|
||||
filetype = 'typescriptreact',
|
||||
linenr = 12,
|
||||
key = [[>]],
|
||||
before = [[<Opt.Input| ]],
|
||||
after = [[<Opt.Input>|</Opt.Input> ]],
|
||||
},
|
||||
{
|
||||
name = '18 php div ',
|
||||
filepath = './sample/index.php',
|
||||
filetype = 'php',
|
||||
linenr = 25,
|
||||
key = [[>]],
|
||||
before = [[<div| ]],
|
||||
after = [[<div>|</div> ]],
|
||||
},
|
||||
-- {
|
||||
-- name = '19 markdown div ',
|
||||
-- filepath = './sample/index.md',
|
||||
-- filetype = 'markdown',
|
||||
-- linenr = 4,
|
||||
-- key = [[>]],
|
||||
-- before = [[<div| ]],
|
||||
-- after = [[<div>|</div> ]],
|
||||
-- },
|
||||
}
|
||||
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)
|
||||
|
@ -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
|
||||
|
||||
|
@ -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 = [[<di|v> dsadsa </div> ]],
|
||||
after = [[<lala|> dsadsa </lala> ]]
|
||||
},
|
||||
{
|
||||
name = "html rename open tag with attr" ,
|
||||
filepath = './sample/index.html',
|
||||
filetype = "html",
|
||||
linenr = 10,
|
||||
key = [[ciwlala]],
|
||||
before = [[<di|v class="lla"> dsadsa </div> ]],
|
||||
after = [[<lala| class="lla"> dsadsa </lala|> ]]
|
||||
},
|
||||
{
|
||||
name = "html rename close tag with attr" ,
|
||||
filepath = './sample/index.html',
|
||||
filetype = "html",
|
||||
linenr = 10,
|
||||
key = [[ciwlala]],
|
||||
before = [[<div class="lla"> dsadsa </di|v> ]],
|
||||
after = [[<lala class="lla"> dsadsa </lala|> ]]
|
||||
},
|
||||
{
|
||||
name = "html not rename close tag on char <" ,
|
||||
filepath = './sample/index.html',
|
||||
filetype = "html",
|
||||
linenr = 10,
|
||||
key = [[i<]],
|
||||
before = [[<div class="lla"> dsadsa |/button> ]],
|
||||
after = [[<div| class="lla"> dsadsa |</button> ]]
|
||||
},
|
||||
{
|
||||
name = "html not rename close tag with not valid" ,
|
||||
filepath = './sample/index.html',
|
||||
filetype = "html",
|
||||
linenr = 12,
|
||||
key = [[ciwlala]],
|
||||
before = {
|
||||
[[<di|v class="lla" ]],
|
||||
[[ dsadsa </div>]]
|
||||
},
|
||||
after = [[<lala class="lla" ]]
|
||||
},
|
||||
-- {
|
||||
-- only=true,
|
||||
-- name = "html not rename close tag if it have parent node map with child nod" ,
|
||||
-- filepath = './sample/index.html',
|
||||
-- filetype = "html",
|
||||
-- linenr = 12,
|
||||
-- key = [[ciwlala]],
|
||||
-- before = {
|
||||
-- [[<d|iv> </div>]],
|
||||
-- [[<div> </div>"]]
|
||||
-- },
|
||||
-- after = [[<d|iv> </div>]]
|
||||
-- },
|
||||
{
|
||||
name = "html not rename close tag with not valid" ,
|
||||
filepath = './sample/index.html',
|
||||
filetype = "html",
|
||||
linenr = 12,
|
||||
key = [[ciwlala]],
|
||||
before = {
|
||||
[[<div class="lla" </d|iv>]],
|
||||
},
|
||||
after = [[<div class="lla" </l|ala>]]
|
||||
},
|
||||
{
|
||||
name = "typescriptreact rename open tag" ,
|
||||
filepath = './sample/index.tsx',
|
||||
filetype = "typescriptreact",
|
||||
linenr = 12,
|
||||
key = [[ciwlala]],
|
||||
before = [[<di|v> dsadsa </div> ]],
|
||||
after = [[<lala|> dsadsa </lala> ]]
|
||||
},
|
||||
{
|
||||
name = "typescriptreact rename open tag with attr" ,
|
||||
filepath = './sample/index.tsx',
|
||||
filetype = "typescriptreact",
|
||||
linenr = 12,
|
||||
key = [[ciwlala]],
|
||||
before = [[<di|v class="lla"> dsadsa </div> ]],
|
||||
after = [[<lala| class="lla"> dsadsa </lala> ]]
|
||||
},
|
||||
{
|
||||
name = "typescriptreact rename close tag with attr" ,
|
||||
filepath = './sample/index.tsx',
|
||||
filetype = "html",
|
||||
linenr = 12,
|
||||
key = [[ciwlala]],
|
||||
before = [[<div class="lla"> dsadsa </di|v> ]],
|
||||
after = [[<lala class="lla"> dsadsa </lala|> ]]
|
||||
},
|
||||
{
|
||||
name = "17 typescriptreact nested indentifer " ,
|
||||
filepath = './sample/index.tsx',
|
||||
filetype = "typescriptreact",
|
||||
linenr = 12,
|
||||
key = [[ciwlala]],
|
||||
before = [[<Opt.In|put></Opt.Input> ]],
|
||||
after = [[<Opt.lala>|</Opt.lala> ]]
|
||||
},
|
||||
{
|
||||
name = "18 rename empty node " ,
|
||||
filepath = './sample/index.tsx',
|
||||
filetype = "typescriptreact",
|
||||
linenr = 12,
|
||||
key = [[ilala]],
|
||||
before = [[<|><div></div></>]],
|
||||
after = [[<|lala><div></div></lala>]]
|
||||
name = 'html rename open tag',
|
||||
filepath = './sample/index.html',
|
||||
filetype = 'html',
|
||||
linenr = 10,
|
||||
key = [[ciwlala]],
|
||||
before = [[<di|v> dsadsa </div> ]],
|
||||
after = [[<lala|> dsadsa </lala> ]],
|
||||
},
|
||||
{
|
||||
name = "19 rename start tag on svelte " ,
|
||||
filepath = './sample/index.svelte',
|
||||
filetype = "svelte",
|
||||
linenr = 18,
|
||||
key = [[ciwlala]],
|
||||
before = [[<|data></data>]],
|
||||
after = [[<|lala></lala>]]
|
||||
name = 'html rename open tag with attr',
|
||||
filepath = './sample/index.html',
|
||||
filetype = 'html',
|
||||
linenr = 10,
|
||||
key = [[ciwlala]],
|
||||
before = [[<di|v class="lla"> dsadsa </div> ]],
|
||||
after = [[<lala| class="lla"> dsadsa </lala|> ]],
|
||||
},
|
||||
{
|
||||
name = "20 rename end tag on svelte " ,
|
||||
filepath = './sample/index.svelte',
|
||||
filetype = "svelte",
|
||||
linenr = 18,
|
||||
key = [[ciwlala]],
|
||||
before = [[<data></da|ta>]],
|
||||
after = [[<lala></lala>]]
|
||||
name = 'html rename close tag with attr',
|
||||
filepath = './sample/index.html',
|
||||
filetype = 'html',
|
||||
linenr = 10,
|
||||
key = [[ciwlala]],
|
||||
before = [[<div class="lla"> dsadsa </di|v> ]],
|
||||
after = [[<lala class="lla"> dsadsa </lal|a> ]],
|
||||
},
|
||||
{
|
||||
name = "21 rescript rename open tag" ,
|
||||
filepath = './sample/index.res',
|
||||
filetype = "rescript",
|
||||
linenr = 12,
|
||||
key = [[ciwlala]],
|
||||
before = [[<di|v> dsadsa </div> ]],
|
||||
after = [[<lala|> dsadsa </lala> ]]
|
||||
name = 'html not rename close tag on char <',
|
||||
filepath = './sample/index.html',
|
||||
filetype = 'html',
|
||||
linenr = 10,
|
||||
key = [[i<]],
|
||||
before = [[<div class="lla"> dsadsa |/button> ]],
|
||||
after = [[<div class="lla"> dsadsa <|/button> ]],
|
||||
},
|
||||
{
|
||||
name = "22 rescript rename open tag with attr" ,
|
||||
filepath = './sample/index.res',
|
||||
filetype = "rescript",
|
||||
linenr = 12,
|
||||
key = [[ciwlala]],
|
||||
before = [[<di|v class="lla"> dsadsa </div> ]],
|
||||
after = [[<lala| class="lla"> dsadsa </lala> ]]
|
||||
},
|
||||
{
|
||||
name = "23 rescript rename close tag with attr" ,
|
||||
filepath = './sample/index.res',
|
||||
filetype = "rescript",
|
||||
linenr = 12,
|
||||
key = [[ciwlala]],
|
||||
before = [[<div class="lla"> dsadsa </di|v> ]],
|
||||
after = [[<lala class="lla"> dsadsa </lala|> ]]
|
||||
},
|
||||
-- {
|
||||
-- only = true,
|
||||
-- name = "18 rename node to empty node " ,
|
||||
-- filepath = './sample/index.tsx',
|
||||
-- filetype = "typescriptreact",
|
||||
-- linenr = 12,
|
||||
-- key = [[ciw<esc>]],
|
||||
-- before = [[<la|la><div></div></lala>]],
|
||||
-- after = [[<|><div></div></>]]
|
||||
-- },
|
||||
|
||||
-- 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 = {
|
||||
[[<di|v class="lla" ]],
|
||||
[[ dsadsa </div>]],
|
||||
},
|
||||
after = [[<lala class="lla" ]],
|
||||
},
|
||||
-- {
|
||||
-- only=true,
|
||||
-- name = "html not rename close tag if it have parent node map with child nod" ,
|
||||
-- filepath = './sample/index.html',
|
||||
-- filetype = "html",
|
||||
-- linenr = 12,
|
||||
-- key = [[ilala]],
|
||||
-- before = [[<span><> <div></div></|><span>]],
|
||||
-- after = [[<span><|lala><div></div></lala></span>]]
|
||||
-- },
|
||||
-- {
|
||||
-- name = "19 rename end empty node " ,
|
||||
-- filepath = './sample/index.tsx',
|
||||
-- filetype = "typescriptreact",
|
||||
-- linenr = 12,
|
||||
-- key = [[ilala]],
|
||||
-- before = [[<><div></div></|>]],
|
||||
-- after = [[<|lala><div></div></lala>]]
|
||||
-- }
|
||||
-- key = [[ciwlala]],
|
||||
-- before = {
|
||||
-- [[<d|iv> </div>]],
|
||||
-- [[<div> </div>"]]
|
||||
-- },
|
||||
-- after = [[<d|iv> </div>]]
|
||||
-- },
|
||||
{
|
||||
|
||||
name = 'html not rename close tag with not valid',
|
||||
filepath = './sample/index.html',
|
||||
filetype = 'html',
|
||||
linenr = 12,
|
||||
key = [[ciwlala]],
|
||||
before = {
|
||||
[[<div class="lla" </d|iv>]],
|
||||
},
|
||||
after = [[<div class="lla" </lala|>]],
|
||||
},
|
||||
{
|
||||
name = 'typescriptreact rename open tag',
|
||||
filepath = './sample/index.tsx',
|
||||
filetype = 'typescriptreact',
|
||||
linenr = 12,
|
||||
key = [[ciwlala]],
|
||||
before = [[<di|v> dsadsa </div> ]],
|
||||
after = [[<lala|> dsadsa </lala> ]],
|
||||
},
|
||||
{
|
||||
name = 'typescriptreact rename open tag with attr',
|
||||
filepath = './sample/index.tsx',
|
||||
filetype = 'typescriptreact',
|
||||
linenr = 12,
|
||||
key = [[ciwlala]],
|
||||
before = [[<di|v class="lla"> dsadsa </div> ]],
|
||||
after = [[<lala| class="lla"> dsadsa </lala> ]],
|
||||
},
|
||||
{
|
||||
name = 'typescriptreact rename close tag with attr',
|
||||
filepath = './sample/index.tsx',
|
||||
filetype = 'html',
|
||||
linenr = 12,
|
||||
key = [[ciwlala]],
|
||||
before = [[<div class="lla"> dsadsa </di|v> ]],
|
||||
after = [[<lala class="lla"> dsadsa </lal|a> ]],
|
||||
},
|
||||
{
|
||||
name = '17 typescriptreact nested indentifer ',
|
||||
filepath = './sample/index.tsx',
|
||||
filetype = 'typescriptreact',
|
||||
linenr = 12,
|
||||
key = [[ciwlala]],
|
||||
before = [[<Opt.In|put></Opt.Input> ]],
|
||||
after = [[<Opt.lala|></Opt.lala> ]],
|
||||
},
|
||||
{
|
||||
name = '18 rename empty node ',
|
||||
filepath = './sample/index.tsx',
|
||||
filetype = 'typescriptreact',
|
||||
linenr = 12,
|
||||
key = [[ilala]],
|
||||
before = [[<|><div></div></>]],
|
||||
after = [[<lala|><div></div></lala>]],
|
||||
},
|
||||
{
|
||||
name = '19 rename start tag on svelte ',
|
||||
filepath = './sample/index.svelte',
|
||||
filetype = 'svelte',
|
||||
linenr = 18,
|
||||
key = [[ciwlala]],
|
||||
before = [[<|data></data>]],
|
||||
after = [[<lala|></lala>]],
|
||||
},
|
||||
{
|
||||
name = '20 rename end tag on svelte ',
|
||||
filepath = './sample/index.svelte',
|
||||
filetype = 'svelte',
|
||||
linenr = 18,
|
||||
key = [[ciwlala]],
|
||||
before = [[<span></spa|n>]],
|
||||
after = [[<lala></lala>]],
|
||||
},
|
||||
{
|
||||
name = "21 rescript rename open tag",
|
||||
filepath = './sample/index.res',
|
||||
filetype = "rescript",
|
||||
linenr = 12,
|
||||
key = [[ciwlala]],
|
||||
before = [[<di|v> dsadsa </div> ]],
|
||||
after = [[<lala|> dsadsa </lala> ]]
|
||||
},
|
||||
{
|
||||
name = "22 rescript rename open tag with attr",
|
||||
filepath = './sample/index.res',
|
||||
filetype = "rescript",
|
||||
linenr = 12,
|
||||
key = [[ciwlala]],
|
||||
before = [[<di|v class="lla"> dsadsa </div> ]],
|
||||
after = [[<lala| class="lla"> dsadsa </lala> ]]
|
||||
},
|
||||
{
|
||||
name = "23 rescript rename close tag with attr",
|
||||
filepath = './sample/index.res',
|
||||
filetype = "rescript",
|
||||
linenr = 12,
|
||||
key = [[ciwlala]],
|
||||
before = [[<div class="lla"> dsadsa </di|v> ]],
|
||||
after = [[<lala class="lla"> dsadsa </lal|a> ]]
|
||||
},
|
||||
{
|
||||
name = '24 test check rename same with parent',
|
||||
filepath = './sample/index.tsx',
|
||||
filetype = 'typescriptreact',
|
||||
linenr = 12,
|
||||
key = 'ciwkey',
|
||||
before = {
|
||||
'<Container>',
|
||||
' <di|v>',
|
||||
'',
|
||||
' <span></span>',
|
||||
'</Container>',
|
||||
},
|
||||
after = {
|
||||
'<Container>',
|
||||
' <key>',
|
||||
'',
|
||||
' <span></span>',
|
||||
'</Container>',
|
||||
},
|
||||
},
|
||||
{
|
||||
name = '25 rename start have same node with parent',
|
||||
filepath = './sample/index.tsx',
|
||||
filetype = 'typescriptreact',
|
||||
linenr = 12,
|
||||
key = [[ciwlala]],
|
||||
before = {
|
||||
'<div>',
|
||||
' <di|v>',
|
||||
' <span>test </span>',
|
||||
' </div>',
|
||||
'</div>',
|
||||
},
|
||||
after = {
|
||||
'<div>',
|
||||
' <lala>',
|
||||
' <span>test </span>',
|
||||
' </lala>',
|
||||
'</div>',
|
||||
},
|
||||
},
|
||||
{
|
||||
name = '26 rename should not rename tag on attribute node',
|
||||
filepath = './sample/index.tsx',
|
||||
filetype = 'typescriptreact',
|
||||
linenr = 12,
|
||||
key = [[ciwlala]],
|
||||
before = {
|
||||
'<div>',
|
||||
'<Navbar className="|a">',
|
||||
' <div className="flex flex-col">',
|
||||
' <div className="flex flex-row">',
|
||||
' </div>',
|
||||
' </div>',
|
||||
'</div>',
|
||||
},
|
||||
after = {
|
||||
'<div>',
|
||||
'<Navbar className="lala">',
|
||||
' <div className="flex flex-col">',
|
||||
' <div className="flex flex-row">',
|
||||
' </div>',
|
||||
' </div>',
|
||||
'</div>',
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
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("<esc>",'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)
|
||||
|
||||
|
191
tests/test-utils.lua
Normal file
191
tests/test-utils.lua
Normal file
@ -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('<esc>')
|
||||
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
|
Loading…
Reference in New Issue
Block a user