Repository navigation
Serve whole soft-wrapped targets to thing-at-point and ffap - #584
Merged
Merged
Conversation
The renderer commits one buffer line per terminal row, so a path or URL longer than the terminal is split by a real newline. Link detection already attaches the whole target to every row, but commands that extract their string from buffer text — thing-at-point, ffap, the find-file M-n default — still stopped at the row break: ffap on a wrapped path resolved to the directory prefix that exists and visited that instead of the file. ghostel-mode now registers buffer-local thing-at-point providers for filename, existing-filename, and url. On a detected link the answer comes from the link's target, so filename drops the :LINE tail and existing-filename is the absolute path detection already validated; elsewhere the logical line is joined before extraction, which also covers the active prompt line detection skips and URLs with detection switched off. On Emacs 30, bounds providers make bounds-of-thing-at-point span the wrap on detected links. The forward-thing provider alist is left alone: an entry there replaces the default motion instead of falling through. file-name-at-point-functions gains a buffer-local member returning the detected file, which feeds the M-n default in find-file prompts. find-file-at-point is remapped to the new ghostel-find-file-at-point, which opens the link at point at its recorded line and column and falls back to find-file-at-point off a link or when the detected file no longer exists. ffap itself offers no early-enough extension point: ffap-alist is consulted only after the existence checks that let the directory-prefix fragment win.
ghostel.el had grown past six thousand lines. The link cluster is self-contained — no other file used its internals — and moves wholesale: the link keymap and open/navigation commands, plain-text URL and file detection with the soft-wrap join machinery, the deferred-detection timer and its state, and the thing-at-point/ffap integration. ghostel.el requires the file eagerly, like ghostel-prompt.el: the renderer attaches ghostel-link-map to OSC 8 spans as it renders, so the map must be bound before any redraw. The mode body's link registrations collapse into the new ghostel-links-setup. The moved defcustoms name :group ghostel explicitly, since the defgroup stays in core, and ghostel-hyperlink-repeat-map now sits next to the navigation commands it repeats. The code is otherwise moved verbatim.
dakra
force-pushed
the
worktree-thingatpt-providers
branch
from
July 29, 2026 11:51
c75140e to
f0a9cf0
Compare
This branch was previously deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The renderer commits one buffer line per terminal row, so a path or URL longer than the terminal is split by a real newline. Link detection already attaches the whole target to every row, but commands that extract their string from buffer text —
thing-at-point, ffap, the find-fileM-ndefault — still stopped at the row break: ffap on a wrapped path resolved to the directory prefix that exists and visited that instead of the file (#582).Commit 1 — the feature:
thing-at-pointproviders forfilename,existing-filename, andurl. On a detected link the answer comes from the link's target (filenamedrops the:LINEtail, so stockexisting-filenameworks and returns the absolute path detection already validated); elsewhere the logical line is joined before extraction, which also covers the active prompt line detection skips and URLs with detection switched off. On Emacs 30, bounds providers makebounds-of-thing-at-pointspan the wrap on detected links. Theforward-thingprovider alist is left alone — an entry there replaces the default motion instead of falling through.file-name-at-point-functionsmember returning the detected file, feedingM-nin find-file prompts.ghostel-find-file-at-point, bound via<remap> <find-file-at-point>: opens the link at point at its recorded line and column; falls back tofind-file-at-pointoff a link or when the detected file no longer exists. ffap itself offers no early-enough extension point:ffap-alistis consulted only after the existence checks that let the directory-prefix fragment win. Known residual: a literalM-x ffapbypasses the remap; that is only fixable upstream.Commit 2 — extraction: the self-contained hyperlink subsystem (link keymap, open/navigation commands, URL/file detection with the soft-wrap join machinery, detection timer, the new integrations) moves to
lisp/ghostel-links.el(~800 lines; ghostel.el drops from 6097 to 5367 lines), eagerly required likeghostel-prompt.el. Kept as a separate commit so the feature diff stays reviewable. Only deviations from a verbatim move::group 'ghostelon the moved defcustoms, the repeat-map relocated next to its commands, and the mode-body registrations collapsed intoghostel-links-setup.Testing: 10 new ERT tests (wrapped/unwrapped links, both fragments, property and joined-line fallbacks, OSC 8 target, bounds span, hook, command fallbacks);
make -j8 allandmake checkdocgreen on both commits; verified end-to-end against the reporter's exact scenario in a native terminal buffer.