Skip to content

Detect bare relative and punctuation-wrapped file paths (#107)#110

Merged
dakra merged 1 commit intomainfrom
fix-107-file-detection
Apr 15, 2026
Merged

Detect bare relative and punctuation-wrapped file paths (#107)#110
dakra merged 1 commit intomainfrom
fix-107-file-detection

Conversation

@dakra
Copy link
Copy Markdown
Owner

@dakra dakra commented Apr 15, 2026

Summary

  • Fixes File detection regex misses bare relative paths #107ghostel--detect-urls now linkifies compiler-output-style paths the old \(?:\./\|/\)…:[0-9]+ regex missed: bare relative paths with a / (Rust retroact-macros/src/lib.rs:43:4, Go pkg/foo/bar.go:12:5, TS src/Button.tsx:17), and paths wrapped in punctuation (Python tracebacks (/home/user/x.js:17:5), [path:N], backtick/quote-wrapped).
  • Captures optional :column; ghostel--open-link moves the cursor to that column when present.
  • New ghostel-file-detection-regex defcustom exposes the pattern. Bare filenames without a / (e.g. main.go:12) are intentionally not matched by default — relying on file-exists-p alone for those risks stat'ing every word:digits token on slow or network filesystems. Users can opt in via the defcustom.
  • Per-scan hash memoizes file-exists-p for repeated paths (Rust --> blocks, Python tracebacks).

Performance

Despite matching strictly more patterns, PTY throughput on URL-heavy output improved:

5 MB cat through PTY Plain ASCII URL-heavy
ghostel (main) 70 MB/s 44 MB/s
ghostel (this PR) 70 MB/s 56 MB/s (+27%)
ghostel (no detect) 70 MB/s 70 MB/s
vterm 34 MB/s 27 MB/s

The old regex had no leading anchor and retried a full path scan at every / in URL text. The new regex anchors on whitespace or common path-wrapper punctuation (([{<\'"`) and uses non-backtracking character classes, so the match-attempt count drops sharply on URL-dense output.

README benchmark numbers were also refreshed to current hardware (M4 Max, Emacs 31) as part of this PR.

Test plan

  • make test — all 115 elisp tests pass, including 5 new cases:
    • bare relative path (existing file → link; nonexistent → skip)
    • paren-wrapped path (Python traceback style) matched
    • bare filename without / skipped (false-positive protection)
    • custom ghostel-file-detection-regex opts into broader matching
    • fileref:PATH:LINE:COL round-trips through ghostel--open-link
  • make bench — url-heavy throughput up 27%, plain unchanged
  • Exercise interactively: run cargo check in a ghostel buffer, click through to the files

Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Updates Ghostel’s plain-text link detection to recognize more compiler/traceback-style file:line[:col] references (including bare relative paths with / and punctuation-wrapped paths), and to jump to the reported column when present.

Changes:

  • Add customizable ghostel-file-detection-regex and update ghostel--detect-urls to use it, including per-scan file-exists-p memoization.
  • Extend fileref: handling in ghostel--open-link to support optional :col.
  • Add tests/bench inputs and refresh README benchmark numbers.

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 2 comments.

File Description
ghostel.el Introduces configurable file detection regex, memoized existence checks, and :col support when opening fileref: links.
test/ghostel-test.el Adds ERT coverage for new file detection patterns and :col cursor positioning.
bench/ghostel-bench.el Expands benchmark URL/path generator with new path formats to reflect updated detection.
README.md Updates benchmark results to current measurements/hardware.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread ghostel.el Outdated
Comment thread ghostel.el Outdated
@dakra dakra force-pushed the fix-107-file-detection branch 7 times, most recently from d1c61da to 4a13868 Compare April 15, 2026 15:37
Broaden `ghostel--detect-urls` to linkify compiler-output-style paths
that the old `\(?:\./\|/\)…:[0-9]+` regex missed:

- Bare relative paths containing at least one `/` — Rust's
  `retroact-macros/src/lib.rs:43:4`, Go's `pkg/foo/bar.go:12:5`,
  TypeScript's `src/components/Button.tsx:17`.
- Paths wrapped in punctuation — Python tracebacks like
  `(/home/user/index.js:17:5)`, bracketed `[path:N]`, backtick or
  quote-wrapped paths.
- Optional `:column` after `:line`; `ghostel--open-link` now moves to
  that column when present.

New `ghostel-file-detection-regex` defcustom exposes the pattern so
users can narrow or widen it.  Group 1 captures the linkified text; the
outer match may include a leading path-boundary character that is not
part of the link.  Bare filenames without a `/` (e.g. `main.go:12`) are
deliberately not matched by default — relying on `file-exists-p` alone
for those risks stat'ing every `word:digits` token on slow or network
filesystems.

The new default regex uses non-backtracking character classes
(`[^ \t\n\r:\"<>/]*/`) and a punctuation-boundary anchor so the scan is
cheap even on URL-heavy output.  A small per-scan hash memoizes
`file-exists-p` so repeated paths in a redraw (common in Rust `-->`
blocks and Python tracebacks) aren't re-stat'd.

PTY benchmark (5 MB url-heavy `cat` through a real pipe):

  ghostel (old regex):  44 MB/s
  ghostel (this PR):    56 MB/s  (+27%, matches strictly more patterns)

Also refreshes README benchmark numbers to current hardware and adds
Rust/Go/TS sample lines to the url bench fixture so the URL-heavy
scenario actually exercises the new matcher.

Fixes #107
@dakra dakra force-pushed the fix-107-file-detection branch from 4a13868 to ed17efb Compare April 15, 2026 15:50
@dakra dakra merged commit ed17efb into main Apr 15, 2026
20 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.

File detection regex misses bare relative paths

2 participants