(feat): graph of bfs from given node (#418)

This commit is contained in:
Johann Klähn
2020-04-10 22:20:43 +02:00
committed by GitHub
parent e327fb3f0c
commit ba1782d361
2 changed files with 35 additions and 5 deletions

View File

@ -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."

View File

@ -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)