From: Javier Sagredo Date: Wed, 6 May 2026 22:09:17 +0000 (+0200) Subject: Document setup for the two Emacs editor-link schemes X-Git-Url: https://git.sagredo.dev/?a=commitdiff_plain;h=a9c7d89470da020116a96e3b71d3b8a46715a5d5;p=classgraph.git Document setup for the two Emacs editor-link schemes Step-by-step org-protocol setup (init.el snippet + xdg-mime desktop entry + macOS pointer) plus a DIY emacs:// scheme path with a sample emacsclient wrapper script. Both end with the "pick from dropdown" step so the user can see the loop close. Co-Authored-By: Claude Opus 4.7 (1M context) --- diff --git a/README.md b/README.md index 863c42f..bea650a 100644 --- a/README.md +++ b/README.md @@ -287,6 +287,149 @@ a clickable link that opens the file at the right line in your editor. Schemes that take a column (`vscode`, `cursor`, `txmt`, `emacs`) get one; `idea`, `emacs-org`, and `file` ignore it. +#### Setting up the Emacs schemes + +The two Emacs variants build: + +| Scheme | URL shape | +|---|---| +| `emacs` | `emacs://open?file=…&line=…&column=…` | +| `emacs-org` | `org-protocol://open-source?url=file://…&line=…` | + +Neither URL scheme is hooked up by default — you need to register a +handler. Pick whichever suits your habits. + +##### `emacs-org` — recommended (org-protocol) + +`org-protocol://` is already understood by a running Emacs once you +load `org-protocol`, so the only host-side wiring is a desktop entry +that hands the URL to `emacsclient`. + +**1. Tell Emacs to run a server, load `org-protocol`, and register a +local handler for `open-source`** (in your `init.el` / +`~/.config/emacs/init.el`): + +```elisp +(require 'server) +(unless (server-running-p) (server-start)) +(require 'org-protocol) + +(defun my/org-protocol-open-source (fname) + "Open a file:// URL with line, bypassing the project-alist remap." + (let* ((data (org-protocol-parse-parameters fname nil '(:url :line))) + (uri (plist-get data :url)) + (line (plist-get data :line)) + (path (cond + ((string-prefix-p "file://" uri) (url-unhex-string (substring uri 7))) + (t (url-unhex-string uri))))) + (find-file path) + (when line + (goto-char (point-min)) + (forward-line (1- (string-to-number line)))) + nil)) + +(add-to-list 'org-protocol-protocol-alist + '("open-source-local" + :protocol "open-source" + :function my/org-protocol-open-source + :kill-client nil)) +``` + +Why the custom handler? The built‑in `org-protocol-open-source` is +designed to remap *web* URLs to a local working copy via +`org-protocol-project-alist` and silently does nothing for plain +`file://` URLs. Shadowing it with a user entry under the same protocol +name (`open-source`) skips the remap and just opens the file at the +given line. If you're on `straight`/`use-package`, make sure these +forms run eagerly (e.g. `:demand t`, not `:defer`/`:commands`) so the +handler is registered at startup. + +Restart Emacs (or `M-x eval-buffer`). Verify with +`M-x server-running-p` returning `t` and +`(assoc "open-source-local" org-protocol-protocol-alist)` returning +your entry. + +**2. Register a desktop entry so the OS knows what to do with +`org-protocol://` URLs.** On Linux, drop the following at +`~/.local/share/applications/org-protocol.desktop`: + +```ini +[Desktop Entry] +Name=Emacs (org-protocol) +Exec=emacsclient -- %u +Icon=emacs +Type=Application +Terminal=false +Categories=Development; +MimeType=x-scheme-handler/org-protocol; +``` + +Refresh the MIME database and make it the default for the scheme: + +```bash +update-desktop-database ~/.local/share/applications/ +xdg-mime default org-protocol.desktop x-scheme-handler/org-protocol +``` + +The first link click in the browser will prompt to confirm; after that +it opens silently. + +On macOS, use a tool like +[OpenWith](https://github.com/sveinbjornt/OpenWith) or a small +Automator app that shells out to +`/usr/local/bin/emacsclient -n -- "$1"` and register it as the +`org-protocol` URL handler in System Settings → *Privacy & Security* +→ *Default web browser …*. + +**3. Pick `Emacs (org-protocol)` from the editor dropdown in the side +panel.** Click any `Defined at` line and the file opens at the right +line in the running Emacs session. + +##### `emacs` — DIY scheme + +Use this if you don't want `org-protocol` in your config or you'd +rather thread the column through too. There is no built-in handler +for `emacs://` — you supply your own. + +**1. Drop a small wrapper script** at, say, +`~/.local/bin/emacs-uri-open`: + +```bash +#!/usr/bin/env bash +# Parse emacs://open?file=PATH&line=LINE&column=COL and pass to emacsclient. +url="$1" +file=$(printf '%s' "$url" | sed -nE 's#.*[?&]file=([^&]+).*#\1#p' | python3 -c 'import sys,urllib.parse; print(urllib.parse.unquote(sys.stdin.read()))') +line=$(printf '%s' "$url" | sed -nE 's#.*[?&]line=([0-9]+).*#\1#p') +col=$( printf '%s' "$url" | sed -nE 's#.*[?&]column=([0-9]+).*#\1#p') +exec emacsclient -n "+${line:-1}:${col:-1}" -- "$file" +``` + +`chmod +x ~/.local/bin/emacs-uri-open`. + +**2. Register a desktop entry** at +`~/.local/share/applications/emacs-uri.desktop`: + +```ini +[Desktop Entry] +Name=Emacs (emacs:// URL) +Exec=/home/YOUR_USER/.local/bin/emacs-uri-open %u +Icon=emacs +Type=Application +Terminal=false +Categories=Development; +MimeType=x-scheme-handler/emacs; +``` + +Then: + +```bash +update-desktop-database ~/.local/share/applications/ +xdg-mime default emacs-uri.desktop x-scheme-handler/emacs +``` + +**3. Pick `Emacs (emacs://)` from the dropdown.** Same UX as above, +plus the column is passed through. + **Source roots are inferred automatically.** The plugin records source paths as GHC saw them (usually relative to each package's source dir), so the viewer needs an absolute prefix to make `vscode://` /