diff --git a/CHANGELOG.md b/CHANGELOG.md index ec6cb40..1897d1e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,7 +7,7 @@ - Add Asciidoctor integration for previewing and exporting documents, reachable from the new `adoc-asciidoctor-menu` transient on `C-c C-c` (and the AsciiDoc menu). `adoc-preview` renders the current buffer with `asciidoctor` and shows the HTML in a side pane - an xwidget WebKit widget when available, otherwise `eww`, configurable via `adoc-preview-backend` - and `adoc-live-preview-mode` re-renders on every save. The preview feeds the buffer to `asciidoctor` through its standard input, so unsaved edits and relative `include::` / image paths both keep working. Export commands `adoc-export-html`, `adoc-export-docbook`, `adoc-export-pdf`, and `adoc-export-epub` run through `compile`, so Asciidoctor's warnings and errors are navigable. - Add context-aware completion via `completion-at-point` (kbd:[M-TAB], or any of corfu/company/built-in completion). Inside `<<` or `xref:` it completes cross-reference ids from the explicit anchors defined in the buffer (`[[id]]`, `[#id]`, `[[[biblio]]]`); inside `{` it completes attribute names (the ones defined with `:name:` plus a set of common built-ins); after `include::` it completes file paths; and inside `[source,` it completes source-block language names. It stays out of the way in plain prose. - Add a Flymake backend (`adoc-flymake`) that runs the buffer through Asciidoctor and reports its parser errors and warnings inline. It's registered automatically, so enabling `flymake-mode` is enough. The check feeds the buffer to Asciidoctor over its standard input, so it works on unsaved edits. -- Make references clickable. Cross-references (`<>`, `xref:id[]`), links and URLs (`link:`, `https:`, `mailto:`, ...), and `include::` macros now highlight on hover and follow with a `mouse-1` (or `mouse-2`) click - the same action as `C-c C-o` / `M-.`. As part of this, `adoc-follow-thing-at-point` now also follows `link:` macros (opening a local target or a URL) and no longer passes the `[label]` along when opening a URL macro. +- Make references clickable. Cross-references (`<>`, `xref:id[]`), links and URLs (`link:`, `https:`, `mailto:`, ...), and `include::` macros now highlight and underline on hover (via the new `adoc-link-mouse-face`) and follow with a `mouse-1` (or `mouse-2`) click - the same action as `C-c C-o` / `M-.`. As part of this, `adoc-follow-thing-at-point` now also follows `link:` macros (opening a local target or a URL) and no longer passes the `[label]` along when opening a URL macro. - Add an `xref` backend over AsciiDoc anchors. In an `adoc-mode` buffer, `M-?` (`xref-find-references`) lists every cross-reference to the anchor at point, and the standard xref machinery (the marker stack, the completion-read prompt, `consult-xref`, ...) now works for AsciiDoc ids. Definitions are anchors (`[[id]]`, `[#id]`, `[[[biblio]]]`) and references are `<>` / `xref:id[]` usages, resolved within the current buffer. `M-.` keeps following URLs and `include::` too, via `adoc-follow-thing-at-point`. - Follow Antora cross-file cross-references. In a file inside an Antora component (one with an `antora.yml` above it), following an `xref:` that targets a page - e.g. `xref:basics/install.adoc[]` or `xref:other.adoc#a-section[]`, including a `module:` prefix - now opens the resolved page (under the target module's `pages/` directory) and jumps to the `#fragment` section. Works from `C-c C-o` / `M-.` and a mouse click, and `M-,` (`xref-go-back`) returns. Resolution is limited to the current component. - Complete Antora `xref:` targets. Inside an `xref:` in an Antora component, completion offers the component's pages as targets (pages in other modules prefixed with `module:`), and after a `#` it offers the target page's section ids and anchors. A same-page `xref:#` completes against the current buffer. diff --git a/adoc-mode.el b/adoc-mode.el index b006183..f1fa670 100644 --- a/adoc-mode.el +++ b/adoc-mode.el @@ -830,6 +830,11 @@ For example the URL part of `http://example.com[foo]', or a raw "Face for reference link titles." :group 'adoc-faces) +(defface adoc-link-mouse-face + '((t (:inherit highlight :underline t))) + "Face used to highlight a link, URL or anchor under the mouse pointer." + :group 'adoc-faces) + (defface adoc-comment-face '((t (:inherit font-lock-comment-face))) "Face for HTML comments." @@ -2090,7 +2095,7 @@ TEXTPROPS is an additional plist with textproperties." (let ((cmd-name (regexp-opt '("http" "https" "ftp" "file" "irc" "mailto" "callto" "link")))) (list `(lambda (end) (adoc-kwf-std end ,(adoc-re-inline-macro cmd-name) '(0) '(0))) - '(0 '(face nil keymap adoc-link-keymap mouse-face highlight help-echo "mouse-1: visit this link")) ; clickable + '(0 '(face nil keymap adoc-link-keymap mouse-face adoc-link-mouse-face help-echo "mouse-1: visit this link")) ; clickable `(1 '(face adoc-url-face adoc-reserved t adoc-flyspell-ignore t) t) ; cmd-name `(2 '(face adoc-url-face adoc-reserved t) t) ; : `(3 '(face adoc-url-face adoc-reserved t adoc-flyspell-ignore t) t) ; target @@ -2102,7 +2107,7 @@ TEXTPROPS is an additional plist with textproperties." (let ((cmd-name (regexp-opt '("http" "https" "ftp" "file" "irc" "mailto" "callto" "link")))) (list `(lambda (end) (adoc-kwf-std end ,(adoc-re-inline-macro cmd-name nil nil 'empty) '(0) '(0))) - '(0 '(face nil keymap adoc-link-keymap mouse-face highlight help-echo "mouse-1: visit this link")) ; clickable + '(0 '(face nil keymap adoc-link-keymap mouse-face adoc-link-mouse-face help-echo "mouse-1: visit this link")) ; clickable '(1 '(face adoc-url-face adoc-reserved t adoc-flyspell-ignore t) append) ; cmd-name '(2 '(face adoc-url-face adoc-reserved t) append) ; : '(3 '(face adoc-url-face adoc-reserved t adoc-flyspell-ignore t) append) ; target @@ -2146,7 +2151,7 @@ TEXTPROPS is an additional plist with textproperties." (both (concat "\\(?:" url "\\)\\|\\(?:" url<> "\\)\\|\\(?:" email "\\)"))) (list `(lambda (end) (adoc-kwf-std end ,both '(0) '(0))) - '(0 '(face adoc-url-face adoc-reserved t adoc-flyspell-ignore t keymap adoc-link-keymap mouse-face highlight help-echo "mouse-1: visit this URL") append t)))) + '(0 '(face adoc-url-face adoc-reserved t adoc-flyspell-ignore t keymap adoc-link-keymap mouse-face adoc-link-mouse-face help-echo "mouse-1: visit this URL") append t)))) ;; bug: escapes are not handled yet ;; TODO: give the inserted character a specific face. But I fear that is not @@ -2500,7 +2505,7 @@ for multiline constructs to be matched." '(4 '(face adoc-meta-hide-face adoc-reserved block-del))) ; ] ;; include (list "^\\(\\(include1?::\\)\\([^ \t\n]*?\\)\\(\\[\\)\\(.*?\\)\\(\\]\\)\\)[ \t]*$" - '(1 '(face nil adoc-reserved block-del keymap adoc-link-keymap mouse-face highlight help-echo "mouse-1: open this include")) ; the whole match + '(1 '(face nil adoc-reserved block-del keymap adoc-link-keymap mouse-face adoc-link-mouse-face help-echo "mouse-1: open this include")) ; the whole match '(2 '(face adoc-preprocessor-face adoc-flyspell-ignore t)) ; macro name '(3 '(face adoc-meta-face adoc-flyspell-ignore t)) ; file name '(4 'adoc-meta-hide-face) ; [ @@ -2790,7 +2795,7 @@ for multiline constructs to be matched." (adoc-kw-inline-macro "anchor" nil nil nil 'adoc-anchor-face t '("xreflabel")) (adoc-kw-inline-macro "xref" nil nil nil '(adoc-reference-face adoc-internal-reference-face) t '(("caption") (("caption" . adoc-reference-face))) - '(keymap adoc-link-keymap mouse-face highlight help-echo "mouse-1: jump to this anchor")) + '(keymap adoc-link-keymap mouse-face adoc-link-mouse-face help-echo "mouse-1: jump to this anchor")) (adoc-kw-inline-macro "footnote" t nil 'adoc-footnote-marker-face nil nil 'adoc-footnote-text-face) (adoc-kw-inline-macro "footnoteref" t 'single-attribute 'adoc-footnote-marker-face nil nil '(("id") (("id" . adoc-internal-reference-face)))) @@ -2835,7 +2840,7 @@ for multiline constructs to be matched." (list (adoc-re-xref 'inline-special-with-caption t) ;; clickable, but not inside code/literal blocks (those set adoc-reserved) '(0 (unless (get-text-property (match-beginning 0) 'adoc-reserved) - '(face nil keymap adoc-link-keymap mouse-face highlight help-echo "mouse-1: jump to this anchor"))) + '(face nil keymap adoc-link-keymap mouse-face adoc-link-mouse-face help-echo "mouse-1: jump to this anchor"))) '(1 'adoc-meta-hide-face) ; << '(2 'adoc-meta-face) ; anchor-id '(3 'adoc-meta-hide-face) ; , @@ -2844,7 +2849,7 @@ for multiline constructs to be matched." ;; reference without caption (list (adoc-re-xref 'inline-special-no-caption t) '(0 (unless (get-text-property (match-beginning 0) 'adoc-reserved) - '(face nil keymap adoc-link-keymap mouse-face highlight help-echo "mouse-1: jump to this anchor"))) + '(face nil keymap adoc-link-keymap mouse-face adoc-link-mouse-face help-echo "mouse-1: jump to this anchor"))) '(1 'adoc-meta-hide-face) ; << '(2 'adoc-reference-face) ; link text = anchor id '(3 'adoc-meta-hide-face)) ; >> diff --git a/test/adoc-mode-navigation-test.el b/test/adoc-mode-navigation-test.el index c5cc248..7adc2d8 100644 --- a/test/adoc-mode-navigation-test.el +++ b/test/adoc-mode-navigation-test.el @@ -347,9 +347,12 @@ "https://example.com[site]" "bare.example.com" "include::other.adoc[]")) (expect (adoc-test--prop-at doc needle 'keymap) :to-be 'adoc-link-keymap) - (expect (adoc-test--prop-at doc needle 'mouse-face) :to-be 'highlight) + (expect (adoc-test--prop-at doc needle 'mouse-face) :to-be 'adoc-link-mouse-face) (expect (adoc-test--prop-at doc needle 'help-echo) :to-be-truthy)))) + (it "underlines references under the mouse pointer" + (expect (face-attribute 'adoc-link-mouse-face :underline nil t) :to-be-truthy)) + (it "leaves plain prose unclickable" (expect (adoc-test--prop-at "just some ordinary prose\n" "ordinary" 'keymap) :to-be nil))