From d87dd011aab176c931d19adb2f7181211e86aa65 Mon Sep 17 00:00:00 2001 From: Kisaragi Hiu Date: Tue, 15 Dec 2020 20:47:51 +0900 Subject: [PATCH] (fix): preserve existing description in a roam: link on replace (#1327) Co-authored-by: Jethro Kuan --- CHANGELOG.md | 7 +-- org-roam-link.el | 114 +++++++++++++++++++++++++++-------------------- 2 files changed, 69 insertions(+), 52 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b975e46..560897a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,7 +9,8 @@ ### Fixed - [#1281](https://github.com/org-roam/org-roam/pull/1281) fixed idle-timer not instantiated on `org-roam-mode` - [#1308](https://github.com/org-roam/org-roam/pull/1308) fixed file renames corrupting database -- [#1325](https://github.com/org-roam/org-roam/pull/1325) make titles and tags extracted unique per note +- [#1325](https://github.com/org-roam/org-roam/pull/1325) make titles and tags extracted unique per note +- [#1327](https://github.com/org-roam/org-roam/pull/1327) preserve existing link description during automatic replacement ## 1.2.3 (13-11-2020) @@ -26,7 +27,7 @@ Org-roam-dailies has also been revamped to include new features, see [this video - [#1264](https://github.com/org-roam/org-roam/pull/1264) add `org-roam-db-update-method` to control when the cache is rebuilt. ### Changed -- [#1264](https://github.com/org-roam/org-roam/pull/1264) renamed `org-roam-update-db-idle-seconds` to `org-roam-db-idle-idle-seconds` +- [#1264](https://github.com/org-roam/org-roam/pull/1264) renamed `org-roam-update-db-idle-seconds` to `org-roam-db-idle-idle-seconds` ### Fixed - [#1074](https://github.com/org-roam/org-roam/issues/1074) fix `org-roam--extract-links` to handle content boundaries. @@ -70,7 +71,7 @@ This change requires you to set `org-roam-directory` to the resolved path of a f - [#974](https://github.com/org-roam/org-roam/pull/974) Protect region targeted by `org-roam-insert` - [#994](https://github.com/org-roam/org-roam/pull/994) Simplify org-roam-store-link - [#1062](https://github.com/org-roam/org-roam/pull/1062) Variable `org-roam-completions-everywhere` allows for completions everywhere from word at point -- [#910](https://github.com/org-roam/org-roam/pull/910), [#1105](https://github.com/org-roam/org-roam/pull/1105) Support fuzzy links of the form [[roam:Title]], [[roam:*Headline]] and [[roam:Title*Headline]] +- [#910](https://github.com/org-roam/org-roam/pull/910), [#1105](https://github.com/org-roam/org-roam/pull/1105) Support fuzzy links of the form `[[roam:Title]]`, `[[roam:*Headline]]` and `[[roam:Title*Headline]]` ### Bugfixes diff --git a/org-roam-link.el b/org-roam-link.el index 45e19d7..7cd06dc 100644 --- a/org-roam-link.el +++ b/org-roam-link.el @@ -71,18 +71,21 @@ noabbrev Absolute path, no abbreviation of home directory." (org-link-set-parameters "roam" :follow #'org-roam-link-follow-link) -(defun org-roam-link-follow-link (path) - "Navigates to location specified by PATH." - (pcase-let ((`(,link-type ,loc ,desc ,mkr) (org-roam-link--get-location path))) +(defun org-roam-link-follow-link (_path) + "Navigates to location in Org-roam link. +This function is called by Org when following links of the type +`roam'. While the path is passed, assume that the cursor is on +the link." + (pcase-let ((`(,link-type ,loc ,desc ,mkr) (org-roam-link--get-location))) (when (and org-roam-link-auto-replace loc desc) (org-roam-link--replace-link link-type loc desc)) (pcase link-type - ("file" - (if loc - (org-roam--find-file loc) - (org-roam-find-file desc nil nil t))) - ("id" - (org-goto-marker-or-bmk mkr))))) + ("file" + (if loc + (org-roam--find-file loc) + (org-roam-find-file desc nil nil t))) + ("id" + (org-goto-marker-or-bmk mkr))))) ;;; Retrieval Functions (defun org-roam-link--get-titles () @@ -184,43 +187,59 @@ star-idx is the index of the asterisk, if any." (t 'title+headline)))) (list type title headline star-index)))) -(defun org-roam-link--get-location (link) - "Return the location of Org-roam fuzzy LINK. +(defun org-roam-link--get-location () + "Return the location of the Org-roam fuzzy link at point. The location is returned as a list containing (link-type loc desc marker). nil is returned if there is no matching location. link-type is either \"file\" or \"id\". loc is the target location: e.g. a file path, or an id. -marker is a marker to the headline, if applicable." - (let (mkr link-type desc loc) - (pcase-let ((`(,type ,title ,headline _) (org-roam-link--split-path link))) - (pcase type - ('title+headline - (let ((file (org-roam-link--get-file-from-title title))) - (if (not file) - (org-roam-message "Cannot find matching file") - (setq mkr (org-roam-link--get-id-from-headline headline file)) - (pcase mkr - (`(,marker . ,target-id) - (setq mkr marker - loc target-id - link-type "id" - desc headline)) - (_ (org-roam-message "cannot find matching id")))))) - ('title - (setq loc (org-roam-link--get-file-from-title title) - desc title - link-type "file")) - ('headline - (setq mkr (org-roam-link--get-id-from-headline headline)) - (pcase mkr - (`(,marker . ,target-id) - (setq mkr marker - loc target-id - desc headline - link-type "id")) - (_ (org-roam-message "Cannot find matching headline"))))) - (list link-type loc desc mkr)))) +marker is a marker to the headline, if applicable. + +desc is either the the description of the link under point, or +the target of LINK (title or heading content)." + (let ((context (org-element-context)) + mkr link-type desc loc) + (pcase (org-element-lineage context '(link) t) + (`nil (error "Not at an Org link")) + (link + (if (not (string-equal "roam" (org-element-property :type link))) + (error "Not at Org-roam link") + (setq desc (and (org-element-property :contents-begin link) + (org-element-property :contents-end link) + (buffer-substring-no-properties + (org-element-property :contents-begin link) + (org-element-property :contents-end link)))) + (pcase-let ((`(,type ,title ,headline _) (org-roam-link--split-path + (org-element-property :path link)))) + (pcase type + ('title+headline + (let ((file (org-roam-link--get-file-from-title title))) + (if (not file) + (org-roam-message "Cannot find matching file") + (setq mkr (org-roam-link--get-id-from-headline headline file)) + (pcase mkr + (`(,marker . ,target-id) + (progn + (setq mkr marker + loc target-id + desc (or desc headline) + link-type "id"))) + (_ (org-roam-message "Cannot find matching id")))))) + ('title + (setq loc (org-roam-link--get-file-from-title title) + link-type "file" + desc (or desc title))) + ('headline + (setq mkr (org-roam-link--get-id-from-headline headline)) + (pcase mkr + (`(,marker . ,target-id) + (setq mkr marker + loc target-id + link-type "id" + desc (or desc headline))) + (_ (org-roam-message "Cannot find matching headline"))))))))) + (list link-type loc desc mkr))) ;;; Conversion Functions (defun org-roam-link--replace-link (link-type loc &optional desc) @@ -241,14 +260,11 @@ DESC is the link description." (save-excursion (goto-char (point-min)) (while (re-search-forward org-link-bracket-re nil t) - (let ((context (org-element-context))) - (pcase (org-element-lineage context '(link) t) - (`nil nil) - (link - (when (string-equal "roam" (org-element-property :type link)) - (pcase-let ((`(,link-type ,loc ,desc _) (org-roam-link--get-location (org-element-property :path link)))) - (when (and link-type loc) - (org-roam-link--replace-link link-type loc desc)))))))))) + (condition-case nil + (pcase-let ((`(,link-type ,loc ,desc _) (org-roam-link--get-location))) + (when (and link-type loc) + (org-roam-link--replace-link link-type loc desc))) + (error nil))))) (defun org-roam-link--replace-link-on-save () "Hook to replace all roam links on save."