helix icon indicating copy to clipboard operation
helix copied to clipboard

Support auto close and rename tag

Open NNBnh opened this issue 4 years ago • 15 comments

Helix would be great if it have the quality-of-life-improvement features from two of the most popular VScode plugins: Auto Close Tag and Auto Rename Tag:

Auto Close Tag

From the "Auto Rename Tag" VScode plugin:

Automatically add HTML/XML close tag, same as Visual Studio IDE or Sublime Text does:

  • Automatically add closing tag when you type in the closing bracket of the opening tag
  • After closing tag is inserted, the cursor is between the opening and closing tag
  • Set the tag list that would not be auto closed
  • Automatically close self-closing tag
  • Support auto close tag as Sublime Text 3
  • Use Keyboard Shortcut or Command Palette to add close tag manually

usage

Auto Rename Tag:

From the "Auto Rename Tag" VScode plugin:

When you rename one HTML/XML tag, automatically rename the paired HTML/XML tag

usage

NNBnh avatar Nov 03 '21 07:11 NNBnh

For closing tags, we already have auto closing brackets which assume that the opening and closing tokens are single width (like (, {, ', etc). Extending it to recognize multi character opening and closing tokens should help in this case.

Similarly we can tweak the surround textobjects to recognize multi character delimiters and then use mr to rename tags.

sudormrfbin avatar Nov 03 '21 08:11 sudormrfbin

I believe this feature shouldn't be part of auto pairs. For example, I might want to disable auto pairs but I want to keep this. Auto pair I don't like the behavior such that it does not always work, but for this the false positive should be much lower.

pickfire avatar Nov 12 '21 06:11 pickfire

Closing tags is auto pairing though, with the pair being a multi-char string.

archseer avatar Nov 14 '21 16:11 archseer

Hi guys!

I'm really interested to work on this, but before I start, I would like to talk a little bit about it before writing any code.

So, the first thing is: The issue is about auto pair and auto rename for xml tag, but I thing this two should come on different PRs. To keep the PR focused on only one feature. If you guys agree, I can create another issue to split this one.

Secondly, I've seen some comments about extending the the current auto pair capability to allow multiple characters, and that makes sense to me to be done on the same PR.

The last thing, is that I would like to get some suggestions, if possible on how we could model the solution based on what we currently have.

What we have right now, is a basic config telling what characters to open and close a pair, ex => open: ( close: )

And I'm thinking if it would be a good idea to extend this to allow some patterns, like: open: <*> close: </*>

This would be interpreted as kind of a dynamic pair, where: < followed by any sequence of characters without space followed by > would be paired with </ followed by the matched sequence and >

This would allow both cases: multi character auto pairing, and xml tags pairing, and also provide some flexibility to let users configure their own auto pairs.

Adding a dynamic thing such as the * token may became a problem if we try to let it to flexible, so the idea is that on this implementation its use would be very restricted, like only allowing one * per pair config. For example:

This is ok:

open: <*> close: </*>

This is not ok:

open <**> close: </**>

Any thoughts on that?

Gabrielbdd avatar Aug 25 '22 00:08 Gabrielbdd

I'm also kind of questioning whether this should be done with auto pairs. Tags are a language-specific construct, and throwing patterns into the mix with auto pairs might make it significantly more complicated.

The current code is set up to operate on single chars, as was mentioned. How to change this to support multiple characters is still not decided. I had an idea that the auto pairs code could use a trie structure that it mutates with every key stroke, and once it hits a leaf, it could trigger the completion. However, what's not clear is how to handle if there are any overlapping sequences, e.g. ' ' and ''' '''. I haven't thought this all the way through.

Now if we add arbitrary patterns into this mix, it's no longer a static trie. And if we do a partial prefix match by accident, like e.g. if you have some inline JavaScript in an HTML doc, and you type a less-than expression like x<y, does it just get stuck in the middle of the trie?

Now a trie isn't the only way to implement this, but I haven't thought about how else to do it. We have to handle it one character at a time, since that is how we're getting the user input. If we do a simple lookback to see if the character we're inserting will complete a pair opening, and we introduce patterns, then how far back do we look if we get a partial match? Do we introduce arbitrary hardcoded limits?

On top of all this, auto pair removals are not yet done in the general way that includes selections, and we'll have to think about how we'd delete these pairs/tags too.

Either way we cut it, tags or no, I have a feeling that multi-char pairs still be very tricky to implement and get right.

dead10ck avatar Aug 25 '22 01:08 dead10ck

The HTML language server for Helix (the same as VS Code) has the ability to rename tags with space-r, for example:

<span>hello</span>
<div>hello</div>

You can easily rename span in the first bracket and it renames only the matching pair. It doesn't do it on the fly, but I don't think that matters much.

It can also do auto-complete like in the video at BUT it does not work out of the box for some reason, in Neovim you need to use nvim-cmp and add a snippet engine for some reason. I had it working perfectly for a while and then it died (classic Neovim). I think making it work in the HTML server in Helix would be a better goal than trying to use auto pairs.

David-Else avatar Aug 25 '22 11:08 David-Else

To me the "<*>" = "</*>" configuration sounds like a simplified form of snippets so I think it would be preferrable to work on snippets #395 rather than these abilities specifically. It also sounds like snippet support would allow tag auto-completion from the HTML Language Server.

the-mikedavis avatar Aug 26 '22 13:08 the-mikedavis

Instead of opening another issue, I would like to suggest adding mst which translates to "make surrounding tag". This would give results similar to ys<movement>t from vim surround.

txtyash avatar Sep 28 '22 17:09 txtyash

Instead of opening another issue, I would like to suggest adding mst which translates to "make surrounding tag". This would give results similar to yst from vim surround.

In line with that, there should also be an mm-style "Jump to closing tag"

LeoniePhiline avatar Jan 31 '23 23:01 LeoniePhiline

The LSP has textDocument/linkedEditingRange.

This is not a snippet. It's like a multi cursor feature.

My plugin below is for neovim, but the implementation is small and may be of some help.

https://github.com/hrsh7th/nvim-linkedit

hrsh7th avatar Jun 19 '23 02:06 hrsh7th

I love Helix, the ability to auto complete tags would make a big difference for me 🙏🙏🙏 And finding out that tags can be renamed with space+r has made my day <3

erasebegin avatar Jul 13 '23 07:07 erasebegin

Instead of opening another issue, I would like to suggest adding mst which translates to "make surrounding tag". This would give results similar to ys<movement>t from vim surround.

This would be amazing. I use vs-code's emmet-wrap-with-abbreviation AAALLL the time. It's extremely useful in all kinds of web dev situations. I spent the better part of a day trying to make this happen in Helix to no avail. Still haven't even figured out any good combination of motions and actions that can do this as efficiently as possible. All very cumbersome

erasebegin avatar Jul 13 '23 07:07 erasebegin

This feature would be very useful for auto-closing LaTeX environments, which can be a lot to type. For example if you write \begin{enumerate} many editors will automatically add \end{enumerate} after the cursor, or provide a shortcut to close the nearest parent environment.

knuesel avatar Mar 28 '24 10:03 knuesel