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: add folding to LSP #650

Open
jackielii opened this issue Mar 29, 2024 · 9 comments
Open

feature: add folding to LSP #650

jackielii opened this issue Mar 29, 2024 · 9 comments
Labels
enhancement New feature or request good first issue Good for newcomers help wanted Extra attention is needed lsp

Comments

@jackielii
Copy link
Contributor

I believe the LSP can add folding support. I believe this is very useful when you have long html tags. Folding them can make one read the code more easily.

@a-h
Copy link
Owner

a-h commented Mar 29, 2024

From the LSP spec, it looks like it is possible to add that. https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#textDocument_foldingRange

The change would be applied here:

func (p *Server) FoldingRanges(ctx context.Context, params *lsp.FoldingRangeParams) (result []lsp.FoldingRange, err error) {
p.Log.Info("client -> server: FoldingRanges")
defer p.Log.Info("client -> server: FoldingRanges end")
// There are no folding ranges in templ files.
// return p.Target.FoldingRanges(ctx, params)
return []lsp.FoldingRange{}, nil
}

First, you'd need to get the source code of the current templ file from the in-memory cache, as per

d, _ := p.TemplSource.Get(string(params.TextDocument.URI))
template, ok, err := p.parseTemplate(ctx, params.TextDocument.URI, d.String())
if err != nil {
p.Log.Error("parseTemplate failure", zap.Error(err))
}
if !ok {
return
}

Then, you'd build on @alehechka's recent work in 22f761a, where he added tracking the positions of HTML elements in the parser tree.

With those changes, it's now possible to walk through the templ object model, find the locations of things you want to fold (e.g. HTML elements etc) and return back the list of folding ranges in the LSP. The structure of a templ file is laid out in https://github.com/a-h/templ/blob/main/parser/v2/structure.go - once parsed, those are the nodes you're looking for in the doc.

This won't be high on the priority list for me, but I'd be happy to take a PR for the change. Anyone reading, let me know if you're going to try.

If you want to build this feature, and aren't sure how LSP stuff works, I did a talk at Gophercon UK about it, and I talk about how it works in templ, so do check it out: https://www.youtube.com/watch?v=EkK8Jxjj95s

@a-h a-h changed the title [LSP] feature request: add folding feature: add folding to LSP Mar 30, 2024
@a-h a-h added enhancement New feature or request help wanted Extra attention is needed good first issue Good for newcomers lsp labels Mar 30, 2024
@jackielii
Copy link
Contributor Author

@a-h Reading the links you provided, I can't help but feeling this would be covered by the "html intellisense" that's proposed here: #498

@alehechka what do you think? Is it worth adding just the folding or is it better to have the full HTML capabilities here that should include folding?

@joerdav
Copy link
Collaborator

joerdav commented Apr 3, 2024

I believe that this won't come by html intellisense being integrated. We will want do our own folding since we will want to allow folding of html, go code and custom templ code. So proxying the html lsp won't suffice here.

@sirgallifrey
Copy link
Contributor

I'll play around with this, but I don't have experience working with LSPs, so no promises

@sirgallifrey
Copy link
Contributor

@a-h I was able to make good progress, so I'm now confident I'll have a PR soon.

still have to write all the tests, and figure out if I'll be able to add folding to Go code, but the rest is looking good.

Screen Recording 2024-04-07 at 02 45 56

@joerdav
Copy link
Collaborator

joerdav commented Apr 8, 2024

Great work! Hopefully go folding will be a case of proxying gopls

@sirgallifrey
Copy link
Contributor

Unfortunately that gif I posted was a blunter, turned out my templ build was not working and that is the default folding VSCode does when there's no LSP

(I I'll not delete my comment to perpetuate my shame 😄 )

But I'm not too far off. My only issue is that the way I did is eating the last line (see pictures)
The spec says you can send a line number and a col number. The col number by default is the end of the line, and col number is optional and even if the serves sends them, the client can choose to ignore.

so my issue is that I send the line number of the closing bracket, on the column right before it and seems VS code is just ignoring it and consuming the entire line.

Screenshot 2024-04-08 at 22 06 24
Screenshot 2024-04-08 at 22 06 41

You can see the folded shows only <head> while the default VSCode implementation would also show the closing tag. Same thing for the brackets.

@sirgallifrey
Copy link
Contributor

@joerdav Yes, That's what I'll try to do, I guess i just have to make sure I just pic the foldings of gopls that correspond to Templs TemplateFileGoExpression nodes

@joerdav
Copy link
Collaborator

joerdav commented Apr 9, 2024

Related to this, for treesitter users folds can be defined by treesitter. I've got a PR for this open, and can confirm it works with nvim.

vrischmann/tree-sitter-templ#43

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request good first issue Good for newcomers help wanted Extra attention is needed lsp
Projects
None yet
Development

No branches or pull requests

4 participants