Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Open
speelbarrow opened this issue May 27, 2024 · 7 comments
Open

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

speelbarrow opened this issue May 27, 2024 · 7 comments

Comments

@speelbarrow
Copy link

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
Copy link
Collaborator

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
Copy link
Author

Awesome! Thanks so much (:

@jasper-at-windswept
Copy link

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

@roycrippen4
Copy link
Contributor

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
Copy link
Collaborator

PriceHiller commented Jul 14, 2024

@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-at-windswept
Copy link

Thanks all for the great work on this!

@roycrippen4
Copy link
Contributor

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants