Function: org-export-async-start

org-export-async-start is a byte-compiled function defined in ox.el.gz.

Signature

(org-export-async-start FUN BODY)

Documentation

Call function FUN on the results returned by BODY evaluation.

FUN is an anonymous function of one argument. BODY should be a valid Elisp source expression. BODY evaluation happens in an asynchronous process, from a buffer which is an exact copy of the current one.

Use org-export-add-to-stack in FUN in order to register results in the stack.

This is a low level function. See also org-export-to-buffer and org-export-to-file for more specialized functions.

Source Code

;; Defined in /usr/src/emacs/lisp/org/ox.el.gz
;;; Asynchronous Export
;;
;; `org-export-async-start' is the entry point for asynchronous
;; export.  It recreates current buffer (including visibility,
;; narrowing and visited file) in an external Emacs process, and
;; evaluates a command there.  It then applies a function on the
;; returned results in the current process.
;;
;; At a higher level, `org-export-to-buffer' and `org-export-to-file'
;; allow exporting to a buffer or a file, asynchronously or not.
;;
;; `org-export-output-file-name' is an auxiliary function meant to be
;; used with `org-export-to-file'.  With a given extension, it tries
;; to provide a canonical file name to write export output to.
;;
;; Asynchronously generated results are never displayed directly.
;; Instead, they are stored in `org-export-stack-contents'.  They can
;; then be retrieved by calling `org-export-stack'.
;;
;; Export Stack is viewed through a dedicated major mode
;;`org-export-stack-mode' and tools: `org-export-stack-refresh',
;;`org-export-stack-remove', `org-export-stack-view' and
;;`org-export-stack-clear'.
;;
;; For backends, `org-export-add-to-stack' add a new source to stack.
;; It should be used whenever `org-export-async-start' is called.

(defun org-export-async-start  (fun body)
  "Call function FUN on the results returned by BODY evaluation.

FUN is an anonymous function of one argument.  BODY should be a valid
Elisp source expression.  BODY evaluation happens in an asynchronous process,
from a buffer which is an exact copy of the current one.

Use `org-export-add-to-stack' in FUN in order to register results
in the stack.

This is a low level function.  See also `org-export-to-buffer'
and `org-export-to-file' for more specialized functions."
  (declare (indent 1))
  ;; Write the full sexp evaluating BODY in a copy of the current
  ;; buffer to a temporary file, as it may be too long for program
  ;; args in `start-process'.
  (with-temp-message "Initializing asynchronous export process"
    (let ((copy-fun (org-element--generate-copy-script (current-buffer)))
          (temp-file (make-temp-file "org-export-process")))
      (let ((coding-system-for-write 'emacs-internal))
        (write-region
         ;; Null characters (from variable values) are inserted
         ;; within the file.  As a consequence, coding system for
         ;; buffer contents could fail to be recognized properly.
         (format ";; -*- coding: utf-8-emacs-unix; lexical-binding:t -*-\n%S"
                 `(with-temp-buffer
                    ,(when org-export-async-debug '(setq debug-on-error t))
                    ;; Ignore `kill-emacs-hook' and code evaluation
                    ;; queries from Babel as we need a truly
                    ;; non-interactive process.
                    (setq kill-emacs-hook nil
                          org-babel-confirm-evaluate-answer-no t)
                    ;; Initialize export framework.
                    (require 'ox)
                    ;; Re-create current buffer there.
                    (funcall ',copy-fun)
                    (restore-buffer-modified-p nil)
                    ;; Sexp to evaluate in the buffer.
                    (print ,body)))
         nil temp-file nil 'silent))
      ;; Start external process.
      (let* ((process-connection-type nil)
             (proc-buffer (generate-new-buffer-name "*Org Export Process*"))
             (process
	      (apply
	       #'start-process
	       (append
		(list "org-export-process"
		      proc-buffer
		      (expand-file-name invocation-name invocation-directory)
		      "--batch")
		(if org-export-async-init-file
		    (list "-Q" "-l" org-export-async-init-file)
		  (list "-l" user-init-file))
		(list "-l" temp-file)))))
        ;; Register running process in stack.
        (org-export-add-to-stack (get-buffer proc-buffer) nil process)
        ;; Set-up sentinel in order to catch results.
        (let ((handler fun))
          (set-process-sentinel
           process
           (lambda (p _status)
             (let ((proc-buffer (process-buffer p)))
               (when (eq (process-status p) 'exit)
                 (unwind-protect
                     (if (zerop (process-exit-status p))
                         (unwind-protect
                             (let ((results
                                    (with-current-buffer proc-buffer
                                      (goto-char (point-max))
                                      (backward-sexp)
                                      (read (current-buffer)))))
                               (funcall handler results))
                           (unless org-export-async-debug
                             (and (get-buffer proc-buffer)
                                  (kill-buffer proc-buffer))))
                       (org-export-add-to-stack proc-buffer nil p)
                       (ding)
                       (message "Process `%s' exited abnormally" p))
                   (unless org-export-async-debug
                     (delete-file temp-file))))))))))))