windwp / nvim-ts-autotag

Use treesitter to auto close and auto rename html tag
MIT License
1.65k stars 87 forks source link

Feature Request - automatically close unpaired tag on '/' #185

Closed speelbarrow closed 2 weeks ago

speelbarrow commented 4 months ago

Would it possible/particularly difficult to implement behaviour that would automatically transform <component / to <component />?

(I'd try to just implement it myself but I have absolutely no experience with Treesitter :/)

Let me know if anything about this request is unclear, I'm happy to clarify!

PriceHiller commented 4 months ago

This should be doable depending on the language and the associated treesitter parser.

I'll look into this when I get some time and other issues I've prioritized are knocked out.

speelbarrow commented 4 months ago

Awesome! Thanks so much (:

jasper-clarke commented 4 months ago

I'd also love to see this! Since in at least react you don't want a paired tag just <Tag />

roycrippen4 commented 2 months ago

I built this feature in my own config and it works pretty well.

Here are the react-specific instructions:

  1. Create a after/ftplugin directory at the top level of your config.
  2. Create javascriptreact.lua, typescriptreact.lua, and javascript.lua files inside that directory.
  3. Paste the snippet below into each one of those files
-- Automatically end a self-closing tag when pressing /
vim.keymap.set('i', '/', function()
  local node = vim.treesitter.get_node()
  if not node then
    return '/'
  end

  if node:type() == 'jsx_opening_element' then
    local char_after_cursor = vim.fn.strcharpart(vim.fn.strpart(vim.fn.getline('.'), vim.fn.col('.') - 1), 0, 1) ---@type string

    if char_after_cursor == '>' then
      return '/'
    end

    local char_at_cursor = vim.fn.strcharpart(vim.fn.strpart(vim.fn.getline('.'), vim.fn.col('.') - 2), 0, 1) ---@type string
    local already_have_space = char_at_cursor == ' '

    return already_have_space and '/>' or ' />'
  end

  return '/'
end, { expr = true, buffer = true })

@PriceHiller this should be straightforward to implement if you want a PR. This strategy can be used in other file-types as long as the correct node type is known. The code is identical in svelte files, except you match for the 'element' node.

PriceHiller commented 2 months ago

@roycrippen4 if you open a PR to me, I'll gladly merge it (preferably with tests, but it's ok if none are written 🙂 ).

Should be gated beind the enable_close_on_slash configuration option.

jasper-clarke commented 2 months ago

Thanks all for the great work on this!

roycrippen4 commented 2 months ago

I'm digging into the solution now, but I need to ensure it's more robust than the snippets I provided above. It's one thing to add stuff that's close enough in your own config; it's a completely different ball game integrating it into a plugin and not breaking it for everyone else.

stale[bot] commented 3 weeks ago

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.