branch: externals/denote commit c2f3ca7cf49a44a50f73ba87fee17100914e32fd Author: Protesilaos Stavrou <i...@protesilaos.com> Commit: Protesilaos Stavrou <i...@protesilaos.com>
Make denote-fontify-links also work with query links The technical discussion for this is in issue 561: <https://github.com/protesilaos/denote/issues/561>. --- denote.el | 128 +++++++++++++++++++++++++++++++++----------------------------- 1 file changed, 68 insertions(+), 60 deletions(-) diff --git a/denote.el b/denote.el index 8658982f0e..9bf7ed4b67 100644 --- a/denote.el +++ b/denote.el @@ -5109,20 +5109,16 @@ file's title. This has the same meaning as in `denote-link'." ;;;;; Link buttons -(defun denote-link--find-file-at-button (button) - "Visit file referenced by BUTTON." - (let* ((id (denote-extract-id-from-string - (buffer-substring-no-properties - (button-start button) - (button-end button)))) - (file (denote-get-path-by-id id))) - (funcall denote-open-link-function file))) +(make-obsolete 'denote-link--find-file-at-button nil "4.0.0") (make-obsolete 'denote-link-buttonize-buffer 'denote-fontify-links-mode "Use the `denote-fontify-links-mode', as it works better than buttonization. Since 3.0.0") +;; NOTE 2025-03-24: This does not work for query links because of how +;; `markdown-follow-link-at-point' is implemented to always check for +;; links. (defun denote-link-markdown-follow (link) "Function to open Denote file present in LINK. To be assigned to `markdown-follow-link-functions'." @@ -5146,67 +5142,78 @@ To be assigned to `markdown-follow-link-functions'." map) "Keymap for mouse actions over fontified Denote links.") +(defun denote--link-open-at-point-subr () + "Open link at point." + (let* ((query (get-text-property (point) 'denote-link-query-part)) + (path (denote-get-path-by-id query))) + (if path + (funcall denote-open-link-function path) + (funcall denote-query-links-buffer-function query denote-query-links-display-buffer-action)))) + +(defun denote-link-open-at-point () + "Open Denote link at point." + (interactive) + (denote--link-open-at-point-subr)) + (defun denote-link-open-at-mouse (ev) "Open Denote link for mouse EV click." (interactive "e") (mouse-set-point ev) - (if-let* ((id (get-text-property (point) 'denote-link-id)) - (path (denote-get-path-by-id id))) - (funcall denote-open-link-function path) - (error "Cannot resolve the link at point"))) - -(defun denote-fontify-links (&optional limit) - "Fontify Denote links up until optional LIMIT. + (denote--link-open-at-point-subr)) +(defun denote--fontify-links-subr (query limit) + "Do the work of the font-lock match for QUERY up to LIMIT. Implementation based on the function `org-activate-links'." (catch :exit - (when-let* ((type (denote-filetype-heuristics (buffer-file-name)))) - (while (re-search-forward (denote--link-in-context-regexp type) limit t) - (save-match-data ; to return the matches to font-lock - (let* ((start (match-beginning 0)) - (end (match-end 0)) - (visible-start (match-beginning 2)) - (visible-end (match-end 2)) - (id (match-string-no-properties 1)) - (path (denote-get-path-by-id id)) - (file-link (concat "file:" path))) - ;; FIXME 2024-06-19: Rewrite this (unless...let...if...) - ;; because it is hard to reason about. But it works, so no - ;; pressure. - (unless (let ((face (get-text-property - (max (1- start) (point-min)) 'face))) - (if (consp face) - (memq 'font-lock-comment-face face) - (eq 'font-lock-comment-face face))) - (let* ((properties `(face denote-faces-link - mouse-face highlight - keymap ,denote-link-mouse-map - denote-link-id ,id - help-echo ,(or (denote-retrieve-title-or-filename path type) - (concat "denote:" id)) - htmlize-link (:uri ,file-link) - font-lock-multiline t)) - (non-sticky-props - '(rear-nonsticky (mouse-face highlight keymap invisible intangible help-echo htmlize-link))) - (face-property 'link) - (hidden (append '(invisible 'denote-link) properties))) - (remove-text-properties start end '(invisible nil)) - (add-text-properties start visible-start hidden) - (add-face-text-property start end face-property) - (add-text-properties visible-start visible-end properties) - (add-text-properties visible-end end hidden) - (dolist (pos (list end visible-start visible-end)) - (add-text-properties (1- pos) pos non-sticky-props))) - (throw :exit t)))))) ; signal success + (while (re-search-forward query limit t) + (save-match-data ; to return the matches to font-lock + (let* ((start (match-beginning 0)) + (end (match-end 0)) + (visible-start (or (match-beginning 2) start)) + (visible-end (or (match-end 2) end)) + (query (match-string-no-properties 1))) + (let* ((properties `(face denote-faces-link + mouse-face highlight + keymap ,denote-link-mouse-map + denote-link-query-part ,query + help-echo query + htmlize-link (:uri ,query) + font-lock-multiline t)) + (non-sticky-props + '(rear-nonsticky (mouse-face highlight keymap invisible intangible help-echo htmlize-link))) + (face-property 'link) + (hidden (append '(invisible 'denote-link) properties))) + (remove-text-properties start end '(invisible nil)) + (add-text-properties start visible-start hidden) + (add-face-text-property start end face-property) + (add-text-properties visible-start visible-end properties) + (add-text-properties visible-end end hidden) + (dolist (pos (list end visible-start visible-end)) + (add-text-properties (1- pos) pos non-sticky-props))) + (throw :exit t)))) ; signal success nil)) -(defun denote-get-identifier-at-point (&optional point) - "Return the Denote identifier at point or optional POINT." +(defun denote-fontify-links (limit) + "Provide font-lock matcher to fontify links up to LIMIT." + (when-let* ((type (denote-filetype-heuristics (buffer-file-name)))) + (denote--fontify-links-subr (denote--link-in-context-regexp type) limit))) + +(defun denote-fontify-query-links (limit) + "Provide font-lock matcher to fontify query links up to LIMIT." + (denote--fontify-links-subr "\\[\\[denote:\\(?1:[^[]*?\\)]]" limit)) + +(define-obsolete-function-alias + 'denote-get-identifier-at-point + 'denote-get-link-identifier-or-query-term-at-point + "4.0.0") + +(defun denote-get-link-identifier-or-query-term-at-point (&optional point) + "Return the Denote identifier or query term at point or optional POINT." (when-let* ((position (or point (point))) (face-at-point (get-text-property position 'face)) ((or (eq face-at-point 'denote-faces-link) (member 'denote-faces-link face-at-point)))) - (or (get-text-property position 'denote-link-id) + (or (get-text-property position 'denote-link-query-part) (when-let* ((link-data (get-text-property position 'htmlize-link)) (link (cadr link-data))) (string-match denote-id-regexp link) @@ -5216,8 +5223,9 @@ Implementation based on the function `org-activate-links'." "Return link to the Denote file path at point or optional POINT. To be used as a `thing-at' provider." (when-let* ((position (or point (point))) - (id (get-text-property position 'denote-link-id))) - (concat "file:" (denote-get-path-by-id id)))) + (id (get-text-property position 'denote-link-query-part)) + (path (denote-get-path-by-id id))) + (concat "file:" path))) (defvar thing-at-point-provider-alist) @@ -5241,12 +5249,12 @@ major mode is not `org-mode' (or derived therefrom). Consider using (if denote-fontify-links-mode (progn (add-to-invisibility-spec 'denote-link) - (font-lock-add-keywords nil '(denote-fontify-links)) + (font-lock-add-keywords nil '((denote-fontify-links) (denote-fontify-query-links))) (setq-local thing-at-point-provider-alist (append thing-at-point-provider-alist '((url . denote--get-link-file-path-at-point))))) (remove-from-invisibility-spec 'denote-link) - (font-lock-remove-keywords nil '(denote-fontify-links)) + (font-lock-remove-keywords nil '((denote-fontify-links) (denote-fontify-query-links))) (setq-local thing-at-point-provider-alist (delete '(url . denote--get-link-file-path-at-point)