mirror of
https://github.com/org-roam/org-roam
synced 2025-08-01 12:17:21 -05:00
(feat): clean up link expansions (#1157)
Adds `org-roam-link-file-path-type`, used for link path computation wherever sensible. This includes in the org-roam backlinks buffer, and in link replacement. Also moves link expansion/fixing from cache build to Org-roam buffer render time. This reduces cache build time, but makes buffer rendering slightly slower.
This commit is contained in:
@ -34,6 +34,7 @@
|
|||||||
(require 'cl-lib)
|
(require 'cl-lib)
|
||||||
(require 'dash)
|
(require 'dash)
|
||||||
(require 's)
|
(require 's)
|
||||||
|
(require 'f)
|
||||||
|
|
||||||
(defvar org-roam-directory)
|
(defvar org-roam-directory)
|
||||||
(defvar org-link-frame-setup)
|
(defvar org-link-frame-setup)
|
||||||
@ -42,6 +43,7 @@
|
|||||||
(defvar org-roam-last-window)
|
(defvar org-roam-last-window)
|
||||||
(defvar org-ref-cite-types) ;; in org-ref-core.el
|
(defvar org-ref-cite-types) ;; in org-ref-core.el
|
||||||
(defvar org-roam-mode)
|
(defvar org-roam-mode)
|
||||||
|
(defvar org-roam--org-link-bracket-typed-re)
|
||||||
|
|
||||||
(declare-function org-roam-db--ensure-built "org-roam-db")
|
(declare-function org-roam-db--ensure-built "org-roam-db")
|
||||||
(declare-function org-roam--extract-ref "org-roam")
|
(declare-function org-roam--extract-ref "org-roam")
|
||||||
@ -51,6 +53,9 @@
|
|||||||
(declare-function org-roam-backlinks-mode "org-roam")
|
(declare-function org-roam-backlinks-mode "org-roam")
|
||||||
(declare-function org-roam-mode "org-roam")
|
(declare-function org-roam-mode "org-roam")
|
||||||
(declare-function org-roam--find-file "org-roam")
|
(declare-function org-roam--find-file "org-roam")
|
||||||
|
(declare-function org-roam--format-link "org-roam")
|
||||||
|
(declare-function org-roam-link-make-string "org-roam-compat")
|
||||||
|
(declare-function org-roam-link-get-path "org-roam-link")
|
||||||
|
|
||||||
(defcustom org-roam-buffer-position 'right
|
(defcustom org-roam-buffer-position 'right
|
||||||
"Position of `org-roam' buffer.
|
"Position of `org-roam' buffer.
|
||||||
@ -101,6 +106,7 @@ For example: (setq org-roam-buffer-window-parameters '((no-other-window . t)))"
|
|||||||
|
|
||||||
(defun org-roam-buffer--find-file (file)
|
(defun org-roam-buffer--find-file (file)
|
||||||
"Open FILE in the window `org-roam' was called from."
|
"Open FILE in the window `org-roam' was called from."
|
||||||
|
(setq file (expand-file-name file))
|
||||||
(if (and org-roam-last-window (window-valid-p org-roam-last-window))
|
(if (and org-roam-last-window (window-valid-p org-roam-last-window))
|
||||||
(progn (with-selected-window org-roam-last-window
|
(progn (with-selected-window org-roam-last-window
|
||||||
(org-roam--find-file file))
|
(org-roam--find-file file))
|
||||||
@ -124,6 +130,22 @@ For example: (setq org-roam-buffer-window-parameters '((no-other-window . t)))"
|
|||||||
,wrong-type))))))
|
,wrong-type))))))
|
||||||
(concat string (when (> l 1) "s"))))
|
(concat string (when (> l 1) "s"))))
|
||||||
|
|
||||||
|
(defun org-roam-buffer-expand-links (content orig-path)
|
||||||
|
"Crawl CONTENT for relative links and corrects them to be correctly displayed.
|
||||||
|
ORIG-PATH is the path where the CONTENT originated."
|
||||||
|
(with-temp-buffer
|
||||||
|
(insert content)
|
||||||
|
(goto-char (point-min))
|
||||||
|
(let (link link-type)
|
||||||
|
(while (re-search-forward org-roam--org-link-bracket-typed-re (point-max) t)
|
||||||
|
(setq link-type (match-string 1)
|
||||||
|
link (match-string 2))
|
||||||
|
(when (and (string-equal link-type "file")
|
||||||
|
(f-relative-p link))
|
||||||
|
(replace-match (org-roam-link-get-path (expand-file-name link (file-name-directory orig-path)))
|
||||||
|
nil t nil 2))))
|
||||||
|
(buffer-string)))
|
||||||
|
|
||||||
(defun org-roam-buffer--insert-ref-links ()
|
(defun org-roam-buffer--insert-ref-links ()
|
||||||
"Insert ref backlinks for the current buffer."
|
"Insert ref backlinks for the current buffer."
|
||||||
(when-let ((path (cdr (with-temp-buffer
|
(when-let ((path (cdr (with-temp-buffer
|
||||||
@ -138,12 +160,14 @@ For example: (setq org-roam-buffer-window-parameters '((no-other-window . t)))"
|
|||||||
(dolist (group grouped-backlinks)
|
(dolist (group grouped-backlinks)
|
||||||
(let ((file-from (car group))
|
(let ((file-from (car group))
|
||||||
(bls (cdr group)))
|
(bls (cdr group)))
|
||||||
(insert (format "** [[file:%s][%s]]\n"
|
(insert (org-roam-link-make-string)
|
||||||
file-from
|
(format "** %s\n"
|
||||||
(org-roam--get-title-or-slug file-from)))
|
(org-roam--format-link file-from
|
||||||
|
(org-roam--get-title-or-slug file-from)
|
||||||
|
"file")))
|
||||||
(dolist (backlink bls)
|
(dolist (backlink bls)
|
||||||
(pcase-let ((`(,file-from _ ,props) backlink))
|
(pcase-let ((`(,file-from _ ,props) backlink))
|
||||||
(insert (propertize (plist-get props :content)
|
(insert (propertize (org-roam-buffer-expand-links (plist-get props :content) file-from)
|
||||||
'help-echo "mouse-1: visit backlinked note"
|
'help-echo "mouse-1: visit backlinked note"
|
||||||
'file-from file-from
|
'file-from file-from
|
||||||
'file-from-point (plist-get props :point)))
|
'file-from-point (plist-get props :point)))
|
||||||
@ -165,9 +189,10 @@ For example: (setq org-roam-buffer-window-parameters '((no-other-window . t)))"
|
|||||||
(let ((file-from (car group))
|
(let ((file-from (car group))
|
||||||
(bls (mapcar (lambda (row)
|
(bls (mapcar (lambda (row)
|
||||||
(nth 2 row)) (cdr group))))
|
(nth 2 row)) (cdr group))))
|
||||||
(insert (format "** [[file:%s][%s]]\n"
|
(insert (format "** %s\n"
|
||||||
file-from
|
(org-roam--format-link file-from
|
||||||
(org-roam--get-title-or-slug file-from)))
|
(org-roam--get-title-or-slug file-from)
|
||||||
|
"file")))
|
||||||
;; Sort backlinks according to time of occurrence in buffer
|
;; Sort backlinks according to time of occurrence in buffer
|
||||||
(setq bls (seq-sort-by (lambda (bl)
|
(setq bls (seq-sort-by (lambda (bl)
|
||||||
(plist-get bl :point))
|
(plist-get bl :point))
|
||||||
@ -176,12 +201,14 @@ For example: (setq org-roam-buffer-window-parameters '((no-other-window . t)))"
|
|||||||
(dolist (props bls)
|
(dolist (props bls)
|
||||||
(insert "*** "
|
(insert "*** "
|
||||||
(if-let ((outline (plist-get props :outline)))
|
(if-let ((outline (plist-get props :outline)))
|
||||||
(string-join outline " > ")
|
(-> outline
|
||||||
|
(string-join " > ")
|
||||||
|
(org-roam-buffer-expand-links file-from))
|
||||||
"Top")
|
"Top")
|
||||||
"\n"
|
"\n"
|
||||||
(propertize
|
(propertize
|
||||||
(s-trim (s-replace "\n" " "
|
(s-trim (s-replace "\n" " "
|
||||||
(plist-get props :content)))
|
(org-roam-buffer-expand-links (plist-get props :content) file-from)))
|
||||||
'help-echo "mouse-1: visit backlinked note"
|
'help-echo "mouse-1: visit backlinked note"
|
||||||
'file-from file-from
|
'file-from file-from
|
||||||
'file-from-point (plist-get props :point))
|
'file-from-point (plist-get props :point))
|
||||||
|
@ -38,6 +38,7 @@
|
|||||||
(require 'org-roam-compat)
|
(require 'org-roam-compat)
|
||||||
|
|
||||||
(defvar org-roam-completion-ignore-case)
|
(defvar org-roam-completion-ignore-case)
|
||||||
|
(defvar org-roam-directory)
|
||||||
(declare-function org-roam--find-file "org-roam")
|
(declare-function org-roam--find-file "org-roam")
|
||||||
(declare-function org-roam-find-file "org-roam")
|
(declare-function org-roam-find-file "org-roam")
|
||||||
|
|
||||||
@ -47,6 +48,21 @@
|
|||||||
:group 'org-roam
|
:group 'org-roam
|
||||||
:type 'boolean)
|
:type 'boolean)
|
||||||
|
|
||||||
|
(defcustom org-roam-link-file-path-type 'relative
|
||||||
|
"How the path name in file links should be stored.
|
||||||
|
Valid values are:
|
||||||
|
|
||||||
|
relative Relative to the current directory, i.e. the directory of the file
|
||||||
|
into which the link is being inserted.
|
||||||
|
absolute Absolute path, if possible with ~ for home directory.
|
||||||
|
noabbrev Absolute path, no abbreviation of home directory."
|
||||||
|
:group 'org-roam
|
||||||
|
:type '(choice
|
||||||
|
(const relative)
|
||||||
|
(const absolute)
|
||||||
|
(const noabbrev))
|
||||||
|
:safe #'symbolp)
|
||||||
|
|
||||||
;;; the roam: link
|
;;; the roam: link
|
||||||
(org-link-set-parameters "roam"
|
(org-link-set-parameters "roam"
|
||||||
:follow #'org-roam-link-follow-link)
|
:follow #'org-roam-link-follow-link)
|
||||||
@ -139,6 +155,18 @@ If there is no corresponding headline, return nil."
|
|||||||
(org-id-get-create))))))))
|
(org-id-get-create))))))))
|
||||||
|
|
||||||
;;; Path-related functions
|
;;; Path-related functions
|
||||||
|
(defun org-roam-link-get-path (path)
|
||||||
|
"Return the PATH of the link to use.
|
||||||
|
Respect `org-link-file-path-type', see the variable documentation for details.
|
||||||
|
If DIR is passed, use DIR as the default directory."
|
||||||
|
(pcase org-roam-link-file-path-type
|
||||||
|
('absolute
|
||||||
|
(abbreviate-file-name (expand-file-name path)))
|
||||||
|
('noabbrev
|
||||||
|
(expand-file-name path))
|
||||||
|
('relative
|
||||||
|
(file-relative-name path))))
|
||||||
|
|
||||||
(defun org-roam-link--split-path (path)
|
(defun org-roam-link--split-path (path)
|
||||||
"Splits PATH into title and headline.
|
"Splits PATH into title and headline.
|
||||||
Return a list of the form (type title has-headline-p headline star-idx).
|
Return a list of the form (type title has-headline-p headline star-idx).
|
||||||
@ -185,8 +213,7 @@ marker is a marker to the headline, if applicable."
|
|||||||
('title
|
('title
|
||||||
(setq loc (org-roam-link--get-file-from-title title)
|
(setq loc (org-roam-link--get-file-from-title title)
|
||||||
desc title
|
desc title
|
||||||
link-type "file")
|
link-type "file"))
|
||||||
(when loc (setq loc (file-relative-name loc))))
|
|
||||||
('headline
|
('headline
|
||||||
(setq mkr (org-roam-link--get-id-from-headline headline))
|
(setq mkr (org-roam-link--get-id-from-headline headline))
|
||||||
(pcase mkr
|
(pcase mkr
|
||||||
@ -209,6 +236,8 @@ DESC is the link description."
|
|||||||
(unless (org-in-regexp org-link-bracket-re 1)
|
(unless (org-in-regexp org-link-bracket-re 1)
|
||||||
(user-error "No link at point"))
|
(user-error "No link at point"))
|
||||||
(replace-match "")
|
(replace-match "")
|
||||||
|
(when (string-equal link-type "file")
|
||||||
|
(setq loc (org-roam-link-get-path loc)))
|
||||||
(insert (org-roam-link-make-string (concat link-type ":" loc) desc)))))
|
(insert (org-roam-link-make-string (concat link-type ":" loc) desc)))))
|
||||||
|
|
||||||
(defun org-roam-link-replace-all ()
|
(defun org-roam-link-replace-all ()
|
||||||
|
42
org-roam.el
42
org-roam.el
@ -536,27 +536,6 @@ The search terminates when the first property is encountered."
|
|||||||
(push (cons prop p) res)))
|
(push (cons prop p) res)))
|
||||||
res)))
|
res)))
|
||||||
|
|
||||||
(defun org-roam--expand-links (content path)
|
|
||||||
"Crawl CONTENT for relative links and expand them.
|
|
||||||
PATH should be the root from which to compute the relativity."
|
|
||||||
(let ((dir (file-name-directory path))
|
|
||||||
link link-type)
|
|
||||||
(with-temp-buffer
|
|
||||||
(insert content)
|
|
||||||
(goto-char (point-min))
|
|
||||||
;; Loop over links
|
|
||||||
(while (re-search-forward org-roam--org-link-bracket-typed-re (point-max) t)
|
|
||||||
(setq link-type (match-string 1)
|
|
||||||
link (match-string 2))
|
|
||||||
(when (and (string-equal link-type "file")
|
|
||||||
(f-relative-p link))
|
|
||||||
(save-excursion
|
|
||||||
(goto-char (match-beginning 2))
|
|
||||||
(delete-region (match-beginning 2)
|
|
||||||
(match-end 2))
|
|
||||||
(insert (expand-file-name link dir)))))
|
|
||||||
(buffer-string))))
|
|
||||||
|
|
||||||
(defun org-roam--get-outline-path ()
|
(defun org-roam--get-outline-path ()
|
||||||
"Return the outline path to the current entry.
|
"Return the outline path to the current entry.
|
||||||
|
|
||||||
@ -624,10 +603,7 @@ it as FILE-PATH."
|
|||||||
(or (org-element-property :content-end element)
|
(or (org-element-property :content-end element)
|
||||||
(org-element-property :end element)))))
|
(org-element-property :end element)))))
|
||||||
(content (string-trim content))
|
(content (string-trim content))
|
||||||
(content (org-roam--expand-links content file-path))
|
(properties (list :outline (org-roam--get-outline-path)
|
||||||
(properties (list :outline (mapcar (lambda (path)
|
|
||||||
(org-roam--expand-links path file-path))
|
|
||||||
(org-roam--get-outline-path))
|
|
||||||
:content content
|
:content content
|
||||||
:point begin))
|
:point begin))
|
||||||
(names (pcase type
|
(names (pcase type
|
||||||
@ -844,16 +820,10 @@ If `org-roam-link-title-format title' is defined, use it with TYPE."
|
|||||||
(defun org-roam--format-link (target &optional description type)
|
(defun org-roam--format-link (target &optional description type)
|
||||||
"Formats an org link for a given file TARGET, link DESCRIPTION and link TYPE.
|
"Formats an org link for a given file TARGET, link DESCRIPTION and link TYPE.
|
||||||
TYPE defaults to \"file\"."
|
TYPE defaults to \"file\"."
|
||||||
(let* ((here (ignore-errors
|
(setq type (or type "file"))
|
||||||
(-> (or (buffer-base-buffer)
|
(when (string-equal type "file")
|
||||||
(current-buffer))
|
(setq target (org-roam-link-get-path target)))
|
||||||
(buffer-file-name)
|
(org-roam-link-make-string (concat type ":" target) description))
|
||||||
(file-name-directory)))))
|
|
||||||
(org-roam-link-make-string
|
|
||||||
(concat (or type "file") ":" (if here
|
|
||||||
(file-relative-name target here)
|
|
||||||
target))
|
|
||||||
description)))
|
|
||||||
|
|
||||||
(defun org-roam--prepend-tag-string (str tags)
|
(defun org-roam--prepend-tag-string (str tags)
|
||||||
"Prepend TAGS to STR."
|
"Prepend TAGS to STR."
|
||||||
@ -1344,7 +1314,7 @@ replaced links are made relative to the current buffer."
|
|||||||
(when (and (f-relative-p path)
|
(when (and (f-relative-p path)
|
||||||
(org-in-regexp org-link-bracket-re 1))
|
(org-in-regexp org-link-bracket-re 1))
|
||||||
(let* ((file-path (expand-file-name path (file-name-directory old-path)))
|
(let* ((file-path (expand-file-name path (file-name-directory old-path)))
|
||||||
(new-path (file-relative-name file-path (file-name-directory (buffer-file-name)))))
|
(new-path (org-roam-link-get-path file-path)))
|
||||||
(replace-match (concat type ":" new-path)
|
(replace-match (concat type ":" new-path)
|
||||||
nil t nil 1))))))))
|
nil t nil 1))))))))
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user