(fix): org-roam-graph--build in seperate process (#679)

org-roam-graph--build accepts a callback function which is passed the
resultant graph file as its sole argument. This prevents a race between
graph building and opening.

See: #666
This commit is contained in:
N V
2020-05-21 13:03:16 -04:00
committed by GitHub
parent 4a9401dd40
commit 525a58dd86

View File

@ -217,24 +217,30 @@ into a digraph."
(insert "}") (insert "}")
(buffer-string)))) (buffer-string))))
(defun org-roam-graph--build (&optional node-query) (defun org-roam-graph--build (&optional node-query callback)
"Generate a graph showing the relations between nodes in NODE-QUERY." "Generate a graph showing the relations between nodes in NODE-QUERY.
(let ((name org-roam-graph-executable)) Execute CALLBACK when process exits successfully.
(unless (stringp name) CALLBACK is passed the graph file as its sole argument."
(user-error "`org-roam-graph-executable' is not a string")) (unless (stringp org-roam-graph-executable)
(unless (executable-find org-roam-graph-executable) (user-error "`org-roam-graph-executable' is not a string"))
(user-error (concat "Cannot find executable \"%s\" to generate the graph. " (unless (executable-find org-roam-graph-executable)
"Please adjust `org-roam-graph-executable'") (user-error (concat "Cannot find executable \"%s\" to generate the graph. "
name)) "Please adjust `org-roam-graph-executable'")
(let* ((node-query (or node-query org-roam-graph-executable))
`[:select [file titles] (let* ((node-query (or node-query
:from titles `[:select [file titles] :from titles
,@(org-roam-graph--expand-matcher 'file t)])) ,@(org-roam-graph--expand-matcher 'file t)]))
(graph (org-roam-graph--dot node-query)) (graph (org-roam-graph--dot node-query))
(temp-dot (make-temp-file "graph." nil ".dot" graph)) (temp-dot (make-temp-file "graph." nil ".dot" graph))
(temp-graph (make-temp-file "graph." nil ".svg"))) (temp-graph (make-temp-file "graph." nil ".svg")))
(call-process name nil 0 nil temp-dot "-Tsvg" "-o" temp-graph) (make-process
temp-graph))) :name "*org-roam-graph--build-process*"
:buffer "*org-roam-graph--build-process*"
:command `(,org-roam-graph-executable ,temp-dot "-Tsvg" "-o" ,temp-graph)
:sentinel (when callback
(lambda (process _event)
(when (= 0 (process-exit-status process))
(funcall callback temp-graph)))))))
(defun org-roam-graph--open (file) (defun org-roam-graph--open (file)
"Open FILE using `org-roam-graph-viewer' with `view-file' as a fallback." "Open FILE using `org-roam-graph-viewer' with `view-file' as a fallback."
@ -249,9 +255,10 @@ into a digraph."
('nil (view-file file)) ('nil (view-file file))
(_ (signal 'wrong-type-argument `((functionp stringp null) ,org-roam-graph-viewer))))) (_ (signal 'wrong-type-argument `((functionp stringp null) ,org-roam-graph-viewer)))))
(defun org-roam-graph--build-connected-component (file &optional max-distance) (defun org-roam-graph--build-connected-component (file &optional max-distance callback)
"Build a graph of nodes connected to FILE. "Build a graph of nodes connected to FILE.
If MAX-DISTANCE is non-nil, limit nodes to MAX-DISTANCE steps." If MAX-DISTANCE is non-nil, limit nodes to MAX-DISTANCE steps.
CALLBACK is passed to `org-roam-graph--build'."
(let* ((file (file-truename file)) (let* ((file (file-truename file))
(files (or (if (and max-distance (>= max-distance 0)) (files (or (if (and max-distance (>= max-distance 0))
(org-roam-db--links-with-max-distance file max-distance) (org-roam-db--links-with-max-distance file max-distance)
@ -260,7 +267,7 @@ If MAX-DISTANCE is non-nil, limit nodes to MAX-DISTANCE steps."
(query `[:select [file titles] (query `[:select [file titles]
:from titles :from titles
:where (in file [,@files])])) :where (in file [,@files])]))
(org-roam-graph--build query))) (org-roam-graph--build query callback)))
;;;; Commands ;;;; Commands
;;;###autoload ;;;###autoload
@ -282,11 +289,9 @@ ARG may be any of the following values:
(unless (org-roam--org-roam-file-p file) (unless (org-roam--org-roam-file-p file)
(user-error "\"%s\" is not an org-roam file" file))) (user-error "\"%s\" is not an org-roam file" file)))
(pcase arg (pcase arg
('nil (org-roam-graph--open (org-roam-graph--build node-query))) ('nil (org-roam-graph--build node-query #'org-roam-graph--open))
('(4) (org-roam-graph--open (org-roam-graph--build-connected-component file))) ('(4) (org-roam-graph--build-connected-component file nil #'org-roam-graph--open))
((pred integerp) (let ((graph (org-roam-graph--build-connected-component file (abs arg)))) ((pred integerp) (org-roam-graph--build-connected-component file (abs arg) (when (>= arg 0) #'org-roam-graph--open)))
(when (>= arg 0)
(org-roam-graph--open graph))))
('(16) (org-roam-graph--build node-query)) ('(16) (org-roam-graph--build node-query))
('- (org-roam-graph--build-connected-component file)) ('- (org-roam-graph--build-connected-component file))
(_ (user-error "Unrecognized ARG: %s" arg))))) (_ (user-error "Unrecognized ARG: %s" arg)))))