Skip to content

LSP features: ... - #85

Merged
hon-gyu merged 7 commits into
mainfrom
hy/260730-lsp
Aug 3, 2026
Merged

LSP features: ...#85
hon-gyu merged 7 commits into
mainfrom
hy/260730-lsp

Conversation

@hon-gyu

@hon-gyu hon-gyu commented Aug 3, 2026

Copy link
Copy Markdown
Owner
  • resolve heading by both exact text and slug
  • lsp: inlay hint for the direction of an intra-note link
  • lsp/backlink: add command when clicking codelens; removing inlay hint
  • FIX,DOC
  • lsp/hover: describe images and binary files instead of dumping their bytes
  • lsp/completion: complete paths and fragments inside Markdown links
  • lsp/docs: correct the footnote spec against what the parser actually does

hon-gyu added 7 commits July 31, 2026 21:23
A link into the note you are already reading gets an arrow and a line
distance after it — [[#setup]]↓8 — so a list of near-identical [[#…]]
tokens says where each target is without following any of them.

The hint sits beside its link rather than at the end of the line: with
two links on a row, end-of-line placement would have to merge them into
one label and leave the reader to map arrows onto links by document
order.

Directions are ↑/↓ with the distance, or →/← for a same-line target
(inline attribute anchors only, where the distance is zero and says
nothing). Cross-note links, unresolved links and whole-note self-links
get no hint at all.

Separate from the reference counts already in inlay_hints.ml: the two
share the response and nothing else, and inlayHints.linkDirection
switches the arrows off on their own.

Spec: feature-inlay-hints-link-direction.mld. The demo vault gains
notes/inlay-hints.md, which shows both hint kinds.
…bytes

Hovering an image link read the file and put its raw bytes in the hover
response: unreadable, and invalid UTF-8 over JSON-RPC. Non-image binary
targets (a PDF, say) had the same problem.

An image is now described — format, dimensions read from the container
header (PNG IHDR, GIF screen descriptor, JPEG SOFn), size — and any other
file whose leading bytes contain a NUL is named as binary. With
hover.imagePreview set, the description is followed by the image itself as
a data: URI, capped by hover.imageMaxBytes. Off by default: whether that
renders is the client's markdown renderer's business.

The hover budget now applies to note content only, since truncating a data
URI would produce a broken image rather than a shorter one.
Only [[wikilinks]] were served, though both syntaxes resolve, diagnose and
navigate the same way — so a vault written in Markdown links got no help
writing the destination it would later be told was broken.

[label](<cursor>) now offers every file in the vault as a vault-relative
path with its extension, escaped so that what is inserted resolves back to
the file it came from: angle brackets for a path with a space, backslashes
for what would end the destination early. [label](note.md#<cursor>) reuses
the wikilink fragment suggestions unchanged. Image syntax sorts images
first without hiding notes.

Items now carry a textEdit with an explicit range instead of an insertText,
for wikilinks too: a client left to its own word rules splits on /, which
turned accepting notes/deep.md after typing notes/ into
notes/notes/deep.md. The response is a CompletionList so a capped path list
can be marked incomplete.

Also drops three docs/dune entries for specs deleted on purpose, and the
one reference left pointing at them.
…does

Checked the three load-bearing claims by parsing a document and reading the
AST.

An undefined footnote reference is not in the AST at all: it is a shortcut
reference link with no definition, so [^ghost] survives as plain Text. The
spec had references coming from the AST, which would have made both
undefined-label features report nothing in the case they exist for.
References are collected textually instead; definitions stay AST-sourced,
where the node knows how far the body extends.

Labels are case-insensitive — case_sensitive_labels defaults to false and
of_string does not override it — so [^KANT] resolves [^kant]. The spec was
silent, which would have left find-references missing occurrences and
rename half-renaming. Identity is now the folded key throughout.

Rename could merge two footnotes and lose a body; that is now a refusal,
with re-spelling a label to a different case explicitly not a collision.

Adds a section on what the textual scan must decline (code spans, code
blocks, escapes, wikilink interiors, the definition's own label), why the
parser is the authority on all of it, and why the collector is the piece to
test hardest. Refreshes the trigger-character list and the item shape, both
stale since the completion work.
@hon-gyu
hon-gyu merged commit 53d2f0e into main Aug 3, 2026
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

Successfully merging this pull request may close these issues.

1 participant