Skip to content

Demo vault + Fix link resolution + detailed truncation notice - #81

Merged
hon-gyu merged 3 commits into
mainfrom
hy/260727-lsp
Jul 27, 2026
Merged

Demo vault + Fix link resolution + detailed truncation notice#81
hon-gyu merged 3 commits into
mainfrom
hy/260727-lsp

Conversation

@hon-gyu

@hon-gyu hon-gyu commented Jul 27, 2026

Copy link
Copy Markdown
Owner

No description provided.

hon-gyu added 3 commits July 27, 2026 22:21
A vault where every LSP feature has somewhere to be tried: open
pkg/oystermark/lsp/demo-vault as the workspace root and start from
start-here.md. It carries its own oysterlsp.json, so daily notes and the
two unresolvedFragment settings are live without any client setup.

command-panel.md is generated by tools/gen_panel.ml from
Command_block.all_of_command and promoted into the source tree. A note
that claims to list every command stops being true the moment the
catalogue grows a constructor; this way it is rebuilt rather than
remembered. Everything else in the vault is written by hand.

Building the vault turned up two things the demo would otherwise have
demonstrated backwards:

- {#id} above a heading was reported as a duplicate anchor. The id
  reaches diagnostics twice — once as the heading's slug, which the
  parser resolves from that attribute, and once as the attribute line —
  and one authored anchor is not a collision. The heading occurrence is
  dropped; a genuine collision between a derived slug and a hand-written
  id still fires. Duplicate ids had no direct test at all, so this adds
  the three that pin it.

- feature-attribute-anchors showed pandoc's trailing form
  (## Overview {#intro}) and an attribute line below a blockquote.
  Neither attaches: the braces are consumed into the heading's inline
  content, no anchor is recorded, and the heading text keeps a trailing
  space that breaks the by-text fragment too. Block attributes go on
  their own line above the block.

The vault is a demo, not a test — nothing asserts against it.

Closes #77.
A bare [[note]] names no directory, so every note.md in the vault is a
legitimate subsequence match. resolve_file took List.find — the first in
index order, which is readdir order. Opening this repo at its root and
following [[links]] from the demo vault landed in
_build/default/pkg/oystermark/lsp/demo-vault/notes/links.md, not because
_build is special but because it happened to be listed first.

The spec defined precedence between exact and subsequence matching and
said nothing about ties within subsequence matching, so there was no
answer to implement. Measured Obsidian's own getFirstLinkpathDest with
pkg/oystermark/obsidian-resolver over a vault built to separate the
candidate rules; it ranks by:

  1. fewest path components,
  2. same folder as the linking note, among equal depths,
  3. creation order — arbitrary to an author.

Proximity to the linking note never beats path length: from
notes/probe.md, [[s1]] reaches s1.md at the root, not the sibling
notes/s1.md. Two measurements pin the tail: [[s5]] chose notes/s5.md
over aaa/s5.md, so the tiebreak is not alphabetical but the source
folder; [[s7]] chose mmm/s7.md over bbb/s7.md, so what remains is
creation order.

The spec now records the ranking with that evidence table, and
resolve_file implements it, keeping index order for candidates that tie
on every rank. The inline test is the same vault, note for note.

_build needs no special case: the source copy is six components deep and
the build copy eight, so the shorter path wins on rule 1.
The notice was a bare "*(truncated)*", which told the reader nothing
about whether to open the file.  Report it in lines, the unit a reader
perceives, with the percentage derived from the very same counts so the
two figures can never disagree:

    *(truncated: showing 42 of 80 lines, 52%)*

When 0 or 1 lines are hidden the counts carry no information (the
remainder is one long line, e.g. a wide table row), so the notice
switches wholesale to bytes rather than mixing units.  The percentage is
rounded down and clamped to [1, 99]: truncation did happen, so the
reader is never told 0% or 100%.

The budget now applies to the body alone, with the path header
prepended afterwards, so the header survives however small
hover.maxChars is.

Closes #79.
@hon-gyu
hon-gyu merged commit c4c6243 into main Jul 27, 2026
0 of 2 checks passed
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