From b1d82f875f1954722b7b85f03c95ffac063a42bc Mon Sep 17 00:00:00 2001 From: Daniel Borchmann Date: Sat, 26 Sep 2020 14:12:21 +0200 Subject: [PATCH 1/8] Do not let org-roam change matching data when determining the face It is not clear what function really changes the matching data, but it's called by `org-roam--id-link-face', and this is where we save the matching data now. TODO: check whether this has been reported or even fixed upstream. --- init.el | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/init.el b/init.el index 3345ce6..140a2ad 100644 --- a/init.el +++ b/init.el @@ -1333,7 +1333,19 @@ (apply orig-fun args))) (advice-add 'org-roam--update-file-name-on-title-change - :around #'db/org-roam--no-titlechange-if-title-is-nil))) + :around #'db/org-roam--no-titlechange-if-title-is-nil) + + ;; `org-roam--id-link-face' apparently changes the matching data, + ;; resulting in `org-finalize-agenda' to fail while applying text + ;; properties to ID links; let's warp `save-match-data' around calls + ;; to it. + + (defun db/save-match-data (orig-fun &rest args) + (save-match-data + (apply orig-fun args))) + + (advice-add 'org-roam--id-link-face + :around #'db/save-match-data))) (use-package org-ref :config (progn From a6f77f8d716792127a1355d15f9153fcabe31d36 Mon Sep 17 00:00:00 2001 From: Daniel Borchmann Date: Sat, 26 Sep 2020 14:14:45 +0200 Subject: [PATCH 2/8] Add simple helper function to find items linking to the current one Only ID links are supported by now. --- init.el | 3 ++- site-lisp/db-org.el | 14 ++++++++++++++ 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/init.el b/init.el index 140a2ad..642ab9f 100644 --- a/init.el +++ b/init.el @@ -715,7 +715,8 @@ db/find-csv-in-org db/org-mark-current-default-task db/export-diary - db/org-copy-template-for-periodic-task)) + db/org-copy-template-for-periodic-task + db/org-find-items-linking-to-id)) (use-package org :pin "gnu" diff --git a/site-lisp/db-org.el b/site-lisp/db-org.el index 2de131f..32949e9 100644 --- a/site-lisp/db-org.el +++ b/site-lisp/db-org.el @@ -592,6 +592,20 @@ This is done only if the value of this variable is not null." (org-icalendar-combine-agenda-files) (message "Exporting diary ... done."))))))) + +;;; Find items by link to current headline + +(defun db/org-find-items-linking-to-id (&optional id) + "List all Org Mode items that link to ID. +Uses `org-search-view' to conduct the actual search. ID must be +a UUID as generated by, e.g., `org-id-get-create'. If ID is not +given, use the ID of the current item, if in Org Mode." + (interactive (list (when (derived-mode-p 'org-mode) + (org-id-get)))) + (if id + (org-search-view nil (format "[id:%s]" id)) + (user-error "No ID given and not in Org Mode."))) + ;;; End From cde56c819e75416af43f6f4dc1aab362b19b8b12 Mon Sep 17 00:00:00 2001 From: Daniel Borchmann Date: Sat, 26 Sep 2020 15:00:34 +0200 Subject: [PATCH 3/8] Extend backward link searching function Now support CUSTOM_ID as well, and check arguments for plausibility. --- site-lisp/db-org.el | 30 ++++++++++++++++++++++-------- 1 file changed, 22 insertions(+), 8 deletions(-) diff --git a/site-lisp/db-org.el b/site-lisp/db-org.el index 32949e9..0adc50b 100644 --- a/site-lisp/db-org.el +++ b/site-lisp/db-org.el @@ -595,16 +595,30 @@ This is done only if the value of this variable is not null." ;;; Find items by link to current headline -(defun db/org-find-items-linking-to-id (&optional id) +;; TODO: expand: let the user choose the item that is to be linked to +;; interactively +(defun db/org-find-items-linking-by-id (&optional id custom-id) "List all Org Mode items that link to ID. Uses `org-search-view' to conduct the actual search. ID must be -a UUID as generated by, e.g., `org-id-get-create'. If ID is not -given, use the ID of the current item, if in Org Mode." - (interactive (list (when (derived-mode-p 'org-mode) - (org-id-get)))) - (if id - (org-search-view nil (format "[id:%s]" id)) - (user-error "No ID given and not in Org Mode."))) +a UUID as generated by, e.g., `org-id-get-create', and CUSTOM-ID +must consist of ASCII letters, numbers, and hyphens only. If ID +and CUSTOM-ID are not given, use the values of the current item +if in Org Mode." + (interactive (when (derived-mode-p 'org-mode) + (list (org-id-get) (org-entry-get nil "CUSTOM_ID")))) + + (unless (string-match-p "^[a-f0-9]\\{8\\}-[a-f0-9]\\{4\\}-[a-f0-9]\\{4\\}-[a-f0-9]\\{4\\}-[a-f0-9]\\{12\\}$" id) + (user-error "Given ID is not a valid UUID: %s" id)) + (unless (string-match-p "[-a-zA-Z0-9]" custom-id) + ;; sorry, only ASCII right now … + (user-error "CUSTOM_ID must consist of alphanumeric charaters only")) + + (let ((query (cond + ((and id custom-id) (format "{\\[\\[id:%s\\]\\|\\[\\[#%s\\]}" id custom-id)) + (id (format "[[id:%s]" id)) + (custom-id (format "[[#%s]" custom-id)) + (t (user-error "No ID given and not in Org Mode."))))) + (org-search-view nil query))) ;;; End From 994be97397a8de4c7217a8f089514d91053a2f8a Mon Sep 17 00:00:00 2001 From: Daniel Borchmann Date: Sat, 26 Sep 2020 15:12:28 +0200 Subject: [PATCH 4/8] Fix consistency check for link finder function --- site-lisp/db-org.el | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/site-lisp/db-org.el b/site-lisp/db-org.el index 0adc50b..11201d3 100644 --- a/site-lisp/db-org.el +++ b/site-lisp/db-org.el @@ -607,9 +607,13 @@ if in Org Mode." (interactive (when (derived-mode-p 'org-mode) (list (org-id-get) (org-entry-get nil "CUSTOM_ID")))) - (unless (string-match-p "^[a-f0-9]\\{8\\}-[a-f0-9]\\{4\\}-[a-f0-9]\\{4\\}-[a-f0-9]\\{4\\}-[a-f0-9]\\{12\\}$" id) + (unless (or (not id) + (and (stringp id) + (string-match-p "^[a-f0-9]\\{8\\}-[a-f0-9]\\{4\\}-[a-f0-9]\\{4\\}-[a-f0-9]\\{4\\}-[a-f0-9]\\{12\\}$" id))) (user-error "Given ID is not a valid UUID: %s" id)) - (unless (string-match-p "[-a-zA-Z0-9]" custom-id) + (unless (or (not custom-id) + (and (stringp custom-id) + (string-match-p "[-a-zA-Z0-9]" custom-id))) ;; sorry, only ASCII right now … (user-error "CUSTOM_ID must consist of alphanumeric charaters only")) From c219d77ab91e7107fcacc6a8eac33bc9910830a3 Mon Sep 17 00:00:00 2001 From: Daniel Borchmann Date: Sat, 26 Sep 2020 15:12:49 +0200 Subject: [PATCH 5/8] Query for headline in link finder function when outside of Org Mode --- site-lisp/db-org.el | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/site-lisp/db-org.el b/site-lisp/db-org.el index 11201d3..11f87c6 100644 --- a/site-lisp/db-org.el +++ b/site-lisp/db-org.el @@ -595,17 +595,21 @@ This is done only if the value of this variable is not null." ;;; Find items by link to current headline -;; TODO: expand: let the user choose the item that is to be linked to -;; interactively (defun db/org-find-items-linking-by-id (&optional id custom-id) "List all Org Mode items that link to ID. Uses `org-search-view' to conduct the actual search. ID must be a UUID as generated by, e.g., `org-id-get-create', and CUSTOM-ID -must consist of ASCII letters, numbers, and hyphens only. If ID -and CUSTOM-ID are not given, use the values of the current item -if in Org Mode." - (interactive (when (derived-mode-p 'org-mode) - (list (org-id-get) (org-entry-get nil "CUSTOM_ID")))) +must consist of ASCII letters, numbers, and hyphens only. When +called interactively in Org Mode, use the values ID and CUSTOM_ID +of the current item. When called interactively outside of Org +Mode, prompt the user for the user for a headline." + (interactive (if (derived-mode-p 'org-mode) + (list (org-id-get) (org-entry-get nil "CUSTOM_ID")) + (let ((pom (nth 3 (org-refile-get-location)))) + (if (not pom) + (user-error "Invalid location") + (org-with-point-at pom + (list (org-id-get) (org-entry-get nil "CUSTOM_ID"))))))) (unless (or (not id) (and (stringp id) From b0a36749e620d88c9026639c41e5b0cee70ba02f Mon Sep 17 00:00:00 2001 From: Daniel Borchmann Date: Sat, 26 Sep 2020 15:20:11 +0200 Subject: [PATCH 6/8] Refactor Org Mode link finder function The main entry point is now `db/org-find-links-to-current-item', which decides how to obtain the ID and CUSTOM_ID of the item to look for. The main work is done by `db/org-find-items-linking-to-id', which does some checks, build the query, and then calls `org-search-view' (which, indeed, does the actual work). Users should call `db/org-find-links-to-current-item' only. --- init.el | 2 +- site-lisp/db-org.el | 33 ++++++++++++++++++++------------- 2 files changed, 21 insertions(+), 14 deletions(-) diff --git a/init.el b/init.el index 642ab9f..cd86938 100644 --- a/init.el +++ b/init.el @@ -716,7 +716,7 @@ db/org-mark-current-default-task db/export-diary db/org-copy-template-for-periodic-task - db/org-find-items-linking-to-id)) + db/org-find-links-to-current-item)) (use-package org :pin "gnu" diff --git a/site-lisp/db-org.el b/site-lisp/db-org.el index 11f87c6..73df062 100644 --- a/site-lisp/db-org.el +++ b/site-lisp/db-org.el @@ -595,22 +595,13 @@ This is done only if the value of this variable is not null." ;;; Find items by link to current headline -(defun db/org-find-items-linking-by-id (&optional id custom-id) +(defun db/org-find-items-linking-by-id (id custom-id) "List all Org Mode items that link to ID. Uses `org-search-view' to conduct the actual search. ID must be a UUID as generated by, e.g., `org-id-get-create', and CUSTOM-ID -must consist of ASCII letters, numbers, and hyphens only. When -called interactively in Org Mode, use the values ID and CUSTOM_ID -of the current item. When called interactively outside of Org -Mode, prompt the user for the user for a headline." - (interactive (if (derived-mode-p 'org-mode) - (list (org-id-get) (org-entry-get nil "CUSTOM_ID")) - (let ((pom (nth 3 (org-refile-get-location)))) - (if (not pom) - (user-error "Invalid location") - (org-with-point-at pom - (list (org-id-get) (org-entry-get nil "CUSTOM_ID"))))))) - +must consist of ASCII letters, numbers, and hyphens only. Each +of ID and CUSTOM-ID may be nil, but at least one of them must be +not." (unless (or (not id) (and (stringp id) (string-match-p "^[a-f0-9]\\{8\\}-[a-f0-9]\\{4\\}-[a-f0-9]\\{4\\}-[a-f0-9]\\{4\\}-[a-f0-9]\\{12\\}$" id))) @@ -628,6 +619,22 @@ Mode, prompt the user for the user for a headline." (t (user-error "No ID given and not in Org Mode."))))) (org-search-view nil query))) +(defun db/org-find-links-to-current-item (arg) + "Find links to current item. +Only links using the ID or CUSTOM_ID property are considered. + +If ARG is given, or if not in an Org Mode buffer, interactively +prompt for an item." + (interactive "P") + (apply #'db/org-find-items-linking-by-id + (if (and (derived-mode-p 'org-mode) (not arg)) + (list (org-id-get) (org-entry-get nil "CUSTOM_ID")) + (let ((pom (nth 3 (org-refile-get-location)))) + (if (not pom) + (user-error "Invalid location") + (org-with-point-at pom + (list (org-id-get) (org-entry-get nil "CUSTOM_ID")))))))) + ;;; End From dd30d5d7be66846261d9d8f2888894e1548aae4e Mon Sep 17 00:00:00 2001 From: Daniel Borchmann Date: Sat, 26 Sep 2020 15:24:07 +0200 Subject: [PATCH 7/8] Set default buffer when querying for Org Mode headlines Apparently, if the current buffer is not associated with a file, things break. --- site-lisp/db-org.el | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/site-lisp/db-org.el b/site-lisp/db-org.el index 73df062..7a57158 100644 --- a/site-lisp/db-org.el +++ b/site-lisp/db-org.el @@ -629,7 +629,7 @@ prompt for an item." (apply #'db/org-find-items-linking-by-id (if (and (derived-mode-p 'org-mode) (not arg)) (list (org-id-get) (org-entry-get nil "CUSTOM_ID")) - (let ((pom (nth 3 (org-refile-get-location)))) + (let ((pom (nth 3 (org-refile-get-location nil (get-file-buffer db/org-default-org-file))))) (if (not pom) (user-error "Invalid location") (org-with-point-at pom From 48d9979fbdfa3de372151e26e0cd952125c92418 Mon Sep 17 00:00:00 2001 From: Daniel Borchmann Date: Sat, 26 Sep 2020 15:24:29 +0200 Subject: [PATCH 8/8] Add default key binding for backlink searching in Org Mode buffers --- init.el | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/init.el b/init.el index cd86938..d026bc0 100644 --- a/init.el +++ b/init.el @@ -185,7 +185,7 @@ (bind-key "" #'bm-toggle) (bind-key "" #'bm-next) (bind-key "" #'bm-previous) - (bind-key "" #'helm-org-agenda-files-headings) + (bind-key "" #'db/org-find-links-to-current-item) (bind-key "C-," #'mc/skip-to-previous-like-this) (bind-key "C-." #'mc/skip-to-next-like-this) (bind-key "C-;" #'iedit-mode)