From a72a2a5f7410d3350909494aba964088c23ffa2e Mon Sep 17 00:00:00 2001 From: Peter Stuifzand Date: Sat, 10 Jul 2021 10:50:35 +0200 Subject: [PATCH] LSP references to browse the backlinks of the link under the caret (#58) --- CHANGELOG.md | 1 + internal/adapter/lsp/server.go | 67 ++++++++++++++++++++++++++++++++++ 2 files changed, 68 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index b24ae06..c892bd8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,7 @@ All notable changes to this project will be documented in this file. * `{{json title}}` prints with quotes `"An interesting note"` * `{{json .}}` serializes the full template context as a JSON object. * Use `--header` and `--footer` options with `zk list` to print arbitrary text at the start or end of the list. +* Support for LSP references to browse the backlinks of the link under the caret (contributed by [@pstuifzand](https://github.com/mickael-menu/zk/pull/58)). ### Fixed diff --git a/internal/adapter/lsp/server.go b/internal/adapter/lsp/server.go index e07ec0c..c139525 100644 --- a/internal/adapter/lsp/server.go +++ b/internal/adapter/lsp/server.go @@ -104,6 +104,8 @@ func NewServer(opts ServerOpts) *Server { ResolveProvider: boolPtr(true), } + capabilities.ReferencesProvider = &protocol.ReferenceOptions{} + return protocol.InitializeResult{ Capabilities: capabilities, ServerInfo: &protocol.InitializeResultServerInfo{ @@ -389,6 +391,71 @@ func NewServer(opts ServerOpts) *Server { return actions, nil } + handler.TextDocumentReferences = func(context *glsp.Context, params *protocol.ReferenceParams) ([]protocol.Location, error) { + doc, ok := server.documents.Get(params.TextDocument.URI) + if !ok { + return nil, nil + } + + link, err := doc.DocumentLinkAt(params.Position) + if link == nil || err != nil { + return nil, err + } + + notebook, err := server.notebookOf(doc) + if err != nil { + return nil, err + } + + target, err := server.noteForHref(link.Href, doc, notebook) + if link == nil || target == nil || err != nil { + return nil, err + } + + p, err := notebook.RelPath(target.Path) + if err != nil { + return nil, err + } + + opts := core.NoteFindOpts{ + LinkTo: &core.LinkFilter{Paths: []string{p}}, + } + + notes, err := notebook.FindNotes(opts) + if err != nil { + return nil, err + } + + var locations []protocol.Location + + for _, note := range notes { + pos := strings.Index(note.RawContent, target.Path[0:len(target.Path)-3]) + var line uint32 = 0 + if pos < 0 { + line = 0 + } else { + linePos := strings.Count(note.RawContent[0:pos], "\n") + line = uint32(linePos) + } + + locations = append(locations, protocol.Location{ + URI: pathToURI(filepath.Join(notebook.Path, note.Path)), + Range: protocol.Range{ + Start: protocol.Position{ + Line: line, + Character: 0, + }, + End: protocol.Position{ + Line: line, + Character: 0, + }, + }, + }) + } + + return locations, nil + } + return server }