org-macs: Accept nested org-async callbacks

* lisp/org-macs.el (org-async--execute-callback, org-async-call): Change
the org-async call arguments callback form to start with the symbol
org-async-task.  This allows for a list of callbacks to be
differentiated from a single callback.  `org-async-call' is also
extended to accept a a callback of this form as its sole argument.

* lisp/org-latex-preview.el (org-latex-preview--image-extract-async,
org-latex-preview--tex-compile-async, org-create-formula-image-async):
Use the new async callback form.
This commit is contained in:
TEC 2022-12-30 01:48:30 +08:00
parent 1223971314
commit fe5712eac8
Signed by: tec
SSH Key Fingerprint: SHA256:eobz41Mnm0/iYWBvWThftS0ElEs1ftBr6jamutnXc/A
2 changed files with 76 additions and 52 deletions

View File

@ -594,16 +594,16 @@ MOVEFILES."
(img-extract-async
(org-latex-preview--image-extract-async extended-info)))
(if (eq processing-type 'dvisvgm)
(plist-put (cdr img-extract-async) :success
(plist-put (cddr img-extract-async) :success
#'org-latex-preview--dvisvgm-callback)
(plist-put (cdr img-extract-async) :success
(plist-put (cddr img-extract-async) :success
#'org-latex-preview--cleanup-callback))
(if (and (eq processing-type 'dvipng)
(member "--follow" (car img-extract-async)))
(apply #'org-async-call img-extract-async)
(plist-put (cdr tex-compile-async) :success img-extract-async)
(plist-put (cdr tex-compile-async) :failure img-extract-async))
(apply #'org-async-call tex-compile-async))))
(member "--follow" (cadr img-extract-async)))
(org-async-call img-extract-async)
(plist-put (cddr tex-compile-async) :success img-extract-async)
(plist-put (cddr tex-compile-async) :failure img-extract-async))
(org-async-call tex-compile-async))))
(defun org-preview-latex--create-tex-file (processing-info preview-strings)
"Create a LaTeX file based on PROCESSING-INFO and PREVIEW-STRINGS.
@ -667,12 +667,12 @@ The path of the created LaTeX file is returned."
(tex-formatted-command
(split-string-shell-command
(format-spec tex-compile-command tex-command-spec))))
(list ; `org-async-call' arguments
tex-formatted-command
:buffer tex-process-buffer
:dir temporary-file-directory
:info extended-info
:failure "LaTeX compilation for preview failed! (error code %d)")))
(list 'org-async-task
tex-formatted-command
:buffer tex-process-buffer
:dir temporary-file-directory
:info extended-info
:failure "LaTeX compilation for preview failed! (error code %d)")))
(defun org-latex-preview--image-extract-async (extended-info)
"Create an `org-async-call' spec to extract images according to EXTENDED-INFO."
@ -713,11 +713,11 @@ The path of the created LaTeX file is returned."
(img-formatted-command
(split-string-shell-command
(format-spec img-extract-command img-command-spec))))
(list ; `org-async-call' arguments
img-formatted-command
:buffer img-process-buffer
:info extended-info
:failure "LaTeX preview image conversion failed! (error code %d)")))
(list 'org-async-task
img-formatted-command
:buffer img-process-buffer
:info extended-info
:failure "LaTeX preview image conversion failed! (error code %d)")))
(defun org-latex-preview--cleanup-callback (_exit-code _stdout extended-info)
"Move and delete files after image creation, in accords with EXTENDED-INFO."

View File

@ -398,6 +398,14 @@ run using `start-process' with the car as the command and the cdr
as the arguments. The process will be executed in DIR (if set)
or `default-directory'.
There is also a \"special form\" of PROC, namely a list where the
first item is the symbol org-async-task, and the rest constitutes
an argument list for `org-async-call'. This form allows for easy
specification of callbacks that are themselves async tasks, e.g.
\\=(org-async-call '(\"sleep 1\")
:success '(org-async-task (\"notify-send\" \"done\")))
When using this form, all other arguments are ignored.
When BUFFER is provided, the output of PROC will be directed to it.
Shoud BUFFER be t, then a temp buffer will be created and removed
during `org-async--cleanup-process'.
@ -417,37 +425,47 @@ runs for more than TIMEOUT seconds, the FAILURE callback will be run.
When NOW is non-nil, the PROC is started immediately, regardless
of `org-async-process-limit'."
(if (or now (< (length org-async--stack) org-async-process-limit))
(let ((proc
(let ((default-directory (or dir default-directory)))
(cond ((processp proc) proc)
((stringp proc)
(start-process-shell-command
(format "org-async-%d" (cl-incf org-async--counter))
buffer proc))
((consp proc)
(apply #'start-process
(format "org-async-%s-%d"
(car proc) (cl-incf org-async--counter))
buffer proc))
(t (error "Asycnc process input %S not a recognised format"
proc)))))
(timeout (or timeout org-async-timeout)))
(set-process-sentinel proc #'org-async--sentinel)
(when filter
(set-process-filter proc filter))
(push (list proc
:success success
:failure failure
:timeout timeout
:buffer (if (eq buffer t)
(cons :temp (generate-new-buffer " *temp*" t))
buffer)
:info info
:start-time (float-time))
org-async--stack)
(org-async--monitor t)
(car org-async--stack))
(cond
;; Called with a task (as can be used with callbacks), so re-call
;; with expanded arguments.
((and (consp proc)
(eq (car proc) 'org-async-task))
(apply #'org-async-call (cdr proc)))
;; Start the async process now.
((or now (< (length org-async--stack) org-async-process-limit))
(let ((proc
(let ((default-directory (or dir default-directory)))
(cond ((processp proc) proc)
((stringp proc)
(start-process-shell-command
(format "org-async-%d" (cl-incf org-async--counter))
buffer proc))
((consp proc)
(apply #'start-process
(format "org-async-%s-%d"
(car proc) (cl-incf org-async--counter))
buffer proc))
(t (error "Async process input %S not a recognised format"
proc)))))
(timeout (or timeout org-async-timeout)))
(set-process-sentinel proc #'org-async--sentinel)
(when filter
(set-process-filter proc filter))
(push (list proc
:success success
:failure failure
:filter filter
:timeout timeout
:buffer (if (eq buffer t)
(cons :temp (generate-new-buffer " *temp*" t))
buffer)
:info info
:start-time (float-time))
org-async--stack)
(org-async--monitor t)
(car org-async--stack)))
;; Queue the task to be run later.
(t
(setq org-async--wait-queue
(append org-async--wait-queue
(list (list proc
@ -458,7 +476,7 @@ of `org-async-process-limit'."
:buffer buffer
:timeout timeout
:filter filter))))
(last org-async--wait-queue)))
(last org-async--wait-queue))))
(defun org-async--sentinel (process _signal)
"Watch PROCESS for death, and cleanup accordingly.
@ -506,7 +524,10 @@ CALLBACK can take one of four forms:
PROCESS-BUFFER, and INFO as arguments.
- A function, which is called with EXIT-CODE, PROCESS-BUFFER,
and INFO as arguments.
- A list, which is used as an argument list for a new `org-async-call' invocation.
- A list, which is either:
- An (org-async-task ...) structure, which passed to an
`org-async-call' invocation.
- A list of callbacks, which are individually evaluated.
- nil, which does nothing."
(cond
((stringp callback)
@ -514,7 +535,10 @@ CALLBACK can take one of four forms:
((functionp callback)
(funcall callback exit-code process-buffer info))
((consp callback)
(apply #'org-async-call callback))
(if (eq (car callback) 'org-async-task)
(org-async-call callback)
(dolist (clbk callback)
(org-async--execute-callback clbk exit-code process-buffer info))))
((null callback)) ; Do nothing.
(t (message "Ignoring invalid `org-async-call' callback: %S" callback))))