diff --git a/lua/nvim-ts-autotag/internal.lua b/lua/nvim-ts-autotag/internal.lua index a3b2d64..bab1345 100644 --- a/lua/nvim-ts-autotag/internal.lua +++ b/lua/nvim-ts-autotag/internal.lua @@ -23,8 +23,6 @@ M.tbl_skipTag = { 'input', 'keygen', 'link', 'meta', 'param', 'source', 'track', 'wbr', 'menuitem' } -local ERROR_TAG = "ERROR" - -- stylua: ignore local HTML_TAG = { filetypes = { @@ -35,13 +33,13 @@ local HTML_TAG = { 'php', 'xml', }, - start_tag_pattern = 'start_tag', - start_name_tag_pattern = 'tag_name', - end_tag_pattern = "end_tag", - end_name_tag_pattern = "tag_name", - close_tag_pattern = 'erroneous_end_tag', - close_name_tag_pattern = 'erroneous_end_tag_name', - element_tag = 'element', + start_tag_pattern = { 'start_tag' }, + start_name_tag_pattern = { 'tag_name' }, + end_tag_pattern = { 'end_tag' }, + end_name_tag_pattern = { 'tag_name' }, + 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' }, } -- stylua: ignore @@ -50,13 +48,13 @@ local JSX_TAG = { 'typescriptreact', 'javascriptreact', 'javascript.jsx', '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', + start_tag_pattern = { 'jsx_opening_element', 'start_tag' }, + start_name_tag_pattern = { 'identifier', 'nested_identifier', 'tag_name', 'member_expression', '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' }, + close_name_tag_pattern = { 'member_expression', 'nested_identifier', 'jsx_identifier', 'identifier', '>' }, + element_tag = { 'jsx_element', 'element' }, skip_tag_pattern = { 'jsx_closing_element', 'jsx_expression', 'string', 'jsx_attribute', 'end_tag', 'string_fragment' @@ -68,13 +66,13 @@ local JSX_TAG = { -- stylua: ignore local HBS_TAG = { 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', + 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' }, } @@ -82,13 +80,13 @@ local HBS_TAG = { -- stylua: ignore local SVELTE_TAG = { filetypes = { 'svelte' }, - start_tag_pattern = 'start_tag', - start_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', + start_tag_pattern = { 'start_tag' }, + start_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', 'erroneous_end_tag_name' }, + element_tag = { 'element' }, skip_tag_pattern = { 'quoted_attribute_value', 'end_tag' }, } @@ -99,7 +97,7 @@ local all_tag = { } M.enable_rename = true M.enable_close = true -M.enable_close_on_slash = true +M.enable_close_on_slash = false M.setup = function(opts) opts = opts or {} @@ -183,8 +181,7 @@ local function find_child_match(opts) if target == nil or pattern == nil then return nil end - local tbl_pattern = vim.split(pattern, "|") - for _, ptn in pairs(tbl_pattern) do + for _, ptn in pairs(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 @@ -202,8 +199,7 @@ local function find_parent_match(opts) if target == nil or pattern == nil then return nil end - local tbl_pattern = vim.split(pattern, "|") - for _, ptn in pairs(tbl_pattern) do + for _, ptn in pairs(pattern) do local cur_node = target local cur_depth = 0 while cur_node ~= nil do @@ -248,6 +244,7 @@ local function find_tag_node(opt) pattern = tag_pattern, skip_tag_pattern = skip_tag_pattern, }) + else node = find_parent_match({ target = target, @@ -258,31 +255,17 @@ local function find_tag_node(opt) if node == nil then return nil end - local name_node = node - local tbl_name_pattern = {} - 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, - }) - if name_node then - return name_node - end - end + local name_node = find_child_match({ + target = node, + pattern = name_tag_pattern, + }) + if name_node then + return name_node 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, - }) - end -- check current node is have same name of tag_match - if is_in_table(tbl_name_pattern, node:type()) then + if is_in_table(name_tag_pattern, node:type()) then return node end return name_node @@ -298,11 +281,6 @@ local function find_start_tag(current) if not ts_tag then return nil end - - if current:type() ~= "ERROR" then - return nil - end - local target = nil target = find_child_match({ @@ -333,8 +311,9 @@ local function check_close_tag(close_slash_tag) if close_slash_tag then -- Find start node from non closed tag local current = ts_utils.get_node_at_cursor() - + -- log.debug(current) target = find_start_tag(current) + -- log.debug(target) end local tag_node = find_tag_node({ @@ -407,7 +386,7 @@ local function replace_text_node(node, tag_name) 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 }) + vim.api.nvim_buf_set_lines(0, start_row, start_row + 1, true, { newline }) end end @@ -422,10 +401,6 @@ local function validate_tag_regex(node, start_regex, end_regex) return false end --- local function validate_tag(node) --- return validate_tag_regex(node,"^%<","%>$") --- end - local function validate_start_tag(node) return validate_tag_regex(node, "^%<%w", "%>$") end @@ -457,7 +432,7 @@ local function rename_start_tag() tag_node = find_parent_match({ target = parent_node, - pattern = ts_tag.element_tag .. "|" .. ERROR_TAG, + pattern = ts_tag.element_tag, max_depth = 2, }) @@ -471,6 +446,7 @@ local function rename_start_tag() 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(), @@ -480,38 +456,25 @@ local function rename_start_tag() end if close_tag_node ~= nil then - local error_node = find_child_match({ - target = tag_node, - 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 + log.debug(close_tag_node:type()) + local close_tag_name = get_tag_name(close_tag_node) + -- 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 - - 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) - -- 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, "") + end + if tag_name ~= close_tag_name then + -- log.debug("do replace") + -- log.debug(tag_name) + -- log.debug(close_tag_name) + if close_tag_name == '>' then + tag_name = tag_name .. '>' end + replace_text_node(close_tag_node, tag_name) end end end @@ -525,7 +488,6 @@ local function rename_end_tag() 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 @@ -549,30 +511,36 @@ local function rename_end_tag() 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 + if start_tag_node and 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 + log.debug('replace end tag') replace_text_node(start_tag_node, tag_name) end end end -local function validate_rename() - local cursor = vim.api.nvim_win_get_cursor(0) - 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 - return true +local function is_before(regex, range) + return function() + local cursor = vim.api.nvim_win_get_cursor(0) + local line = vim.api.nvim_get_current_line() + local char = line:sub(cursor[2] + range, cursor[2] + range) + -- only rename when last character is a word + if string.match(char, regex) then + return true + end + return false end - return false end +local is_before_word = is_before('%w', 1) +local is_before_arrow = is_before('<', 0) + M.rename_tag = function() - if validate_rename() and parsers.has_parser() then + if is_before_word() and parsers.has_parser() then parsers.get_parser():parse() rename_start_tag() rename_end_tag() @@ -586,6 +554,7 @@ M.attach = function(bufnr, lang) if is_in_table(M.tbl_filetypes, vim.bo.filetype) then setup_ts_tag() + local group = vim.api.nvim_create_augroup('nvim-ts-autotag', { clear = true }) if M.enable_close == true then vim.api.nvim_buf_set_keymap(bufnr or 0, "i", ">", ">", { noremap = true, @@ -605,7 +574,10 @@ M.attach = function(bufnr, lang) callback = function() local row, col = unpack(vim.api.nvim_win_get_cursor(0)) vim.api.nvim_buf_set_text(bufnr or 0, row - 1, col, row - 1, col, { "/" }) - M.close_slash_tag() + if is_before_arrow() then + log.debug('is_before_arrow') + M.close_slash_tag() + end local new_row, new_col = unpack(vim.api.nvim_win_get_cursor(0)) vim.api.nvim_win_set_cursor(0, { new_row, new_col + 1 }) end, @@ -614,6 +586,7 @@ M.attach = function(bufnr, lang) if M.enable_rename == true then bufnr = bufnr or vim.api.nvim_get_current_buf() vim.api.nvim_create_autocmd("InsertLeave", { + group = group, buffer = bufnr, callback = M.rename_tag, }) diff --git a/sample/index.tsx b/sample/index.tsx index 51b677b..a23ca34 100644 --- a/sample/index.tsx +++ b/sample/index.tsx @@ -16,9 +16,6 @@ const SamplePage: React.FC = () => { - - - ) } diff --git a/tests/close_slash_tag_spec.lua b/tests/close_slash_tag_spec.lua index 56d8ded..86eaf8b 100644 --- a/tests/close_slash_tag_spec.lua +++ b/tests/close_slash_tag_spec.lua @@ -1,24 +1,8 @@ -if not _G.test_close then - return -end - local ts = require('nvim-treesitter.configs') -local helpers = {} 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) -end - -function helpers.insert(text) - helpers.feed('a' .. text, 'x') -end local data = { { @@ -193,6 +177,5 @@ describe('[close slash tag]', function() _G.Test_withfile(run_data, { mode = 'i', cursor_add = 0, - before_each = function(value) end, }) end) diff --git a/tests/closetag_spec.lua b/tests/closetag_spec.lua index 91699bf..2d1a6d0 100644 --- a/tests/closetag_spec.lua +++ b/tests/closetag_spec.lua @@ -1,24 +1,8 @@ -if not _G.test_close then - return -end - local ts = require('nvim-treesitter.configs') -local helpers = {} 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) -end - -function helpers.insert(text) - helpers.feed('a' .. text, 'x') -end local data = { { diff --git a/tests/minimal.vim b/tests/minimal.vim index 90ddb63..950b620 100644 --- a/tests/minimal.vim +++ b/tests/minimal.vim @@ -26,13 +26,16 @@ 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', 'embedded_template' } require("plenary/busted") vim.cmd[[luafile ./tests/test-utils.lua]] -require("nvim-ts-autotag").setup() +require("nvim-ts-autotag").setup({ + enable = true, + enable_rename = true, + enable_close = true, + enable_close_on_slash = true, +}) EOF diff --git a/tests/renametag_spec.lua b/tests/renametag_spec.lua index faff451..a18fe0e 100644 --- a/tests/renametag_spec.lua +++ b/tests/renametag_spec.lua @@ -1,30 +1,13 @@ local ts = require 'nvim-treesitter.configs' - -local log = require('nvim-ts-autotag._log') - -if not _G.test_rename then - return -end - -local helpers = {} ts.setup({ ensure_installed = _G.ts_filetypes, highlight = { - use_languagetree = true, + use_languagetree = false, 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) -end - -function helpers.insert(text) - helpers.feed('i' .. text, 'x') -end local data = { { diff --git a/tests/test-utils.lua b/tests/test-utils.lua index 0b86a90..072485c 100644 --- a/tests/test-utils.lua +++ b/tests/test-utils.lua @@ -1,5 +1,4 @@ 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 @@ -59,8 +58,7 @@ local compare_text = function(linenr, text_after, name, cursor_add, end_cursor) ) for i = 1, #text_after, 1 do local t = string.gsub(text_after[i], '%|', '') - if - t + if t and new_text[i] and t:gsub('%s+$', '') ~= new_text[i]:gsub('%s+$', '') then @@ -175,16 +173,16 @@ _G.Test_withfile = function(test_data, cb) end _G.dump_node = function(node) - local text = ts_utils.get_node_text(node) + local text = utils.get_node_text(node) for _, txt in pairs(text) do - print(txt) + log.debug(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) + local text = utils.get_node_text(node) log.debug('type:' .. node_type .. ' ') log.debug(text) end