branch: externals/denote commit ecc7922a7741f9fdf7e4e3b08cd1aed032f2309f Author: Protesilaos Stavrou <i...@protesilaos.com> Commit: Protesilaos Stavrou <i...@protesilaos.com>
BREAKING remove support for hardcoded backlinks We will find a more robust solution that will be with us for the long-term. The gist is that we need links that work even when the user renames the underlying file. Only the identifier is a constant: it is unreasonable to expect that, say, the keywords in the file name of a note will never change. As such, writing the full path is not a viable option. Relevant discussions on the GitHub mirror: * <https://github.com/protesilaos/denote/issues/13> * <https://github.com/protesilaos/denote/issues/13> This, by the way, is the first time a project of mine is busy on GitHub. You are welcome to use the mirror or the official mailing list. Whatever works for you (that's why I maintain all those sources, after all). --- README.org | 4 +- denote-link.el | 127 +++++++-------------------------------------------------- 2 files changed, 16 insertions(+), 115 deletions(-) diff --git a/README.org b/README.org index bca06ae3d7..5484472d84 100644 --- a/README.org +++ b/README.org @@ -542,8 +542,8 @@ participate in the development of Denote. The linking facility is subject to review and there will likely be breaking changes. This is the only area that needs to be fixed before -we release the first stable version of the package. WHAT FOLLOWS IS NOT -DEFINITIVE. +we release the first stable version of the package. *What follows is +not up-to-date as of 2022-06-14 17:01 +0300.* #+findex: denote-link Denote has a basic linking facility to quickly establish connections diff --git a/denote-link.el b/denote-link.el index 8e765483f5..17f78798c4 100644 --- a/denote-link.el +++ b/denote-link.el @@ -36,60 +36,29 @@ "Link facility for Denote." :group 'denote) -;;; User options - -(defcustom denote-link-insert-functions nil - "Functions that run after `denote-link'. -Each function accepts a TARGET file and a BACKLINK argument. -Both are supplied by `denote-link'. - -Advanced users are encouraged to study `denote-link-backlink' for -how those arguments are used. Add that function to this hook if -you want Denote to automatically insert backlinks in the -applicable files. Though you might prefer to use the command -`denote-link-backlinks', which does not touch the underlying -files." - :type 'hook - :group 'denote-link) - ;;;; Link to note (defconst denote-link--link-format-org "[[file:%s][%s (%s)]]" "Format of Org link to note.") -(defconst denote-link--backlink-format-org "[[file:%s][backlink: %s (%s)]]" - "Format of Org backlink to note.") - (defconst denote-link--link-format-markdown "[%2$s (%3$s)](file:%1$s)" "Format of Markdown link to note.") -(defconst denote-link--backlink-format-markdown "[backlink: %2$s (%3$s)](file:%1$s)" - "Format of Markdown backlink to note.") - (defconst denote-link--link-format-text "<LINK: %s> [NAME %s (%s)]" "Format of plain text link to note.") -(defconst denote-link--backlink-format-text "BACKLINK: <%s> [NAME %s (%s)]" - "Format of plain text backlink to note.") - -(defconst denote-link--backlink-regexp "\\[\\[file:\\(.*?\\)\\]\\[backlink: \\(.*?\\) (\\(.*?\\))\\]\\]" - "Regexp of `denote-link--backlink-format-org'.") - -(defun denote-link--file-type-format (file &optional backlink) - "Return link pattern based on FILE format. -With optional BACKLINK, return a backlink pattern" +(defun denote-link--file-type-format (file) + "Return link pattern based on FILE format." (pcase (file-name-extension file) - ("markdown" (if backlink denote-link--backlink-format-markdown denote-link--link-format-markdown)) - ("text" (if backlink denote-link--backlink-format-text denote-link--link-format-text)) - (_ (if backlink denote-link--backlink-format-org denote-link--link-format-org)))) ; Includes backup files. Maybe we can remove them? + ("markdown" denote-link--link-format-markdown) + ("text" denote-link--link-format-text) + (_ denote-link--link-format-org))) ; Includes backup files. Maybe we can remove them? (defun denote-link--format-link (file pattern) "Prepare link to FILE using PATTERN." - (let* ((dir (denote-directory)) - (file-id (denote-retrieve--value file denote-retrieve--identifier-regexp)) - (file-path (file-name-completion file-id dir)) + (let* ((file-id (denote-retrieve--value file denote-retrieve--identifier-regexp)) (file-title (denote-retrieve--value file denote-retrieve--title-regexp))) - (format pattern file-path file-title file-id))) + (format pattern file-id file-title))) ;;;###autoload (defun denote-link (target) @@ -97,10 +66,13 @@ With optional BACKLINK, return a backlink pattern" Run `denote-link-insert-functions' afterwards." (interactive (list (denote-retrieve--read-file-prompt))) (let* ((origin (buffer-file-name)) - (link (denote-link--format-link target (denote-link--file-type-format origin))) - (backlink (denote-link--format-link origin (denote-link--file-type-format target :backlink)))) - (insert link) - (run-hook-with-args 'denote-link-insert-functions target backlink))) + (link (denote-link--format-link target (denote-link--file-type-format origin)))) + (insert link))) + +;; TODO 2022-06-14: Write `denote-link-find-file' command. It should be +;; able to enhance this core idea: +;; +;; (file-name-completion file-id dir) ;;;; Backlinks' buffer (WORK-IN-PROGRESS) @@ -154,76 +126,5 @@ PROOF-OF-CONCEPT." (with-current-buffer buf (add-hook 'compilation-finish-functions #'denote-link--prettify-compilation nil t)))) -;;;; Automatic backlink insertion (SUBJECT TO REMOVAL) - -(defconst denote-link-backlink-heading "Denote backlinks" - "String of the backlink's heading. -This heading is appended to a file when another links to it.") - -(defvar denote-link-backlink-warning - "Do not edit past this line; this is for denote.el and related." - "String that warns about not editing the backlinks' section.") - -(defvar denote-link--markdown-comment "<!-- %s -->" - "Specifier for Markdown comments passed to `format'.") - -(defvar denote-link--org-comment "# %s" - "Specifier for Markdown comments passed to `format'.") - -(defun denote-link--format-comment (comment filetype) - "Use appropriate COMMENT for FILETYPE." - (pcase filetype - ("md" (format denote-link--markdown-comment comment)) - (_ (format denote-link--org-comment comment)))) - -(defvar denote-link--markdown-heading "%s\n# %s\n\n" - "Specifier for Markdown heading passed to `format'.") - -(defvar denote-link--org-heading "%s\n* %s\n\n" - "Specifier for Org heading passed to `format'.") - -(defvar denote-link--text-heading "%s\n%s\n%s\n\n" - "Specifier for plain text heading passed to `format'.") - -(defun denote-link--format-heading (heading filetype comment) - "Use appropriate HEADING for FILETYPE, while prepending COMMENT." - (pcase filetype - ("md" (format denote-link--markdown-heading comment heading)) - ("org" (format denote-link--org-heading comment heading)) - (_ (format denote-link--text-heading comment heading (make-string 16 ?=))))) - -(defun denote-link--format-backlinks-heading (heading) - "Format HEADING for backlinks." - (let* ((ext (file-name-extension (buffer-file-name))) - (comment (denote-link--format-comment denote-link-backlink-warning ext))) - (denote-link--format-heading heading ext comment))) - -(defun denote-link-backlink (target backlink) - "Insert BACKLINK to TARGET file." - (let ((default-directory (denote-directory)) - (heading denote-link-backlink-heading) - heading-point) - (with-current-buffer (find-file-noselect target) - (goto-char (point-max)) - (unless (save-excursion (setq heading-point (re-search-backward heading nil t))) - (unless (denote--line-regexp-p 'empty 0) - (newline)) - (insert (denote-link--format-backlinks-heading heading))) - (insert (format "- %s\n" backlink)) - ;; delete duplicate links - (when heading-point - (delete-duplicate-lines heading-point (point-max) nil nil t))))) - -(defun denote-link-clear-stale-backlinks () - "Delete backlinks that no longer point to files." - (interactive) - (let ((default-directory (denote-directory))) - (save-excursion - (goto-char (point-min)) - (when (re-search-forward denote-link-backlink-heading nil t) - (while (re-search-forward denote-link--backlink-regexp nil t) - (unless (file-exists-p (match-string-no-properties 1)) - (delete-region (point-at-bol) (point-at-bol 2)))))))) - (provide 'denote-link) ;;; denote-link.el ends here