mirror of
https://github.com/org-roam/org-roam
synced 2025-08-01 12:17:21 -05:00
refactor: improve speed of retrieving and formatting nodes
The original code uses macros that when expanded use a lot memory and are relatively slow. This removes some of that processing: - Add a constructor to org-roam-node that does uses parameters by position instead or by name - Add the option of using a function to format nodes. The current code uses a string template. But this template is processes for every node. Using a function will further improve performance significantly. Simplified expected return value user's template function. As suggested by akashpal-21, the return value of the user's template function can be simpler. I have refactored the code such that the function only returns a string (potentially propertized) with the formatted node. I have also modified the documentation of org-roam-node-display-template with an example of the user defined function. Acknowledgement: akashpal-21 for the suggestion for improvement Close: #2511
This commit is contained in:
committed by
Dustin Farris
parent
2ff616fbd8
commit
fed577f805
108
org-roam-node.el
108
org-roam-node.el
@ -39,6 +39,16 @@
|
|||||||
;;;; Completing-read
|
;;;; Completing-read
|
||||||
(defcustom org-roam-node-display-template "${title}"
|
(defcustom org-roam-node-display-template "${title}"
|
||||||
"Configures display formatting for Org-roam node.
|
"Configures display formatting for Org-roam node.
|
||||||
|
|
||||||
|
If it is a function, it will be called to format a node.
|
||||||
|
Its result is expected to be a string (potentially with
|
||||||
|
embedded properties).
|
||||||
|
|
||||||
|
If it is a string and it will be used as described in org-roam
|
||||||
|
(see org-roam-node-display-template)
|
||||||
|
|
||||||
|
When it is a string, the following processing is done:
|
||||||
|
|
||||||
Patterns of form \"${field-name:length}\" are interpolated based
|
Patterns of form \"${field-name:length}\" are interpolated based
|
||||||
on the current node.
|
on the current node.
|
||||||
|
|
||||||
@ -64,7 +74,21 @@ as many characters as possible and will be aligned accordingly.
|
|||||||
|
|
||||||
A closure can also be assigned to this variable in which case the
|
A closure can also be assigned to this variable in which case the
|
||||||
closure is evaluated and the return value is used as the
|
closure is evaluated and the return value is used as the
|
||||||
template. The closure must evaluate to a valid template string."
|
template. The closure must evaluate to a valid template string.
|
||||||
|
|
||||||
|
When org-roam-node-display-template is a function, the function is
|
||||||
|
expected to return a string, potentially propertized. For example, the
|
||||||
|
following function shows the title and base filename of the node:
|
||||||
|
|
||||||
|
\(defun my--org-roam-format (node)
|
||||||
|
\"formats the node\"
|
||||||
|
(format \"%-40s %s\"
|
||||||
|
(if (org-roam-node-title node)
|
||||||
|
(propertize (org-roam-node-title node) 'face 'org-todo)
|
||||||
|
\"\")
|
||||||
|
(file-name-nondirectory (org-roam-node-file node))))
|
||||||
|
|
||||||
|
\q(setq org-roam-node-display-template 'my--org-roam-format)"
|
||||||
:group 'org-roam
|
:group 'org-roam
|
||||||
:type '(string function))
|
:type '(string function))
|
||||||
|
|
||||||
@ -151,6 +175,11 @@ This path is relative to `org-roam-directory'."
|
|||||||
|
|
||||||
;;; Definition
|
;;; Definition
|
||||||
(cl-defstruct (org-roam-node (:constructor org-roam-node-create)
|
(cl-defstruct (org-roam-node (:constructor org-roam-node-create)
|
||||||
|
(:constructor org-roam-node-create-from-db
|
||||||
|
(title aliases ; 2
|
||||||
|
id file file-title level todo ; 5
|
||||||
|
point priority scheduled deadline properties ;;5
|
||||||
|
olp file-atime file-mtime tags refs)) ;;5
|
||||||
(:copier nil))
|
(:copier nil))
|
||||||
"A heading or top level file with an assigned ID property."
|
"A heading or top level file with an assigned ID property."
|
||||||
file file-title file-hash file-atime file-mtime
|
file file-title file-hash file-atime file-mtime
|
||||||
@ -352,23 +381,27 @@ nodes."
|
|||||||
(defun org-roam-node-list ()
|
(defun org-roam-node-list ()
|
||||||
"Return all nodes stored in the database as a list of `org-roam-node's."
|
"Return all nodes stored in the database as a list of `org-roam-node's."
|
||||||
(let ((rows (org-roam-db-query
|
(let ((rows (org-roam-db-query
|
||||||
"SELECT
|
"
|
||||||
|
SELECT
|
||||||
|
title,
|
||||||
|
aliases,
|
||||||
|
|
||||||
id,
|
id,
|
||||||
file,
|
file,
|
||||||
filetitle,
|
filetitle,
|
||||||
\"level\",
|
\"level\",
|
||||||
todo,
|
todo,
|
||||||
|
|
||||||
pos,
|
pos,
|
||||||
priority ,
|
priority ,
|
||||||
scheduled ,
|
scheduled ,
|
||||||
deadline ,
|
deadline ,
|
||||||
title,
|
|
||||||
properties ,
|
properties ,
|
||||||
|
|
||||||
olp,
|
olp,
|
||||||
atime,
|
atime,
|
||||||
mtime,
|
mtime,
|
||||||
'(' || group_concat(tags, ' ') || ')' as tags,
|
'(' || group_concat(tags, ' ') || ')' as tags,
|
||||||
aliases,
|
|
||||||
refs
|
refs
|
||||||
FROM
|
FROM
|
||||||
(
|
(
|
||||||
@ -417,32 +450,20 @@ FROM
|
|||||||
LEFT JOIN refs ON refs.node_id = nodes.id
|
LEFT JOIN refs ON refs.node_id = nodes.id
|
||||||
GROUP BY nodes.id, tags.tag, aliases.alias )
|
GROUP BY nodes.id, tags.tag, aliases.alias )
|
||||||
GROUP BY id, tags )
|
GROUP BY id, tags )
|
||||||
GROUP BY id")))
|
GROUP BY id
|
||||||
(cl-loop for row in rows
|
")))
|
||||||
append (pcase-let* ((`(
|
(mapcan
|
||||||
,id ,file ,file-title ,level ,todo ,pos ,priority ,scheduled ,deadline
|
(lambda (row)
|
||||||
,title ,properties ,olp ,atime ,mtime ,tags ,aliases ,refs)
|
(let (
|
||||||
row)
|
(all-titles (cons (car row) (nth 1 row)))
|
||||||
(all-titles (cons title aliases)))
|
)
|
||||||
(mapcar (lambda (temp-title)
|
(mapcar (lambda (temp-title)
|
||||||
(org-roam-node-create :id id
|
(apply 'org-roam-node-create-from-db (cons temp-title (cdr row))))
|
||||||
:file file
|
all-titles)
|
||||||
:file-title file-title
|
))
|
||||||
:file-atime atime
|
rows)
|
||||||
:file-mtime mtime
|
)
|
||||||
:level level
|
)
|
||||||
:point pos
|
|
||||||
:todo todo
|
|
||||||
:priority priority
|
|
||||||
:scheduled scheduled
|
|
||||||
:deadline deadline
|
|
||||||
:title temp-title
|
|
||||||
:aliases aliases
|
|
||||||
:properties properties
|
|
||||||
:olp olp
|
|
||||||
:tags tags
|
|
||||||
:refs refs))
|
|
||||||
all-titles)))))
|
|
||||||
|
|
||||||
;;;; Finders
|
;;;; Finders
|
||||||
(defun org-roam-node-marker (node)
|
(defun org-roam-node-marker (node)
|
||||||
@ -556,6 +577,25 @@ PROMPT is a string to show at the beginning of the mini-buffer, defaulting to \"
|
|||||||
(or (cdr (assoc node nodes))
|
(or (cdr (assoc node nodes))
|
||||||
(org-roam-node-create :title node))))
|
(org-roam-node-create :title node))))
|
||||||
|
|
||||||
|
(defun org-roam--format-nodes-using-template (nodes)
|
||||||
|
"Formats NODES using org-roam template features.
|
||||||
|
Uses org-roam--node-display-template."
|
||||||
|
(let (
|
||||||
|
(wTemplate (org-roam-node--process-display-format org-roam-node-display-template))
|
||||||
|
)
|
||||||
|
(mapcar (lambda (node)
|
||||||
|
(org-roam-node-read--to-candidate node wTemplate)) nodes))
|
||||||
|
)
|
||||||
|
|
||||||
|
(defun org-roam--format-nodes-using-function (nodes)
|
||||||
|
"Formats NODES using the function org-roam-node-display-template."
|
||||||
|
(mapcar (lambda (node)
|
||||||
|
(cons
|
||||||
|
(propertize (funcall org-roam-node-display-template node) 'node node)
|
||||||
|
node))
|
||||||
|
nodes)
|
||||||
|
)
|
||||||
|
|
||||||
(defun org-roam-node-read--completions (&optional filter-fn sort-fn)
|
(defun org-roam-node-read--completions (&optional filter-fn sort-fn)
|
||||||
"Return an alist for node completion.
|
"Return an alist for node completion.
|
||||||
The car is the displayed title or alias for the node, and the cdr
|
The car is the displayed title or alias for the node, and the cdr
|
||||||
@ -565,15 +605,17 @@ and when nil is returned the node will be filtered out.
|
|||||||
SORT-FN is a function to sort nodes. See `org-roam-node-read-sort-by-file-mtime'
|
SORT-FN is a function to sort nodes. See `org-roam-node-read-sort-by-file-mtime'
|
||||||
for an example sort function.
|
for an example sort function.
|
||||||
The displayed title is formatted according to `org-roam-node-display-template'."
|
The displayed title is formatted according to `org-roam-node-display-template'."
|
||||||
(let* ((template (org-roam-node--process-display-format org-roam-node-display-template))
|
(let* (
|
||||||
(nodes (org-roam-node-list))
|
(nodes (org-roam-node-list))
|
||||||
(nodes (if filter-fn
|
(nodes (if filter-fn
|
||||||
(cl-remove-if-not
|
(cl-remove-if-not
|
||||||
(lambda (n) (funcall filter-fn n))
|
(lambda (n) (funcall filter-fn n))
|
||||||
nodes)
|
nodes)
|
||||||
nodes))
|
nodes))
|
||||||
(nodes (mapcar (lambda (node)
|
(nodes (if (functionp org-roam-node-display-template)
|
||||||
(org-roam-node-read--to-candidate node template)) nodes))
|
(org-roam--format-nodes-using-function nodes)
|
||||||
|
(org-roam--format-nodes-using-template nodes)))
|
||||||
|
|
||||||
(sort-fn (or sort-fn
|
(sort-fn (or sort-fn
|
||||||
(when org-roam-node-default-sort
|
(when org-roam-node-default-sort
|
||||||
(intern (concat "org-roam-node-read-sort-by-"
|
(intern (concat "org-roam-node-read-sort-by-"
|
||||||
|
Reference in New Issue
Block a user