Closed emi2k01 closed 2 years ago
Hi there, thanks for reporting a bug! I don't actually know what characters are "valid" for HTML; is it just alphanums + hyphens + periods?
Maybe I'll just make it "any non-whitespace character"; do you mind testing out the following config? Sorry for the verboseness:
local config = require("nvim-surround.config")
require("nvim-surround").setup({
surrounds = {
["t"] = {
add = function()
local input = M.get_input("Enter the HTML tag: ")
if input then
local element = input:match("^<?([^%s>]*)")
local attributes = input:match("^<?[^%s>]*%s+(.-)>?$")
local open = attributes and element .. " " .. attributes or element
local close = element
return { { "<" .. open .. ">" }, { "</" .. close .. ">" } }
end
end,
find = function()
return M.get_selection({ textobject = "t" })
end,
delete = "^(%b<>)().-(%b<>)()$",
change = {
target = "^<([^%s>]*)().-([^/]*)()>$",
replacement = function()
local input = M.get_input("Enter the HTML tag: ")
if input then
local element = input:match("^<?([^%s>]*)")
local attributes = input:match("^<?[^%s>]*%s+(.-)>?$")
local open = attributes and element .. " " .. attributes or element
local close = element
return { { open }, { close } }
end
end,
},
},
["T"] = {
add = function()
local input = M.get_input("Enter the HTML tag: ")
if input then
local element = input:match("^<?([^%s>]*)")
local attributes = input:match("^<?[^%s>]*%s+(.-)>?$")
local open = attributes and element .. " " .. attributes or element
local close = element
return { { "<" .. open .. ">" }, { "</" .. close .. ">" } }
end
end,
find = function()
return M.get_selection({ textobject = "t" })
end,
delete = "^(%b<>)().-(%b<>)()$",
change = {
target = "^<([^>]*)().-([^/]*)()>$",
replacement = function()
local input = M.get_input("Enter the HTML tag: ")
if input then
local element = input:match("^<?([^%s>]*)")
local attributes = input:match("^<?[^%s>]*%s+(.-)>?$")
local open = attributes and element .. " " .. attributes or element
local close = element
return { { open }, { close } }
end
end,
},
},
},
})
For JSX, it's way too complex. It lets you do things like <Component<{ a: x, b: typeof (30 + 20) }> />
.
If I read this correctly, I think anything goes: https://html.spec.whatwg.org/#tag-name-state
Oh wow this is exactly what I was looking for; I'll try to write a Lua pattern for this soon-ish. @emi2k01 I don't think I'll be supporting self-closing tags since that kind of defeats the purpose of a "delimiter pair"; are there any examples of more complicated pairs of HTML/JSX tags? Also the link you sent seems to target HTML in particular, is there anything that describes JSX tags in the same way?
Yes, there is: https://facebook.github.io/jsx/#prod-JSXElement
I think a simplified form of JSX would be good because it's too complex. Probably, doing it like HTML would be good. Basically, no generics because everything goes there (e.g. <Component<{ a: b, c: typeof (3+1)}>>bla</Component>
)
So, the idea would be to match the tag name as any character before a space
@kylechui I tried the config you commented earlier, it works good. Thanks!
It's actually still scuffed, but if you know Lua patterns you can try fixing new problems as they arise. I've edited the original message with slightly better pattern-matching.
I tried the last edit but for my use-case it's basically just replacing tags with hyphens and periods, and it works good.
Why do you say it's scuffed?
The original one broke when you ended the tag with the optional >
, since I forgot to account for that. I'm going to take a look at JSX syntax later and see if I can get something working there; if not then all non-whitespace seems like a "good enough" heuristic for me.
For the most recent example, <Component<{ a: b, c: typeof (3+1)}>>bla</Component>
, it's not even detected by Neovim's at
text-object. I think the real answer here is to use "non-whitespace" as a heuristic for most HTML tags, and use Tree-sitter for anything more complicated (which is being worked on in #123).
I installed the tsx
Tree-sitter language parser, and it handles your complicated <Component<{ a: b, c: typeof (3+1)}>>bla</Component>
case quite well. Funnily enough there's no jsx
parser, although TBH I don't really code in either. Feel free to subscribe to #123 to stay up-to-date on how I handle integrating Tree-sitter into this plugin :)
Awesome, thanks for the update!. Let me know if there's something I can help with
I'll close this as "completed" for now (merging into #123); the two big things that you could do for me right now are
I appreciate you taking the time to report this!
Checklist
main
branch?:h nvim-surround
to see if there might be any relevant information there?To reproduce
Try to replace a tag with
<foo.bar>
, it will only replace it with<foo>
Expected behavior
Tags are updated with the whole input
Actual behavior
Tags are truncated up to the first punctuation character
Additional context
This is useful for react components