mirror of
https://github.com/org-roam/org-roam
synced 2025-08-03 12:27:23 -05:00
(feat): graph of bfs from given node (#418)
This commit is contained in:
@ -263,6 +263,32 @@ If the file does not have any connections, nil is returned."
|
||||
(files (mapcar 'car-safe (emacsql (org-roam-db) query file))))
|
||||
files))
|
||||
|
||||
(defun org-roam-db--links-with-max-distance (file max-distance)
|
||||
"Return all files reachable from/connected to FILE in at most MAX-DISTANCE steps,
|
||||
including the file itself. If the file does not have any connections, nil is returned."
|
||||
(let* ((query "WITH RECURSIVE
|
||||
links_of(file, link) AS
|
||||
(SELECT \"from\", \"to\" FROM links UNION
|
||||
SELECT \"to\", \"from\" FROM links),
|
||||
-- Links are traversed in a breadth-first search. In order to calculate the
|
||||
-- distance of nodes and to avoid following cyclic links, the visited nodes
|
||||
-- are tracked in 'trace'.
|
||||
connected_component(file, trace) AS
|
||||
(VALUES($s1, json_array($s1))
|
||||
UNION
|
||||
SELECT lo.link, json_insert(cc.trace, '$[' || json_array_length(cc.trace) || ']', lo.link) FROM
|
||||
connected_component AS cc JOIN links_of AS lo USING(file)
|
||||
WHERE (
|
||||
-- Avoid cycles by only visiting each file once.
|
||||
(SELECT count(*) FROM json_each(cc.trace) WHERE json_each.value == lo.link) == 0
|
||||
-- Note: BFS is cut off early here.
|
||||
AND json_array_length(cc.trace) < ($s2 + 1)))
|
||||
SELECT DISTINCT file, min(json_array_length(trace)) AS distance
|
||||
FROM connected_component GROUP BY file ORDER BY distance;")
|
||||
;; In principle the distance would be available in the second column.
|
||||
(files (mapcar 'car-safe (emacsql (org-roam-db) query file max-distance))))
|
||||
files))
|
||||
|
||||
;;;;; Updating
|
||||
(defun org-roam-db--update-titles ()
|
||||
"Update the title of the current buffer into the cache."
|
||||
|
@ -130,7 +130,7 @@ into a digraph."
|
||||
(let* ((nodes (org-roam-db-query node-query))
|
||||
(edges-query
|
||||
`[:with selected :as [:select [file] :from ,node-query]
|
||||
:select [to from] :from links
|
||||
:select :distinct [to from] :from links
|
||||
:where (and (in to selected) (in from selected))])
|
||||
(edges (org-roam-db-query edges-query)))
|
||||
(insert "digraph \"org-roam\" {\n")
|
||||
@ -186,18 +186,22 @@ If PREFIX, then the graph is generated but the viewer is not invoked."
|
||||
(call-process org-roam-graph-viewer nil 0 nil temp-graph)
|
||||
(view-file temp-graph)))))
|
||||
|
||||
(defun org-roam-graph-show-connected-component (&optional prefix)
|
||||
(defun org-roam-graph-show-connected-component (&optional max-distance no-display)
|
||||
"Like `org-roam-graph-show', but only show nodes connected to the current entry.
|
||||
If PREFIX is non-nil, the graph is generated but the viewer is not invoked."
|
||||
If MAX-DISTANCE is non-nil, only nodes within the given number of steps are shown.
|
||||
If NO-DISPLAY is non-nil, the graph is generated but the viewer is not invoked."
|
||||
(interactive "P")
|
||||
(unless (org-roam--org-roam-file-p)
|
||||
(user-error "Not in an Org-roam file"))
|
||||
(let* ((file (file-truename (buffer-file-name)))
|
||||
(files (or (org-roam-db--connected-component file) (list file)))
|
||||
(files (or (if (and max-distance (>= (prefix-numeric-value max-distance) 0))
|
||||
(org-roam-db--links-with-max-distance file max-distance)
|
||||
(org-roam-db--connected-component file))
|
||||
(list file)))
|
||||
(query `[:select [file titles]
|
||||
:from titles
|
||||
:where (in file [,@files])]))
|
||||
(org-roam-graph-show prefix query)))
|
||||
(org-roam-graph-show no-display query)))
|
||||
|
||||
(provide 'org-roam-graph)
|
||||
|
||||
|
Reference in New Issue
Block a user